Skip to main content

大疆无人机日志取证的手工分析

前话:一把梭软件: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文件的结构如下:

偏移大小备注
0x014字节文件长度(小端)
0x07不定长直到第一个0x00字节结束
0x11BDAT文件大小

接着可以将前面删除,后面的内容才是重头戏,如下图1

图1

其结构如下

描述
header
record1
record2
……

其中,header长度为0x100,即上图选中部分。对于header的主要解析如下

偏移大小备注
0x001机型
0x1032(0x20)BUILD时间
0xf210版本号

对于机型的映射关系如下图2

图2

因此对于图1中出现的header数据,解析出来是机型为SPARK,版本号为DJI_LOG_V3

record

接着是多条record内容的解析,每一条record记录结构如下(偏移从0x100开始)

偏移大小备注
0x01起始固定值 (0x55)
0x11记录的大小length
0x22保留/未指定
0x42数据类型
0x64序列号
0xa记录大小 - 12data数据(经异或)
Length - 22crc16-ccitt校验值

为了更直观的表达,可见图3中框选部分。

图3

首先第一块0x55是每条record记录的头部,如图选中部分能看出,在0x129处也是0x55,即下一个record块。

接着是0x29代表record的大小,即选中的部分。

然后是数据类型0x0800,常见的数据类型保存如下:

数据(小端)类型
0x0800惯性测量单元
0x0830经纬度信息
0x8000电池信息

再接着是4字节的序列号0x00932A0D

然后是30字节的数据,通过查找发现该数据是与(序列号&0xff)异或后得到的,而序列号&0xff即取最低位0x0D,如图4

图4

至此就能直接解析出电池信息这类简单的信息,而在取证过程中重点需要关注的是经纬度信息,上述分析提到经纬度类型是0x0830,如图5

图5

按照之前的解析方式进行解析,如图6

图6

得到的内容并非全是printable内容,分析后能够得到以下结构

偏移长度备注
0x004年月日
0x044时分秒
0x084经度的10^7
0x0b4纬度的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

图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类型:

  1. OSD
  2. HOME
  3. GIMBAL
  4. RC
  5. CUSTOM
  6. DEFORM
  7. CENTER_BATTERY
  8. SMART_BATTERY
  9. APP_TIP
  10. APP_WARN
  11. RC_GPS - format unknown
  12. RC_DEBUG - format unknown
  13. RECOVER
  14. APP_GPS
  15. FIRMWARE
  16. OFDM_DEBUG - format unknown
  17. VISION_GROUP - format unknown
  18. VISION_WARN - format unknown
  19. MC_PARAM - format unknown
  20. APP_OPERATION - format unknown
  21. (–23.) unknown
  22. APP_SER_WARN
  23. (–39.) unknown
  24. COMPONENT
  25. (–56.) unknown
  26. JPEG - format described below
  27. (–254.) unknown
  28. not used

对于每条record记录如下:

偏移长度备注
0x001记录类型
0x011记录长度L
0x02Lpayload
L+2+11结尾数据0xff

以第一段record数据为例,如图8。第一字节0x28代表类型为SERIAL_NUMBER,第二字节0x14代表数据长度为0x14,第三字节0x42代表keyByte,通过简单修改scrambleBytes.cpp为python代码,可以得到key为0xf55e0100e76c027f

image-20240529195227332

修改的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

进行异或就能得到明文信息:

image-20240529195646564

最后是一段detail数据,图中高亮的400字节则为本txt文件的detail数据

image-20240529195719655

这段数据……没怎么解析懂,不过能直接看到两串序列号0BMLE874010018和0C0AE5D03100LR,以及版本SPARK。