<h1 id="Hack-The-Box">Hack The Box - Reversing (Medium 2)</h1> ![image](https://hackmd.io/_uploads/HyybUq-eC.png) Ghi chú: <ul> <li>Medium: 7-12 challenge</li> <ul> <li><a href="#Breakin">7. Breakin</a></li> <li><a href="#Mr. Abilgate">8. Mr. Abilgate</a></li> <li><a href="#Curse Breaker">9. Curse Breaker</a></li> <li><a href="#RetoRetro">10. RetoRetro</a></li> <li><a href="#Alien Saboteur">11. Alien Saboteur</a></li> <li><a href="#Bombs Landed">12. Bombs Landed</a></li> </ul> </li> </ul> <h2>Difficulty: Medium </h2> <div id="Breakin"></div> <h3>Challenge 7: Breakin</h3> The group regularly changes cryptographic keys, and we believe this server is being used to coordinate them. If you can discover how the keys are being derived, then we'll be able to decrypt all their past communication! <a href="https://drive.google.com/file/d/1e1Aciwl6jA0q-AyCJsSXDjzGUqTxaVq_/view?usp=sharing">Download Challenge Here</a> <h3>Solution</h3> `/proc` trong Linux là một hệ thống tệp ảo đặc biệt cung cấp một giao diện giống như tệp để truy cập thông tin về hệ thống và các tiến trình đang chạy. Nói cách khác, nó không phải là một hệ thống tệp thông thường lưu trữ dữ liệu mà là một cửa sổ thể hiện trạng thái đang chạy của hệ thống. Ta sẽ kết nối với `Instance`, chúng ta có thể truy cập vào danh sách thư mục từ một `Linux root`. Vì chúng ta để có thể duyệt đến bất kỳ tệp nào chúng ta muốn, chúng tôi có thể sử dụng hệ thống tệp `/proc`. Khi duyệt đến * `/proc/self/maps hoặc /proc/self/cmdline` chúng ta có thể khám phá đường dẫn sẽ có sự thay đổi. * `/proc/self/exe` cũng tải xuống tệp thực thi. Mình đã để tệp đó để mọi người có thể tải. Chúng ta có thể sử dụng lệnh 'file' để cung cấp cái nhìn tổng quan về loại tệp. ![image](https://hackmd.io/_uploads/Hy9ljr9sp.png) Mở file trong IDA64, ta thấy có xuất hiện của các `regex strings` kèm theo `method + function` | Method | Regex strings | Function | | ----------- | ----------- | ---------| | GET | `^/exec$ ` | `pingGet` | | POST | `^/exec/([a-zA-Z0-9]+)` | `execPost` | | GET | `^/secret$` | `execGet` | | GET | | `secretGet` | | GET | | `defaultGet` | 1. Hàm `pingGet`, hàm GET REQUEST với đường dẫn "/ping", thực hiện triển khai giao thức giao tiếp `ping/pong` bằng cách sử dụng `SimpleWeb Framework` để xử lý các `HTTP request và response`. 2. Hàm `execPost`, hàm đọc dữ liệu từ một `request` và phân tích nó dưới dạng JSON, kiểm tra xem một số trường dữ liệu có tồn tại trong yêu cầu không. Nếu các trường dữ liệu cần thiết được tìm thấy, hàm tiếp tục giải mã một số dữ liệu hexa từ yêu cầu, tạo một đối tượng `payload` và liên kết nó với một tên trong một bản đồ. 3. Hàm `execGet`, hàm sẽ tìm kiếm tệp trong danh sách chương trình. Nếu tìm thấy chương trình , server sẽ thực thi chương trình đó và gửi kết quả như là phản hồi. 4. Hàm `secretGet`, khi ta truy cập đến `/secret endpoint`, `password` sẽ được truyền vào bằng tham số được điền. Kiểm tra `password` của ta có giống của chương trình không. Từ đó, ta biết ta cần truy cập với đường dẫn `/secret?password=<password>` 5. Hàm `defaultGet` xử lý `GET REQUEST` mặc định trong ứng dụng server. Hàm khởi tạo và trích xuất đường dẫn tệp và thư mục từ `GET REQUEST`. Nếu đường dẫn trích xuất là một thư mục, hàm sẽ tạo một danh sách các tệp trong thư mục đó và gửi nó như là một phản hồi. ![image](https://hackmd.io/_uploads/HJjB5Iqsa.png) Ta truy cập với đường dẫn `/secret?password=!IEN*113hRt^9@Z8Rz9hmy!E`. Ta có thể upload `python bytecode`, thêm nó vào trong danh sách các tệp và thực thi nó. Ta cần tạo một `POST REQUEST` đến `/exec endpoint` ở dạng `json` và tạo một `GET REQUEST` đến `/exec/<program>` để thực thi tệp đó. ![image](https://hackmd.io/_uploads/r1CpDwcop.png) Trong hàm `secretGet`, chương trình tạo chuỗi mới v24 bằng cách ghép các phần tử HTML cố định với nhau. Đoạn mã xây dựng phần HTML liên quan đến chương trình vào biến toàn cục `Program`, phần HTML của form tải lên cùng với một đoạn mã JavaScript để xử lý tải lên tệp và gửi dữ liệu lên máy chủ. Đoạn `python bytecode` của ta cũng sẽ được lưu vào biến `Program`. ![image](https://hackmd.io/_uploads/SkHVcPqja.png) Trang web cung cấp cho ta `creds, key, stats`. ![image](https://hackmd.io/_uploads/HkJvaD9op.png) Hàm `executePython()` thực hiện đúng như tên gọi của nó - `load python object từ bytecode`. Thực thi mã Python bằng cách nhập nó như một module bằng `PyImport_ExecCodeModule`. Gọi hàm `main` từ module bằng cách sử dụng `PyObject_CallMethod`. Kiểm tra nếu là chuỗi Unicode, xử lý cả chuỗi bằng thành `chuỗi UTF8 và chuỗi byte`. Chúng ta cần tạo ra một đoạn mã Python và biên dịch nó thành mã bytecode. Đoạn mã Python này sẽ ghi ra tất cả các module được load trong chương trình. :::info ``` import sys import marshal code_to_compile = """ def call_tracer(frame, event, arg): import marshal with open('./dump','wb') as f: o = marshal.dumps(frame.f_code) f.write(o) return None def main(): import sys sys.settrace(call_tracer) return dir(sys.modules['payload'].main) """ compiled_code = compile(code_to_compile, 'test', 'exec') marshalled_code = marshal.dumps(compiled_code) with open('dump.dmp', 'wb') as dump_file: dump_file.write(marshalled_code) ``` ::: Ta thử thực thi các chương trình `creds, key, stats` đồng thời quan sát `dump file` được tạo, ta phát hiện chỉ khi thực tệp `key` thì hệ thống mới load các module mới, trong đó có: `binascii, unhexlify, hexdigest, hashlib, hasher` Ta có thứ tự thực thi sau: 1. Chạy đoạn mã ở trên để tạo tệp `dump.dmp` 2. Upload tệp `dump.dmp` lên web server. 3. Thực thi chương trình vừa được ta tải lên để tiến hành ghi lại `load module` 3. Thực thi chương trình `key`, `load các module mới` 4. Tải tệp `dump` đã ghi lại thông tin `load module` của hệ thống. Tiến hành trích nội dung từ tệp `dump` :::info ``` import dis import marshal with open('dump', 'rb') as dump_file: bytecode = dump_file.read() dis.dis(marshal.loads(bytecode)) ``` ::: ![image](https://hackmd.io/_uploads/SJxTkEssa.png) Dùng https://kt.gy/tools.html để xem nội dung chuỗi hexa. ![image](https://hackmd.io/_uploads/Hyc0J4oop.png) :::success ``` Flag: HTB{1_h0p3_y0u_w4lk3d_th3_tr33_f0r_m3?} ``` ::: <div id="Mr. Abilgate"></div> <h3>Challenge 8: Mr. Abilgate</h3> Mr. Abilgate, the CFO of a Fortune 500 company, has reportedly been the victim of a recent spree of ransomware attacks. The behavior of the malware seems consistent with our current APT target's tactics, but the ransom note makes us think it's a targeted attack. We suspect bad faith from corporate espionage gone wrong. Could you investigate? <a href="https://drive.google.com/file/d/1UXwvH0wh5z1g5_XplBoGeeI-xjExSyWp/view?usp=sharing">Download Challenge Here</a> <h3>Solution</h3> Tôi làm bài này theo hướng giải của HTB. Sau khi đọc bài này, mình đã học được rất nhiều, cũng như các viết script mình cũng sẽ có sự thay đổi. <a href="https://www.hackthebox.com/blog/business-ctf-2022-write-up-mr-abilgate"> Các bạn nên đọc tại đây.</a> :::success ``` Flag: HTB{b1g_br41ns_b1gg3r_p0ck3ts_sm4ll3r_p4y0uts} ``` ::: <div id="Curse Breaker"></div> <h3>Challenge 9: Curse Breaker</h3> A dark wizard placed a curse on you - if you open your mouth to say anything, it'll strike! Only by perfectly reciting the counter-spell can you escape... <a href="https://drive.google.com/file/d/1boaY1S3lpDif2aIgNpH6agvF_e9xukSI/view?usp=sharing">Download Challenge Here</a> <h3>Solution</h3> Chúng ta có thể sử dụng lệnh 'file' để cung cấp cái nhìn tổng quan về loại tệp. ![image](https://hackmd.io/_uploads/r1tw8nJhT.png) Mở file trong IDA64, ta thay đổi kiểu dữ liệu từ `char s[8]` thành `char s[56]`. ![image](https://hackmd.io/_uploads/rJWyD31nT.png) Ta sẽ cần phân tích hàm `install_filter()` và lệnh `syscall` ở dưới cùng. ![image](https://hackmd.io/_uploads/SyZjv2y3a.png) >Seccomp (viết tắt của "short for secure computing") là một cơ sở bảo mật máy tính trong nhân Linux, cho phép một quá trình thực hiện quá trình chuyển đổi một chiều sang trạng thái "an toàn" trong đó nó không thể thực hiện bất kỳ lệnh gọi hệ thống nào ngoại trừ `exit()`, `sigreturn()`, `read()`, `write()`. Nếu nó thử bất kỳ lệnh gọi hệ thống nào khác, kernel sẽ chỉ ghi nhật ký sự kiện hoặc chấm dứt quá trình bằng `SIGKILL hoặc SIGSYS`. >Tóm lại: rule seccomp chỉ cho phép thực thi các syscall: open, read, write, mprotect, alarm, exit và exit_group. Tiến hành sử dụng <a href="https://github.com/david942j/seccomp-tools"> seccomp tools</a> để dump rule seccomp: ![image](https://hackmd.io/_uploads/HkAlnny3T.png) Luồng chương trình thực thi như sau: 1. Kiểm tra `arch == ARCH_X86_64` và `sys_number ==0x258` 2. Kiểm tra `args[0] != 0` * `Nếu đúng` -> đến `dòng 41` -> đến `dòng 75` -> đến `dòng 109` -> `dòng 143` = `Exit` * `Nếu sai`, cứ thực hiện 5 phép toán thì gán `A = 0 (dòng 8, 42, 76, 110)`. Mỗi lần thực hiện phép toán, `kí tự kế tiếp = kí tự trước đó - kí tự hiện tại` Ta thực hiện trích dữ liệu để tính toán. :::info ``` seccomp-tools dump ./breaker | grep -oP '(?<=if \(A ==)[^)]*' | tail -n +3 | while read -r n; do echo $((n > 2147483647 ? n - 4294967296 : n)); done | tr '\n' ' ' | sed 's/ $/\n/' | sed 's/ /, /g' # Result: 72, 12, 54, 69, 46, 101, -2, 101, -53, 162, 112, -67, 164, -64, 116, 98, 16, 36, -3, 128 ``` ::: Từ đó, ta viết chương trình giải mã: :::info ``` data = [72, 12, 54, 69, 46, 101, -2, 101, -53, 162, 112, -67, 164, -64, 116, 98, 16, 36, -3, 128] flag = '' for i in range(0,len(data)): if i%5 == 0: flag += (chr(data[i])) else: flag += (chr(data[i-1]+data[i])) print(flag) ``` ::: :::success ``` Flag: HTB{secc0mp-ad4br4!} ``` ::: <div id="RetoRetro"></div> <h3>Challenge 10: RetoRetro</h3> Welcome back to the eighties! Some mediocre game programmer from the 80s has hidden an old ROM inside a modern executable. Can you find it and beat the game to gain the flag? <a href="https://drive.google.com/file/d/1XUA7SA67CWeeaWOxfc-y2zlyzh0aJOGT/view?usp=sharing">Download Challenge Here</a> <h3>Solution</h3> Chúng ta có thể sử dụng lệnh 'file' để cung cấp cái nhìn tổng quan về loại tệp. ![image](https://hackmd.io/_uploads/Sku8PfmkA.png) Mở chương trình trong IDA, chương trình yêu cầu ta nhập dữ liệu từ bàn phím. Với dữ liệu được nhập, chương trình tiếp tục mã băm MD5 của nó. Giá trị băm sẽ được lưu vào `byte_5150` ![image](https://hackmd.io/_uploads/S1G1JQXk0.png) Tại hàm `sub_1205`, với giá trị băm MD5 đó, chương trình thực hiện so sánh. Nếu trả về đúng thì mã băm của ta chính xác, nếu sai thì sử dụng giá trị băm theo dữ liệu từ bàn phím. Ta có thể tính toán cơ bản, giá trị băm MD5 đúng là `E7D52842CBE43040630B6B1E01093BC4`. ![image](https://hackmd.io/_uploads/rJMmeQXy0.png) Tại hàm `sub_1397` nhận tham số gồm: mã băm MD5, bytecode, buffer và n = 1010. ![image](https://hackmd.io/_uploads/SyWPgQQJA.png) Chương trình sử dụng mã băm MD5 là key trong thuật toán mã hóa AES để giải mã dữ liệu từ biến bytecode. Ta có thể dùng CyberChef để tìm ra giá trị được giải mã ![image](https://hackmd.io/_uploads/SkAww7XJA.png) Tiếp đó, chương trình cho ta nhập `cheatcode` gồm 4 kí tự, với cheatcode này ta sẽ mã hóa giá trị tại `byte_50E0` và thực hiện so sánh giá trị như sau: ![image](https://hackmd.io/_uploads/ByAZO7myR.png) Ta dễ dàng tìm được giá trị `cheatcode = 6507` :::info ``` data = [ 0x34, 0x37, 0x32, 0x35, 0x34, 0x3F, 0x36, 0x35, 0x48, 0x77, 0x72, 0x49, 0x48, 0x77, 0x72, 0x49, 0x2C, 0x13, 0x12, 0x25, 0x38, 0x37, 0x12, 0x2B, 0x48, 0x77, 0x52, 0x65, 0x7C, 0x73, 0x72, 0x49, 0x08, 0x75, 0xB0, 0x8B, 0xF4, 0xB7, 0x74, 0x0F, 0x08, 0x75, 0xB0, 0x8B, 0xF4, 0xB7, 0x74, 0x0F, 0x46, 0x7D, 0x78, 0x7F, 0x46, 0x75, 0x70, 0x77, 0x0A, 0x77, 0x8D, 0xD0, 0xC9, 0xEE, 0x4E, 0x0B] print (chr(data[1]^ 2)) # 1 print (chr(data[8]^ 126)) # 0 print (chr(data[58]^ 189)) # 2 print (chr(data[63]^ 60)) # 3 ``` ::: ![image](https://hackmd.io/_uploads/BJ05OXXkA.png) Một công cụ chỉnh sửa sprite 8-bit nhỏ gọn dành cho máy Atari VCS (Atari 2600) là một công cụ thú vị cho cả các đam mê và nhà phát triển, cho phép họ tạo ra đồ họa tùy chỉnh để sử dụng trong các trò chơi Atari 2600. Atari 2600, nổi tiếng với đồ họa 8-bit đặc trưng của mình, đã thu hút các game thủ suốt nhiều thập kỷ. ![image](https://hackmd.io/_uploads/BJ4kEVX10.png) Thật ra bạn có thể tìm ra flag từ đoạn giải mã AES rồi. Ta biểu diễn các số hex theo hệ máy Atari :::info ``` hex_string = "004242427e7e4242420018181818181818ff00e0909090e09090e000304040c0c040403000fe828282fe8080fe003e4080bcc2824438000101017f4141417f00fc848484fc8080fc003f2121213f010101007e42427e7e42427e003e4080bcc2824438007e4262524a46427e000404047c44444440000404047c44444440007e4262524a46427e000404047c44444440001a2622120e02221c00fc848484fc8080fc007048484870404040003c0404043c20203c0002020202020a060200404040e040505020007e4262524a46427e000018202020180000003f2121213f010101000018202020180000003e4080bcc28244380002020202020a060200101010080402021e0002020202020a0602007e42427e7e42427e001a2622120e02221c007e4262524a46427e003e4080bcc2824438003e4080bcc2824438007048484870404040000c0202030302020c00" flag = "" for i in range(0, len(hex_string), 2): hex_pair = hex_string[i:i+2] binary_char = bin(int(hex_pair, 16))[2:].zfill(8) flag = binary_char.replace("1", "X").replace("0", " ") + "\n" + flag print(flag) ``` ::: :::success ``` Flag: HTB{6e96d8e04404a6b51f0cdce1718a0eeb} ``` ::: <div id="Alien Saboteur"></div> <h3>Challenge 11: Alien Saboteur</h3> You finally manage to make it into the main computer of the vessel, it's time to get this over with. You try to shutdown the vessel, however a couple of access codes unknown to you are needed. You try to figure them out, but the computer start speaking some weird language, it seems like gibberish... <a href="https://drive.google.com/file/d/1JGjhyrsWlwEbCC7-d1xc_Lq7o3DPww4B/view?usp=sharing">Download Challenge Here</a> <h3>Solution</h3> Chúng ta có thể sử dụng lệnh 'file' để cung cấp cái nhìn tổng quan về loại tệp. ![image](https://hackmd.io/_uploads/B1l6V7NyA.png) Mở chương trình trong IDA. ![image](https://hackmd.io/_uploads/Hk8uEmEJA.png) Ta có thể dự đoán chương trình sẽ tạo một máy ảo (VM) và chạy chương trình trên đó. Ta mở hàm `vm_create` để quan sát thêm. ![image](https://hackmd.io/_uploads/rk6q3NNJR.png) Hàm vm_create được sử dụng để tạo ra một đối tượng máy ảo (VM) và cấp phát bộ nhớ cho ba mảnh bộ nhớ khác nhau trên heap. * Đối tượng VM có kích thước 0xA8 byte. * Hai mảnh bộ nhớ khác có kích thước 0x10000 byte và 0x200 * 4 byte (tương đương với 0x800 byte). Tiếp theo làm hàm `vm_run` ![image](https://hackmd.io/_uploads/HJmFhVEyR.png) Hàm `vm_run` gọi hàm `vm_step` ![image](https://hackmd.io/_uploads/rJCK3N4y0.png) Khi giá trị của `v1 > 0x19` thì điều kiện không hợp lệ trong quá trình thực thi của VM và thoát chương trình. Hàm sử dụng con trỏ hàm `original_ops` thể hiện máy ảo này có một tập hợp các lệnh được quản lý thông qua một mảng các con trỏ hàm. |`1. vm_add` |`6. vm_muli` | `11. vm_push` | `16. vm_print`| `21. vm_jge` | |---|---|--- |---|---| |`2. vm_addi`| `7. vm_div` | `12. vm_pop` | `17. vm_putc`| `22. vm_xor` | |`3. vm_sub` | `8. vm_cmp` | `13. vm_mov` | `18. vm_je` | `23. vm_store` | |`4. vm_subi`| `9. vm_jmp` | `14. vm_nop` | `19. vm_jne`| `24. vm_load` | |`5. vm_mul` | `10. vm_inv`| `15. vm_exit`| `20. vm_jle` | `25. vm_input` | Lười quá không làm nổi nữa!! Sau khi đọc bài này, mình đã học được rất nhiều, cũng như các viết script mình cũng sẽ có sự thay đổi. <a href="https://iscsc.fr/posts/reversing-alien-gibberish-xlitoni/ "> Các bạn nên đọc tại đây.</a> :::info ```python permut_byte_array = b'\x13\x19\x0F\x0A\x07\x00\x1D\x0E\x16\x10\x0C\x01\x0B\x1F\x18\x14\x08\x09\x1C\x1A\x21\x04\x22\x12\x05\x1B\x11\x20\x06\x02\x15\x17\x0D\x1E\x23\x03' Xor_Key_byte_array = b'\x16\xB0\x47\xB2\x01\xFB\xDE\xEB\x82\x5D\x5B\x5D\x10\x7C\x6E\x21\x5F\xE7\x45\x2A\x36\x23\xD4\xD7\x26\xD5\xA3\x11\xED\xE7\x5E\xCB\xDB\x9F\xDD\xE2' Solution_Compare_String = b'\x31\x5D\x77\x4A\x33\x40\x56\x35\x75\x37\x5D\x35\x6E\x6E\x66\x32\x6C\x36\x70\x66\x61\x6A\x31\x79\x5D\x31\x70\x7F\x6C\x60\x33\x32\x36\x7B\x31\x5D' PermutDict = {} for i in range(len(permut_byte_array)) : PermutDict[permut_byte_array[i]] = i def Xor(bytes_array_a,value) : return bytes(a^value for a in bytes_array_a) def swapbytes(byte_array,i,j) : res = b'' for c in range(len(byte_array)) : if c == i : res += bytearray( [byte_array[j]] ) elif c == j : res += bytearray( [byte_array[i]] ) else : res += bytearray( [byte_array[c]] ) return res def PermutByteArray(bytes_array) : byte_res = bytes_array for i in range(36)[::-1] : byte_res = swapbytes(byte_res,i,permut_byte_array[i]) return byte_res for i in range(36) : Solution_Compare_String = PermutByteArray(Xor(Solution_Compare_String,Xor_Key_byte_array[35-i])) print(Solution_Compare_String) ``` ::: :::success ``` Flag: HTB{5w1rl_4r0und_7h3_4l13n_by73c0d3} ``` ::: <div id="Bombs Landed"></div> <h3>Challenge 12: Bombs Landed</h3> Can you find the password? Enter the password as flag in the following form: HTB{passwordhere} <a href="https://drive.google.com/file/d/1GqHyetF_NhQKbd1OzSK5L7p5XJ4TahAO/view?usp=drive_link">Download Challenge Here</a> <h3>Solution</h3> Chúng ta có thể sử dụng lệnh 'file' để cung cấp cái nhìn tổng quan về loại tệp. ![image](https://hackmd.io/_uploads/SJYYZNiiT.png) IDA chưa thể decompile chương trình được. Ta sẽ `tạo hàm` từ `0x8048937` đến `0x08048AE6` để IDA có thể decompile hàm `main()`. ![image](https://hackmd.io/_uploads/ryI8kRt9a.png) Chương trình thực hiện kiểm tra đã được truyền bốn tham số chưa. Sau đó `sub_80491A0() ^ 0x63` để tạo một hàm mới. Ta dùng IDAPython để viết patch script. :::info ``` import ida_bytes start_address = 0x080491A0 end_address = 0x08049336 for i in range(start_address,end_address): tmp = ida_bytes.get_byte(i) ida_bytes.patch_byte(i,tmp^0x63) ``` ::: ![image](https://hackmd.io/_uploads/BJo5lRK5T.png) Chương trình giải mã các chuỗi thành các chuỗi đọc được như sau: * `s ^ 0x14` nhằm tạo chuỗi `input password: ` * `v3 ^ 0x14` nhằm tạo chuỗi `you win.` * `(v6 + v5) ^ 0xA` để tạo và trả về chuỗi `younevergoingtofindme` :::success ``` Flag: HTB{younevergoingtofindme} ``` :::