简介
msdelta.dll
包含了一系列用于对文件进行补丁操作的API 鉴于网上资料极少且官方文档简陋 记录一下学习过程
Patch(补丁)
对于msdelta.dll
中的Patch 它为一个字节流 产生于一个原字节流Source
和目标字节流Target
可以用这个Python wrapper来产生一个从源文件到目标文件的补丁文件
整体上它记录了补丁前后内容的差异 一个对Delta_Patch
结构体包含信息的描述如下:
1 | typedef struct _DELTA_HEADER_INFO |
用这个Wrapper可以方便地执行获取补丁信息和打补丁的操作:
1 | import ctypes |
打补丁
由于官方没有给出patch过程的技术细节 我也没逆清楚( 所以就归纳一下多次尝试得出的有关patch过程的结论:
1 | 补丁作用于源文件得到的目标文件是固定不变的 |
如果不满足这些条件 根据调用规定ApplyDelta API在返回后在RAX中存放错误码 比较常见的是0xD:无效补丁
至于无效补丁的成因 先说明补丁包含的内容中哪些对打补丁的结果有作用
以AmateursCTF2024的一道题为例:
AmateursCTF2024/rev/patchflag
题目的要求就是成功利用给出的补丁 dump出这个补丁:
正常的补丁开头的4bytes是补丁的CRC32 题目给出的补丁抹去了这个信息 PA30
是生成补丁的标准 但是这两个内容不影响补丁结果 这里直接插入4bytes的0得到补丁的信息:
还有两个不影响打补丁的内容(小端序) 分别标志了两个时间:
后续的一个字0x23 18
用处暂不明确 再后续一个字0x8 36 8
[:4]与校验结果使用的hash算法有关 下文会给出说明 [4:24]是目标文件的字节长度 [24:]不确定详细含义 但是与生成补丁时的选项标志位有关
接下来的一个字0x8004
为校验使用的hash算法ID 根据实验其只支持md系列算法以及文档中给出的两种特殊标志:
所使用的hash校验算法会影响上面说的4位标志位 已经试出来的有:
1 | 1.当使用md系列hash时 flag = 0b1000 |
再接下来的一个字猜测与hash的结果长度有关 这些字节都会影响打补丁的失败与否 接下来的hash_size
个字节为预期目标文件的hash校验码 进行补丁后需要计算结果hash与这个hash进行对比 如果校验失败则返回0xD错误码 后续的字节就是经过压缩的差异信息
对于这一题 hash校验值明显已经被魔改 可以再次魔改补丁让其不进行hash校验:
1 | from test import get_patch_info |
另外一个方法就是在获取目标hash值(compo::PullcapiContext::GetHash
)前获取到目标字节流