REVERSING WITH IDA FROM SCRATCH (P36)

Posted: July 28, 2021 in IDA Tutorials, REVERSING WITH IDA FROM SCRATCH (P36)
Tags: ,

Ở phần 36 này, tôi sẽ thực hiện lại ví dụ trong phần trước nhưng sẽ sử dụng mona đã tích hợp với Windbg. Do mona không hoạt động trong IDA được nên chúng ta sẽ sử dụng WinDbg riêng mà không sử dụng tích hợp với IDA.

Từ màn hình console, tôi chạy DEP.exe kèm theo một tham số truyền vào cho chương trình, nó sẽ dừng lại và đợi thông tin chúng ta nhập vào từ bàn phím:

Ta hoàn toàn có thể thực thi chương trình từ WinDbg, mục đích đơn giản là để dừng sự thực thi ở đâu đó khi mà DLL sẽ sử dụng làm ROP được nạp vào bộ nhớ. Cũng không quan trọng ngay cả khi chương trình bị crash. Trong trường hợp này, tôi đang ở bên trong hàm gets_s()Mypepe.dll đã được nạp vào bộ nhớ. Mở WinDbg (x86) và nhấn F6 để thực hiện Attach process:

Nhấn OK để WinDbg thực hiện attach DEP.exe, ta sẽ dừng lại tại đây:

Gõ lệnh lm để liệt kê danh sách các modules đã được nạp:

deferred” có nghĩa là module được nạp nhưng không có symbols, tuy nhiên điều ta cần là module đó đã được nạp vào bộ nhớ rồi. Tiếp theo, gõ lệnh .reload –f để thực hiện xóa toàn bộ thông tin các symbols của các modules và tiến hành nạp lại các symbols này:

Các symbols đã được nạp lại như trên hình. Ta tiến hành load mona:

Sau đó nhờ mona tìm các ROP trong mypepe.dll và chờ xem kết quả mà mona cung cấp. Gõ lệnh sau: !py mona rop -m Mypepe

Sẽ mất một thời gian dài để mona hoàn tất công việc, do đó trong thời gian chờ đợi hãy đi làm một cốc café :). Mặc dù, không phải lúc nào mona cũng tìm thấy một ROP hoàn chỉnh, đôi khi nó chỉ cung cấp cho ta một rop gần hoàn chỉnh và đưa thêm thông tin về những gì còn thiếu để từ đó ta tự tìm kiếm bằng cơm (manual). Vậy nên, hãy cứ để nó làm nhiệm vụ của mình …

Mona có tùy chọn –cp nhằm cung cấp khả năng lọc kết quả của ROP theo các tiêu chí khác nhau. Như hình dưới, các bạn thấy có lựa chọn nonnull để tìm kiếm các lệnh không chứa null bytes, ngoài ra nó cũng có khả năng lọc số với tùy chọn –cpb dành cho các kí tự cụ thể.

Khi mona hoàn tất công việc, nó sẽ xuất thông tin ra các file .txt:

Mở file rop_chains.txt, bạn sẽ tìm thấy thông tin sau:

Như trên hình, nó cung cấp thông tin về những giá trị cần có của các thanh ghi trước khi sử dụng PUSHAD RET như ta đã làm ở phần trước. Bên cạnh đó, nó cũng cung cấp thêm cho ta một lựa chọn khác để sử dụng VirtualAlloc. Ngoài ra, nó cũng gợi ý một rop chain khác cũng dùng PUSHAD nhưng sử dụng hàm API VirtualProtect:

Dựa vào các thông tin có được này, ta sẽ biết nếu ta thực hiện bằng cơm cho VirtualAlloc hoặc VirtualProtect thì những giá trị nào cần phải khởi tạo cho từng thanh ghi trước khi thực hiện PUSHAD-RET. Tiếp theo, ta xem nó sẽ làm gì với các ROP đã tìm được cho VirtualAlloc:

Các bạn thấy rằng mona đã tìm được rop và đưa ra một cách thực hiện dễ dàng hơn thay vì sử dụng một địa chỉ IAT của hàm khác bên dưới hàm VirtualAlloc như ta đã làm ở phần trước, thay vào đó theo cách này nó sẽ nhảy gián tiếp và tránh được việc chuyển địa chỉ VA giữa các thanh ghi.

Như trên hình, mona sinh mã ở ngôn ngữ Python, ta sẽ chép đoạn mã này vào trong script của chúng ta. Vì đoạn code Python này được mona định nghĩa là một hàm, vì vậy ta sẽ để nó ở đầu của script. Ngoài ra, mona cũng sinh ra lệnh theo các ngôn ngữ khác như Ruby/C/JavaScript.

