# babybof - zer0pts CTF 2020 (pwn, 590p, 17 solved)## Introduction
babybof is a pwn task.
An archive containing a binary, and a libc is provided.
## Reverse engineering
The binary is a `baby` task : it is minimalist.
It only sets up the stream buffers by calling `setbuf` on `stdin`, `stdout` and`stderr`. It then read 0x200 bytes in a 32-bytes buffer and calls exit.
This yields ROP, but there are only 7 gadgets in total :```0x0040043e: call qword [rbp+0x48] ;  (1 found)0x00400498: dec ecx ; ret  ;  (1 found)0x00400499: leave  ; ret  ;  (1 found)0x0040049b: pop r15 ; ret  ;  (1 found)0x0040047c: pop rbp ; ret  ;  (1 found)0x0040049c: pop rdi ; ret  ;  (1 found)0x0040049e: pop rsi ; ret  ;  (1 found)```
The binary imports function from the libc, but the global offset table isread-only.
## Exploitation
While the global offset table is read-only, the pointers to `stdin`, `stdout`and `stderr` are stored at the beginning of the BSS section, and are writeable.
The idea is to call read multiple times :1. first to pivot a new stack in the BSS section (for example at BSS +   0x50) and clear the stack for a one-gadget2. then pivot again, this time before the stream buffers3. finall, overwrite one of the stream buffers partially and use it as a return   address
The 3 last bytes of a one-shot gadget (libc + 0xF1147) can be used. This resultin an exploit that works once every 4096 times on average.
**Flag**: `zer0pts{b0f_i5_4lw4y5_d4ng3r0u5}`
## Appendices
### pwn.php
```php#!/usr/bin/phpwrite($payload);
usleep(5e5);
try {	@$t->write("/bin/cat /home/pwn/*flag*\n");	while($packet = @$t->readLine())		printf("%s\n", $packet);} catch(TypeError $e) {	exit;} catch(Exception $e) {	exit;}```