Plxsmarex/SuspendedSyscalls
GitHub: Plxsmarex/SuspendedSyscalls
通过创建挂起进程读取未被 hook 的干净 syscall 编号,并利用间接 syscall 技术进行入口点 shellcode 注入的 Windows 攻防工具。
Stars: 2 | Forks: 0
# SuspendedSyscalls
在使用 `indirect syscalls` 将 shellcode 注入到**挂起进程**之前,从该进程中提取干净的 `syscall` 编号。
# Windows 系统调用
要在 Windows 上执行 `syscall`,你需要**系统服务编号**(也称为 syscall 编号)。问题在于它们在不同版本的操作系统上可能有所不同,因此将它们硬编码是不安全的。
Windows 在 `ntdll.dll` 中的 `Nt`/`Zw` **原生 API** 函数以及 `win32u.dll` 中的 `NtUser` 和 `NtGdi` 函数上使用了 `syscalls`。解决此问题的方法应该是动态地从这些库中查找 **syscall 编号**,以便它始终能获取当前操作系统版本对应的正确编号。像 **Hell's Gate** 这样的项目通过在内存中找到 `NTDLL` 中**原生函数**的地址,然后从中提取 **syscall 编号**来实现这一点。你也可以使用 **Windows API** 从磁盘读取 `NTDLL`,但 **EDRs** 可能会觉得这很可疑。
**Hell's Gate** 的问题在于,许多 **EDRs** 和其他安全解决方案会 hook 这些**原生 API**,这也隐藏了 **syscall 编号**,这意味着试图直接查找**原生函数的 syscall 编号**会失败。因此,一个名为 **Halo's Gate** 的新项目被创建出来。它增加了一个检测第一个字节是否为 `JMP` 指令的功能,如果是,它将搜索附近的**原生函数**并获取其 **syscall 编号**,然后根据它为了找到干净函数而遍历的**原生函数**数量来加上或减去相应的数字。这之所以有效,是因为 Windows 的 **syscall 编号**是按升序排列的;你可以根据其他相邻的函数来预测某个函数的编号。
但是,如果每个**原生函数**都被 hook 了怎么办?那么你可以简单地把它们都找出来并按地址排序,这之所以有效是因为 Windows 将它们按顺序排列。这种做法的一个潜在问题是,如果 Windows 将来决定不按顺序排列 **syscall 编号**,这种方法就会失效。安全解决方案也可能通过添加虚假函数来欺骗它。
**SuspendedSyscalls** 是解决所有这些问题的方案;它不关心函数是否被 hook,不关心 **syscall 编号**的顺序,而且 **EDRs** 大概率也不会在意它用来查找这些编号的 **APIs**。
# 工作原理
**SuspendedSyscalls** 首先会创建一个**挂起进程**,通过这样做,**EDRs** 和其他安全解决方案还来不及 hook `NTDLL`,这让我们可以轻松读取 **syscall 编号**,而无需担心 hooks 或任何其他类型的潜在混淆。对于找到的每个 syscall 编号,**SuspendedSyscalls** 会将其连同其所属函数的符号名一起打印出来。在遍历每一个时,我们将锁定几个目标函数并保存它们的 **syscall 编号**。
在程序开始阶段,我们获取了几个**原生函数**的地址,在循环结束后我们保存了这些函数的 **syscall 编号**,现在我们将使用它们来执行 `indirect syscalls`...
# Indirect syscalls
对于一个要在 Windows 上执行 `syscall` 的程序,最常见的方法是复现**原生函数**存根中发生的过程并将其嵌入到程序中,这通常被称为 `direct syscall`。虽然 `direct syscalls` 一直效果不错,但它们有几个重大问题;首先,`syscall` 指令 (`0x0F05`) 在使用它们的程序反汇编代码中清晰可见,合法程序在 Windows 上极少使用它,因此这是一个可靠的**入侵指标**,其次甚至更大的问题是 **EDRs** 可以监视 `callstack`,这会显示程序直接调用了 `kernel`,中间没有像正常情况那样调用库函数。
解决此问题的方法是 `JMP` 到像 `NTDLL` 这样的库中的 `syscall` 指令,因此 `callstack` 会显示 `syscall` 来自合法库,这样做被称为 `indirect syscall`。不过它们仍然有一些问题;`callstack` 现在显示了对**原生 API** 的直接调用,虽然这在合法软件中有时也会发生,但直接调用像 `NtProtectVirtualMemory` 这样具有风险的 **原生 APIs** 可能会是一种**入侵指标**,这可以通过使用其他技术来避免,但在本示例中我们不会深入讨论这一点。对 `indirect syscalls` 的另一种检测方式是尝试查看 `syscall` 指令是被直接跳转到的,还是由正常的**原生 API** 调用触发的,例如,如果**原生函数**被 **EDR** hook 了,合法的 `callstack` 会显示它进入了 **EDR's** 模块,但由于 `indirect syscall` 绕过了所有的 hooks,因此这在 `callstack` 上是不可见的。
# 入口点注入
继续回到 **SuspendedSyscalls**,现在我们将使用 `indirect syscalls` 来获取**挂起进程**主模块的基址并定位**入口点**,然后我们将**入口点**的内存保护属性设置为可读写(`RW`),这让我们可以将 payload 直接写入**入口点**,之后,我们将恢复其原始保护属性,即只读可执行(`RX`),最后,我们将恢复进程的运行,从而执行我们的 messagebox shellcode。
这种注入方法非常有效,因为它允许我们在 **backed memory** 中执行 payload,这可以绕过很多检测,而且执行它的过程不像分配内存和创建线程等更常见的方法那样广为人知。
**SuspendedSyscalls** 还使用了我的 **Shellcode-Toolkit** 库,这意味着它还会编译出一个紧凑的 `3840` 字节的与位置无关的 flat binary 文件,以及一个 `4608` 字节的可执行文件。
**SuspendedSyscalls** 的实际运行效果:
将 **SuspendedSyscalls'** 的 shellcode 形式注入到 **Microsoft Edge** 中,在伪装成合法进程的同时进行提取和注入:
# 潜在问题
**SuspendedSyscalls** 本身可以通过 **API hooking/monitoring** 被检测到,因为它需要使用 `CreateProcessA` 和 `ReadProcessMemory` 来获取远程的 **syscall 编号**。
如果出现重大 Windows 更改了 `NTDLL` 的结构,或改变了进程的运行方式,可能会导致一些问题。
# 鸣谢与参考
https://github.com/am0nsec/HellsGate - **Hell's Gate** 项目
https://blog.sektor7.net/#!res/2021/halosgate.md - **Halo's Gate** 项目
https://blog.sektor7.net/#!res/2021/perunsfart.md - 使用**挂起进程**干净的 `NTDLL` 来 unhook **APIs**,给了我创建这个项目的灵感
https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams/ - 提到了按 syscall 地址排序的技术
https://www.ired.team/offensive-security/code-injection-process-injection/addressofentrypoint-code-injection-without-virtualallocex-rwx - 将代码注入到**挂起进程的入口点**
将 **SuspendedSyscalls'** 的 shellcode 形式注入到 **Microsoft Edge** 中,在伪装成合法进程的同时进行提取和注入:
# 潜在问题
**SuspendedSyscalls** 本身可以通过 **API hooking/monitoring** 被检测到,因为它需要使用 `CreateProcessA` 和 `ReadProcessMemory` 来获取远程的 **syscall 编号**。
如果出现重大 Windows 更改了 `NTDLL` 的结构,或改变了进程的运行方式,可能会导致一些问题。
# 鸣谢与参考
https://github.com/am0nsec/HellsGate - **Hell's Gate** 项目
https://blog.sektor7.net/#!res/2021/halosgate.md - **Halo's Gate** 项目
https://blog.sektor7.net/#!res/2021/perunsfart.md - 使用**挂起进程**干净的 `NTDLL` 来 unhook **APIs**,给了我创建这个项目的灵感
https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams/ - 提到了按 syscall 地址排序的技术
https://www.ired.team/offensive-security/code-injection-process-injection/addressofentrypoint-code-injection-without-virtualallocex-rwx - 将代码注入到**挂起进程的入口点**标签:C/C++, DNS 反向解析, Halo's Gate, Hell's Gate, ntdll.dll, Shellcode注入, SSH蜜罐, Windows内部机制, 中高交互蜜罐, 事务性I/O, 云资产清单, 免杀技术, 动态解析系统调用号, 原生API, 安全AI, 安全对抗, 客户端加密, 底层安全, 恶意软件开发, 挂起进程, 数据展示, 暴力破解检测, 汇编编程, 红队, 绕过EDR, 网络安全, 进程注入, 逆向工程, 间接系统调用, 隐私保护