Core Security Introduction To Software Vulnerability Exploitation
Core Security Introduction To Software Vulnerability Exploitation
Exploitation (2017)
Ricardo Narvaja – Daniel Kazimirow
43 4f 52 45
C O R E (or even E R O C)
The Memory: Addressing
byte 0 08 01 00 BD
byte 4 31 AB 11 10
.
.
byte 100 4A 21 65 89
byte 104 4A 21 65 89
byte 108 4A 21 65 89
byte 10c 4A 21 65 89
.
.
byte n 2D 3F 6A 2D
byte n+4 45 24 10 76
byte n+8 25 46 79 80
The Memory: Addressing
00000000
Physical
memory
Operating
Virtual System
Address
space processor
other
storage
(HD/swap)
FFFFFFFF
The Memory: Memory map of a windows process
32 bits
32 bits
32 bits
32 bits
32 bits
08 01 00 BD
31 AB 11 10
32 bits
.
.
616c6f48
d0d8d490
6f6c6548 100h 48 6F 6C 61
mov eax, [100] ECX
EDX 104h
mov ebx, [104] 48 65 6C 6F
ESI
add eax, ebx EDI 108h 31
90 AB
D4 11
D8 10
D0
EBP
mov [108], eax ESP .
EIP .
EFLAGS 2D 3F 6A 2D
45 24 10 76
25 46 79 80
45 24 10 76
Microprocessor: Assembly Flags
32 bits
add sub
carry
inc dec
zero
sign
and or xor
overflow
shl/r rol/r
direction
cmp test
cld std
EFLAGS
clc stc cmc
Microprocessor: Assembly Branching Operations
Microprocessor: Assembly Branching Operations
Microprocessor: Assembly Branching Operations
32 bits
00000100 mov eax, 50
00000050
00001234
EAX
EBX 00000105 or eax, eax
ECX
EDX 00000107 jz 110
ESI 00000109 mov eax, 1234
EDI
EBP 0000010e jmp 115
ESP
00000110 mov eax, 0abcd
00000115
00000109
00000107
00000105
00000100
0000010e
EIP
EFLAGS 00000115 ...
Microprocessor: Assembly Branching Operations
32 bits
00000100 mov eax, 50
00000050
00000000
0000abcd
EAX
EBX 00000105 xor eax, eax
ECX
EDX 00000107 jz 110
ESI 00000109 mov eax, 1234
EDI
EBP 0000010e jmp 115
ESP
00000110 mov eax, 0abcd
00000100
00000115
00000110
00000107
00000105
EIP
EFLAGS 00000115 ...
Microprocessor: Assembly Branching Operations
32 bits
00000100 mov eax, 50
00000050
0000abcd
EAX
EBX 00000105 call 110
ECX
EDX 0000010a nop
ESI 0000010b jmp 10a
EDI
EBP
ESP
00000110 mov eax, 0abcd
0000010b
00000115
00000110
00000105
00000100
0000010a
EIP
EFLAGS 00000115 ret
Microprocessor: Signed vs Unsigned
C code
Assembly
#define MAX_SIZE 80
C code
Assembly
#define MAX_SIZE 80
C code
Assembly
...
call memcpy
Microprocessor: Stack Operations
32 bits
EAX
EBX
ECX push pop
EDX
pushf popf
ESI
EDI
pusha popa
EBP
ESP call ret
EIP
EFLAGS
Microprocessor: Assembly Stack Operations
32 bits
12345678
EAX
EBP
bffffff8
bffffffc
c0000000
ESP
EFLAGS
00000112 ret
Microprocessor: C Calling Convention
push envp
main(argc, push argv
argv, envp); push argc
call main main's ret addr
... add esp, c argc
... argv
envp
exit(2);
push 2
} call exit
...
Microprocessor: C Calling Convention
} prologue
char buffer[80]; push ebp
mov ebp, esp
buffer
sub esp, 84
...
... cookie
gets(buffer);
ebp before main
push &buffer
call gets main's ret addr
...
pop ecx argc
argv
return 3; EBP
... envp
} ...
mov eax, 3
} epilogue
mov esp, ebp
pop ebp
ret
Microprocessor: C Calling Convention
push envp
push argv
push argc
main(argc,
call main
argv, envp); add esp, c
...
...
push 2 argc
exit(2); call exit exit'sargv
ret addr
} envp
2
...
Understanding and exploiting the
bugs
Understanding the bugs: Buffer Overflow
stack1.c:
int main() {
int cookie;
char buf[80];
buf 80 bytes
cookie 4 bytes
EBP 4 bytes
main's return addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Understanding the bugs: Buffer Overflow
C code Memory
Assembly
int main(int argc, char **argv)
gets' ret addr
{ main:
&buffer
int cookie; push ebp
char buffer[80]; mov ebp, esp
sub esp, 54
buffer
...
...
gets(buffer); cookie
push &buffer ebp before main
... call gets argc
pop ecx main's ret addr
EBP argv
envp
return 3;
...
} mov eax, 3
stack2.c:
int main() {
int cookie;
char buf[80];
buf 80 bytes
cookie 4 bytes
EBP 4 bytes
main's return addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Understanding the bugs: Buffer Overflow
stack3.c:
int main() {
int cookie;
char buf[80];
buf 80 bytes
cookie 4 bytes
EBP 4 bytes
main's return addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Understanding the bugs: Buffer Overflow
stack4.c:
int main() {
int cookie;
char buf[80];
buf 80 bytes
cookie 4 bytes
EBP 4 bytes
main's return addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Understanding the bugs: Buffer Overflow
C code Memory
Assembly
gets' ret addr
int main(int argc, char **argv) &buffer
{ main:
int cookie; push ebp
char buffer[80]; mov ebp, esp buffer
sub esp, 54
...
... cookie
gets(buffer); main's old ebp
push &buffer main's ret addr
call gets argc
... pop ecx
argv
EBP envp
return 3; ...
} mov eax, 3
C code Memory
Assembly
int main(int argc, char **argv)
{ main:
int cookie; push ebp
char buffer[80]; mov ebp, esp
sub esp, 54
...
...
gets(buffer); push &buffer main's ret addr
call gets argc
... pop ecx
argv
EBP envp
return 3; ...
} mov eax, 3
EIP
mov esp, ebp
pop ebp
ret
Understanding the bugs: Buffer Overflow
abo1.c:
void f(int nada) {
char buf[1024];
gets(buf);
}
abo2.c:
int main(int argc,char **argv) {
char buf[1024];
gets(buf);
exit(1);
}
abo3.c:
int main(int argc,char **argv) {
extern system,puts;
void (*fn)(char*)=(void(*)(char*))&system;
char buf[256];
fn=(void(*)(char*))&puts;
gets(buf);
fn(argc[2]);
exit(1);
}
gets(buf);
gets(pbuf);
fn(buf);
while (1); our address
}
padding y bytes
pbuf 4 bytes
padding x bytes
main's ebp 4 bytes
main's return addr 4 bytes
main's arguments n bytes
write-anything-anywhere primitive
Use-After-Free
Exploiting the bugs: Use-After-Free
heap0.c
int main(int argc, char **argv) {
char buf[80];
fgets(buf, sizeof(buf), stdin);
&edit user
size=4 code controlled
vftable ptr buffer
Exploiting the bugs: Use-After-Free
heap0.c
int main(int argc, char **argv) {
char buf[80];
fgets(buf, sizeof(buf), stdin);
user
size=4 controlled
vftable ptr buffer
Understanding the bugs: Use-After-Free – Hands on!
/* .. who’s there? */
class contact {
public:
virtual void edit(unsigned int contact, string
name);
};
• Range:
•0x80000000 … 0 … 0x7FFFFFFF
Understanding the bugs: Signed vs Unsigned
• Ex:
•v = 3 0x00000003
•v = -3 0xFFFFFFFD
• Negating a number ( 3 -3 ):
•v = 3 NOT ( 0x00000003 ) 0xFFFFFFFC + 1
•v = -3 0xFFFFFFFD
•“cmp eax,ebx”
•“jb 0x80808080” ( JUMP is BELOW ) … ?
•“jl 0x80808080” ( JUMP is LESS ) … ?
Integer Overflow
Understanding the bugs: Integer Overflow
• Canary (Cookies)
• Data Execute Prevention (bit NX)
• ASLR
• Windows SEH Protections
• Heap Protections
Protections: Stack – Stackguard
example.c
int main() {
char buf[80];
gets(buf);
}
buf 80 bytes
ebp before
cookie main 4 bytes
canary 4 bytes
main's ret addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Protections: Propolice and /GS
example.c
int main() {
char buf[80];
gets(buf);
}
cookie 4 bytes
buf 80 bytes
canary 4 bytes
esi before main 4 bytes
edi before main 4 bytes
ebp before main 4 bytes
main's ret addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Protections: W^X - DEP
example.c
int main() {
char buf[80];
gets(buf);
}
W + X
Memory
buf 80 bytes
ebp before
cookie main 4 bytes
main's ret addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Protections: ASLR
example.c
int main() {
char buf[80];
gets(buf);
}
memory
buf 80 bytes
ebp before
cookie main 4 bytes
? main's ret addr 4 bytes
main's argc 4 bytes
main's argv 4 bytes
Protections: Windows SEH protections
SAFE SEH
Handlers white list (only modules compiled with “/SafeSEH”)
SEHOP
The last “SEH handler” has to point to
“ntdll!FinalExceptionHandler” (ASLR is the problem !)
Protections: Heap protections
example.c
int main() {
...
free( B );
safe unlink
cookies
pointer encoding
direct mmap
A B C
Protections: Heap protections
function
pointers
Protections: Hardware DEP
Gadget definition
Bypassing DEP: ROP techniques – Gadget example