*Apprentice's Return* was the first pwn challenge of SwampCTF 2018. A singlebinary, `return`, is provided, an x86 32-bit unstripped ELF.
Opening the file in a dissasembler, we see three functions we're interested in:
* `main()`* `doBattle()`* `slayTheBeast()`
The first, `main()`, simply calls `doBattle()`.
The function `slayTheBeast()` outputs the flag, so this is our target function.
`doBattle()` prints out some story, then performs a `read()` of 50 bytes fromstdin to a buffer. Looking at the stack, we see the input buffer resides at`ebp-0x26`, meaning we can overflow it by 12 bytes. The return address resides8 bytes away from the end of the buffer, so it can be overwritten, as well asanother 4 bytes after.
Before the function returns, however, the return address is checked. If thevalue is greater than or equal to 0x8048595, the program exits, otherwise itoutputs a line and returns, giving the attacker control over `eip`.
The first choice here would be to overwrite `eip` with the address of the`slayTheBeast()` function, however that does not work as the address 0x80485dbis larger than the permitted value. If we try the largest permitted value, wesee it lands at the `nop` instruction at the very end of the `doBattle()`function.
This is where the additional extra four bytes we can overflow come into play.We have exactly enough room for another address. If we choose the maximum valuefor our first address, it would appear that you could loop back and return tothe second address provided. This is the basis of return-oriented programming(ROP) attacks. The challenge and binary name are clues to this. However, the`leave` instruction before the `ret` is a hinderance, as it messes up the stackframe, meaning our second address is not used.
Instead, we look for a different gadget. Using[ROPgadget](https://github.com/JonathanSalwan/ROPgadget), we can even specify arange of addresses, so that we don't get any gadgets with an address greaterthan the allowed maximum:
```shROPgadget --binary return --range 0-0x8048594```
This gives us 59 unique gadgets. Of these, the simple `ret` gadget will work.Our first return will jump from 0x8048596 to this address, 0x0804835a, poppingthe value from the stack. The next `ret` from the gadget will be executed,popping our second value from the stack. This has no restrictions, and so wecan use the address of the `slayTheBeast()` function. This function is returnedto, and we get our flag.
```sh#!/bin/sh
# arg1 = first return addr - ret gadget (0x0804835A)# arg2 = target addr - slayTheBeast() (0x80485db)
echo -n $(perl -e 'print "A" x 42, "\x5a\x83\x04\x08", "\xdb\x85\x04\x08"') \	| nc chal1.swampctf.com 1802 | grep flag```
This gives us the flag: `flag{f34r_n0t_th3_4nc13n7_R0pn1qu3}`