Lo-Fi

Lần đầu tiên cũng là lần cuối cùng mình tham gia cuộc thi SVATTT. Nói chung là phế toàn tập 😥 😥 😥. Cơ mà cũng vui được tham gia cuộc thi quốc gia cũng rất vui rồi 😄. Mình chơi mảng RE, bài khó vl. Chắc do trình kém 😞. Thi xong còn tức nên cố làm bài Lo-Fi rồi viết WU chia sẻ mọi người.

Tóm tắt nội dung: MD5 nhưng ko phải MD5 nhưng mà là MD5 😛. Giống như gần đây mình học “ Tư bản ko thể xuất hiện từ lưu thông và cũng ko thể xuất hiện ở bên ngoài lưu thông. Nó phải xuất hiện trong lưu thông và đồng thời ko phải trong lưu thông”

Link: Lo-Fi

Okie, Cùng giải nó vào 😜

Đầu tiên check xem em nó là gì cái nhỉ 😃:

Một chương trình viết bằng ngôn ngữ Pascal. Nó làm mình gợi nhớ những kỷ niệm không tốt năm học cấp 2 😠. Với chương trình MS-DOS (16 bits) này thì Windows 10 ko chạy được. Thế thì đành cái DosBox chạy thử vậy.


Kiểu rất cổ điển. Yêu cầu nhập vào dữ liệu hợp lý thì sẽ có thông báo thành công. Ở đây thông báo chỉ in ra “Congrats!” ko có in ra flag nên có thể dễ dàng đoán được input nhập vào là flag luôn.


Với chương trình này mình dùng máy Windows XP cùng với Turbo Debuggerđể debugger chương trình chạy. Có 2 chỗ quan trọng như các bạn đã thấy đó là hàm gọi call far ptr và sub_10013


Với call far ptr thì IDA chịu rồi ko biết hàm đó ở đâu. Thôi dùng Turbo Debugger để biết vậy. Đây là phần đầu của e nó:


Map qua chúng ta có thể dễ dàng tìm đoạn code này nắm ở seg001 trong IDA:


À quên mất mình phải xem nó truyền vào gì chứ nhỉ 😜

Ở phần nhập phía trên thì input nhập vào length được lưu ở 0x50B8 phía sau sẽ là data mình nhập tức là băt đầu 0x50B9 là vùng dữ liệu của mình nhập vào các bạn debuger sẽ thấy. Cơ bản thì nó lấy mỗi lần 2 ký tự liền kề truyền vào hàm call far ptr. Okie quay lại hàm, trong hàm chúng ra sẽ thấy các hằng số đặc biệt và dễ dàng liên tưởng đến ngày hash MD5:


Suy đoán hàm call far ptr thực chất là mã hóa MD5 của chuổi 2 ký tự truyền vào. Test ngay nhập vào “12” ta có chuổi mã hóa: A5FC099D94CC90596C899D1E31F419B7


Tạch luôn. MD5(“12”) = C20AD4D76FE97759AA27A0C99BFF6710. Sai chỗ nào nhỉ. Sau một hồi nhìn lại. Mình đã tìm ra. Đó là giá trị khởi tạo ban đầu của thuật toán hash MD5


Giá trị khởi tạo thứ 3 và thứ 4 bị thay đổi so với ban đầu là:


Okie. Đến đây thì hoàng thành xong hàm call far ptr. Fuck tạp, chuyển qua hàm sub_10013:


Nhận tham số truyền vào là từng byte trong 16 bytes sau khi dùng MD5 hash chuỗi nhập vào.

Cơ bản thì hàm này đơn giản thôi thực hiển giống như hexdigest() trong python vậy. Chuyển từ hex value sang hex string. Okie. phần cuối so sánh

Cơ bản là lấy giá trị sau khi chuyển sang hex string xor với giá trị khởi tạo ban đầu chương trình (nguyên tờ sớ dài vô tận phía trên ấy) nếu bằng 0 thì nhập đúng (Ở đây dùng xor ko phải cmp nên thứ tự có thể bị đổi).

Okie tổng kết lại flow chương trình

Nhập dữ liệu đầu vào chuỗi “12” => call far ptr (“12”) => ‘\xA5\xFC\x09\x9D\x94\xCC\x90\x59\x6C\x89\x9D\x1E\x31\xF4\x19\xB7’ => For each byte call sub_10013(‘\xA5’) => “A5” => ord(‘A’) ^ ord(‘5’) ^ ord(‘0’) ^ ord(‘C’) == 0 => Correct

Okie viết mã giải thôi. Ở đây chương trình chỉ hash 2 ký tự nên brute dễ dàng và nhanh chóng. (Code MD5 được lấy từ https://rosettacode.org/wiki/MD5/Implementation). Code solve:

Cảm ơn các bạn đã dành thời gian đọc bài viết 😀

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s