56-IAT 隐藏与混淆-自定义伪句柄
概述
如前所述,使用 API 哈希来伪装实现的 IAT 是一种有效的方法。但是,如果可行,有时替换 WinAPI 本身可以增强 IAT 的隐藏,减少哈希值的数量,以及减少与 API 哈希算法关联的潜在启发式签名。此外,为 WinAPI 函数实现自定义代码可用于各种实现,从而简化整体 IAT 隐藏过程的自动化。
考虑到这一点,本模块将完成使用调试器分析两个检索伪句柄的函数,然后创建它们的自定义版本的过程。同样,目标是避免这些函数出现在 IAT 中,并且不利用 API 哈希。将要分析的函数有:
GetCurrentProcess - 检索调用进程的伪句柄。
GetCurrentThread - 检索调用线程的伪句柄。
何谓伪句柄?
伪句柄是一种句柄,它并不对应任何特定的系统资源,而仅作为当前进程或线程的引用。
函数分析
如前文提到,这两个函数都为各自的目标对象返回一个伪句柄,无论是进程还是线程。本节将使用 xdbg 调试器分析这些函数,以了解其内部运作原理。
首先在导出 DLL “kernel32.dll” 中查找 GetCurrentProcess
函数。该函数的地址为 0x00007FFD9A4A5040
。
![image](https://maldevacademy.s3.amazonaws.com/images/Basic/pseudo-handle-124505341-1cca443b-e5d2-4d90-8a75-5f77b08bfe56.png)
转到这个地址并注意 jmp
指令。
![image](https://maldevacademy.s3.amazonaws.com/images/Basic/pseudo-handle-224505515-1079792a-5685-4051-a364-6a7424d95646.png)
跟踪跳转到达函数代码。指令 or rax, FFFFFFFFFFFFFFFF
将把 RAX
寄存器设置为该值,而 ret
指令将返回 0xFFFFFFFFFFFFFFFF
。0xFFFFFFFFFFFFFFFF
的二进制补码表示为 -1。
![image](https://maldevacademy.s3.amazonaws.com/images/Basic/pseudo-handle-324505523-586c63fa-8f52-4564-b01f-a52c3a34524f.png)
对 GetCurrentThread
函数执行相同的步骤。类似地,此函数返回 0xFFFFFFFFFFFFFFFE
。0xFFFFFFFFFFFFFFFE
的二进制补码表示为 -2。
![image](https://maldevacademy.s3.amazonaws.com/images/Basic/pseudo-handle-424505527-99a803e2-eaff-49a3-9ac2-470bc1fb8c69.png)
自实现
由于 GetCurrentProcess
返回 -1,GetCurrentThread
返回 -2,因此可以用以下宏替换这些函数。注意,返回值类型转换为 HANDLE
类型。
#define NtCurrentProcess() ((HANDLE)-1) // 返回当前进程的伪句柄
#define NtCurrentThread() ((HANDLE)-2) // 返回当前线程的伪句柄
32 位系统
GetCurrentProcess
和 GetCurrentThread
函数的 64 位版本与 32 位版本仅在 HANDLE
数据类型的长度上有所不同。在 32 位系统中,HANDLE
数据类型为 4 个字节。下图显示了 32 位系统中的 GetCurrentProcess
。
![图片](https://maldevacademy.s3.amazonaws.com/images/Basic/pseudo-handle-524524030-94c0a3e8-71c0-4df6-b4b5-e95b2e76edca.png)
总结
本模块介绍了替换 WinAPI 而不是利用 API 哈希隐藏实现的 IAT 的概念,并介绍了本地线程和进程的伪句柄概念。值得一提的是,并非所有 WinAPI 函数都可以用自定义代码替换,因为它们中的大多数比本模块中展示的函数复杂得多。有关其他 WinAPI 函数替换,请访问 VX-API Github 存储库。