Saturday, 18 February 2012

From the Archives: Printing the SEH Chain from a Running Process on Windows in C

A quick post about some code we came across in our archives originally written in July 2007. Around then we had been reading what Matt Pietrek had written in his excellent overview but there was no self contained code available. The function below takes takes a handle to a process and a thread and then dumps the current SEH chain. At the time we used it in a debug event loop in our fuzzing rig.

int PrintSEH(HANDLE hProc, HANDLE hThread)
{
 CONTEXT Context;

 // Get the full context of the processor 
 Context.ContextFlags = CONTEXT_FULL;
 if(GetThreadContext( hThread, &Context ) == 0){
  fwprintf(stdout,L"[!] GetThreadContext failed!\n");
  return 1;
 }

 // this bit of leetness came from the code breakers journal 
 // http://powerhacker.net/documents/Reverse_Engineering/codebreakers_journal/CBJ-2005-65.pdf
 LDT_ENTRY ldtSel;
 if (!GetThreadSelectorEntry(hThread, Context.SegFs, &ldtSel)){
  fwprintf(stdout,L"[!] GetThreadSelectorEntry failed!\n");
  return 1;
 }

 // http://archives.neohapsis.com/archives/fulldisclosure/2004-10/att-0339/sessmgr.c
 DWORD dwFSBase = (ldtSel.HighWord.Bits.BaseHi << 24 ) | ( ldtSel.HighWord.Bits.BaseMid << 16 ) | ( ldtSel.BaseLow );
 fwprintf(stdout,L"[i] FS:[0] (TIB) is @ 0x%08X\n",dwFSBase);
 
 DWORD dwNext=0;
 DWORD dwHandler=0;
 DWORD dwCount=0;

 // Now walk the structure
 dwNext=dwFSBase; 
 while(dwNext!=0xFFFFFFFF){
  // Read the Current
  if (!ReadProcessMemory(hProc,(LPCVOID)(dwNext+4),&(dwHandler),sizeof(DWORD),NULL) ){
   fwprintf(stdout,L"[!] ReadProcessMemory failed!\n");
   return 1;
  }

  // Read the Next
  if (!ReadProcessMemory(hProc,(LPCVOID)(dwNext),&(dwNext),sizeof(DWORD), NULL) ){
   fwprintf(stdout,L"[!] ReadProcessMemory failed!\n");
   return 1;
  }

  if(dwCount>0){
   fwprintf(stdout,L"[i] Exception Handler [%d] is handled by 0x%08X 0x%08X \n",dwCount,dwHandler,dwNext);
  }
  
  dwCount++;
 }

 if(dwCount==0){
  fwprintf(stdout,L"[i] Not SEH Chain Entries Found! - This could be because it's not populated yet! \n");
 }

 return 0;
}

An example of the output when used in a debug event loop is as follows:

[!*] BreakPoint @ 01007147
[i] FS:[0] (TIB) is @ 0x7FFDF000
[i] Exception Handler [1] is handled by 0x010075BA 0x0007FFE0
[i] Exception Handler [2] is handled by 0x7C839AA8 0xFFFFFFFF
[i] Unsetting breakpoint @ 0x01007147
[i] Re-Setting breakpoint @ 0x01007147
[!*] BreakPoint @ 01002b87
[i] FS:[0] (TIB) is @ 0x7FFDF000
[i] Exception Handler [1] is handled by 0x7E440457 0x0007FE08
[i] Exception Handler [2] is handled by 0x7E440457 0x0007FE5C
[i] Exception Handler [3] is handled by 0x7E440457 0x0007FFB0
[i] Exception Handler [4] is handled by 0x010075BA 0x0007FFE0
[i] Exception Handler [5] is handled by 0x7C839AA8 0xFFFFFFFF
[i] Unsetting breakpoint @ 0x01002b87
[i] Re-Setting breakpoint @ 0x01002b87
[!*] BreakPoint @ 01007147
[i] FS:[0] (TIB) is @ 0x7FFDF000
[i] Exception Handler [1] is handled by 0x7E440457 0x0007FE08
[i] Exception Handler [2] is handled by 0x7E440457 0x0007FE5C
[i] Exception Handler [3] is handled by 0x7E440457 0x0007FFB0
[i] Exception Handler [4] is handled by 0x010075BA 0x0007FFE0
[i] Exception Handler [5] is handled by 0x7C839AA8 0xFFFFFFFF
[i] Unsetting breakpoint @ 0x01007147

So that's it, short and sweet. The license is public domain, use as you see fit.

No comments:

Post a Comment