Skip to content

Instantly share code, notes, and snippets.

@odzhan
Last active December 15, 2023 01:11
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save odzhan/fe278c2588e462edf3a9fd61f3c51d93 to your computer and use it in GitHub Desktop.
Save odzhan/fe278c2588e462edf3a9fd61f3c51d93 to your computer and use it in GitHub Desktop.
Locating kernel32!BaseThreadInitThunk in NTDLL
//
// Every new thread starts with ntdll!RtlUserThreadStart and it typically calls kernel32!BaseThreadInitThunk
//
// Some applications like Mozilla Firefox and Microsoft Edge will replace this with their own function for hooking purposes.
// The following code shows how to find it without using debugging symbols.
//
// @modexpblog
//
#define PHNT_VERSION PHNT_VISTA
#include <phnt_windows.h>
#include <phnt.h>
#include <cstdio>
#pragma comment(lib, "ntdll")
VOID
WINAPI
BaseThreadInitThunk(
IN DWORD LdrReserved,
IN LPTHREAD_START_ROUTINE lpStartAddress,
IN LPVOID lpParameter)
{
printf("New Thread created...\n");
RtlExitUserThread(0);
}
int
main(void) {
auto fn = (ULONG_PTR)GetProcAddress(GetModuleHandleA("kernel32"), "BaseThreadInitThunk");
auto m = (PBYTE)GetModuleHandleA("ntdll");
auto nt = (PIMAGE_NT_HEADERS)(m + ((PIMAGE_DOS_HEADER)m)->e_lfanew);
auto sh = IMAGE_FIRST_SECTION(nt);
ULONG_PTR *ds = NULL, Kernel32ThreadInitThunkFunction = NULL;
ULONG cnt = 0;
for (DWORD i=0; i<nt->FileHeader.NumberOfSections; i++) {
if(*(PDWORD)sh[i].Name == *(PDWORD)".data") {
ds = (PULONG_PTR)(m + sh[i].VirtualAddress);
cnt = sh[i].Misc.VirtualSize / sizeof(ULONG_PTR);
break;
}
}
printf("Searching for kernel32!BaseThreadInitThunk (%p) in ntdll.dll\n", (PVOID)fn);
for (DWORD i=0; i<cnt; i++) {
if (ds[i] == fn) {
printf("Found ntdll!Kernel32ThreadInitThunkFunction @ %p\n", (PVOID)&ds[i]);
Kernel32ThreadInitThunkFunction = (ULONG_PTR)&ds[i];
break;
}
}
//
// Overwrite with our function.
//
_InterlockedCompareExchangePointer((PVOID*)Kernel32ThreadInitThunkFunction, (PVOID)BaseThreadInitThunk, (PVOID)fn);
//
// Create new thread that executes our function indirectly.
//
CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ExitThread, NULL, 0, NULL));
printf("Press any key to continue...\n");
getchar();
//
// Restore original pointer, removing our function.
//
_InterlockedCompareExchangePointer((PVOID*)Kernel32ThreadInitThunkFunction, (PVOID)fn, (PVOID)BaseThreadInitThunk);
printf("Done.\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment