[Plaid CTF 2016] quite quixotic quest (Re300)

Hãy chuẩn bị tinh thần, vì đây là bài 300 điểm của một giải có rating 90.

2016fd1c9ed8-0e7f-40f3-b2b9-a23104c6361e

quite quixotic quest

Reversing (300 pts)

Well yes, it certainly is quite quixotic. (Yes, the flag format is PCTF{} )

Link dự phòng: quixotic

Đề bài là một file ELF 32 bit. Mặc dù đã có trong tay IDA phiên bản hịn (mà cả thế giới đều có), mình vẫn ưa 32 bit. Cười trong ô tô thì vẫn thích hơn là khóc trên xe đạp, right?

Xem danh sách string, dễ thấy nó chính là curl cải trang:

Mình đã định dùng BinDiff, nhưng thật thô bỉ khi đồng đội của mình chỉ cho mình cái này:

Tức là flag sẽ được nhập qua option –pctfkey. No fun.

Still no fun, chuỗi Validating key… kia đáng ra cần được che giấu kỹ càng hơn. Mình hoàn toàn cảm thấy bị xúc phạm khi mọi thứ cứ thẳng tuồn tuột như thế.

Vì EAX = magic_buf, rồi ESP = EAX, nên ESP = magic_buf. Sau khi debug một chút, chúng ta thấy rằng (có vẻ như) chương trình thực thi một rop chain (trỏ bởi magic_buf). Sau khi step over một hồi, chúng ta sẽ gặp badboy, được build từng char một (‘w’, ‘r’, ‘o’, ‘n’, ‘g’) bằng câu lệnh:

F8 không văn minh lắm, hãy chuyển qua chức năng trace của IDA. Đặt BP ở 0x08052AC7 và chạy lại, bật Instruction Tracing -> F9 -> Badboy -> Mở Trace window (mình quy ước rằng trace log mình post chỉ chứa những câu lệnh mà các bạn cần quan tâm):

Ta thấy EBX = len(key) (mình đang nhập key PCTF{123456}), sau đó EDX -= EBX, tiếp theo EAX = 0x94 và EBX = 0. Nếu cờ ZF = 0 thì lệnh CMOVNZ làm cho EAX = EBX = 0, ngược lại EAX giữ nguyên = 0x94. Sau đó EDI = EAX và ESP += EDI.

Do cờ ZF được quyết định bởi lệnh SUB EDX, EBX, nên kết quả của phép trừ EDX (0x35) cho EBX (len(key)) sẽ ảnh hưởng trực tiếp đến luồng thực thi của chương trình (hoặc ESP += 0, hoặc ESP += 0x94). Như vậy, len(key) = 0x35.

yOy5OI1

Nhập key mới (PCTF{1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJK}) và trace lại:

Đoạn code này làm nhiệm vụ cộng từng ký tự của key vào [EDX]. Khi đã nắm được ý tưởng, ta có thể filter log trace, hoặc đặt BP và F9 để qua nhanh nhưng vẫn đảm bảo việc theo dõi được vòng lặp. Thực tế thì chương trình chỉ tính sum(key[1:]) mà thôi.

Giá trị 01F9933D khi đổi qua DEC sẽ là 33133373, không có gì đặc biệt, mình chỉ nhắc thế thôi. Hãy chuyển sang debug để quan sát stack và các vùng nhớ liên quan. Tại hàm Curl_md5it, tham số thứ 2 trỏ đến 081CCF6C, đúng bằng [eax+4Ch], và chuỗi MD5 kết quả sẽ lưu ở 081CE9C0. Tổng kết lại, đến thời điểm này chúng ta có giả mã sau:

Tiếp tục:

Mã giả tương ứng:

Đoạn code sau sẽ cho ta biết giá trị của s:

Input lại một key phù hợp (PCTF{eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed}).

Đoạn trên là một vòng lặp, với EDX sẽ trỏ đến key và EBX+5E5B30C4 trỏ đến chuỗi MD5.
Sắp xong rồi, cố lên >:(

36

Debug để thấy giá trị các biến, ta thấy rằng chương trình thực hiện việc lấy từng dword trong key (sau khi đã xor với chuỗi MD5), rồi trừ cho ECX, và OR vào EDX. Khi bắt đầu, EDX = 0. Các giá trị của ECX lần lượt như sau:

Ở đây lại là một trick tương tự mà mình đã nhắc đến phần đầu bài, khi mà cờ ZF sẽ ảnh hưởng đến luồng thực thi của chương trình. Cờ ZF được quyết định ở câu lệnh AND EAX, EDX, và vì EAX = 0xFFFFFFFF, EDX cần bằng 0 để cờ này được bật.
Ta nhớ rằng EDX là phép OR của mọi giá trị EAX – ECX, do đó để EDX = 0 thì mọi hiệu EAX – ECX phải bằng 0, hay nói cách khác, EAX phải bằng ECX. Đoạn code sau, như mọi khi, mang lại cho chúng ta flag:

Nếu bạn thắc mắc tại sao với cách làm hư cấu thế này, mà mình lại có thể trở thành người giải ra thứ hai (:”>), thì bạn thắc mắc đúng rồi đấy. Trong lúc thi mình không hề dùng cách này. Hihi.

32

4 thoughts on “[Plaid CTF 2016] quite quixotic quest (Re300)

  1. Tạ Quang Khánh says:

    Thực sự cảm thấy hư cấu…

  2. xss says:

    alert(‘Test’)

  3. Ngọc Au says:

    Cho e hỏi a Tạ Quang Khánh học at9B phải ko ạ

Leave a Reply

Your email address will not be published. Required fields are marked *