Skip to content

Commit

Permalink
Inlined native functions to eradicate flagging by import enumeration.
Browse files Browse the repository at this point in the history
  • Loading branch information
st4ckh0und committed May 12, 2022
1 parent c150923 commit 906b94c
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 42 deletions.
12 changes: 10 additions & 2 deletions hook-buster/hook-buster.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,14 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<DebugInformationFormat>None</DebugInformationFormat>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
Expand All @@ -132,17 +134,23 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>None</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<ItemGroup>
<MASM Include="native.asm">
<UseSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</UseSafeExceptionHandlers>
</MASM>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
Expand Down
5 changes: 5 additions & 0 deletions hook-buster/hook-buster.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="native.asm">
<Filter>Source Files</Filter>
</MASM>
</ItemGroup>
</Project>
232 changes: 192 additions & 40 deletions hook-buster/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
#include <winternl.h>
#include <stdio.h>

#pragma comment(lib, "ntdll")

#define DIRECTORY_QUERY 0x0001
#define DIRECTORY_TRAVERSE 0x0002

Expand All @@ -12,14 +10,38 @@ typedef enum _SECTION_INHERIT {
ViewUnmap=2
} SECTION_INHERIT, *PSECTION_INHERIT;

extern NTSTATUS NTAPI NtClose(HANDLE Handle);
extern NTSTATUS NTAPI NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
extern NTSTATUS NTAPI NtOpenSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
extern NTSTATUS NTAPI NtMapViewOfSection(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID* BaseAddress, ULONG ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Protect);
extern NTSTATUS NTAPI NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress);
extern NTSTATUS NTAPI RtlInitUnicodeStringEx(PUNICODE_STRING DestinationString, PCWSTR SourceString);
extern NTSTATUS ZwClose_impl(HANDLE Handle);
extern NTSTATUS ZwOpenDirectoryObject_impl(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
extern NTSTATUS ZwOpenSection_impl(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes);
extern NTSTATUS ZwMapViewOfSection_impl(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID* BaseAddress, ULONG ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize, SECTION_INHERIT InheritDisposition, ULONG AllocationType, ULONG Protect);
extern NTSTATUS ZwUnmapViewOfSection_impl(HANDLE ProcessHandle, PVOID BaseAddress);

NTSTATUS NTAPI RtlInitUnicodeStringEx(PUNICODE_STRING DestinationString, PWSTR SourceString)
{
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
DestinationString->Buffer = SourceString;

if (SourceString == NULL)
return 0;

SIZE_T Length = (SIZE_T)-1;

do
Length++;
while (SourceString[Length] != 0);

if (Length >= 0x7fff)
return 0xC0000106;

USHORT ByteLength = (Length & 0xffff) * sizeof(wchar_t);

DestinationString->Length = ByteLength;
DestinationString->MaximumLength = ByteLength + sizeof(wchar_t);
return 0;
}

BOOL GetKnownDllSectionHandle(LPCWSTR DllName, PHANDLE SectionHandle)
BOOL GetKnownDllSectionHandle(LPWSTR DllName, PHANDLE SectionHandle)
{
BOOL Result = FALSE;

Expand All @@ -36,7 +58,7 @@ BOOL GetKnownDllSectionHandle(LPCWSTR DllName, PHANDLE SectionHandle)

HANDLE KnownDllDirectoryHandle = NULL;

if (NT_SUCCESS(NtOpenDirectoryObject(&KnownDllDirectoryHandle, DIRECTORY_TRAVERSE | DIRECTORY_QUERY, &KnownDllAttributes)) && KnownDllDirectoryHandle != NULL)
if (NT_SUCCESS(ZwOpenDirectoryObject_impl(&KnownDllDirectoryHandle, DIRECTORY_TRAVERSE | DIRECTORY_QUERY, &KnownDllAttributes)) && KnownDllDirectoryHandle != NULL)
{
UNICODE_STRING SectionName = { 0 };

Expand All @@ -45,17 +67,43 @@ BOOL GetKnownDllSectionHandle(LPCWSTR DllName, PHANDLE SectionHandle)
OBJECT_ATTRIBUTES SectionAttributes = { 0 };
InitializeObjectAttributes(&SectionAttributes, &SectionName, OBJ_CASE_INSENSITIVE, KnownDllDirectoryHandle, NULL);

if (NT_SUCCESS(NtOpenSection(SectionHandle, SECTION_MAP_EXECUTE | SECTION_MAP_READ | SECTION_QUERY, &SectionAttributes)))
if (NT_SUCCESS(ZwOpenSection_impl(SectionHandle, SECTION_MAP_EXECUTE | SECTION_MAP_READ | SECTION_QUERY, &SectionAttributes)))
Result = TRUE;
}

NtClose(KnownDllDirectoryHandle);
ZwClose_impl(KnownDllDirectoryHandle);
}

return Result;
}

