Lần đầu tiên ra đề cho một giải lớn, năm nay mình góp vui 2 đề cho FUSecathon. Hy vọng các bạn đã có một khoảng thời gian vui vẻ khi giải bài :D # FIA love regex ## Description Một người nào đó trong FIA vừa đẹp vừa có chiều sâu đi tìm kho báu của Trương Mỹ Lan tắt báo thức 5 ngày 5 đêm ngủ một phát qua hết deadlines để thật tỉnh táo đọc regex. Flag là chuỗi thỏa mãn regex sau. ``` ^FUSec\{(?<=(?=.{53}(?!.)).(?=.{44}nisu).(?=.{23}fia).{4})(?=.{4}(.).{11}\1)(?=.{4}(.).{6}\2)(?=.{6}(.).{27}\3)(?=.{35}(.)\4)(?=.{9}(.).{3}\5)(?=.{15}(.).{10}\6)(?=.{7}(.).{36}\7)(?=.{18}(.).{6}\8)(?=.{16}(.).{7}\9)(?=.{29}(.).{3}\10)(?=(.).{8}\11)(?=.{8}(.).{19}\12)(?=.{37}(.).{4}\13)(?=.{27}(.).{3}\14)(?=.{10}(.).{34}\15)(?=.{11}(.).{11}\16)(?=.{2}(.).{31}\17)(?=.{14}(.).{10}\18)(?=.{38}(.).{4}\19)(?=.{3}(.).{13}\20)(?=.{5}(.).{20}\21)(?=.{10}(.).{11}\22)(?=.{36}(.)\23)(?=.{12}(.).{31}\24)(?=.{15}(.).\25)(?=.(.).{32}\26)(?=.{28}(.).{15}\27)(?=.{30}(.).{14}\28)(?=.{29}(.).{2}\29)(?=.{16}(.).{8}\30)(?=.{26}(.).{17}\31)(?=.{22}(.).{17}\32)(?=.{18}(.).{2}\33)(?=.{20}(.).{7}\34)(?=.(.).{17}\35)(?=.{13}(.).{20}\36)(?=.{31}(.).\37)(?=.{32}(.).{8}\38)(?=.{39}(.).{3}\39).*}$ ``` ### Objective - Luyện kiến thức về regular expression ### Category `Misc` ### Difficulty `easy` ### Flag `FUSec{fffiaifiifiaifaiaiafiaiaaaisisisssfuuunnisunii}` ## Solved Để làm bài này ta sẽ cần một công cụ để debug regex, làm từng bước để tìm ra chuỗi thỏa mãn. [link](https://regex101.com/) Ta break nhỏ từng phần của regex ra cho dễ nhìn: ``` ^FUSec\{(?<=(?=.{53}(?!.)).(?=.{44}nisu).(?=.{23}fia).{4}) (?=.{4}(.).{11}\1) (?=.{4}(.).{6}\2) (?=.{6}(.).{27}\3) (?=.{35}(.)\4) (?=.{9}(.).{3}\5) (?=.{15}(.).{10}\6) (?=.{7}(.).{36}\7) (?=.{18}(.).{6}\8) (?=.{16}(.).{7}\9) (?=.{29}(.).{3}\10) (?=(.).{8}\11) (?=.{8}(.).{19}\12) (?=.{37}(.).{4}\13) (?=.{27}(.).{3}\14) (?=.{10}(.).{34}\15) (?=.{11}(.).{11}\16) (?=.{2}(.).{31}\17) (?=.{14}(.).{10}\18) (?=.{38}(.).{4}\19) (?=.{3}(.).{13}\20) (?=.{5}(.).{20}\21) (?=.{10}(.).{11}\22) (?=.{36}(.)\23) (?=.{12}(.).{31}\24) (?=.{15}(.).\25) (?=.(.).{32}\26) (?=.{28}(.).{15}\27) (?=.{30}(.).{14}\28) (?=.{29}(.).{2}\29) (?=.{16}(.).{8}\30) (?=.{26}(.).{17}\31) (?=.{22}(.).{17}\32) (?=.{18}(.).{2}\33) (?=.{20}(.).{7}\34) (?=.(.).{17}\35) (?=.{13}(.).{20}\36) (?=.{31}(.).\37) (?=.{32}(.).{8}\38) (?=.{39}(.).{3}\39) .*}$ ``` Ta sẽ giải nghĩa từng phần một để thấu hiểu đoạn regex trên. Tham khảo [cheatsheet](https://www.rexegg.com/regex-quickstart.html). Ở bài này kỹ thuật chủ yếu dùng là `Lookarounds`. - `^FUSec\{`: bắt đầu bằng chuỗi "FUSec{" - `(?=.{53}(?!.)).`: lấy đúng duy nhất 1 ký tự khi đã đếm đủ 53 ký tự tính từ phải sang, ngoài ra không lấy bất kỳ ký tự nào khác. ![image](https://hackmd.io/_uploads/HyuBAX8QR.png) - `(?=.{44}nisu).`: lấy 1 ký tự tiếp theo mà tính từ ký tự đó, 44 ký tự sau được tiếp nối bởi chuỗi "nisu" ![image](https://hackmd.io/_uploads/HJ3ByEUQC.png) - `(?=.{23}fia).{4}`: lấy 4 ký tự tiếp theo mà tính từ ký tự đầu tiên, 23 ký tự sau được tiếp nối bởi chuỗi "fia" ![image](https://hackmd.io/_uploads/r1N4g4IQC.png) - Cộng thêm `}$` chuỗi sẽ kết thúc bằng "}" Sau dòng đầu tiên chuỗi matched là "FUSEC{" trong điều kiện chuỗi dưới đây: `FUSec{qqqqqqqqqqqqqqqqqqqfiaqqqqqqqqqqqqqqqqqnisuqqq}` ![image](https://hackmd.io/_uploads/B1TugVUQ0.png) - Với `?<=` (`positive lookbehind`), những regex sau đó sẽ được tìm sau chuỗi "FUSec{" có nghĩa là từ khúc sau là điều kiện để thỏa mãn ruột của flag `qqqqqqqqqqqqqqqqqqqfiaqqqqqqqqqqqqqqqqqnisuqqq`. - `(?=.{4}(.).{11}\1)`: sau 4 ký tự đầu tiên, ký tự thứ 5 sẽ được nhóm vào `group 1`, tiếp tục sau đó 11 ký tự thì ký tự kế tiếp sẽ phải giống với ký tự trong `group 1`. Nghĩa là ký tự thứ 5 phải giống với ký tự thứ 17. ![image](https://hackmd.io/_uploads/ryFtZ4Im0.png) - `(?=.{4}(.).{6}\2)`: sau 4 ký tự đầu tiên, ký tự thứ 5 sẽ được nhóm vào `group 2`, tiếp tục sau đó 6 ký tự thì ký tự kế tiếp sẽ phải giống với ký tự trong `group 2`. Nghĩa là ký tự thứ 5 phải giống với ký tự thứ 12. ![image](https://hackmd.io/_uploads/Bkl_f4L7C.png) - `(?=.{6}(.).{27}\3)`: sau 6 ký tự đầu tiên, ký tự thứ 7 sẽ được nhóm vào `group 3`, tiếp tục sau đó 27 ký tự thì ký tự kế tiếp sẽ phải giống với ký tự trong `group 3`. Nghĩa là ký tự thứ 7 phải gioogns với ký tự thứ 35. ![image](https://hackmd.io/_uploads/SkqJEEU70.png) - Tiếp tục với logic trên xét hết các mệnh đề còn lại thì ta sẽ ra flag thỏa mãn toàn bộ regex. Ta có thể debug làm dần bằng tay hoặc sử dụng script sau. ```python= from z3 import Solver, IntVector, sat S = Solver() x = IntVector('X', 53) for i,c in enumerate('FUSec{'): S.add(x[i] == ord(c)) S.add(x[52] == ord('}')) pointer = 1 S.add(x[pointer + 44] == ord('n')) S.add(x[pointer + 45] == ord('i')) S.add(x[pointer + 46] == ord('s')) S.add(x[pointer + 47] == ord('u')) pointer = 2 S.add(x[pointer + 23] == ord('f')) S.add(x[pointer + 24] == ord('i')) S.add(x[pointer + 25] == ord('a')) point = 6 S.add(x[point + 4] == x[point + 4 + 1 + 11]) S.add(x[point + 4] == x[point + 4 + 1 + 6]) S.add(x[point + 6] == x[point + 6 + 1 + 27]) S.add(x[point + 35] == x[point + 35 + 1 + 0]) S.add(x[point + 9] == x[point + 9 + 1 + 3]) S.add(x[point + 15] == x[point + 15 + 1 + 10]) S.add(x[point + 7] == x[point + 7 + 1 + 36]) S.add(x[point + 18] == x[point + 18 + 1 + 6]) S.add(x[point + 16] == x[point + 16 + 1 + 7]) S.add(x[point + 29] == x[point + 29 + 1 + 3]) S.add(x[point + 0] == x[point + 0 + 1 + 8]) S.add(x[point + 8] == x[point + 8 + 1 + 19]) S.add(x[point + 37] == x[point + 37 + 1 + 4]) S.add(x[point + 27] == x[point + 27 + 1 + 3]) S.add(x[point + 10] == x[point + 10 + 1 + 34]) S.add(x[point + 11] == x[point + 11 + 1 + 11]) S.add(x[point + 2] == x[point + 2 + 1 + 31]) S.add(x[point + 14] == x[point + 14 + 1 + 10]) S.add(x[point + 38] == x[point + 38 + 1 + 4]) S.add(x[point + 3] == x[point + 3 + 1 + 13]) S.add(x[point + 5] == x[point + 5 + 1 + 20]) S.add(x[point + 10] == x[point + 10 + 1 + 11]) S.add(x[point + 36] == x[point + 36 + 1 + 0]) S.add(x[point + 12] == x[point + 12 + 1 + 31]) S.add(x[point + 15] == x[point + 15 + 1 + 1]) S.add(x[point + 1] == x[point + 1 + 1 + 32]) S.add(x[point + 28] == x[point + 28 + 1 + 15]) S.add(x[point + 30] == x[point + 30 + 1 + 14]) S.add(x[point + 29] == x[point + 29 + 1 + 2]) S.add(x[point + 16] == x[point + 16 + 1 + 8]) S.add(x[point + 26] == x[point + 26 + 1 + 17]) S.add(x[point + 22] == x[point + 22 + 1 + 17]) S.add(x[point + 18] == x[point + 18 + 1 + 2]) S.add(x[point + 20] == x[point + 20 + 1 + 7]) S.add(x[point + 1] == x[point + 1 + 1 + 17]) S.add(x[point + 13] == x[point + 13 + 1 + 20]) S.add(x[point + 31] == x[point + 31 + 1 + 1]) S.add(x[point + 32] == x[point + 32 + 1 + 8]) S.add(x[point + 39] == x[point + 39 + 1 + 3]) if S.check() == sat: M = S.model() f = '' for i in range(53): f+= chr(M[x[i]].as_long()) print(f'Flag: {f}') ``` # No suspicious ## Description Tôi cá là ở đây không có gì sú bằng kho báu của Trương Mỹ Lan ### Objective - FakeTLS investigation ### Category `Forensic` ### Difficulty `easy` ### Flag `FUSec{f4k3_TLS_1s_s0m3th1ng_bruuhhh}` ## Solved Đề bài cung cấp cho ta một file pcap, vào phần export object của HTTP sẽ thấy có nhiều request đến trang `haitactihon.com` tuy nhiên mấy cái này chẳng có gì sú :D Request sú là đến trang `truytimkhobau.com`, đã GET về một file ELF ở đây tên là `treasure`. ![1](https://hackmd.io/_uploads/r1pOrU8X0.png) Export ra rồi load vào IDA phân tích có một số đặc điểm đáng chú ý sau: ![2](https://hackmd.io/_uploads/B1EcBII7A.png) - File PE này khi được chạy sẽ kết nối với server `4.236.191.192` - Thực hiện một số hàm `snd_cli_hel`, `cnsm_serv_hel_plus`, `snd_cli_hel_fin`. - Sử dụng key với thuật toán mã hóa RC2. Ok tổng quan trước mắt là vậy, chi tiết như nào thì chưa rõ, ta chưa biết sau khi kết nối thì file PE này đã làm gì. Tuy nhiên đây là một bài cate Forensic chứ không phải RE :D Bài này tác giả không strip binary cũng không thực hiện các kỹ thuật anti RE nào nên các bạn có thể xem source code clean hoàn toàn. Các bạn có thể giải được bài này mà cần rất ít kỹ năng RE, ta cần một chút kỹ năng `Threat Intelligence` hoặc `Osint` nhé :D Thông thường khi gặp một malware thì xu hướng của một người Forensic sẽ đi tra cứu xem có report nào liên quan đến malware family này hay chưa thông qua các hằng số, tên hàm cũng như là đặc điểm của hàm. ![3](https://hackmd.io/_uploads/Sks9SLUXR.png) ![4](https://hackmd.io/_uploads/B1xiHLUXA.png) Một đặc điểm nữa ta có thể thấy PE có sử dụng các chuỗi được fix cứng là các domain legit để qua mắt người phân tích pcap. ![5](https://hackmd.io/_uploads/H1Ior8LQ0.png) Công việc tiếp theo chỉ cần đọc bài [blog](https://zhuanlan.zhihu.com/p/564232225) phân tích này là có thể hiểu được hành vi của file PE từ đó giải mã được traffic. Tóm tắt như sau: - Đây là kỹ thuật fake TLS, giả mạo các gói tin TLS để exfiltrate data đến C2 server. - Đầu tiên, mã độc này sẽ giả mạo các gói tin `Client Hello`, `Change Cipher Spec` bằng những đoạn hard code có sẵn để bắt đầu giả mạo một session TLS. - Tiếp theo nhận command từ C2 server, giải mã nó bằng key `79 E1 0A 5D 87 7D 9F 46 49 41 2E 11 65 AC E3 25` bằng thuật toán RC2 (mã hóa và giải mã giống RC4) rồi thực thi comand đó. Sau khi thực thi xong, lấy kết quả mã hóa lại cũng với key trên và bằng thuật toán RC2 rồi gửi đến cho C2. Vậy giờ ta sẽ giải mã C2 traffic trên. Filter `ip.addr == 4.236.191.192`. Lấy phần data của các gói `Application Data` để đi giải mã. ![6](https://hackmd.io/_uploads/B1hoHLUQC.png) ![7](https://hackmd.io/_uploads/SyZhBLI7A.png) Giải mã từng gói application ta sẽ nhận được flag. ![8](https://hackmd.io/_uploads/HJOnrLImC.png)