论文阅读:HookChain

TODO

  1. 行文风格需要改
  2. 标题序号需要改

0.摘要

通过精确结合 IAT Hooking 技术、动态 SSN 解析和间接系统调用,HookChain 以一种仅作用于 Ntdll.dll 的 EDR 的警惕之眼不可见的方式重定向 Windows

1.介绍

在本研究中,着重阐述 HookChain 为先进的安全规避技术带来的全新视角,即通过巧妙绕过用户模式下 EDR 实施的监控机制,尤其是在 Ntdll.dll 库中的相关机制。对于大多数 EDR 而言,该库是遥测数据收集的关键节点,处于访问操作系统内核(环 0)前的最后一道防线。

通过一种复杂的方法,该方法将 IAT 挂钩(一种通过操纵导入表进行函数调用拦截的方式)与系统服务号(SSN)的动态解析以及间接系统调用(间接系统调用)相结合,HookChain 能够重定向所有主要 Windows 子系统的执行流,例如 kernel32.dll、kernelbase.dll 和 user32.dll。这意味着,一旦部署,HookChain 可确保在应用程序环境内的所有 API 调用都能透明地执行,完全避免被端点检测与响应(EDR)工具检测到。

不同之处在于,这种技术的执行无需对要执行的应用程序或恶意软件的源代码进行任何修改,在本研究的制定和发布之时,确保能完全避开大多数终端检测与响应(EDR)系统安装的 Ntdll.dll 监控机制。

2.

2.2 System Service Dispatching

x64中,ntdll.dll 直接调用syscall:

0:002> u ntdll!NtReadFile
ntdll!NtReadFile:
00007ffe`b258d090 4c8bd1 mov r10,rcx
00007ffe`b258d093 b806000000 mov eax,6
...
00007ffe`b258d0a2 0f05 syscall
00007ffe`b258d0a4 c3 ret

并且进入内核之后,系统调用号和三环是一样的:

lkd> uf nt!ZwReadFile
nt!ZwReadFile:
fffff806`0e7f9e00 488bc4 mov rax,rsp
fffff806`0e7f9e03 fa cli
fffff806`0e7f9e04 4883ec10 sub rsp,10h
fffff806`0e7f9e08 50 push rax
fffff806`0e7f9e09 9c pushfq
fffff806`0e7f9e0a 6a10 push 10h
fffff806`0e7f9e0c 488d052d880000 lea rax,[nt!KiServiceLinkage (fffff806`0e802640)]
fffff806`0e7f9e13 50 push rax
fffff806`0e7f9e14 b806000000 mov eax,6
fffff806`0e7f9e19 e9e2710100 jmp nt!KiServiceInternal (fffff806`0e811000)

之后就是进入Ntoskrnl中的KiServiceInternal,执行NtReadFile的实际实现

2.3 Image Loader

Image Loader是一段用户模式驻留代码,位于 Ntdll.dll 中,而非内核库中。通过这种方式,可以确保 Ntdll.dll 始终存在于正在运行的进程中(Ntdll.dll 始终会被加载)。

在应用程序的初始化和加载过程中,**导入地址表(IAT)**会填充应用程序引用的每个函数的当前地址。此过程执行以下步骤:

  1. 加载可执行文件(PE)导入表中引用的每个动态链接库(DLL)。
  2. 检查相关DLL是否已加载到进程内存中:若未加载,则从磁盘读取该DLL并将其映射到内存。
  3. 将DLL映射到内存后,对该DLL重复此过程,以导入其使用的依赖项。
  4. 每个DLL加载完成后,系统会处理导入地址表(IAT),查找需要导入的特定函数。通常,此过程通过函数名执行,但也可能通过索引编号完成。对于每个导入的函数名,加载程序会检查被导入DLL的导出表,并尝试定位目标函数。若未找到目标函数,则会终止此操作。

alt text

2.4 HOOK

2.4.1 JMP or CALL

这种策略通常用于更改ntdll.dll 内原生函数调用的代码

比如,原本的NtCreateProces是这样:

0:002> u ntdll!NtCreateProcess
ntdll!NtCreateProcess:
00007ffe`b258e700 4c8bd1 mov r10,rcx
00007ffe`b258e703 b8ba000000 mov eax,0BAh
...
00007ffe`b258e712 0f05 syscall
00007ffe`b258e714 c3 ret
00007ffe`b258e715 cd2e int 2Eh
00007ffe`b258e717 c3 ret

如果存在EDR,可以看到第一条指令变为JMP或者CALL:

0:004> u ntdll!NtCreateProcess
ntdll!NtCreateProcess:
00007fff`96bee700 e9f81b1600 jmp 00007fff`96d502fd
00007fff`96bee705 cc int 3
00007fff`96bee706 cc int 3
00007fff`96bee707 cc int 3
...
00007fff`96bee712 0f05 syscall
00007fff`96bee714 c3 ret

并且跳转指令(JMP)的目标地址未与任何已知模块(DLL)关联,因此这是在运行时注入的代码:

0:004> !address 00007fff`96d502fd
Usage: <unknown>
Base Address: 00007fff`96d50000
End Address: 00007fff`96d53000
Region Size: 00000000`00003000 ( 12.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000020 PAGE_EXECUTE_READ
Type: 00020000 MEM_PRIVATE
Allocation Base: 00007fff`96d50000
Allocation Protect: 00000002 PAGE_READONLY
Content source: 1 (target), length: 2d03

2.4.2 IAT HOOK

alt text

上图7展示了应用程序的原始执行流程。当应用程序需要进行外部函数调用(引用另一个DLL中的函数)时,它会在导入地址表(IAT)中查找目标函数的地址,然后对该地址执行CALL指令。

另一方面,从图8中可以观察到,导入地址表(IAT)中的函数地址已被替换为任意地址(拦截函数),该地址可选择性地执行原始函数。

在由终端检测与响应系统(EDR)执行此拦截的场景中,导入地址表(IAT)中存在的地址将是EDR函数的地址,该函数将执行遥测处理、检查、日志记录以及EDR规划的其他任务。

alt text

2.5 已知的pass方法

关于绕过EDR所实施的HOOK技术,目前已有若干公开披露的可行方法,但通常可归纳为以下几类:
• 重新映射Ntdll.dll以获取原始代码,或覆盖先前映射内存区域中的函数代码。
• 直接系统调用(direct syscalls)。

当前市场上的大部分EDR在用户模式下,均通过使用JMP技术拦截Ntdll.dll中的函数调用来集中设置监控点。因此,迄今为止公开报道的用户模式钩子绕过技术,均围绕Ntdll.dll展开。

2.5.1 Ntdll.dll 重映射

该技术有很多中变体,通常是读取磁盘dll的内容,然后覆盖被HOOK的函数的相关区域。

另一种方法是,在挂起模式下创建一个进程,然后读取这个进程中的Ntdll.dll,由于这个时候进程加载还没有完成,EDR还没有收到注入其Hook dll的回调 ,进程中的ntdll副本完好,没有被hook

2.5.2 直接系统调用

这个具体原理就不说了,没啥说的。

优点是可以绕过r3的hook,但还是能被EDR识别出来,比如进程执行的总时间,执行连,就是dll的调用顺序。