int main(int argc, char* argv[])
DWORD ComputeHash8(LPCSTR string)
{
DWORD hash = 0;

while (*string != 0)
{
hash = _rotr(hash, 13);
hash += *string++;
}

return hash;
}

DWORD ComputeHash16(LPCWSTR string)
{
DWORD hash = 0;

while (*string != 0)
{
hash = _rotr(hash, 13);
hash += *string++;
}

return hash;
}

PVOID GetModuleHandleH(DWORD hash)
{
PEB* peb = NtCurrentTeb()->ProcessEnvironmentBlock;

Expand All @@ -69,52 +117,156 @@ int main(int argc, char* argv[])
UNICODE_STRING* fullname = &entry->FullDllName;
UNICODE_STRING* basename = (UNICODE_STRING*)((PBYTE)fullname + sizeof(UNICODE_STRING));

IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)entry->DllBase;
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)((PBYTE)entry->DllBase + dos->e_lfanew);
if (ComputeHash16(basename->Buffer) == hash)
return entry->DllBase;

next = next->Flink;
}

return NULL;
}

typedef struct _NATIVE_FUNCTION
{
DWORD hash;
PBYTE function;
} NATIVE_FUNCTION;

typedef struct _NATIVE_FUNCTION_ARRAY
{
DWORD size;
NATIVE_FUNCTION functions[4096];
} NATIVE_FUNCTION_ARRAY;

NATIVE_FUNCTION_ARRAY g_function_array = { 0 };

void CollectNativeFunctions(PBYTE base)
{
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(base + dos->e_lfanew);

PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

if (exports->AddressOfNames != 0)
{
PWORD ordinals = (PWORD)(base + exports->AddressOfNameOrdinals);
PDWORD names = (PDWORD)(base + exports->AddressOfNames);
PDWORD functions = (PDWORD)(base + exports->AddressOfFunctions);

for (DWORD i = 0; i < exports->NumberOfNames; i++)
{
LPSTR name = (LPSTR)(base + names[i]);
PBYTE function = (PBYTE)(base + functions[ordinals[i]]);

if (function > base + nt->OptionalHeader.BaseOfCode &&
function < base + nt->OptionalHeader.BaseOfCode + nt->OptionalHeader.SizeOfCode)
{
if (name[0] == 'Z' && name[1] == 'w')
{
g_function_array.functions[g_function_array.size].hash = ComputeHash8(name);
g_function_array.functions[g_function_array.size].function = function;
g_function_array.size++;
}
}
}
}
}

void BubbleSortFunctions()
{
for (DWORD i = 0; i < g_function_array.size - 1; i++)
{
for (DWORD j = 0; j < g_function_array.size - i - 1; j++)
{
if (g_function_array.functions[j].function > g_function_array.functions[j + 1].function)
{
NATIVE_FUNCTION swap = { 0 };
memcpy(&swap, &g_function_array.functions[j + 1], sizeof(NATIVE_FUNCTION));
memcpy(&g_function_array.functions[j + 1], &g_function_array.functions[j], sizeof(NATIVE_FUNCTION));
memcpy(&g_function_array.functions[j], &swap, sizeof(NATIVE_FUNCTION));
}
}
}
}

