Close

19 Sept 2021

A project log for Obtaining Control of JXD523 : the $20 drone

Obtaining access to a drone which is currently set to communicate with android application, allowing custom software to be built for it.

kynanKynan 09/19/2021 at 06:370 Comments

Continuing on in my quest for control over this device I decided to test whether other methods of controlling the drone will lead to some output on the device itself.

Theory 1 :

Packets sent not frequently enough.

As seen above there a large number of the larger packets being sent as opposed to the smaller packet example (when in reference to the 2 packets mentioned in 18 Sept 2021 Log).

Theory 2: 

In my last recording I had picked up a new request which has not come up earlier when trying to scan over a network on my pc while my android device controls the drone.

After Googling about this protocol I found that this was to do with giving IP addresses as devices joined then I digressed back into testing Theory 1.

To test this I configured the code slightly so that It will not just pause in the while true loop.

s2.send(bytes.fromhex('7F'))
while True:
    data, addr = s1.recvfrom(1500)    
    sys.stdout.write(str(data))
    s2.send(bytes.fromhex('19 FF FF FF FF 7F 7F E6'))
    print("\r\n sent")
    #data = s2.recv(106)
    print(data)

After testing this on the device on both ports given by the RSTP request 

I then tested sending both codes in sequence in the while loop.

s2.send(bytes.fromhex('7F'))
s2.send(bytes.fromhex('19 FF FF FF FF 7F 7F E6'))

This did not yield results either thus began the test with the most accurate representation to what we see in the live environment.

This allows for 11 of the more frequent messages to be sent before the smaller one.

Alas this did not bring about any visible change on the device.

n = 0
while True:
    data, addr = s1.recvfrom(1500)
    sys.stdout.write(str(data))
    s2.send(bytes.fromhex('19 FF FF FF FF 7F 7F E6'))
    if n == 10:
        s2.send(bytes.fromhex('7F'))
    print("\r\n sent")
    #data = s2.recv(106)
    print(data)
    n = n+1

After pondering for some time as to what the difference was between the code that works and my code.

I then realized that perhaps the port I am communicating using is not recognized because it differs from the one receiving video.

I then decided to only loop the program once and printout the address and then configured the following code to send from the next port up from the one currently bound to receive packets.

s1 = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s1.bind(("",57795))

s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.bind(("", 57796))

[loop code change]

n=0
while True:
    data, addr = s1.recvfrom(1500)
    data2, addr2 = s2.recvfrom(1500)
    s2.sendto(bytes.fromhex('19 FF FF FF FF 7F 7F E6'),0,addr2)
    print("\r\n S1 Address = " + str(addr))
    print("\r\n S2 Address = " + str(addr2))
    if n == 10:
        s2.sendto(bytes.fromhex('7F'),0,addr2)
       n = 0
    print("\r\n s2 packet sent")
    #data = s2.recv(106)
    print(data)
    print(data2)
    n = n+1

Which this appears to be allowing myself to receive packets and also had an interesting effect on the lights on the drone, as it seems to engage them in the same way when you pressed the on button(in the android app) before which the LEDs seem to flash consistently.

I also receive this in the output console on my code.

b'OPTIONS rtsp://192.168.1.1:7070/webcam RTSP/1.0\r\nCSeq: 1\r\nUser-Agent: Lavf56.40.101\r\n\r\n'
package sent
package recved
b'RTSP/1.0 200 OK\r\nCSeq: 1\r\nPublic: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n\r\n'
b'DESCRIBE rtsp://192.168.1.1:7070/webcam RTSP/1.0\r\nAccept: application/sdp\r\nCSeq: 2\r\nUser-Agent: Lavf56.40.101\r\n\r\n'
package sent
package recved
b'RTSP/1.0 200 OK\r\nCSeq: 2\r\nContent-Base: rtsp://192.168.1.1:7070/webcam/\r\nContent-Type: application/sdp\r\nCo'
b'SETUP rtsp://192.168.1.1:7070/webcam/track0 RTSP/1.0\r\nTransport: RTP/AVP/UDP;unicast;client_port=57795\r\nCSeq: 3\r\nUser-Agent: Lavf56.40.101\r\n\r\n'
package sent
package recved
b'ntent-Length: 122\r\n\r\nv=0\r\no=- 1 1 IN IP4 127.0.0.1\r\ns=Test\r\na=type:broadcast\r\nt=0 0\r\nc=IN IP4 0.0.0.0\r\nm=v'
b'ideo 0 RTP/AVP 26\r\na=control:track0\r\nRTSP/1.0 200 OK\r\nCSeq: 3\r\nTransport: RTP/AVP;unicast;client_port=57795-57796;server_port=56262-56263\r\nSession: B4B5B6B7B8B9BABBBCBDBEBFC0C1C2\r\n\r\n'
Session: B4B5B6B7B8B9BABBBCBDBEBFC0C1C2
['server_port', '56262-56263']
b'PLAY rtsp://192.168.1.1:7070/webcam RTSP/1.0\r\nRange: npt=0.000-\r\nCSeq: 4\r\nUser-Agent: Lavf56.40.101\r\nSession: B4B5B6B7B8B9BABBBCBDBEBFC0C1C2\r\n\r\n'
b'RTSP/1.0 200 OK\r\nCSeq: 4\r\nSession: B4B5B6B7B8B9BABBBCBDBEBFC0C1C2\r\n\r\n'
 S1 Address = ('192.168.1.1', 56262)
 S2 Address = ('192.168.1.1', 56263)
 s2 packet sent