除了可能被识别出来,还有缺点是:

  1. 需要手动映射每个SSN,而且每个版本的SSN可能不一样
  2. 需要付出大量编程工作,将使用Windows子系统DLL的目标代码移植为仅通过直接系统调用(Syscall)使用原生函数。
  3. 现有代码的可移植性较低。因为需要调整应用程序的源代码,使其仅使用如Nt…和Zw…等原生调用。

2.5.3 间接系统调用

上述技术的一种广泛使用的变体是间接系统调用(Indirect Syscall),其原理是修改函数,使其不直接执行SYSCALL指令,而是跳转到Ntdll.dll内存中包含Syscall指令的地址。

比如可以这样:

0:002> u ntdll!NtCreateProcess
ntdll!NtCreateProcess:
00007ffe`b258e700 4c8bd1 mov r10,rcx
00007ffe`b258e703 b8ba000000 mov eax,0BAh
...
00007ffe`b258e712 0f05 syscall
00007ffe`b258e714 c3 ret
00007ffe`b258e715 cd2e int 2Eh
00007ffe`b258e717 c3 ret

可以修改函数的副本,设置EAX之后,执行一条jmp,跳到syscall的地方:

NtAllocateVirtualMemory PROC
mov r10, rcx
mov eax, <SSN>
JMP 00007ffe`b258e712
ret
NtAllocateVirtualMemory ENDP

这个微小的改动带来了显著的效果,因为从执行链遥测的角度来看,系统调用指令的调用将不再直接来自应用程序的代码,而是来自Ntdll.dll。

2.5.4 动态解析SSN

2020年12月,@modexpblog在其博客中发表了一篇题为《红队绕过用户模式钩子与系统调用直接调用》的文章。文中详细介绍了如何实现系统调用号(SSN)与其关联函数的动态关联,从而使绕过技术更加可靠,因为它无需在应用程序中内置针对每个Windows版本的固定SSN列表。该技术采用以下流程:

  1. 使用线程环境块(TEB)和进程环境块(PEB)表定位Ntdll.dll的基地址。
  2. 枚举所有以“Zw”开头的函数。在用户模式下,Nt…和Zw…函数指向同一地址,因此在此场景中使用Zw或Nt实际并无区别。
  3. 将前一步枚举到的函数的相对虚拟地址(RVA)和名称存储在数组中。在该算法的实现中,作者使用了一种EDR规避技术:不将函数名作为比较键保存和使用,而是通过一种专有算法对ROR(循环右移)进行算术运算来计算哈希值,并将其作为比较键。
  4. 按函数地址对数组进行排序。
  5. 将SSN定义为数组的索引值。

alt text

2.5.4 动态解析SSN - 光环之门 Halo’s Gate

过去几年还发布了其他动态分辨率技术,例如 2020 年 6 月发布的地狱之门 [10] 和 Sektor7 的 Reenz0h 于 2021 年 4 月发布的光环之门 [11]。

通常来说,“Halo之门”执行以下流程:

  1. 在Ntdll.dll中定位目标函数的当前地址。
  2. 读取该函数的字节(当前为32字节),并检查这些字节是否与汇编指令(mov r10, rcx; mov eax, SSN)匹配。
  3. 如果字节不匹配,则说明该函数正被监控(即已设置钩子),但邻近的函数(前后)可能未设置钩子。
  4. 在邻近函数(上下方)中搜索未设置钩子的函数,并计算找到的函数与当前函数的距离,从而获取当前函数的系统调用号(SSN)编码。

如下图:

alt text

示例代码片段:

// Quick and dirty fix in case the function has been hooked
			WORD cw = 0;
			while (TRUE) {
				// check if syscall, in this case we are too far
				if (*((PBYTE)pFunctionAddress + cw) == 0x0f && *((PBYTE)pFunctionAddress + cw + 1) == 0x05)
					return FALSE;

				// check if ret, in this case we are also probably too far
				if (*((PBYTE)pFunctionAddress + cw) == 0xc3)
					return FALSE;

				// First opcodes should be :
				//    MOV R10, RCX
				//    MOV RCX, <syscall>
				if (*((PBYTE)pFunctionAddress + cw) == 0x4c
					&& *((PBYTE)pFunctionAddress + 1 + cw) == 0x8b
					&& *((PBYTE)pFunctionAddress + 2 + cw) == 0xd1
					&& *((PBYTE)pFunctionAddress + 3 + cw) == 0xb8
					&& *((PBYTE)pFunctionAddress + 6 + cw) == 0x00
					&& *((PBYTE)pFunctionAddress + 7 + cw) == 0x00) {
					BYTE high = *((PBYTE)pFunctionAddress + 5 + cw);
					BYTE low = *((PBYTE)pFunctionAddress + 4 + cw);
					pVxTableEntry->wSystemCall = (high << 8) | low;
					break;
				}

3. 初步分析

3.1 分析目标

本分析着重对 HookChain 技术进行初步的可行性、有效性及范围验证。针对市场上各种终端检测与响应(EDR)解决方案开展了枚举,详情如下。

3.2 测试方法和局限性

为使此枚举在所有平台上具有线性且可靠,采用了以下前提条件:

  1. 所有测试使用唯一且相同的代码。
  2. 应用程序用 C 语言开发,并在 64 位 Windows 环境中使用 GCC 进行编译。
  3. 在枚举过程中不进行更改和 / 或重新编译。在所有测试环境中提供完全相同的可移植可执行文件(EXE)用于执行。所有方案都执行相同的 EXE,因此所有解决方案的行为和哈希值都相同。
  4. 应用程序在开发过程中未对这些解决方案采取任何绕过或规避措施。
  5. 在任何版本的 Windows 系统上以非特权用户身份运行应用程序,即无需本地管理员权限。

3.3 分析要点

本次分析所开发的artifact(可执行程序)会在应用程序的两个不同点执行钩子存在性验证:

  1. Ntdll.dll的函数;
  2. 导入地址表(IAT)HOOK。

3.3.1 Ntdll Hook

为了验证是否有NTdll Hook

  1. 列出所有名称以 Zw 或 Nt 开头的函数
  2. 检查函数代码中是否存在 JMP 指令;

3.3.2 IAT Hook

为了验证进程中加载的动态链接库(DLL)的导入地址表(IAT)中是否存在钩子(Hooks),执行了以下步骤:

  1. 列出进程中加载的所有动态链接库;
  2. 检查所有已加载 DLL 的导入地址表(IAT)中是否有对 Ntdll.dll 的导入引用,以及是否使用了名称以 Zw 或 Nt 开头的函数
  3. 检查导入地址表(IAT)中存在的地址是否与 Ntdll 中函数的实际地址不同

3.4 结果

可以在https://github.com/helviojunior/hookchain/tree/main/enum/results_enum这里到找部分EDR的结果

这是一个示例:

[+] Listing ntdll Nt/Zw functions
------------------------------------------
NtCreateThreadEx is hooked
NtCreateUserProcess is hooked
NtDuplicateObject is hooked
NtFreeVirtualMemory is hooked
NtLoadDriver is hooked
NtMapUserPhysicalPages is hooked
NtMapViewOfSection is hooked
NtOpenProcess is hooked
NtQuerySystemInformation is hooked
NtQuerySystemInformationEx is hooked
NtQuerySystemTime is hooked
NtQueueApcThread is hooked
NtQueueApcThreadEx is hooked
NtQueueApcThreadEx2 is hooked
NtReadVirtualMemory is hooked
NtResumeThread is hooked
NtSetContextThread is hooked
NtSetInformationProcess is hooked
NtSetInformationThread is hooked
NtTerminateProcess is hooked
NtUnmapViewOfSection is hooked
NtWriteVirtualMemory is hooked
Mapped 478 functions

[+] Listing loaded modules
------------------------------------------
C:\Users\M4v3r1ck\Desktop\hookchain_finder64.exe is loaded at 0x00007ff770d10000.
C:\WINDOWS\SYSTEM32\ntd1l.dll is loaded at 0x0000015158f10000.
C:\WINDOWS\System32\kern3l32.dll is loaded at 0x0000015159110000.
C:\WINDOWS\SYSTEM32\ntdll.dll is loaded at 0x00007ff9e1290000.
C:\WINDOWS\System32\KERNEL32.DLL is loaded at 0x00007ff9e0250000.
C:\WINDOWS\System32\KERNELBASE.dll is loaded at 0x00007ff9de950000.
C:\Program Files\SentinelOne\Sentinel Agent 23.3.3.264\InProcessClient64.dll is loaded at 0x00007ff9de4d0000.
C:\WINDOWS\System32\ADVAPI32.dll is loaded at 0x00007ff9e0780000.
C:\WINDOWS\System32\msvcrt.dll is loaded at 0x00007ff9df9a0000.
C:\WINDOWS\System32\sechost.dll is loaded at 0x00007ff9e0530000.
C:\WINDOWS\System32\RPCRT4.dll is loaded at 0x00007ff9df2d0000.
C:\WINDOWS\System32\bcrypt.dll is loaded at 0x00007ff9decc0000.
C:\WINDOWS\SYSTEM32\FLTLIB.DLL is loaded at 0x00007ff9de460000.
C:\WINDOWS\System32\ucrtbase.dll is loaded at 0x00007ff9defb0000.

[+] Listing hooked modules
------------------------------------------
Checking ntdll.dll at KERNEL32.DLL IAT
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtEnumerateKey is hooked to 0x00007ff9e132d610
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtTerminateProcess is hooked to 0x00007ff9e132d550
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtMapUserPhysicalPagesScatter is hooked to 0x00007ff9e132d030
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtDeleteValueKey is hooked to 0x00007ff9e132eaa0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetValueKey is hooked to 0x00007ff9e132dbc0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryInstallUILanguage is hooked to 0x00007ff9e132f9e0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryLicenseValue is hooked to 0x00007ff9e132fa40
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtMapViewOfSection is hooked to 0x00007ff9e132d4d0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtCreateSection is hooked to 0x00007ff9e132d910
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtUnmapViewOfSection is hooked to 0x00007ff9e132d510
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryInformationThread is hooked to 0x00007ff9e132d470
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryEvent is hooked to 0x00007ff9e132da90
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtRaiseHardError is hooked to 0x00007ff9e132fce0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryVolumeInformationFile is hooked to 0x00007ff9e132d8f0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtReplacePartitionUnit is hooked to 0x00007ff9e132fea0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryValueKey is hooked to 0x00007ff9e132d2b0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryInformationToken is hooked to 0x00007ff9e132d3f0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtOpenProcessToken is hooked to 0x00007ff9e132f4e0
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtSetInformationThread is hooked to 0x00007ff9e132d170
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtOpenThreadToken is hooked to 0x00007ff9e132d450
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtOpenKey is hooked to 0x00007ff9e132d210
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtIsSystemResumeAutomatic is hooked to 0x00007ff9e132f020
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtInitiatePowerAction is hooked to 0x00007ff9e132f000
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtWaitForSingleObject is hooked to 0x00007ff9e132d050
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtCreateEvent is hooked to 0x00007ff9e132d8d0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtFsControlFile is hooked to 0x00007ff9e132d6f0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtOpenFile is hooked to 0x00007ff9e132d630
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtClose is hooked to 0x00007ff9e132d1b0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryInformationFile is hooked to 0x00007ff9e132d1f0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetInformationFile is hooked to 0x00007ff9e132d4b0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetInformationDebugObject is hooked to 0x00007ff9e13302a0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetSystemInformation is hooked to 0x00007ff9e1330540
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryInformationProcess is hooked to 0x00007ff9e132d2f0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtFindAtom is hooked to 0x00007ff9e132d250
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryInformationAtom is hooked to 0x00007ff9e132f8c0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtAddAtomEx is hooked to 0x00007ff9e132dce0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtDeleteAtom is hooked to 0x00007ff9e132e9c0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtFlushKey is hooked to 0x00007ff9e132ed00
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtCreateKey is hooked to 0x00007ff9e132d370
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtCreateFile is hooked to 0x00007ff9e132da70
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtCreateJobSet is hooked to 0x00007ff9e132e5a0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetInformationJobObject is hooked to 0x00007ff9e13302e0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryInformationJobObject is hooked to 0x00007ff9e132f920
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtCreateJobObject is hooked to 0x00007ff9e132e580
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtAssignProcessToJobObject is hooked to 0x00007ff9e132e1a0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtTerminateJobObject is hooked to 0x00007ff9e13307e0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtOpenJobObject is hooked to 0x00007ff9e132f3c0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetEaFile is hooked to 0x00007ff9e1330220
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetSecurityObject is hooked to 0x00007ff9e13304e0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryEaFile is hooked to 0x00007ff9e132f880
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQuerySecurityObject is hooked to 0x00007ff9e132fb40
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtSetInformationProcess is hooked to 0x00007ff9e132d350
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQuerySection is hooked to 0x00007ff9e132d9f0
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtFreeVirtualMemory is hooked to 0x00007ff9e132d390
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtWriteFile is hooked to 0x00007ff9e132d0d0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtEnumerateValueKey is hooked to 0x00007ff9e132d230
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtUnlockFile is hooked to 0x00007ff9e1330940
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtReadFile is hooked to 0x00007ff9e132d090
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtLockFile is hooked to 0x00007ff9e132f120
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtAllocateVirtualMemory is hooked to 0x00007ff9e132d2d0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryVirtualMemory is hooked to 0x00007ff9e132d430
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtProtectVirtualMemory is hooked to 0x00007ff9e132d9d0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtCreateMailslotFile is hooked to 0x00007ff9e132e620
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryDirectoryFile is hooked to 0x00007ff9e132d670
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryWnfStateData is hooked to 0x00007ff9e132fc40
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtPowerInformation is hooked to 0x00007ff9e132dba0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtGetDevicePowerState is hooked to 0x00007ff9e132ee80
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetThreadExecutionState is hooked to 0x00007ff9e13305a0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetSystemEnvironmentValueEx is hooked to 0x00007ff9e1330520
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQuerySystemEnvironmentValueEx is hooked to 0x00007ff9e132fbe0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetVolumeInformationFile is hooked to 0x00007ff9e1330640
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtDeviceIoControlFile is hooked to 0x00007ff9e132d0b0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryAttributesFile is hooked to 0x00007ff9e132d770
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryFullAttributesFile is hooked to 0x00007ff9e132f8a0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtSetTimerResolution is hooked to 0x00007ff9e1330600
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtQueryTimerResolution is hooked to 0x00007ff9e132fc20
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtReadVirtualMemory is hooked to 0x00007ff9e132d7b0
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtWaitForMultipleObjects is hooked to 0x00007ff9e132db20
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtClearEvent is hooked to 0x00007ff9e132d790
  |-- KERNEL32.DLL IAT to ntdll.dll of function NtApphelpCacheControl is hooked to 0x00007ff9e132d950
  |-- KERNEL32.DLL IAT to ntdll.dll of function *NtQuerySystemInformation is hooked to 0x00007ff9e132d690
  +-- 81 hooked functions.

Checking ntdll.dll at KERNELBASE.dll IAT
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryInformationFile is hooked to 0x00007ff9e132d1f0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQuerySecurityObject is hooked to 0x00007ff9e132fb40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenFile is hooked to 0x00007ff9e132d630
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryWnfStateData is hooked to 0x00007ff9e132fc40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetInformationFile is hooked to 0x00007ff9e132d4b0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtFsControlFile is hooked to 0x00007ff9e132d6f0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryVolumeInformationFile is hooked to 0x00007ff9e132d8f0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateFile is hooked to 0x00007ff9e132da70
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtWaitForSingleObject is hooked to 0x00007ff9e132d050
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtNotifyChangeDirectoryFileEx is hooked to 0x00007ff9e132f2e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCopyFileChunk is hooked to 0x00007ff9e132e420
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtQuerySystemInformation is hooked to 0x00007ff9e132d690
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenKey is hooked to 0x00007ff9e132d210
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryEaFile is hooked to 0x00007ff9e132f880
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtFlushBuffersFile is hooked to 0x00007ff9e132d930
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateEvent is hooked to 0x00007ff9e132d8d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryValueKey is hooked to 0x00007ff9e132d2b0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenMutant is hooked to 0x00007ff9e132f460
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtReleaseMutant is hooked to 0x00007ff9e132d3d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateKeyTransacted is hooked to 0x00007ff9e132e5c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateKey is hooked to 0x00007ff9e132d370
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetValueKey is hooked to 0x00007ff9e132dbc0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryDirectoryFile is hooked to 0x00007ff9e132d670
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtTerminateProcess is hooked to 0x00007ff9e132d550
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetDefaultLocale is hooked to 0x00007ff9e13301c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDeleteValueKey is hooked to 0x00007ff9e132eaa0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtEnumerateValueKey is hooked to 0x00007ff9e132d230
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryInstallUILanguage is hooked to 0x00007ff9e132f9e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtEnumerateKey is hooked to 0x00007ff9e132d610
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtGetNlsSectionPtr is hooked to 0x00007ff9e132ef00
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDeleteKey is hooked to 0x00007ff9e132ea40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateSection is hooked to 0x00007ff9e132d910
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtMapViewOfSection is hooked to 0x00007ff9e132d4d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryDefaultLocale is hooked to 0x00007ff9e132d270
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtNotifyChangeKey is hooked to 0x00007ff9e132f300
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryInformationToken is hooked to 0x00007ff9e132d3f0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryLicenseValue is hooked to 0x00007ff9e132fa40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenSymbolicLinkObject is hooked to 0x00007ff9e132f580
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQuerySymbolicLinkObject is hooked to 0x00007ff9e132fba0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryMultipleValueKey is hooked to 0x00007ff9e132fa60
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenPrivateNamespace is hooked to 0x00007ff9e132f4c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDeletePrivateNamespace is hooked to 0x00007ff9e132ea80
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreatePrivateNamespace is hooked to 0x00007ff9e132e6e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtClose is hooked to 0x00007ff9e132d1b0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryInformationProcess is hooked to 0x00007ff9e132d2f0
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtDuplicateObject is hooked to 0x00007ff9e132d750
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtResetEvent is hooked to 0x00007ff9e132ff00
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryEvent is hooked to 0x00007ff9e132da90
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtSetInformationProcess is hooked to 0x00007ff9e132d350
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryKey is hooked to 0x00007ff9e132d290
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtLoadKeyEx is hooked to 0x00007ff9e132f100
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryVirtualMemory is hooked to 0x00007ff9e132d430
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenProcessTokenEx is hooked to 0x00007ff9e132d5d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateWnfStateName is hooked to 0x00007ff9e132e940
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDeleteWnfStateName is hooked to 0x00007ff9e132eae0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetSecurityObject is hooked to 0x00007ff9e13304e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtUnmapViewOfSection is hooked to 0x00007ff9e132d510
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQuerySecurityAttributesToken is hooked to 0x00007ff9e132fb20
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtGetCachedSigningLevel is hooked to 0x00007ff9e132ede0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDeviceIoControlFile is hooked to 0x00007ff9e132d0b0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtReadFile is hooked to 0x00007ff9e132d090
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtWaitForMultipleObjects is hooked to 0x00007ff9e132db20
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetSystemInformation is hooked to 0x00007ff9e1330540
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtYieldExecution is hooked to 0x00007ff9e132d890
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDuplicateToken is hooked to 0x00007ff9e132d810
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAllocateLocallyUniqueId is hooked to 0x00007ff9e132dde0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAccessCheck is hooked to 0x00007ff9e132cfd0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAccessCheckByType is hooked to 0x00007ff9e132dc20
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAccessCheckByTypeResultList is hooked to 0x00007ff9e132dc40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenProcessToken is hooked to 0x00007ff9e132f4e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenThreadToken is hooked to 0x00007ff9e132d450
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetInformationToken is hooked to 0x00007ff9e1330360
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAdjustPrivilegesToken is hooked to 0x00007ff9e132d7f0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAdjustGroupsToken is hooked to 0x00007ff9e132dd40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtPrivilegeCheck is hooked to 0x00007ff9e132f6c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAccessCheckAndAuditAlarm is hooked to 0x00007ff9e132d4f0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAccessCheckByTypeAndAuditAlarm is hooked to 0x00007ff9e132daf0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAccessCheckByTypeResultListAndAuditAlarm is hooked to 0x00007ff9e132dc60
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAccessCheckByTypeResultListAndAuditAlarmByHandle is hooked to 0x00007ff9e132dc80
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenObjectAuditAlarm is hooked to 0x00007ff9e132f480
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtPrivilegeObjectAuditAlarm is hooked to 0x00007ff9e132f6e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCloseObjectAuditAlarm is hooked to 0x00007ff9e132d730
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDeleteObjectAuditAlarm is hooked to 0x00007ff9e132ea60
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtPrivilegedServiceAuditAlarm is hooked to 0x00007ff9e132f700
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtSetInformationThread is hooked to 0x00007ff9e132d170
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtImpersonateAnonymousToken is hooked to 0x00007ff9e132ef60
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtFilterToken is hooked to 0x00007ff9e132ec60
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetCachedSigningLevel is hooked to 0x00007ff9e1330120
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtLockVirtualMemory is hooked to 0x00007ff9e132f180
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtUnlockVirtualMemory is hooked to 0x00007ff9e1330960
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtReadVirtualMemory is hooked to 0x00007ff9e132d7b0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtProtectVirtualMemory is hooked to 0x00007ff9e132d9d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtWriteVirtualMemory is hooked to 0x00007ff9e132d710
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAllocateVirtualMemory is hooked to 0x00007ff9e132d2d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAllocateVirtualMemoryEx is hooked to 0x00007ff9e132de80
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtFreeVirtualMemory is hooked to 0x00007ff9e132d390
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenEvent is hooked to 0x00007ff9e132d7d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtGetWriteWatch is hooked to 0x00007ff9e132ef40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtResetWriteWatch is hooked to 0x00007ff9e132ff20
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetInformationVirtualMemory is hooked to 0x00007ff9e13303c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtAllocateUserPhysicalPages is hooked to 0x00007ff9e132de20
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtFreeUserPhysicalPages is hooked to 0x00007ff9e132ed80
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtMapUserPhysicalPages is hooked to 0x00007ff9e132f240
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenDirectoryObject is hooked to 0x00007ff9e132dad0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryObject is hooked to 0x00007ff9e132d1d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateSymbolicLinkObject is hooked to 0x00007ff9e132e7e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateDirectoryObjectEx is hooked to 0x00007ff9e132e4c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtLoadEnclaveData is hooked to 0x00007ff9e132f0a0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtTerminateEnclave is hooked to 0x00007ff9e13307c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateNamedPipeFile is hooked to 0x00007ff9e132e660
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtWriteFile is hooked to 0x00007ff9e132d0d0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtLockFile is hooked to 0x00007ff9e132f120
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtUnlockFile is hooked to 0x00007ff9e1330940
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCancelIoFile is hooked to 0x00007ff9e132db60
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCancelIoFileEx is hooked to 0x00007ff9e132e200
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCancelSynchronousIoFile is hooked to 0x00007ff9e132e220
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtReadFileScatter is hooked to 0x00007ff9e132d590
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtWriteFileGather is hooked to 0x00007ff9e132d330
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetEvent is hooked to 0x00007ff9e132d190
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtClearEvent is hooked to 0x00007ff9e132d790
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtPulseEvent is hooked to 0x00007ff9e132f780
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateSemaphore is hooked to 0x00007ff9e132e7c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenSemaphore is hooked to 0x00007ff9e132f540
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtReleaseSemaphore is hooked to 0x00007ff9e132d110
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateMutant is hooked to 0x00007ff9e132e640
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateTimer2 is hooked to 0x00007ff9e132e840
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCreateTimer is hooked to 0x00007ff9e132e820
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenTimer is hooked to 0x00007ff9e132f5c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetTimerEx is hooked to 0x00007ff9e13305e0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCancelTimer is hooked to 0x00007ff9e132dbe0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSignalAndWaitForSingleObject is hooked to 0x00007ff9e13306c0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtDelayExecution is hooked to 0x00007ff9e132d650
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtOpenProcess is hooked to 0x00007ff9e132d490
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtCompareObjects is hooked to 0x00007ff9e132e320
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetInformationObject is hooked to 0x00007ff9e132db40
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSetSystemTime is hooked to 0x00007ff9e1330580
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryAuxiliaryCounterFrequency is hooked to 0x00007ff9e132f7a0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtConvertBetweenAuxiliaryCounterAndPerformanceCounter is hooked to 0x00007ff9e132e400
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtCreateThreadEx is hooked to 0x00007ff9e132e800
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtResumeThread is hooked to 0x00007ff9e132da10
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtTerminateThread is hooked to 0x00007ff9e132da30
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtOpenThread is hooked to 0x00007ff9e132f5a0
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtQueryInformationThread is hooked to 0x00007ff9e132d470
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtSuspendThread is hooked to 0x00007ff9e1330780
  |-- KERNELBASE.dll IAT to ntdll.dll of function NtGetContextThread is hooked to 0x00007ff9e132ee20
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtSetContextThread is hooked to 0x00007ff9e1330160
  |-- KERNELBASE.dll IAT to ntdll.dll of function *NtQueueApcThreadEx2 is hooked to 0x00007ff9e132fca0
  +-- 147 hooked functions.

Checking ntdll.dll at InProcessClient64.dll IAT
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtOpenSection is hooked to 0x00007ff9e132d6b0
  |-- InProcessClient64.dll IAT to ntdll.dll of function *NtQueueApcThread is hooked to 0x00007ff9e132d870
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtQueryVirtualMemory is hooked to 0x00007ff9e132d430
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtQueryObject is hooked to 0x00007ff9e132d1d0
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtQuerySection is hooked to 0x00007ff9e132d9f0
  |-- InProcessClient64.dll IAT to ntdll.dll of function *NtSetInformationThread is hooked to 0x00007ff9e132d170
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtQueryKey is hooked to 0x00007ff9e132d290
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtCreateFile is hooked to 0x00007ff9e132da70
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtQueryInformationProcess is hooked to 0x00007ff9e132d2f0
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtQueryInformationThread is hooked to 0x00007ff9e132d470
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtCallbackReturn is hooked to 0x00007ff9e132d070
  |-- InProcessClient64.dll IAT to ntdll.dll of function NtGetNextThread is hooked to 0x00007ff9e132eee0
  +-- 12 hooked functions.

Checking ntdll.dll at ADVAPI32.dll IAT
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryValueKey is hooked to 0x00007ff9e132d2b0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtClose is hooked to 0x00007ff9e132d1b0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtOpenThreadToken is hooked to 0x00007ff9e132d450
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtOpenProcessToken is hooked to 0x00007ff9e132f4e0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtSetInformationToken is hooked to 0x00007ff9e1330360
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtDuplicateToken is hooked to 0x00007ff9e132d810
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtCompareTokens is hooked to 0x00007ff9e132e360
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtOpenFile is hooked to 0x00007ff9e132d630
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryInformationProcess is hooked to 0x00007ff9e132d2f0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryKey is hooked to 0x00007ff9e132d290
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtDeviceIoControlFile is hooked to 0x00007ff9e132d0b0
  |-- ADVAPI32.dll IAT to ntdll.dll of function *NtQuerySystemInformation is hooked to 0x00007ff9e132d690
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtCreateKey is hooked to 0x00007ff9e132d370
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtSetValueKey is hooked to 0x00007ff9e132dbc0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtDeleteKey is hooked to 0x00007ff9e132ea40
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtEnumerateKey is hooked to 0x00007ff9e132d610
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryVolumeInformationFile is hooked to 0x00007ff9e132d8f0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtOpenSymbolicLinkObject is hooked to 0x00007ff9e132f580
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQuerySymbolicLinkObject is hooked to 0x00007ff9e132fba0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryInformationFile is hooked to 0x00007ff9e132d1f0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtTraceControl is hooked to 0x00007ff9e1330860
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtRenameKey is hooked to 0x00007ff9e132fe40
  |-- ADVAPI32.dll IAT to ntdll.dll of function *NtSetInformationThread is hooked to 0x00007ff9e132d170
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtOpenKey is hooked to 0x00007ff9e132d210
  |-- ADVAPI32.dll IAT to ntdll.dll of function *NtQuerySystemTime is hooked to 0x00007ff9e132db10
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtWaitForSingleObject is hooked to 0x00007ff9e132d050
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryInformationThread is hooked to 0x00007ff9e132d470
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQuerySecurityObject is hooked to 0x00007ff9e132fb40
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryPerformanceCounter is hooked to 0x00007ff9e132d5f0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtCreateMutant is hooked to 0x00007ff9e132e640
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtOpenPrivateNamespace is hooked to 0x00007ff9e132f4c0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtCreatePrivateNamespace is hooked to 0x00007ff9e132e6e0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtWaitForMultipleObjects is hooked to 0x00007ff9e132db20
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtCreateFile is hooked to 0x00007ff9e132da70
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtWriteFile is hooked to 0x00007ff9e132d0d0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtReadFile is hooked to 0x00007ff9e132d090
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtAlpcQueryInformation is hooked to 0x00007ff9e132e0e0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryObject is hooked to 0x00007ff9e132d1d0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryMutant is hooked to 0x00007ff9e132fa80
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtReplaceKey is hooked to 0x00007ff9e132fe80
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtSaveKey is hooked to 0x00007ff9e1330040
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtSaveMergedKeys is hooked to 0x00007ff9e1330080
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtQueryInformationToken is hooked to 0x00007ff9e132d3f0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtSetSystemInformation is hooked to 0x00007ff9e1330540
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtOpenKeyEx is hooked to 0x00007ff9e132f3e0
  |-- ADVAPI32.dll IAT to ntdll.dll of function NtSetInformationKey is hooked to 0x00007ff9e1330300
  +-- 46 hooked functions.

Checking ntdll.dll at msvcrt.dll IAT
  +-- 0 hooked functions.

Checking ntdll.dll at sechost.dll IAT
  |-- sechost.dll IAT to ntdll.dll of function NtOpenProcessTokenEx is hooked to 0x00007ff9e132d5d0
  |-- sechost.dll IAT to ntdll.dll of function NtOpenKey is hooked to 0x00007ff9e132d210
  |-- sechost.dll IAT to ntdll.dll of function NtQueryValueKey is hooked to 0x00007ff9e132d2b0
  |-- sechost.dll IAT to ntdll.dll of function *NtSetInformationThread is hooked to 0x00007ff9e132d170
  |-- sechost.dll IAT to ntdll.dll of function NtQueryInformationThread is hooked to 0x00007ff9e132d470
  |-- sechost.dll IAT to ntdll.dll of function *NtQueueApcThread is hooked to 0x00007ff9e132d870
  |-- sechost.dll IAT to ntdll.dll of function NtQueryInformationFile is hooked to 0x00007ff9e132d1f0
  |-- sechost.dll IAT to ntdll.dll of function NtCancelIoFile is hooked to 0x00007ff9e132db60
  |-- sechost.dll IAT to ntdll.dll of function NtTraceControl is hooked to 0x00007ff9e1330860
  |-- sechost.dll IAT to ntdll.dll of function NtSetSystemInformation is hooked to 0x00007ff9e1330540
  |-- sechost.dll IAT to ntdll.dll of function NtSetIntervalProfile is hooked to 0x00007ff9e1330400
  |-- sechost.dll IAT to ntdll.dll of function *NtQuerySystemInformation is hooked to 0x00007ff9e132d690
  |-- sechost.dll IAT to ntdll.dll of function NtQueryIntervalProfile is hooked to 0x00007ff9e132fa00
  |-- sechost.dll IAT to ntdll.dll of function NtWaitForMultipleObjects is hooked to 0x00007ff9e132db20
  |-- sechost.dll IAT to ntdll.dll of function NtQueryPerformanceCounter is hooked to 0x00007ff9e132d5f0
  |-- sechost.dll IAT to ntdll.dll of function NtSetEvent is hooked to 0x00007ff9e132d190
  |-- sechost.dll IAT to ntdll.dll of function *NtTerminateProcess is hooked to 0x00007ff9e132d550
  |-- sechost.dll IAT to ntdll.dll of function NtOpenThreadToken is hooked to 0x00007ff9e132d450
  |-- sechost.dll IAT to ntdll.dll of function NtClose is hooked to 0x00007ff9e132d1b0
  |-- sechost.dll IAT to ntdll.dll of function NtQueryInformationToken is hooked to 0x00007ff9e132d3f0
  |-- sechost.dll IAT to ntdll.dll of function NtOpenProcessToken is hooked to 0x00007ff9e132f4e0
  +-- 21 hooked functions.

Checking ntdll.dll at RPCRT4.dll IAT
  |-- RPCRT4.dll IAT to ntdll.dll of function NtQueryValueKey is hooked to 0x00007ff9e132d2b0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtOpenKey is hooked to 0x00007ff9e132d210
  |-- RPCRT4.dll IAT to ntdll.dll of function NtWaitForAlertByThreadId is hooked to 0x00007ff9e1330a00
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlertThreadByThreadId is hooked to 0x00007ff9e132ddc0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAllocateUuids is hooked to 0x00007ff9e132de60
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAdjustPrivilegesToken is hooked to 0x00007ff9e132d7f0
  |-- RPCRT4.dll IAT to ntdll.dll of function *NtQuerySystemTime is hooked to 0x00007ff9e132db10
  |-- RPCRT4.dll IAT to ntdll.dll of function NtPrivilegeCheck is hooked to 0x00007ff9e132f6c0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcCreateResourceReserve is hooked to 0x00007ff9e132df60
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcCancelMessage is hooked to 0x00007ff9e132dec0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcDeleteSecurityContext is hooked to 0x00007ff9e132e020
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcCreateSecurityContext is hooked to 0x00007ff9e132dfa0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcConnectPortEx is hooked to 0x00007ff9e132df00
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcConnectPort is hooked to 0x00007ff9e132dee0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtCreateSection is hooked to 0x00007ff9e132d910
  |-- RPCRT4.dll IAT to ntdll.dll of function NtDuplicateToken is hooked to 0x00007ff9e132d810
  |-- RPCRT4.dll IAT to ntdll.dll of function NtImpersonateAnonymousToken is hooked to 0x00007ff9e132ef60
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcCreateSectionView is hooked to 0x00007ff9e132df80
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcCreatePortSection is hooked to 0x00007ff9e132df40
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAllocateReserveObject is hooked to 0x00007ff9e132de00
  |-- RPCRT4.dll IAT to ntdll.dll of function NtSetIoCompletionEx is hooked to 0x00007ff9e1330440
  |-- RPCRT4.dll IAT to ntdll.dll of function *NtQueueApcThreadEx is hooked to 0x00007ff9e132fc80
  |-- RPCRT4.dll IAT to ntdll.dll of function NtOpenThreadToken is hooked to 0x00007ff9e132d450
  |-- RPCRT4.dll IAT to ntdll.dll of function NtDeleteWnfStateName is hooked to 0x00007ff9e132eae0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtCreateWnfStateName is hooked to 0x00007ff9e132e940
  |-- RPCRT4.dll IAT to ntdll.dll of function NtQuerySecurityObject is hooked to 0x00007ff9e132fb40
  |-- RPCRT4.dll IAT to ntdll.dll of function NtOpenDirectoryObject is hooked to 0x00007ff9e132dad0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtDelayExecution is hooked to 0x00007ff9e132d650
  |-- RPCRT4.dll IAT to ntdll.dll of function NtWaitForSingleObject is hooked to 0x00007ff9e132d050
  |-- RPCRT4.dll IAT to ntdll.dll of function NtFsControlFile is hooked to 0x00007ff9e132d6f0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtCreateEvent is hooked to 0x00007ff9e132d8d0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtQueryVolumeInformationFile is hooked to 0x00007ff9e132d8f0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcCreatePort is hooked to 0x00007ff9e132df20
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcQueryInformation is hooked to 0x00007ff9e132e0e0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcSendWaitReceivePort is hooked to 0x00007ff9e132e140
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcAcceptConnectPort is hooked to 0x00007ff9e132dea0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcDeletePortSection is hooked to 0x00007ff9e132dfc0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcDeleteSectionView is hooked to 0x00007ff9e132e000
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcDisconnectPort is hooked to 0x00007ff9e132e040
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcQueryInformationMessage is hooked to 0x00007ff9e132e100
  |-- RPCRT4.dll IAT to ntdll.dll of function NtClose is hooked to 0x00007ff9e132d1b0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtCreateFile is hooked to 0x00007ff9e132da70
  |-- RPCRT4.dll IAT to ntdll.dll of function NtCreateNamedPipeFile is hooked to 0x00007ff9e132e660
  |-- RPCRT4.dll IAT to ntdll.dll of function NtWriteFile is hooked to 0x00007ff9e132d0d0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcSetInformation is hooked to 0x00007ff9e132e160
  |-- RPCRT4.dll IAT to ntdll.dll of function NtReadFile is hooked to 0x00007ff9e132d090
  |-- RPCRT4.dll IAT to ntdll.dll of function *NtQuerySystemInformation is hooked to 0x00007ff9e132d690
  |-- RPCRT4.dll IAT to ntdll.dll of function NtSetInformationFile is hooked to 0x00007ff9e132d4b0
  |-- RPCRT4.dll IAT to ntdll.dll of function *NtSetInformationThread is hooked to 0x00007ff9e132d170
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcOpenSenderThread is hooked to 0x00007ff9e132e0c0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcOpenSenderProcess is hooked to 0x00007ff9e132e0a0
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcImpersonateClientContainerOfPort is hooked to 0x00007ff9e132e060
  |-- RPCRT4.dll IAT to ntdll.dll of function NtAlpcImpersonateClientOfPort is hooked to 0x00007ff9e132e080
  +-- 53 hooked functions.

Checking ntdll.dll at bcrypt.dll IAT
  |-- bcrypt.dll IAT to ntdll.dll of function NtOpenKey is hooked to 0x00007ff9e132d210
  |-- bcrypt.dll IAT to ntdll.dll of function NtQueryValueKey is hooked to 0x00007ff9e132d2b0
  |-- bcrypt.dll IAT to ntdll.dll of function NtQueryInformationProcess is hooked to 0x00007ff9e132d2f0
  |-- bcrypt.dll IAT to ntdll.dll of function NtClose is hooked to 0x00007ff9e132d1b0
  |-- bcrypt.dll IAT to ntdll.dll of function NtDeviceIoControlFile is hooked to 0x00007ff9e132d0b0
  |-- bcrypt.dll IAT to ntdll.dll of function NtOpenFile is hooked to 0x00007ff9e132d630
  |-- bcrypt.dll IAT to ntdll.dll of function *NtTerminateProcess is hooked to 0x00007ff9e132d550
  +-- 7 hooked functions.

Checking ntdll.dll at FLTLIB.DLL IAT
  |-- FLTLIB.DLL IAT to ntdll.dll of function NtCreateFile is hooked to 0x00007ff9e132da70
  |-- FLTLIB.DLL IAT to ntdll.dll of function NtDeviceIoControlFile is hooked to 0x00007ff9e132d0b0
  |-- FLTLIB.DLL IAT to ntdll.dll of function NtWaitForSingleObject is hooked to 0x00007ff9e132d050
  |-- FLTLIB.DLL IAT to ntdll.dll of function NtFsControlFile is hooked to 0x00007ff9e132d6f0
  +-- 4 hooked functions.

------------------------------------------
Completed

3.5 结果

下表展示了 2024 年 3 月 1 日至 3 月 22 日期间进行的枚举结果

alt text

结论:

  1. 94%的被分析EDR解决方案(16个中有15个)在Ntdll.dll之上的子系统层未显示钩子。这意味着,在对应用程序中加载的所有引用Ntdll的DLL进行验证时,仅有一个EDR解决方案在导入地址表(IAT)中显示存在钩子。
  2. 50%的被分析EDR解决方案(16个中有8个)在用户模式下未显示存在钩子。

4.HookChain

在本次讨论中,我们首先概述并简化介绍本文重点关注的技术——HookChain。随后,我们将从技术层面详细解析HookChain:在4.2节中介绍所使用的数据结构和表格,接着在4.3节阐述填充这些表格的方法。之后,我们会在4.4节详细说明导入地址表(IAT)的挂钩过程,最后在4.5节展示功能测试以及HookChain植入在调用栈中的隐蔽性。

4.1. Overview

一般来说,HookChain技术基于以下流程:

  1. 使用前文提到的系统调用号(SSN)动态映射技术之一,例如Halo’s gate。
  2. 映射某些基础函数以便在后续步骤中使用,例如:
    a. NtAllocateReserveObject
    b. NtAllocateVirtualMemory
    c. NtQueryInformationProcess
    d. NtProtectVirtualMemory
    e. NtReadVirtualMemory
    f. NtWriteVirtualMemory
  3. 创建并填充一个数组,每个数组项包含以下内容:
    a. 系统调用号(SSN)
    b. Ntdll.dll中的函数地址
    c. 该函数在Ntdll.dll中最近的SYSCALL指令的内存地址
  4. 预加载其他DLL(如果已知正在运行的应用程序将动态加载并使用当前进程中尚未加载的其他DLL),并验证待加载的DLL是否会调用Ntdll.dll的函数。
  5. 使用间接系统调用(Indirect Syscall)结合步骤2中映射的函数,对所有已加载DLL的导出表和导入表结构进行读取、枚举和处理。
  6. 修改关键DLL的导入地址表(IAT),这些DLL包括kernel32、kernelbase、bcrypt、bcryptPrimitives、gdi32、mswsock、netutils和urlmon等调用Ntdll.dll的组件。此操作旨在将IAT中原生Nt/Zw调用的目标地址修改为应用程序的内部函数。这样一来,当诸如kernel32之类的子系统DLL调用Ntdll.dll中的函数时,实际执行的将是HookChain植入的代码,从而实现本文2.3.2节所述的IAT挂钩。

在采取这些操作之后,API 和子系统将以常规方式继续使用,因为流量转移和规避层已经实施,无需进一步操作。因此,对 Ntdll.dll 的调用将通过我们应用程序的内部函数执行,但对于正在执行的 PE(可移植可执行文件)来说是透明的,因为它将继续使用子系统 API,如图 14 所示。

alt text

这种方法能够绕过所有在 Ntdll.dll 上执行的用户模式挂钩,因为所有执行控制都在应用程序自身内部。与这里介绍的其他技术相比,具有以下优点:

  1. 对于遥测技术的规则,被事件数据记录器识别的概率降低,比如:
    1. 流程执行的总时间
    2. 执行链
  2. 便携性
    1. 无需对现有代码/应用程序的执行进行任何工作和/或修改,因为拦截过程对正在运行的应用程序具有广泛的透明性。

4.2 数据结构和表

4.2.1 SYSCALL_INFO

如4.1中说的,需要创建填充一个数组,其中记录了执行过程中将会用到的各种信息:

typedef struct _SYSCALL_INFO {
    DWORD64 dwSsn; // 系统调用号
    PVOID pAddress;//用于存储Ntdll内函数的VA
    PVOID pSyscallRet;//用于存储NTdll内syscall执行的VA地址
    PVOID pStubFunction;//HookChain 拦截(植入)函数的地址存储字段,该地址是所有对相关函数的调用都将指向的目标。换句话说,这是将在导入地址表(IAT)中分配的地址,用于替换 Ntdll 函数的虚拟地址。
    DWORD64 dwHash;// 函数的hash值
} SYSCALL_INFO, * PSYSCALL_INFO;

4.2.2 SYSCALL_LIST

#define MAX_ENTRIES 512
typedef struct _SYSCALL_LIST
{
    DWORD64 Count;// 表中当前的数量
    SYSCALL_INFO Entries[MAX_ENTRIES];
} SYSCALL_LIST, * PSYSCALL_LIST;

4.2.2 引用和索引

下一个数据结构实际上是一个指向我们应用程序 .data 段的指针,在汇编中定义如下:

qIdx0 - qIdx5:变量,用于存储初始进程和操作所需的原生函数信息在数组中的位置。这些变量的名称以 0 到 5 的值结尾,存储以下函数的索引:0 - ZwOpenProcess,1 - ZwProtectVirtualMemory,2 - ZwReadVirtualMemory,3 - ZwWriteVirtualMemory,4 - ZwAllocateVirtualMemory,5 - ZwDelayExecution。

.data
qTableAddr QWORD 0h         # 存储 SYSCALL_LIST 表
qListEntrySize QWORD 28h    # 该变量包含 SYSCALL_LIST->Entries 中每个条目的大小(以字节为单位)
qStubEntrySize QWORD 14h    # 包含 HookChain 使用的每个拦截函数大小(以字节为单位)的变量。本文后面将提供有关这些函数及其使用方法的更多详细信息

qIdx0 QWORD 0h
qIdx1 QWORD 0h
qIdx2 QWORD 0h
qIdx3 QWORD 0h
qIdx4 QWORD 0h
qIdx5 QWORD 0h

4.3 填充表

static SYSCALL_LIST SyscallList;

步骤如下:

  1. 使用TEB和PEB定位Ntdll的地址
  2. 枚举所有名称以 “Zw” 或 “Nt” 开头的函数
  3. 检查所讨论的函数是否为将通过间接系统调用无条件使用的函数之一。如果是,则在数组 SyscallList.Entries 中添加一个新条目,并在变量 qIdx0 - qIdx5 中保存该函数在数组中的位置。以下是函数列表:
    • NtAllocateReserveObject
    • NtAllocateVirtualMemory
    • NtQueryInformationProcess
    • NtProtectVirtualMemory
    • NtReadVirtualMemory
    • NtWriteVirtualMemory
  4. 检查所讨论的函数代码中是否存在 JMP 指令,该指令表明存在 EDR 应用的钩子。如果存在,则在数组 SyscallList.Entries 中添加一个新条目。

在这个过程结束时,数组将填充所有具有 EDR 挂钩的 Nt/Zw 函数, 以及qIdx0-qIdx5这几个未来会用的函数

在步骤3和4中,通过 “光环之门” 技术中使用的校验算法获取 SSN。

对应代码中的:GetSSNGetNextSyscallInstruction

4.4 IAT

接下来修改一家在DLL的IAT。

然而,如果我们此时执行该过程,随后加载另一个动态库且该新库的导入地址表(IAT)中包含对Ntdll的引用,我们将不得不再次执行操作该DLL的IAT的过程。为避免这种重复处理,建议在执行IAT挂钩之前加载必要的库。

4.4.1 预加载 DLLs

嘶,,这块没咋看懂?

4.4.2 IAT HOOK

4.4.3 执行流

完成上述步骤后,HookChain 植入所需的所有程序即已确定,从这一刻起,对 Windows 子系统的所有调用将不会在 Ntdll.dll 层面受到 EDR 的拦截和监控。 通过这种方式,让我们更深入地了解 HookChain 植入完成后应用程序的执行流程。

alt text

图16详细展示了HookChain植入后函数调用的执行流程,具体说明如下:

  1. 以应用程序通过Kernel32.dll API/子系统中的CreateProcessW函数创建新进程为例。
  2. 由于该特定函数实现在Kernelbase.dll中,kernel32.dll仅将执行流程重定向至kernelbase。
  3. 在kernelbase DLL的CreateProcessW代码中,经过一些参数检查后,代码将执行属于Ntdll.dll的ZwCreateUserProcess函数。
  4. 因此,CreateProcessW代码会在内核基(kernelbase)的导入地址表(IAT)中查找地址——该位置原本存储Ntdll.dll中ZwCreateUserProcess函数的地址,但在HookChain植入后,IAT中的此位置将替换为HookChain植入函数的地址。
  5. 在获取已部署函数的地址后,CreateProcessW代码将调用(CALL)该地址,而非Ntdll.dll中ZwCreateUserProcess函数的地址,从而转向HookChain部署的函数。
  6. 每个HookChain拦截函数均使用特定名称/索引创建,在我们的示例场景中函数名为Fnc0002,因此SyscallList.Entries数组中的对应索引为0x0002。通过这种方式,HookChain代码将在表(数组SyscallList.Entries[0x0002])中查找先前存储的信息,如系统调用号(SSN)和Ntdll中系统调用指令的地址。
  7. 掌握所有必要信息后,HookChain代码会重现Ntdll中函数的执行逻辑(mov r10, rcx; mov eax, SSN),并随后将执行流程转发至包含系统调用指令的Ntdll地址。
  8. 在当前流程的栈顶位置,将包含返回地址——该地址为kernelbase的CreateProcessW执行CALL操作时插入栈中的下一条指令的地址。随后,Ntdll执行系统调用指令。当内核返回时,流程将导向CreateProcessW函数内的相应返回地址。

注意:HookChain 的运行并不需要使用 CreateProcessW 函数或任何类似的分支机制。所提供的图表仅展示了 HookChain 植入后的函数调用过程。

4.5 调用栈遥测

使用 HookChain 的优点之一是,即使这并非其主要目的,它也不会改变调用的调用栈(从 EDR 的角度来看)。通过这种方式,本测试旨在可视化并理解 HookChain 植入前后函数的调用栈。因此,测试代码执行 3 个操作:

  1. 使用 CreateProcessW API 启动 Notepad.exe 进程。此过程在 HookChain 植入之前执行。
  2. 所有HookChain植入操作均已执行。
  3. 使用 CreateProcessW API 启动一个新的 Notepad.exe 进程。由于此时 HookChain 已经完成了所有的植入和绕过操作,Ntdll.dll 中的原始 ZwCreateUserProcess 函数将不会被执行。

这里有好多图,我就不加了,后面再加

结果:调用栈跟踪遥测未发生变化,以至于 HOOK 可能不会被内核层的EDR检查发现。

5. HOOKCHAIN – TESTES

在这些测试中,选取了 14 款终端检测与响应(EDR)产品,截至 2023 年 12 月 31 日,其中 9 款产品被纳入 Gartner’s Magic Quadrant [15]。

alt text

在上述图片中,Gartner’s Magic Quadrant中的被测产品以绿色高亮显示,而灰色标记的产品无法进行测试。
此外,还测试了4款未列入Gartner象限的产品,分别是:Acronis、Cylance、Elastic和MalwareBytes。
针对这些测试,按如下描述准备了两个版本的HookChain:

alt text

绿色表示无警报和拦截 黄色表示部分执行(未成功)且无报警,或者执行(成功)但有报警 红色表示执行因受阻和警报而失败(大概率是因为R0的作用)