IMAGE_EXPORT_DIRECTORY* exports = (IMAGE_EXPORT_DIRECTORY*)((PBYTE)entry->DllBase + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD GetFunctionId(DWORD hash)
{
for (DWORD i = 0; i < g_function_array.size; i++)
{
if (g_function_array.functions[i].hash == hash)
return i;
}

return 0xffffffff;
}

int main(int argc, char* argv[])
{
PVOID ntdll = GetModuleHandleH(0xcef6e822);;

if (ntdll != NULL)
{
CollectNativeFunctions((PBYTE)ntdll);
BubbleSortFunctions();

if (exports->AddressOfNames != 0)
PEB* peb = NtCurrentTeb()->ProcessEnvironmentBlock;
LIST_ENTRY* head = &peb->Ldr->InMemoryOrderModuleList;
LIST_ENTRY* next = head->Flink;

while (next != head)
{
printf("Checking for hooks in %S\n", basename->Buffer);
LDR_DATA_TABLE_ENTRY* entry = (LDR_DATA_TABLE_ENTRY*)((PBYTE)next - offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks));

UNICODE_STRING* fullname = &entry->FullDllName;
UNICODE_STRING* basename = (UNICODE_STRING*)((PBYTE)fullname + sizeof(UNICODE_STRING));

IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)entry->DllBase;
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)((PBYTE)entry->DllBase + dos->e_lfanew);

HANDLE section = NULL;
IMAGE_EXPORT_DIRECTORY* exports = (IMAGE_EXPORT_DIRECTORY*)((PBYTE)entry->DllBase + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

if (GetKnownDllSectionHandle(basename->Buffer, &section))
if (exports->AddressOfNames != 0)
{
PVOID base = 0;
SIZE_T size = 0;
printf("Checking for hooks in %S\n", basename->Buffer);

if (NT_SUCCESS(NtMapViewOfSection(section, GetCurrentProcess(), &base, 0, 0, 0, &size, ViewUnmap, 0, PAGE_READONLY)))
HANDLE section = NULL;

if (GetKnownDllSectionHandle(basename->Buffer, &section))
{
WORD* ordinals = (WORD*)((PBYTE)entry->DllBase + exports->AddressOfNameOrdinals);
DWORD* names = (DWORD*)((PBYTE)entry->DllBase + exports->AddressOfNames);
DWORD* functions = (DWORD*)((PBYTE)entry->DllBase + exports->AddressOfFunctions);
PVOID base = 0;
SIZE_T size = 0;

for (DWORD i = 0; i < exports->NumberOfNames; i++)
if (NT_SUCCESS(ZwMapViewOfSection_impl(section, (PVOID)-1, &base, 0, 0, 0, &size, ViewUnmap, 0, PAGE_READONLY)))
{
char* name = (char*)((PBYTE)entry->DllBase + names[i]);
void* function = (void*)((PBYTE)entry->DllBase + functions[ordinals[i]]);
WORD* ordinals = (WORD*)((PBYTE)entry->DllBase + exports->AddressOfNameOrdinals);
DWORD* names = (DWORD*)((PBYTE)entry->DllBase + exports->AddressOfNames);
DWORD* functions = (DWORD*)((PBYTE)entry->DllBase + exports->AddressOfFunctions);

if ((PBYTE)function > (PBYTE)entry->DllBase + nt->OptionalHeader.BaseOfCode &&
(PBYTE)function < (PBYTE)entry->DllBase + nt->OptionalHeader.BaseOfCode + nt->OptionalHeader.SizeOfCode)
for (DWORD i = 0; i < exports->NumberOfNames; i++)
{
DWORD offset = (DWORD)((PBYTE)function - (PBYTE)entry->DllBase);
void* mapped = (void*)((PBYTE)base + offset);
char* name = (char*)((PBYTE)entry->DllBase + names[i]);
void* function = (void*)((PBYTE)entry->DllBase + functions[ordinals[i]]);

if ((PBYTE)function > (PBYTE)entry->DllBase + nt->OptionalHeader.BaseOfCode &&
(PBYTE)function < (PBYTE)entry->DllBase + nt->OptionalHeader.BaseOfCode + nt->OptionalHeader.SizeOfCode)
{
DWORD offset = (DWORD)((PBYTE)function - (PBYTE)entry->DllBase);
void* mapped = (void*)((PBYTE)base + offset);

if (memcmp(function, mapped, 5) != 0)
printf("Detected hook in %S!%s\n", basename->Buffer, name);
if (memcmp(function, mapped, 5) != 0)
printf("Detected hook in %S!%s\n", basename->Buffer, name);
}
}

ZwUnmapViewOfSection_impl((PVOID)-1, base);
}

NtUnmapViewOfSection(GetCurrentProcess(), base);
ZwClose_impl(section);
}

NtClose(section);
}
}

next = next->Flink;
next = next->Flink;
}
}

return 0;
Expand Down
Loading

0 comments on commit 906b94c

Please sign in to comment.