🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Untitled

posted in DruinkJournal
Published July 16, 2007
Advertisement
I got distracted at lunch today. I read a bunch of stuff about the Vista kernel in this months TechNet, and I decided to write some API hooking code, just to see what's involved and what cool things I can do.

I never realised how much effort it is to get the base address for another process. Your own process base address is equal to the HINSTANCE passed to WinMain, so that's easy enough. You could assume that the other process is at 0x00400000, and almost all of them will be - but that's bound to trip you up at some point.

To get the base address for another process, you need to read the FS segment from a thread in that process, get the Thread Environment Block, get the address of the Process Environment Block from that, and then get the process base address from there.

Now, that wouldn't be quite so bad if the structures were implemented as something other than a series of BYTE and DWORD arrays called dwReserved1 and suchlike.
I can completely understand why that's been done, since it could change at any point (I'll be testing this on Vista when I get home), but it's still annoying.

Anyway, chunk of code to get the base address (Assumes hThread and hProcess are handles to a thread in the process and the process itself respectively):
// Get thread contextCONTEXT theContext;theContext.ContextFlags = CONTEXT_FULL;if(!GetThreadContext(hThread, &theContext))	return false;// Get address of the FS segmentLDT_ENTRY selEntry;if(!GetThreadSelectorEntry(hThread, theContext.SegFs, &selEntry))	return false;DWORD dwFSBase = (selEntry.HighWord.Bits.BaseHi << 24) |	(selEntry.HighWord.Bits.BaseMid << 16) |	selEntry.BaseLow;// Read thread/process environment block to get image base addressDWORD dwBaseAddress=0;DWORD dwBytes;{	// Read entire TEB	TEB theTEB;	if(!ReadProcessMemory(hProcess, (void*)dwFSBase, &theTEB, sizeof(theTEB), &dwBytes) ||		dwBytes!=sizeof(theTEB))	{		return false;	}	// PEB address is in TEB at byte offset 0x30	DWORD dwPEBAddress = *(DWORD*)(((BYTE*)&theTEB)+0x30);	// Base address is in the PEB at offset 0x08	if(!ReadProcessMemory(hProcess, (void*)(dwPEBAddress+8), &dwBaseAddress, sizeof(dwBaseAddress), &dwBytes) ||		dwBytes!=sizeof(dwBaseAddress))	{		return false;	}}// Read the DOS headerIMAGE_DOS_HEADER dosHeader;if(!ReadProcessMemory(hProcess, (void*)dwBaseAddress, &dosHeader, sizeof(dosHeader), &dwBytes) ||	dwBytes!=sizeof(dosHeader)){	return false;}// Validate itif(dosHeader.e_magic != IMAGE_DOS_SIGNATURE){	return false;}// Read NT headerIMAGE_NT_HEADERS ntHeader;if(!ReadProcessMemory(hProcess, (void*)(dwBaseAddress+dosHeader.e_lfanew), &ntHeader, sizeof(ntHeader), &dwBytes) ||	dwBytes!=sizeof(ntHeader)){	return false;}// Validate itif(ntHeader.Signature != IMAGE_NT_SIGNATURE){	return false;}

Well, I'm going to recover from that by doing some Nitro Character stuff (oh god, why me...)
Previous Entry Untitled
Next Entry Untitled
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement