Locating kernel32!BaseThreadInitThunk in NTDLL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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