03/11/2018, 11:55

Tìm hiểu về Pack và Unpack

Việc Pack các file thực thi (Executable) được thực hiện nhằm mục đích ngăn chặn phân tích hay tạo ra một tập tin nhẹ hơn giúp công việc tải về được dễ dàng hơn. Nếu file thực thi được Pack, việc kiểm tra các chương trình gốc sẽ gặp khó khăn và ngăn chặn việc phân tích tĩnh các hoạt ...

Việc Pack các file thực thi (Executable) được thực hiện nhằm mục đích ngăn chặn phân tích hay tạo ra một tập tin nhẹ hơn giúp công việc tải về được dễ dàng hơn. Nếu file thực thi được Pack, việc kiểm tra các chương trình gốc sẽ gặp khó khăn và ngăn chặn việc phân tích tĩnh các hoạt động của file này.

Cụ thể khi sử dụng, Packer nén, mã hóa, lưu hoặc dấu code gốc của chương trình, tự động bổ sung một hoặc nhiều section, sau đó sẽ thêm đoạn code Unpacking Stub và chuyển hướng Entry Point (EP) tới vùng code này. Bình thường một file không đóng gói (Nonpacked) sẽ được tải bởi OS. Với file đã đóng gói thì Unpacking Stub sẽ được tải bởi OS, sau đó chương trình gốc sẽ tải Unpacking Stub. Lúc này code EP của file thực thi sẽ trỏ tới Unpacking Stub thay vì trỏ vào mã gốc. Để hiểu được các phần trên thì các bạn cần hiểu cấu trúc PE file và cách thực thi của nó. Bạn có thể xem bài viết Tìm hiểu cấu trúc PE file.

Cấu trúc đầy đủ của một PE file như sau:

Trong môi trường DOS, chương trình sẽ kiểm tra DOS header và nếu hợp lệ sẽ thực thi DOS Stub. Còn bình thường file của chúng ta hay chạy trên Windows thì 2 trường này có thể bỏ qua. Trường này là một cấu trúc có 19 thành phần.

Cuối trường DOS header sẽ có một thành phần là: e_lfanew sẽ chứa offset của PE header so với vị trí đầu file. Chương trình sẽ thực thi đến PE header. Tiếp đến là đọc Section Table để xem trong chương trình có những section nào. Sau đó chương trình sẽ nhảy đến từng section và thực thi. Entry Point thường nằm ở các section đầu nếu file chưa bị đóng gói.

Tìm hiểu các kỹ thuật phân tích tĩnh cơ bản mà bất kỳ người lập trình nào cũng cần phải biết

Nguyên lí hoạt động của Packer
Cấu trúc của file PE ban đầu sẽ có dạng như sau:

File này sẽ bị nén và mã hóa rồi được thêm vào một hay nhiều section do packer tự tạo ra.

Khi chạy file thì chương trình sẽ được thực thi như sau:

Tiếp theo chương trình sẽ thực thi PE header:

Sau khi nhảy đến Entry Point của section UMPACKER thì toàn bộ giá trị của các thanh ghi sẽ được lưu lại nhờ lệnh PUSHAD. Sau đó Import Table sẽ được tính toán lại. Trong một file bị pack, Import Table sẽ bị thay đổi và các dữ liệu sẽ bị mã hóa.

Tiếp theo chương trình sẽ khôi phục lại giá trị các thanh ghi đã được lưu trong Stack bằng lệnh POPAD. Cuối cùng chương trình sẽ nhảy đến Origin EntryPoint và thực thi như file lúc chưa bị đóng gói.

Nguyên lí Unpack

Đầu tiên ta phải nhận biết được xem một file có bị đóng gói hay không bằng cách dùng các công cụ như PEiD :

Ở đây mình dùng file UnPackMe_ASPack2.12 làm đối tượng để test thử. File trên đã bị đóng gói bằng ASPack. Thông thường, các bước cơ bản để thực hiện unpack như sau:

  1. Tìm OEP (Origin Entry Point): Orginal entry point là nơi mà chương trình gốc thực sự bắt đầu thực thi. Ta sẽ dùng một số công cụ debug file như OllyDbg và IDA để tìm lại OEP.
  1. Kết xuất file (Dump): Sau khi nhảy đến OEP ta sẽ tiến hành dump file. Mục đích của việc này là fix lại các section và import table như file ban đầu trước khi bị đóng gói. Sử dụng Plugin OllyDumpEx để dump file.

  1. Sửa lại IAT (Repair Import Address Table): Sử dụng công cụ ImportREC.

  1. Kiểm tra file xem còn các cơ chế Anti hoặc ngăn chặn việc thực thi hay không rồi tiến hành chỉnh sửa. Đảm bảo file sau unpack thực thi bình thường (Phần này sẽ được giới thiệu trong các phần sau).

ĐÓN ĐỌC: Phân tích, phát hiện và gỡ bỏ mã độc Practical Malware Analysis Lab01-02

0