# KCSC CTF 2023 ## Gues > Các bài rev ở đây thường không có description :D Chạy file: ![](https://hackmd.io/_uploads/B1aE1llr2.png) Code trong IDA (đã được rename function và biến): ![](https://hackmd.io/_uploads/SymO1elSh.png) Như ta có thể thấy, chương trình nhận vào input 4 kí tự nếu lớn hơn thì xuất ra "too long" và exit. Còn đây là bên trong susfunction: ![](https://hackmd.io/_uploads/HJhxxggrn.png) Function này khá là rối, mình không chắc cái này có thể dịch ngược hoàn toàn, tuy nhiên dựa vào length của input khá ít nên mình có thể dễ dàng solve bằng bruteforce: ```python from subprocess import * import struct import string import requests from concurrent.futures import ThreadPoolExecutor n = 0 m = string.printable m = string.ascii_letters x = [] for i in m: for j in m: for k in m: for l in m: x.append((i+j+k+l).encode()) def func(user_input): p = Popen([r'gues.exe', 'f'], stdout = PIPE, stdin = PIPE, stderr = STDOUT) p.stdin.write(user_input) testresult = p.communicate()[0] return testresult def check(x): for i in x: if chr(i) not in string.printable: return False return True n = 0 for ui in x: res = func(ui) if b'C{' in res: print(res,ui) n+=1 ``` > Vì mình code bài này khá vội nên là như mì ăn liền vậy, code không clean mọi người thông cảm:V Ban đầu có thể nói là brute khá lâu, nhma thay vì dùng `string.printable` thì mình chuyển sang `string.ascii_letters` và đây là kết quả: ![](https://hackmd.io/_uploads/rkngWggB2.png) Flag: "KCSC{brut6_n6rv6r_die} # Mix Như cái tên bài thì bài này mix giữa C# và C++. Đầu tiên mình dùng Die để detect: ![](https://hackmd.io/_uploads/HJSyXelS3.png) Do là file là C# obfuscated nên mình đã dùng tool để deobfuscate trước, cụ thể là de4dot: ![](https://hackmd.io/_uploads/BJS4mleB3.png) Có được file Mix-cleaned.exe, load nó bằng dnspy và đây là hàm main: ![](https://hackmd.io/_uploads/r1FFmxgrn.png) Đa số các hàm đều là built-in function ví dụ như `smethod_17()` chỉ đơn giản là compare 2 buffer,... Ref Flagenc, mình có được flag_encrypted: ![](https://hackmd.io/_uploads/ry6AQxlrh.png) Về input của mình chỉ đơn giản là chuyển thành bytes, sau đó encrypt bởi hàm `enc()` và đem so sánh với flagenc. Mình thử debug và stepinto `enc` tuy nhiên không có kết quả là mấy. ![](https://hackmd.io/_uploads/SyFSElxH3.png) ![](https://hackmd.io/_uploads/H1-IVggS2.png) Tuy nhiên, tên bài là Mix mình nghĩ vẫn còn code đâu đó, cụ thể là C++, thử load vào IDA bằng IDA: ![](https://hackmd.io/_uploads/BJE04eeB3.png) Sau khi xem string thì mình thấy có 1 thứ rất khả nghi, đó là "expand 64-byte k" Mình nhận ra đây rất có thể là Salsa20 hoặc là ChaCha20, còn đây là hàm `enc` mà mình tìm được: ![](https://hackmd.io/_uploads/ByrrrxlHn.png) Như đã thấy, ta có 32 bytes của key nằm ở v9 và nonce là 8 bytes nằm ở v9[4]. Sau khi xem hàm `sub_140001F10` thì mình khá chắc chắn là đây là chacha20. ![](https://hackmd.io/_uploads/Bk0oBleSn.png) Sau đó mình thử viết script (có salsa 20 bởi vì lúc viết script mình chạy không ra, nghi ngờ là do mình đoán sai): ```python from pwn import * from Crypto.Cipher import Salsa20,ChaCha20,ChaCha20_Poly1305 flag_enc = bytes([143,124,41,217,251,185,171,26,74,83,173,236,169,239,22,115,128,248,92,93]) print(flag_enc,flag_enc.hex()) def ls2bytes(ls): return b"".join([bytes.fromhex(x)[::-1] for x in ls]) secret = [0]*7 secret[0] = "43604259" secret[1] = "45724033" secret[2] = "1763427E" secret[3] = "5B725F70" secret[4] = "507D527F" secret[5] = "193D1976" secret[6] = "3713371337133713" nonce = [0]*2 nonce[0] = "03010200" nonce[1] = "11FF0005" secret = ls2bytes(secret) nonce = ls2bytes(nonce) print(secret.hex(),nonce.hex()) new_secret = [] for i in range(0,32,2): new_secret.append(secret[i]^0x13) new_secret.append(secret[i+1]^0x37) new_secret = bytes(new_secret)[:32] #+b'\x00'*32 print(new_secret,nonce) cipher = cipher = Salsa20.new(key=new_secret, nonce=nonce) plaintext = cipher.decrypt(flag_enc) print("Salsa:",plaintext) cipher = cipher = ChaCha20.new(key=new_secret, nonce=nonce) plaintext = cipher.decrypt(flag_enc) print("Chacha:",plaintext) ``` Tuy nhiên cả 2 plaintext đều không phải flag. Mình cũng không hiểu tại sao, có thể là do đoạn "expand 64 byte k" (thường là 32). Do đó vi tính chất đối xứng, nên mình quyết định debug và patch input của mình thành flagenc => `enc(flagenc) = flag`. ![](https://hackmd.io/_uploads/Bky-wegHh.png) Đoạn này đổi string lại thành bytes của flagenc. Sau đó dựa theo địa chỉ cùa ptr để tìm ra vị trí của nó trên memory: ![](https://hackmd.io/_uploads/Hy9Svxxr3.png) ![](https://hackmd.io/_uploads/rJYIvxgS3.png) ![](https://hackmd.io/_uploads/HkWYDxeSn.png) Lúc đầu mình làm không ra, tuy nhiên mình phát hiện patch sai 1 bytes, ![](https://hackmd.io/_uploads/HJksPegB2.png) Đoạn ...73 3F F8... nếu đúng như flagenc thì phải là ...73 80 F8... Ta chỉ cần sửa đoạn này lại, hoặc từ đầu có thể patch bytes thẳng vào memory(cách này hay hơn :V), đặt breakpoint ngay chổ so sánh và tìm flag trên memory: ![](https://hackmd.io/_uploads/rkTf_xgHn.png) ![](https://hackmd.io/_uploads/HyKD_eeS3.png) Flag: "KCSC{h3Ll0_fR0M_c##}"