Sign in to follow this  
  • entries
    557
  • comments
    1237
  • views
    420959

Untitled

Sign in to follow this  
Evil Steve

52 views

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 context
CONTEXT theContext;
theContext.ContextFlags = CONTEXT_FULL;
if(!GetThreadContext(hThread, &theContext))
return false;

// Get address of the FS segment
LDT_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 address
DWORD 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 header
IMAGE_DOS_HEADER dosHeader;
if(!ReadProcessMemory(hProcess, (void*)dwBaseAddress, &dosHeader, sizeof(dosHeader), &dwBytes) ||
dwBytes!=sizeof(dosHeader))
{
return false;
}

// Validate it
if(dosHeader.e_magic != IMAGE_DOS_SIGNATURE)
{
return false;
}

// Read NT header
IMAGE_NT_HEADERS ntHeader;
if(!ReadProcessMemory(hProcess, (void*)(dwBaseAddress+dosHeader.e_lfanew), &ntHeader, sizeof(ntHeader), &dwBytes) ||
dwBytes!=sizeof(ntHeader))
{
return false;
}

// Validate it
if(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...)
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now