深入解析OneDrive日志格式与逆向分析技术

本文详细解析了OneDrive日志(.odl)的二进制格式结构,包括文件头和数据块的具体定义,探讨了字符串混淆机制及其解密方法,并提供了实用的Python解析脚本,为数字取证调查提供重要技术支撑。

读取OneDrive日志

由于OneDrive的普及,它已成为数字取证中的重要证据来源。上周,Brian Maloney发布了他从usercid.dat文件重建文件夹树的研究,并提供了实现此功能的脚本。在这篇简短的文章中,我们将探讨OneDrive日志的格式,并提供一个解析工具。在后续文章中,我将展示使用案例场景。

在哪里找到它们?

OneDrive日志的扩展名为.odl,位于用户配置文件的以下位置:

  • 在Windows上 - C:\Users\<USER>\AppData\Local\Microsoft\OneDrive\logs\
  • 在macOS上 - /Users/<USER>/Library/Logs/OneDrive/

在这些位置,通常有3个文件夹 - Common、Business1和Personal,每个都包含日志。顾名思义,Business1是OneDrive for Business版本。

图1 - Business1文件夹内容

.odl文件是当前活动的日志,而.odlgz文件是已压缩的旧日志。根据您所在的文件夹(和操作系统),您可能还会看到.odlsent和.aodl文件,它们具有类似的格式。

里面有什么?

这些是二进制文件,无法在文本编辑器中直接查看。以下是在十六进制编辑器中看到的.odl文件内容。

图2 - 十六进制编辑器中的.odl文件

这是一种典型的二进制文件格式,具有256字节的文件头和随后的数据块。初步检查显示,它似乎是程序进行的所有重要函数调用的日志。在某些没有其他日志记录且需要证明文件/文件夹的上传/下载或同步,甚至发现磁盘/云上不再存在的项目的情况下,拥有这种低级别运行日志可能会很有用。

您会注意到一些看起来有趣的字符串(以红色突出显示)。稍后会详细介绍。

格式

通过一些逆向工程,文件头格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
struct {
    char     signature[8]; // EBFGONED
    uint32   unk_version;  // 观察到的值 = 2
    uint32   unknown2;
    uint64   unknown3;     // 观察到的值 = 0
    uint32   unknown4;     // 观察到的值 = 1
    char     one_drive_version[0x40];
    char     os_version[0x40];
    byte     reserved[0x64];
} Odl_header;

数据块的结构如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
struct {
    uint64     signature; // CCDDEEFF 0000000
    uint64     timestamp; // Unix毫秒时间
    uint32     unk1;
    uint32     unk2;
    byte       unk3_guid[16];
    uint32     unk4;
    uint32     unk5;  // 大多数为1
    uint32     data_len;
    uint32     unk6;  // 大多数为0
    byte       data[data_len];
} Data_block;

struct {
    uint32    code_file_name_len;
    char      code_file_name[code_file_name_len];
    uint32    unknown;
    uint32    code_function_name_len;
    char      code_function_name[code_function_name_len];
    byte      parameters[];
} Data;

对于.odlgz文件,Odl_header相同,后面跟着一个gzip压缩的blob。可以解压缩该blob以解析Data_block结构。

现在,我们可以尝试解释数据。除了几个未知字段外,数据块主要包括时间戳(事件发生的时间)、被调用的函数名称、该函数所在的代码文件以及传递给函数的参数。参数可以是各种类型,如int、char、float等,这部分尚未完全逆向工程,但仅提取字符串就能给我们提供大量有用信息。然而,字符串是被混淆的!

解混淆字符串

由于Microsoft将这些日志上传到其服务器以进行遥测和调试,他们对属于文件/文件夹名称、URL字符串或用户名的任何内容进行混淆。但是文件扩展名不会被混淆。这种方式的工作原理是,被识别为需要混淆的数据被替换为一个存储在字典中的单词。该字典以文件ObfuscationStringMap.txt的形式提供,通常位于与.odl文件相同的文件夹中。要解混淆,只需找到字符串并用它们的原始版本替换即可。

图3 - ObfuscationStringMap.txt的片段

这是一个制表符分隔的文件,根据您运行的是macOS还是Windows,存储为UTF-8或UTF-16LE。

现在,回到图2中原始的有趣字符串 - /LeftZooWry/LogOneMug/HamUghVine/MuchDownRich/QuillRodEgg/KoiWolfTad/LawFlyOwl.txt .. 解混淆后变为 ../Users/ykhatri/Library/Logs/OneDrive/Business1/telemetry-dll-ramp-value.txt

需要注意的是,由于扩展名未被混淆,即使路径中的某些或所有部分无法解码,它们仍然可以提供有价值的信息。

这个过程看起来很简单,但并非所有混淆的字符串都是文件/文件夹名称或路径/URL的一部分。有些是多行字符串。另一个问题是单词(或字典的键)被重复使用!因此您可能会在ObfuscationStringMap中多次看到相同的键。要记住的是,新条目会添加在文件的顶部,而不是底部,因此在读取文件时,键的第一次出现应该是最新的。

此外,有时键找不到,因为它在一段时间后被清理掉了。同样,无法判断字典中的条目对于正在解析的特定日志文件是过时的还是有效的。所有这些都意味着解码后的字符串需要持保留态度。

基于以上内容,解析ODL日志的Python脚本可在此处获取。脚本产生的输出片段如下所示。

图4 - 输出片段

在后续文章中,我们将详细介绍这些日志中感兴趣的项目,如帐户链接/取消链接、上传、下载、文件信息等。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计