-
-
攻破 Window AMD64 平台的 PatchGuard - 搜索加密的 PatchGuard Context
-
发表于:
2018-11-23 22:33
7736
-
攻破 Window AMD64 平台的 PatchGuard - 搜索加密的 PatchGuard Context
代码基本已经写好, 这几天闲, 把文章补上.
在Windows 7 和 Windows 8 上 因为只有一层xor 加密
(密钥存在循环)
, 前人已经研究的非常透彻, 所以找到 PatchGuard Context 还是比较简单的工作. 自Windows 10 (17134) 版本之后, 微软xor 的基础上增加了一条 btc 指令 (btc rax, rax), 经过btc 运算的密钥无法逆向, 所以只有知道了 Context 长度 才能完整的解密 Context, 长度位于 Context + 0xc4 的位置, 长度是 4个字节, 但如果你有接触这方面的资料, 应该知道在 Windows 8.1 (9600)以后, 头部的0xc8 个字节是经过双重加密的, 并且第二层加密方法是从10种加密方法中随机选取的, 具体的解密过程请自行观看这几个函数的异常处理过程. :
// PopThermalZoneDpc
// KiBalanceSetManagerDeferredRoutine
// IopIrpStackProfilerDpcRoutine
// IopTimerDispatch
// ExpCenturyDpcRoutine
// ExpTimeZoneDpcRoutine
// ExpTimeRefreshDpcRoutine
// CmpLazyFlushDpcRoutine
// CmpEnableLazyFlushDpcRoutine
// ExpTimerDpcRoutine
那么需要换一种思路, 不解密头部直接找后面一次加密的数据, 由于算法 (请自行观看 CmpAppendDllSection 函数) 是只能从高地址往低地址解密, 所以需要知道明文数据, 用IDA查看 CmpAppendDllSection 函数的引用地址 (只有一个), 在INIT 节初始化Context 部分 只需向下翻一翻就可以 看到 Context 内部的成员 (Fields), 我使用的方法是使用4个未加密的并且连续的成员去碰撞内存地址, 需要考虑xor 加密需要对齐内存 算法如下 :
RorKeyIndex = 0;
RorKey = CompareFields[3] ^ CollCompareFields[3];
RorKey = __ROR64(RorKey, PG_FIELD_BITS); // 此处是要碰撞的最后一个成员相对于 (Context + 0xc0) 处的偏移 / sizeof(ULONG64)
RorKey = _btc64(RorKey, RorKey);
RorKeyIndex++;
if ((ULONG64)(CompareFields[2] ^ RorKey) == (ULONG64)CollCompareFields[2]) {
RorKey = __ROR64(RorKey, PG_FIELD_BITS - RorKeyIndex);
RorKey = _btc64(RorKey, RorKey);
RorKeyIndex++;
if ((ULONG64)(CompareFields[1] ^ RorKey) == (ULONG64)CollCompareFields[1]) {
RorKey = __ROR64(RorKey, PG_FIELD_BITS - RorKeyIndex);
RorKey = _btc64(RorKey, RorKey);
RorKeyIndex++;
if ((ULONG64)(CompareFields[0] ^ RorKey) == (ULONG64)CollCompareFields[0]) {
// 找到数据 由于密钥可能是 0 这里有两种情况
// 一种数据已经被解密 正在执行
// 无用数据
}
}
}
图随手画的 (见谅), 剩下的工作就是如何找Fields, 定位 NonPagePool 相关的指针, 定位 SystemSpace 相关的数据结构我觉得这部分工作都是比较基础的, 没必要细说,下一节讲找到 Context 之后应该如何处理, 让 PatchGuard 正常退出.
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课