2

So I bought this GVM-560AS LED photography light on Amazon. It is a really good light for the job; but to control it remotely you have to download a really dodgy APK from the GVM website, a package which flagged red across the board on VirusTotal.com

So in the spirit of experimentation I loaded the control app onto the Android emulator and captured the packets it sent to the light over WiFi.

It is sending UDP messages to port 2525 on the broadcast address 192.168.4.255(/24), When I replay these UDP messages with Python it has the desired effect in controlling the light. The issue is that I can't make sense of the message generation mechanism, and enumerating the 65,000 potential states seems a little tedious.

The message to turn the light on is ffffffffffff20720d390dfa0800450000341213400040119e54c0a80402c0a804ff92b009dd00207e4934433534303930303230353730303030303130313338354230333030303000000000900000000000

The message to turn the light off is ffffffffffff20720d390dfa080045000034f14040004011bf26c0a80402c0a804ff83ed09dd00208c0e3443353430393030323035373030303030313030323837417375620b5f6700000000900000000000

The message to set the brightness to 11% at 3200K is ffffffffffff20720d390dfa0800450000340bb640004011a4b1c0a80402c0a804ffb4e809dd002046f03443353430393030323035373030303230313062463737310035002ff1ba00000000900000000000

The message to set the brightness to 63% at 3200K is ffffffffffff20720d390dfa080045000034aee7400040110180c0a80402c0a804ff9cbf09dd002060163443353430393030323035373030303230313366383141360035002fd18cb003ff3f900000000000

I am guessing that this is just a weird encoding scheme that I can't figure out, rather than it being some kind of proprietary RPC. Any suggestions or pointers towards the generation mechanism would be much appreciated!

5
  • It would be helpful if you extracted the actual payload with wireshark. Then you would not have to put all the Ethernet/IP/UDP headers on stackoverflow. – Mike76 Mar 17 '19 at 0:57
  • @Mike76 This comes from having to feed Python's socket.socket the full UDP frame :( 3443353430393030323035373030303 0 303130 3032383741 Off 3443353430393030323035373030303 0 303130 3133383542 On 3443353430393030323035373030303 2 303130 6246373731 11% @ 3200K 3443353430393030323035373030303 2 303136 3436413338 99% @ 3200K The spaces are not part of the payload, I have added them. – GDev Mar 17 '19 at 2:11
  • I also don't overly mind having the MAC addresses of the emulator and virtual NAT interface on the tinterwebz ^_^ – GDev Mar 17 '19 at 3:29
  • Hi! I bought one of these, discovered the same dodgy APK, and started reverse-engineering the protocol as well. 😂 I might try disassembling the APK to find some answers as to what's going on. – Nathan Osman Dec 12 '19 at 4:17
  • I've been struggling with this as well. I can send the OFF message, but that's about it. Has anyone made real progress here? – EricWF Feb 20 at 0:53
3

First things first. After stripping the Ethernet / IP headers from your packets and interpreting the payload as an ASCII string, we come up with the following values:

4C540900205700000100287A ⟵ turn on
4C540900205700000101385B ⟵ turn off
4C54090020570002010bF771 ⟵ set brightness to 11%
4C54090020570002013f81A6 ⟵ set brightness to 63%

Next, I obtained a copy of the APK, extracted the DEX file, and disassembled it. Fortunately the code was not obfuscated and it was very easy to see how the values were being generated.

From what I can tell, the payload is a string consisting of the following components:

  • The string 4C5409
  • The device ID (00 in your case)
  • The device type (20 in your case)
  • The string 57000
  • The command (1 character)
  • The string 01
  • The parameter (2-4 characters)
  • The CRC-16/XMODEM checksum*

* the checksum is computed by taking the concatenated value of the preceding components and interpreting it as hexadecimal byte values

The parameters differ based on what command is being sent to the device:

0 ⟶ set state (parameter is 00 for on and 01 for off - go figure)
2 ⟶ set brightness (parameter is percentage of intensity; for example: 63)
4 ⟶ set temperature (parameter is temperature; for example: 4500)

0

NodeJs Example

const dgram = require('dgram');
const mainSocket = dgram.createSocket('udp4');

const sendCMD = (command) => {
    mainSocket.send(
        command,
        0,
        command.length,
        2525,
        '192.168.4.1'
      );
  };

//Example sending command
sendCMD('4C540900205700000101385B');

// Note Status is received on port 1112

2
  • Please don't post raw code without explanation, comments, or how the code answers the question. – schroeder Feb 4 at 8:15
  • Could you please say more? I'm struggling to get this to work. – EricWF Feb 19 at 20:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.