跳至主要內容

56-IAT 隐藏与混淆-自定义伪句柄

Maldevacademy大约 3 分钟安全开发

概述

如前所述,使用 API 哈希来伪装实现的 IAT 是一种有效的方法。但是,如果可行,有时替换 WinAPI 本身可以增强 IAT 的隐藏,减少哈希值的数量,以及减少与 API 哈希算法关联的潜在启发式签名。此外,为 WinAPI 函数实现自定义代码可用于各种实现,从而简化整体 IAT 隐藏过程的自动化。

考虑到这一点,本模块将完成使用调试器分析两个检索伪句柄的函数,然后创建它们的自定义版本的过程。同样,目标是避免这些函数出现在 IAT 中,并且不利用 API 哈希。将要分析的函数有:

何谓伪句柄?

伪句柄是一种句柄,它并不对应任何特定的系统资源,而仅作为当前进程或线程的引用。

函数分析

如前文提到,这两个函数都为各自的目标对象返回一个伪句柄,无论是进程还是线程。本节将使用 xdbg 调试器分析这些函数,以了解其内部运作原理。

首先在导出 DLL “kernel32.dll” 中查找 GetCurrentProcess 函数。该函数的地址为 0x00007FFD9A4A5040

image
image

转到这个地址并注意 jmp 指令。

image
image

跟踪跳转到达函数代码。指令 or rax, FFFFFFFFFFFFFFFF 将把 RAX 寄存器设置为该值,而 ret 指令将返回 0xFFFFFFFFFFFFFFFF0xFFFFFFFFFFFFFFFF 的二进制补码表示为 -1。

image
image

GetCurrentThread 函数执行相同的步骤。类似地,此函数返回 0xFFFFFFFFFFFFFFFE0xFFFFFFFFFFFFFFFE 的二进制补码表示为 -2。

image
image

自实现

由于 GetCurrentProcess 返回 -1,GetCurrentThread 返回 -2,因此可以用以下宏替换这些函数。注意,返回值类型转换为 HANDLE 类型。

#define NtCurrentProcess() ((HANDLE)-1) // 返回当前进程的伪句柄
#define NtCurrentThread()  ((HANDLE)-2) // 返回当前线程的伪句柄

32 位系统

GetCurrentProcessGetCurrentThread 函数的 64 位版本与 32 位版本仅在 HANDLE 数据类型的长度上有所不同。在 32 位系统中,HANDLE 数据类型为 4 个字节。下图显示了 32 位系统中的 GetCurrentProcess

图片
图片

总结

本模块介绍了替换 WinAPI 而不是利用 API 哈希隐藏实现的 IAT 的概念,并介绍了本地线程和进程的伪句柄概念。值得一提的是,并非所有 WinAPI 函数都可以用自定义代码替换,因为它们中的大多数比本模块中展示的函数复杂得多。有关其他 WinAPI 函数替换,请访问 VX-API Github 存储库open in new window