大疆无人机日志取证的手工分析
前话:一把梭软件:CsvView、TXTlogToCSVtool,想直接做题的下载这两软件即可
————————————————————————————————————————————————————————————
研究为简单分析。
大疆无人机一共分 为两种日志,一种是无人机本体自带的飞行记录日志,命名为{日期时间}_FLY{number}.DAT
,例如24-05-29-11-45-14_FLY096.DAT
,另一种是远程控制软件如dji go,其日志是以txt格式进行存储,命名格式为DJIFlightRecord_{日期}_[{时间}].txt
,例如DJIFlightRecord_2024-05-29_[11-45-14].txt
DAT日志分析
得到的dat日志是经过压缩的,需要用zlib进行解压(zlib.decompress()),解压后的zlib文件的结构如下:
偏移 | 大小 | 备注 |
---|---|---|
0x01 | 4字节 | 文件长度(小端) |
0x07 | 不定长 | 直到第一个0x00字节结束 |
0x11B | DAT文件大小 |
接着可以将前面删除,后面的内容才是重头戏,如下图1
其结构如下
描述 |
---|
header |
record1 |
record2 |
…… |
其中,header长度为0x100,即上图选中部分。对于header的主要解析如下
header
偏移 | 大小 | 备注 |
---|---|---|
0x00 | 1 | 机型 |
0x10 | 32(0x20) | BUILD时间 |
0xf2 | 10 | 版本号 |
对于机型的映射关系如下图2
因此对于图1中出现的header数据,解析出来是机型为SPARK
,版本号为DJI_LOG_V3
record
接着是多条record内容的解析,每一条record记录结构如下(偏移从0x100开始)
偏移 | 大小 | 备注 |
---|---|---|
0x0 | 1 | 起始固定值 (0x55) |
0x1 | 1 | 记录的大小length |
0x2 | 2 | 保留/未指定 |
0x4 | 2 | 数据类型 |
0x6 | 4 | 序列号 |
0xa | 记录大小 - 12 | data数据(经异或) |
Length - 2 | 2 | crc16-ccitt校验值 |
为了更直观的表达,可见图3中框选部分。
首先第一块0x55是每条record记录的头部,如图选中部分能看出,在0x129处也是0x55,即下一个record块。
接着是0x29代表record的大小,即选中的部分。
然后是数据类型0x0800,常见的数据类型保存如下:
数据(小端) | 类型 |
---|---|
0x0800 | 惯性测量单元 |
0x0830 | 经纬度信息 |
0x8000 | 电池信息 |
再接着是4字节的序列号0x00932A0D
然后是30字节的数据,通过查找发现该数据是 与(序列号&0xff
)异或后得到的,而序列号&0xff
即取最低位0x0D,如图4
至此就能直接解析出电池信息这类简单的信息,而在取证过程中重点需要关注的是经纬度信息,上述分析提到经纬度类型是0x0830,如图5
按照之前的解析方式进行解析,如图6
得到的内容并非全是printable内容,分析后能够得到以下结构
偏移 | 长度 | 备注 |
---|---|---|
0x00 | 4 | 年月日 |
0x04 | 4 | 时分秒 |
0x08 | 4 | 经度的10^7 |
0x0b | 4 | 纬度的10^7 |
在解析时,依旧是以小端进行解析,例如上图分别为0x01346543
,0x00011376
,0x4411bbc3
,0x0d460691
第一段0x01346543
转换为10进制为20211011
,即2021年10月11日
第二段0x00011376
转换为10进制为70518
,即07时05分18秒,注意,长度如果为5位则时的首位0被省略,分和秒是不会被省略的
第三段0x4411bbc3
转换为10进制为1142012867
,反过来除以10的7次方得到经度为114.2012867
第四段0x0d460691
转换为10进制为222693009
,除以10的7次方得到纬度为22.2693009
最后是两字节的CRC校验,这里不做过多描述。
TXT日志分析
接着是解析txt日志文件,这里就简单解析一下,建议还是直接用工具
从0x64=100字节处开始为record记录,前面部分为header,见图7
对于header记录来说,前8字节代表record记录的结束位置即0x0447ec,0x08~0x09共2字节代表detail长度即0x0190,0x0a字节代表版本号即0x0b(11)
对于其record解析,与dat日志其实大差不差,不过查询后本人得到的结论是在2020年1月20前key的生成方式是基于一种静态的码表,而从后开始使用的是基于crc64函数的加密方式。其解析代码在该网站:http://djilogs.live555.com/doxygen/html/scrambleBytes_8cpp_source.html
然后是对record类型进行解析,首先是常见的record类型:
- OSD
- HOME
- GIMBAL
- RC
- CUSTOM
- DEFORM
- CENTER_BATTERY
- SMART_BATTERY
- APP_TIP
- APP_WARN
- RC_GPS - format unknown
- RC_DEBUG - format unknown
- RECOVER
- APP_GPS
- FIRMWARE
- OFDM_DEBUG - format unknown
- VISION_GROUP - format unknown
- VISION_WARN - format unknown
- MC_PARAM - format unknown
- APP_OPERATION - format unknown
- (–23.) unknown
- APP_SER_WARN
- (–39.) unknown
- COMPONENT
- (–56.) unknown
- JPEG - format described below
- (–254.) unknown
- not used
对于每条record记录如下:
偏移 | 长度 | 备注 |
---|---|---|
0x00 | 1 | 记录类型 |
0x01 | 1 | 记录长度L |
0x02 | L | payload |
L+2+1 | 1 | 结尾数据0xff |
以第一段record数据为例,如图8。第一字节0x28代表类型为SERIAL_NUMBER,第二字节0x14代表数据长度为0x14,第三字节0x42代表keyByte,通过简单修改scrambleBytes.cpp为python代码,可以得到key为0xf55e0100e76c027f
修改的python代码如下:
crc64_table = [
0x0,
0x7AD870C830358979, 0xF5B0E190606B12F2,………………取自上面提到的网站
0x536FA08FDFD90E51, 0x29B7D047EFEC8728
]
def crc64check(record_type,key_byte):
data_for_buffer = 0x123456789ABCDEF0 * key_byte
buffer_to_crc = [(data_for_buffer >> (8 * i)) & 0xff for i in range(8)]
crc = record_type + key_byte
for byte in buffer_to_crc:
crc = (crc >> 8) ^ crc64_table[(crc ^ byte) & 0xff]
crc = hex(crc)[2:]
little_endian_output = ''.join(reversed([crc[i:i+2] for i in range(0, len(crc), 2)]))
return little_endian_output
进行异或就能得到明文信息:
最后是一段detail数据,图中高亮的400字节则为本txt文件的detail数据
这段数据……没怎么解析懂,不过能直接看到两串序列号0BMLE874010018和0C0AE5D03100LR,以及版本SPARK。