揭秘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个文件夹 - CommonBusiness1Personal,每个都包含日志文件。顾名思义,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压缩的数据块。解压该数据块后即可解析Data_block结构。

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

反混淆字符串

由于微软将这些日志上传到其服务器进行遥测和调试,他们对属于文件/文件夹名、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 设计