mirror of
https://github.com/wavestone-cdt/EDRSandblast.git
synced 2026-06-10 17:31:23 +00:00
D3FC0N 30 release: Obj callbacks, firewalling, symbols w/ internet, and more
Co-authored-by: Maxime Meignan <maxime.meignan@wavestone.com>
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
#include "PEBBrowse.h"
|
||||
#include "PEParser.h"
|
||||
#include "SW2_Syscalls.h"
|
||||
|
||||
// Code below is adapted from @modexpblog. Read linked article for more details.
|
||||
// https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams
|
||||
|
||||
SW2_SYSCALL_LIST SW2_SyscallList;
|
||||
|
||||
DWORD SW2_HashSyscall(PCSTR FunctionName)
|
||||
{
|
||||
DWORD i = 0;
|
||||
DWORD Hash = SW2_SEED;
|
||||
|
||||
while (FunctionName[i])
|
||||
{
|
||||
WORD PartialName = *(WORD*)((ULONG64)FunctionName + i++);
|
||||
Hash ^= PartialName + SW2_ROR8(Hash);
|
||||
}
|
||||
|
||||
return Hash;
|
||||
}
|
||||
|
||||
int CmpSyscallEntriesByRVA(SW2_SYSCALL_ENTRY const* a, SW2_SYSCALL_ENTRY const* b) {
|
||||
if (a->RVA < b->RVA) {
|
||||
return -1;
|
||||
}
|
||||
else if (a->RVA > b->RVA) {
|
||||
return +1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CmpSyscallEntriesByHash(SW2_SYSCALL_ENTRY const* a, SW2_SYSCALL_ENTRY const* b) {
|
||||
if (a->Hash < b->Hash) {
|
||||
return -1;
|
||||
}
|
||||
else if (a->Hash > b->Hash) {
|
||||
return +1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL SW2_PopulateSyscallList(void)
|
||||
{
|
||||
// Return early if the list is already populated.
|
||||
if (SW2_SyscallList.Count) return TRUE;
|
||||
|
||||
PE* ntdll = PE_create(getModuleEntryFromNameW(L"ntdll.dll")->DllBase, TRUE);
|
||||
// Populate SW2_SyscallList with unsorted Zw* entries.
|
||||
DWORD i = 0;
|
||||
PSW2_SYSCALL_ENTRY Entries = SW2_SyscallList.Entries;
|
||||
for (DWORD nameOrdinal = 0; nameOrdinal < ntdll->exportedNamesLength; nameOrdinal++) {
|
||||
LPCSTR functionName = PE_RVA_to_Addr(ntdll, ntdll->exportedNames[nameOrdinal]);
|
||||
if (*(WORD*)functionName == *((WORD*)"Zw")) {
|
||||
Entries[i].Hash = SW2_HashSyscall(functionName);
|
||||
Entries[i].RVA = PE_functionRVA(ntdll, functionName);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Save total number of system calls found.
|
||||
SW2_SyscallList.Count = i;
|
||||
|
||||
// Sort the list by address in ascending order.
|
||||
qsort(Entries, SW2_SyscallList.Count, sizeof(SW2_SYSCALL_ENTRY), CmpSyscallEntriesByRVA);
|
||||
|
||||
// Deduce the syscall numbers.
|
||||
for (DWORD j = 0; j < SW2_SyscallList.Count; j++) {
|
||||
SW2_SyscallList.Entries[j].SyscallNumber = j;
|
||||
}
|
||||
|
||||
// Sort the list by hash for quicker search.
|
||||
qsort(Entries, SW2_SyscallList.Count, sizeof(SW2_SYSCALL_ENTRY), CmpSyscallEntriesByHash);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash)
|
||||
{
|
||||
// Ensure SW2_SyscallList is populated.
|
||||
if (!SW2_PopulateSyscallList()) return 0xFFFFFFFF;
|
||||
|
||||
DWORD down = 0;
|
||||
DWORD up = SW2_SyscallList.Count;
|
||||
while (up - down > 1) {
|
||||
DWORD mid = (down + up) / 2;
|
||||
if (SW2_SyscallList.Entries[mid].Hash <= FunctionHash) {
|
||||
down = mid;
|
||||
}
|
||||
else {
|
||||
up = mid;
|
||||
}
|
||||
}
|
||||
if (SW2_SyscallList.Entries[down].Hash == FunctionHash) {
|
||||
return SW2_SyscallList.Entries[down].SyscallNumber;
|
||||
}
|
||||
else {
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user