Sau đó tạo rop chain bằng lệnh: rop_chain = create_rop_chain() và chỉnh lại script như sau:

Kiểm tra hoạt động của script vừa chỉnh lại ở trên. Tôi thấy script thực hiện xong nhưng lại không thực thi được ứng dụng calculator như mong muốn … Vậy là thất bại??

Chương trình bị crash và sinh ra file dump:

Như vậy là có điều gì bất thường đã xảy ra trong quá trình thực hiện script. Ta sẽ tiến hành trace code để theo dõi các rop và xem thực tế những gì đã xảy ra trong quá trình thực thi.

Load DEP.exe vào IDA và đặt bp sau khi thực hiện xong hàm gets_s(); Sau đó thực thi script và attach DEP.exe vào như đã làm ở các phần trước. Ta sẽ dừng lại tại đây:

Kiểm tra xem những giá trị gì cần được gán cho các thanh ghi.

Ở đây, script này sử dụng “alternative chain” và các bạn sẽ dễ dàng thấy sự khác biệt ở chỗ nó sử dụng một lệnh JMP [EAX] đặt tại ESI, trong khi ở script trước, ta thực hiện đặt địa chỉ VA của API trong ESI.

Để kiểm tra được chi tiết thì không có cách nào khác là phải trace code. Ta tới gadget đầu tiên:

Lệnh POP sẽ thực hiện gán lại chính địa chỉ 0x78019628 vào EBP và như vậy EBP sẽ lưu địa chỉ của POP EBP # RETN. Trace qua lệnh POP và kiểm tra kết quả của thanh ghi EBP:

Trace qua lệnh ret để tới gadget thứ hai:

Tương tự như script trước, gadget này gán giá trị 0x1 dwsize vào thanh ghi EBX. Tiếp tục trace code:

Gadget trên gán 0x1000 (MEM_COMMIT) vào EDX. Tiếp tục là gadget gán 0x40 (PAGE_EXECUTE_READWRITE) vào ECX:

Sau khi gán cho ECX giá trị 0x40, ta tới gadget thực hiện gán cho EDI địa chỉ của lệnh RET:

Trace tiếp tới gadget thực hiện gán lệnh địa chỉ lệnh JMP [EAX] cho ESI:

Chúng ta thấy rằng sau lệnh POP ESI, thanh ghi ESI sẽ trỏ đến JMP [EAX] đúng như theo kịch bản mong muốn:

Tiếp tục trace để tới gadget gán địa chỉ VA IAT vào EAX, kết quả sau khi thực hiện gadget này:

Kết quả hoàn toàn chính xác đúng như mong đợi, nhưng nếu chúng ta tiếp tục nó sẽ gây ra lỗi.

Lỗi chính xác nằm ở khúc gadget PUSHAD, tại đây có lệnh ADD AL, 80h – lệnh này sẽ cộng thêm giá chi 0x80 vào địa chỉ của IAT của VA, từ đó gây ra lỗi. Do đó, để bù trừ, chúng ta phải trừ 0x80 vào địa chỉ của IAT entry.

Kết quả khi lấy IAT VA trừ đi 0x80:

Python>hex(0x7802E0B0-0x80)

0x7802e030

Sau đó, sửa lại script:

OK, chạy lại script, nó sẽ hoạt động đúng như ta mong muốn:

Qua phần này, các bạn thấy rằng mona đã hỗ trợ chúng ta rất nhiều. Nó cung cấp cho ta hầu hết mọi thứ cần thiết, nhưng đôi khi, ta vẫn cần phải chỉnh sửa lại một chút cho phù hợp. Điều này chỉ để cho thấy rằng, không phải mọi thứ lúc nào cũng hoàn hảo, biết đủ thì sẽ là đủ.

Hẹn gặp lại các bạn ở phần 37!

Xin gửi lời cảm ơn chân thành tới thầy Ricardo Narvaja!

m4n0w4r

Ủng hộ tác giả

Nếu bạn cảm thấy những gì tôi chia sẻ trong bài viết là hữu ích, bạn có thể ủng hộ bằng “bỉm sữa” hoặc “quân huy” qua địa chỉ:

Tên tài khoản: TRAN TRUNG KIEN
Số tài khoản: 0021001560963
Ngân hàng: Vietcombank

Comments
  1. […] 0day in {REA_TEAM}Reversing With Ida From Scratch (P36) […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.