b'\x80\x1a\xb3\xb2\xb1\xc6\xbaB\xad\xac\xab\xaa\x00\x00\x00\x00A\xffP<\x04\xa4\x80\xc0\x00\x00\x00\x80\x17\x10\x11\x14\x11\x0e\x17\x14\x12\x14\x1a\x18\x17\x1b"9%"\x1f\x1f"F25)9RHWUQHPN[f\x83o[a|bNPr\x9bs|\x87\x8b\x92\x94\x92Xm\xa0\xac\x9f\x8e\xaa\x83\x8f\x92\x8d\x18\x1a\x1a"\x1e"C%%C\x8d^P^\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\xe5i)h\xa0\x05\x14\xb4\xda\\\xd0\x02\xd1I\x9aZ\x00\x05H\xa7\x8a\x8a\xa4C@\n\xfd*:\x91\xaa3@\x01\xe9M\xa7u\x14\xd3@\x05\x14Q@\x05(\x14\x94\xb4\x00\xb4\xe1M\x14\xe1@\x0bM\xa5\xa4\xa0\x04\xa0\xd0h\xa0\x06\x9a)i(\x01E:\x9a)h\x01iE%\x14\x00\xeaCFi(\x00\xa2\x8a(\x01\r%8\xd3h\x00\xa5\xa4\xa2\x80$SN\xa6-:\x80\n(\xa3\xa5\x00-\x14\xdf3\'\n\x0b\x1faR\xa5\xb5\xd3\x8c\xad\xac\xa7\xf04\x01\x1d-L\x96\x17\xd2\x1c-\xa3\x83\xef\xc5Y]\x07R~\xab\x1a\x0fv\xa4\x06}\x15\xa6\xde\x1c\xd4\x00\xca<.}\x03U9\xb4\xfb\xf8?\xd6\xdaH=\xc0\xcf\xf2\xa0\n\xf4R3mm\xae\xac\xa7\xd0\x8a\x01\x07\xa1\xa6\x01E-%\x00\x18\xa4\xa5\xa2\x80\x01E\x14P\x01E\x14P\x02\x8a))h\x00\xa2\x8a(\x00\xa2\x8a(\x00\xa0\xd1A\xa0\x06\xf7\xa7\x8agzx\xa0\x07\n\xde\xd1\xbf\xe4\x11\x08\xff\x00i\x8f\xebX\x1d\x8do\xe8\xfcip\x7f\xc0\x8f\xfe<h\x03@S\xc5G\xc9\x1cu\xa9V\x90\xc7)\xa5\xa4\xa3\xa5M\xc0Z\x05\x14\x94\xc0Z)(\xa0\x07QI\x9fZCHc\xb3\xef\xc5\x14\xdc\xd2\x8a\x04\x7f\xff\xd0\xe5i)h\xa0\x02\x8a(\xa0\x02\x8a(\xa0\x05\xa7)\xa6S\x94\xf3@\x12\x1e\x94\xc6\xa7\x8eE5\x86\r\x004R\x1aZC@\tE\x14P\x01E\x14P\x02\x8ap\xa6R\x83@\x0f\xa6\x9a\t\xa6\xe6\x80\x174RQ@\x05\x14\xb4\x94\x00\np\xe9M\xa34\x00\xeaL\xd1E\x00\x14\xb9\xa6\xd2\xd0\x03\x85\x06\x9a\r:\x80\x12\x92\x9dM4\x00P(\xa2\x80\x1e\xbdiK\x00q\xd4\xfa\nH\xc6\xf9Q\x0f\x01\x8e+\xaa\xb0\xb1\xb7\x82%e\x89w\x91\xf7\x8f&\x800\xedt\xab\xdb\xa2\x0e\xcf)?\xbc\xd5\xa9o\xe1\xfbX\x883\xb3L\xdf\x90\xadjk\xc8#R\xccx\xa4\x03b\x86\x18\x17l0\xc6\x83\xd9EI\x93\xebQ\xc5:Hp\x08\xcdK\xc7z\x00\\\x9cu4\xa0\xf1\xc5\'\xb0\xa4c\x8a\x00Eo\x9f\x15&\xf2\xbft\x9f\xce\xa0\x07\xe6\xcfz~@\xeb@\r\x98\xac\xb9\x12D\x8f\xf5Pk>}\x1a\xc6s\xccf&\xff\x00`\xe0~U{\xcd\n\xa7#\x9a\x84\xcaG\n3\xeeM\x00c\xcd\xe1\xf9T\x9f\xb3\xdc+\x0e\xc1\xc6*\xbf\xf65\xfepQ\x07\xb9j\xde\xf3\t\xeb\xd6\x8c\xe7\xbd\x00b\xae\x85rT\x17\x9e5>\x9dh}\x0e\xe0\x03\xb2x\xdc\xfat\xad\x9ai4\\\x0ej{[\x9bc\xfb\xe8X\x01\xfcC\xa5D\x08=+\xabV\xc7\x07\x91\xe8j\xa5\xe6\x93\r\xd0/\t\x11K\xed\xd0\xd3\x1d\x8c\n)\xf3\xc3%\xb4\xa6)\xd7k\x0f\xc8\xd3(\x10R\xd2Q@\x05-\x14P\x01E\x14P\x01Hii\r\x00 \xebO\x15\x1fz\x90P\x02\xf6?J\xe84\x91\x8d.\xdf\xdc\x1f\xfd\x08\xd7<\xdfq\xbe\x86\xbaM4m\xd3-\x81\xfe\xe6\x7fSH\x0bkR\x0e\x95\x1a\xd3\xc5&1\xc34\xb4\xdc\xd3\x87J\x00_\xa1\xa4\xa4\x1dih\xb8X\\\xd1M\xa3\x9a@8Pi\x05\'9\xa1\x00\xa0\xd1\x9a(\x04P\x07\xff\xd1\xe5h\xa2\x8a\x00(\xa2\x83@\x05\x14\x94\xa2\x80\nP))h\x02D\xa5qLSO\'\x8a\x00\x8f\x14Ph\xcd\x006\x8a\r\x14\x00QE\x14\x00\x94\xa2\x8a(\x004QE\x00-\x14\x94\xb4\x00Q\x8aJ(\x00\xa2\x8a(\x00\xa5\xa4\xa5\x14\x00\xb8\xa4\xa5\xa2\x80\x12\x96\x92\x8a\x00u!\xa2\x8a\x00JZJ(\x01rQ\x95\xc7\xf0\x9c\xd7ci kTn\xd5\xc6\x9f\xbak\xa5\xd2nW\xfb=C\x1f\xbb@\x1a&\xe2\x10\t2\x0c\x8e\xd5\x9f<\xde{\xe4\xe4 \xfb\xa3\xfa\xd4r\xcf\xe6\xb9pp\t\xa1X6E \x1f\x19\x01\xb3\xfc\xaa\xec\x13\xaf\n\x7f\n\xce\x07i\xcfQJ\n\x8c\xe3<\xfa\xd0\x06\xda\x90zS&8\x00\xd6tWRG\xd8\x91S4\xc6NI\xa2\xe1bR\xe0S\x19\xf7w\xa8\xf3Fh\x01I\xcd7\xa0\xc5:\x93\x19\xa0\x06\xd2\x95\xc8\xe7\x9a:R\xd2\x18\x9d\x05\x1dh\xa3\x8a`\x14\xe54\xca;\xd0\x04\x93E\r\xd4F+\x85\xc8\xec{\x8a\xe7/ld\xb1\x97k|\xd1\xb7\xdcz\xe87TZ\x82$\xdaL\xc1\xc7\xfa\xa5\xdc\x0f\xbd\x029\xba(\x1ft}(\xa6\x01KE%\x00.(\xa34P\x01Hii\r\x00\'zx\xe9L\x14\xf1@\x03}\xc6\xfaWKc\xc6\x9fk\xff\x00\\\xc5sNp\x87\xe9]5\x9f\xfcx\xdb\x0f\xfad\xbf\xca\x90\x16E<Tb\x9e)0\x17\x14\xb4\x80\xf1Fi\\c\xa9(\xa2\x90\xc5\xa4\xe74QB\x10\xb4\x13I\x9a(\x01z\x8aJUlg\xbd&@\xe9@X\xff\xd2\xe5)i(\xa0\x05\xa3\x9a\x05-\x00&(\xc5-\x14\x00QKE\x00\x14d\xd2Q@\x05!\xa2\x8a\x00(\xa4\xa5\xa0\x02\x8aJ(\x01h\xa2\x8a\x00))i(\x01h\xa2\x92\x80\x16\x92\x96\x8a\x00))h\xa0\x00S\xa9\xb4\xb4\x00\xb4\x94Q@\x0bE%\x14\x00\xb4\x94Q@\x05\x14Q@\x0bWt\xf6\xceP\xf4\xcdR\x19\xa9 \x7f.L\xf64\x01\xb1\xd0\xe0'
b'\x80\xc8\x00\x06\xad\xac\xab\xaa\x83\xaa\x7fr\xc9\xba^5\xb1\xc6\xbaB\x00\x00\x00\x01\x00\x00\x05\xac\x81\xca\x00\x04\xad\xac\xab\xaa\x01\x0eUnnamed stream'

 This now leaves me with yet another packet I am unable to decode, This second packet appears to be not as long as the first however with the same first byte as the original packet.

Perhaps this is the telemetry from the drone itself to allow calculations to be based on the current position of the drone.

However that is where I will leave things today while I try to construct a method of determining all inputs allowed into the s2 socket.

Discussions