Pack và Unpack (phần 2)

Trong phần trước mình đã trình bày với các bạn bài viết tổng quan về Pack và Unpack. Trong phần này mình sẽ giới thiệu tiếp  về một số kĩ thuật để tìm OEP(Origin Entry Point) cơ bản. Đây là quá trình khó nhất trong khi unpack. Như đã giới thiệu trong phần trước thì các bước để unpack một file như sau:

  1. Tìm OEP
  2. Kết xuất file (Dump)
  3. Sửa lại IAT (Repair IAT)
  4. Kiểm tra file xem còn các cơ chế Anti hoặc ngăn chặn không cho thực thi không và tiến hành chỉnh sửa. Đảm bảo file sau unpack thực thi bình thường .

Bài viết sử dụng UnPackMe_ASPack2.12.exe và OllyDbg để minh họa.

1.1   Tìm opcode

Cách này đơn giản và hơi thô, chỉ có thể áp dụng với các trình packer đơn giản, không thể áp dụng nó cho các trình packer khó nhằn như Asprotect. Ý tưởng cơ bản là tìm opcode của lệnh  LONG JMP (0xE9) hoặc LONG CALL (0xE8). Các trình packer sau khi thực hiện đóng gói file thì có khả năng có một lệnh nhảy hoặc một lời gọi hàm (call) tới section đầu tiên, mục đích là để tới được OEP. Với phương pháp này, ta hi vọng các lệnh JUMP hoặc CALL sẽ xuất hiện ngay đầu tiên trong quá trình tìm kiếm hoặc trình packer không có cơ chế tự động chỉnh sửa. Ta chỉ cần tìm kiếm “Binary String” các chuỗi E9,E8. Sau đó xem câu lệnh nào có opcode. Ngoài ra câu lệnh đó phải nằm trong section đầu tiên của chương trình. Chú ý , đôi khi ta xem code của các trình packer sẽ thấy có các lệnh kiểu như CALL EAX, CALL EBX, JMP EAX. Rất nhiều trình packer thường sử dụng các thanh ghi nhằm mục đích để che dấu việc nhảy tới OEP.

1.2 Sử dụng tính năng tìm kiếm OEP của OllyDBG

Mở đối tượng bị đóng gói trong OllyDBG, chọn Options > Debugging options hoặc nhấn phím tắt Alt+O, chuyển tới tab SFX:

vd1

Trong thẻ SFX  có 2 tùy chọn: “blockwise” cho phép tìm kiếm nhanh nhưng độ chính xác có thể không cao; “bytewise” cho phép  tìm kiếm với độ chính xác cao hơn nhưng tốc độ chậm hơn. Chuyển qua thẻ Exceptions, lựa chọn tương tự như hình:

vd2

Sau khi cấu hình xong các bạn khởi động lại OllyDbg thì sẽ được như sau :

vd3

404000 chính là địa chỉ OEP của chương trình.Bạn có thể thử với tùy chọn khác trong SFX. Sau khi thực hiện xong phương pháp này thì phải thiết lập tab SFX trở về tùy chọn ban đầu, nếu không thì OllyDBG sẽ không dừng lại tại EP như bình thường nữa mà luôn luôn thực hiện việc tìm kiếm OEP.

1.3. Sử dụng BPM on access với OllyDBG đã patch để tìm OEP

Load file vào OllyDBG, chuyển tới cửa sổ Memory map, lựa chọn section đầu tiên để thiết lập BPM:

vd4

Chuyển về cửa sổ code, nhấn F9 để chạy, OllyDBG sẽ break và dừng lại tại đây:

vd5

Ta thấy khi trace qua lệnh ret thì chương trình không nằm trong phân vùng đầu tiên nên ta cứ nhấn F9.Khi đó có thông báo hiện ra:

vd6

Khi đó chương trình đã kết thúc.Vậy chỗ OEP không nằm trong section đầu tiên. Ta thử với các section tiếp theo. Với section thứ 2 tại địa chỉ 402000 cũng tương tự section thứ nhất. Ta thử tiếp với section thứ 3 tại địa chỉ 404000.Khi ta nhấn F9 thì chương trình sẽ dừng tại 404000 với câu lệnh WAIT. Vì đây không nằm ngoài section ta đặt break point nên nó là địa chỉ câu lệnh đầu tiên của OEP.

vd7

1.4. PUSHAD Method

Nhiều trình packer sau khi được load vào OllyDBG ta thấy lệnh đầu tiên được thực thi là lệnh PUSHAD. Lệnh này nhằm mục đích bảo toàn các thanh ghi, nó sẽ thực hiện lưu toàn bộ giá trị khởi tạo của tất cả các thành ghi vào stack, sau đó thực hiện quá trình unpack, cuối cùng trước khi nhảy tới OEP, packer sẽ thực hiện việc khôi phục lại giá trị của các thanh ghi đã lưu trên stack bằng lệnh POPAD. Cặp lệnh PUSHAD và POPAD thường đi cùng với nhau. Nếu như ta thấy ở đâu đó trong mã của chương trình xuất hiện lệnh PUSHAD thì bên dưới chắc chắn sẽ có câu lệnh POPAD. Đây là phương pháp được áp dụng thành công cho khá nhiều trình packer. Đầu tiên  load UnPackMe_ASPack2.12  vào OllyDBG và nhấn F9:

vd8

Thực hiện trace qua lệnh PUSHAD và quan sát trên cửa sổ Stack: Như các bạn thấy tại cửa sổ Stack, giá trị ban đầu của các thanh ghi đã được lưu lại.Do vậy, trước khi nhảy tới OEP thì chắc chắn packer phải thực hiện việc khôi phục lại các giá trị đã lưu này. Căn cứ vào đó, ta có thể tiến hành đặt một Hardware BPX On Access trong OllyDBG nhằm break lại khi packer thực hiện lệnh khôi phục giá trị, và khi break ta sẽ dừng lại tại lệnh nhảy tới OEP. Lựa chọn thanh ghi ESP, nhấn chuột phải và chọn Follow in Dump:

vd9

vd10

Sau đó ta đặt breakpoint hardware vào 0018FF6C. Sau khi đặt BP xong, nhấn F9 để chạy, ta sẽ dừng lại tại đây:

vd11

Dưới lệnh POPAD sẽ là câu lệnh nhảy đến 004113BA. Nhưng nếu nhìn kĩ hơn một chút ta sẽ thấy có lệnh push 00404000 và ret. Như vậy đó chính là địa chỉ của OEP. Trên đây mình đã trình bày 4 cách để unpack một file .exe cơ bản. Các bạn có thể tự tìm thêm các ví dụ để thực hành thêm và tham khảo tài liệu có sẵn trên mạng.

Tài liệu tham khảo