1. Trang chủ
  2. » Luận Văn - Báo Cáo

Kết hợp phân tích tĩnh và kiểm tra động trong việc xây dựng đồ thị luồng điều khiển phục vụ phân tích mã nhị phân (luận văn, luận án (theses))

169 8 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 169
Dung lượng 3,3 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Cấu trúc

  • CHƯƠNG 1 GIỚI THIỆU

  • CHƯƠNG 2. KIẾN THỨC NỀN TẢNG

    • 2.1 Đồ thị luồng điều khiển

    • 2.2 Kỹ thuật thực thi ký hiệu

    • 2.3 Kỹ thuật kiểm tra thực thi ký hiệu động

    • 2.4 Chương trình đóng gói

    • 2.5 Mô hình Markov ẩn

    • 2.6 Kiểm tra Chi bình phương

  • CHƯƠNG 3. KHUNG THỨC TỔNG QUÁT XÂY DỰNG ĐỒ THỊLUỒNG ĐIỀU KHIỂN

    • 3.1 Giới thiệu

    • 3.2 Các nghiên cứu liên quan

    • 3.3 Ví dụ minh họa

    • 3.4 Kết luận

  • CHƯƠNG 4. ÁP DỤNG KỸ THUẬT SONG SONG HÓA KẾT HỢP VỚIBẢNG BĂM VÀ GIẢI THUẬT DI TRUYỀN ĐỂ GIẢM THỜI GIAN THỰCTHI CỦA CHƯƠNG TRÌNH

    • 4.1 Giới thiệu

    • 4.2 Những nghiên cứu liên quan

    • 4.3 Ví dụ động cơ

    • 4.4 Nén sử dụng bảng băm

    • 4.5 Mô tả giải thuật xử lý đa luồng

    • 4.6 Thí nghiệm

    • 4.7 Kết luận

  • CHƯƠNG 5. NHẬN DIỆN CHƯƠNG TRÌNH ĐÓNG GÓI SỬ DỤNGKỸ THUẬT CHI BÌNH PHƯƠNG

    • 5.1 Giới thiệu

    • 5.2 Các nghiên cứu liên quan

    • 5.3 Phương pháp thực hiện

    • 5.4 Thí nghiệm

    • 5.5 Kết luận

  • CHƯƠNG 6. NHẬN DIỆN CHƯƠNG TRÌNH ĐÓNG GÓI SỬ DỤNGMÔ HÌNH MARKOV ẨN

    • 6.1 Giới thiệu

    • 6.2 Phương pháp thực hiện

    • 6.3 Thí nghiệm

    • 6.4 Kết luận

  • CHƯƠNG 7. NHẬN DIỆN MÃ ĐỘC SỬ DỤNG PHƯƠNG PHÁPHỌC SÂU

    • 7.1 Giới thiệu

    • 7.2 Những nghiên cứu liên quan

    • 7.3 Phương pháp thực hiện

    • 7.4 Thí nghiệm

    • 7.5 Kết luận

  • CHƯƠNG 8. CÔNG CỤ XÂY DỰNG ĐỒ THỊ LUỒNG ĐIỀU KHIỂNBE-PUM

    • 8.1 Giới thiệu BE-PUM

    • 8.2 Kiến trúc của BE-PUM

    • 8.3 So sánh BE-PUM với các công cụ hiện có

    • 8.4 Thí nghiệm

    • 8.5 Kết luận

  • CHƯƠNG 9. KẾT LUẬN

    • 9.1 Kết luận

    • 9.2 Hướng nghiên cứu trong tương lai

  • TÀI LIỆU THAM KHẢO

Nội dung

HỒ CHÍ MINH TRƯỜNG ĐẠI HỌC BÁCH KHOA NGUYỄN MINH HẢI KẾT HỢP PHÂN TÍCH TĨNH VÀ KIỂM TRA ĐỘNG TRONG VIỆC XÂY DỰNG ĐỒ THỊ LUỒNG ĐIỀU KHIỂN PHỤC VỤ PHÂN TÍCH MÃ NHỊ PHÂN LUẬN ÁN TIẾN SĨ

GIỚI THIỆU

Giới thiệu

Hiện nay, với sự phát triển của phần mềm, cả về số lượng, chất lượng và độ phức tạp, vấn đề phân tích và kiểm tra tính đúng đắn của chương trình nổi lên như một nhu cầu cấp thiết Những thiệt hại gây ra do lỗi chương trình là rất to lớn, không chỉ về mặt kinh tế mà còn tác động rất sâu rộng trên nhiều lĩnh vực Năm 1996, lỗi phần mềm trong tên lửa European Ariane 5 đã làm hệ thống rơi khoảng 40 giây sau khi cất cánh và gây ra thiệt hại ước tính khoảng nửa tỷ đô la [1] Năm 2016, theo một thống kê của Tricentis [2], khoảng 1.1 nghìn tỷ đã được tiêu tốn để khắc phục những thiệt hại do lỗi chương trình Những lỗi này được tìm thấy trong hơn 363 công ty, ảnh hưởng đến hơn

4 tỷ khách hàng và làm mất tổng thời gian hơn 315 năm để khắc phục

Trong phân tích chương trình, kiểm tra (testing) là một khâu quan trọng và không thể thiếu Kiểm thử là một qui trình bao gồm các bước từ xét duyệt và kiểm tra một cách thủ công [3] cho đến sinh ra những trường hợp kiểm tra (test case) phù hợp dựa trên việc phân tích sự bao phủ [4] Tuy nhiên, phương pháp này tồn tại lỗ hổng, do không thể sinh đầy đủ các trường hợp kiểm tra cần thiết để đảm bảo chương trình không có lỗi Mặt khác, phương pháp kiểm thử đòi hỏi thực thi đoạn mã (code) cần kiểm tra trong môi trường thực Điều này trong thực tế khá khó khăn Một giải pháp được đề xuất là xây dựng môi trường giả lập, thông qua các công cụ ảo hóa Tuy nhiên, các công cụ này rất tốn kém và không phản ánh chính xác môi trường thực tế Chính từ những vấn đề này của kiểm thử đã nảy sinh phương pháp kiểm chứng phần mềm (software verification), trong đó tính đúng của phần mềm sẽ được kiểm chứng dựa trên luận lí học (logic) Hướng tiếp cận này chủ yếu dựa vào các phương pháp hình thức (formal method) Ý tưởng chính của phương pháp hình thức là biểu diễn phần mềm và hệ thống thành các đối tượng toán học, từ đó suy luận và xác định các hành vi của chúng Trong lĩnh vực áp dụng phương pháp hình thức để kiểm chứng

2 phần mềm, có hai hướng tiếp cận chủ yếu: chứng minh lí thuyết (theorem proving) và kiểm tra mô hình (model checking) [5]

Các phương pháp hình thức có thể được sử dụng để kiểm tra phần mềm ở nhiều mức độ khác nhau, từ các đặc tả (specification), thiết kế (design), mã nguồn (source code) cho đến mã nhị phân (binary code) [6] Hiện nay, hướng nghiên cứu sử dụng phương pháp hình thức cho mã nhị phân ngày càng được sử dụng rộng rãi trong giới học thuật lẫn cộng đồng doanh nghiệp do một số nguyên nhân sau

1.1.1 Những lợi ích của việc phân tích mã nhị phân

Thứ nhất, hầu hết các mã nguồn hiện nay thường đóng nên việc kiểm tra là khó khả thi, đặc biệt là đối với các mã độc Trên thực tế, phân tích mã độc là một ví dụ điển hình và rõ ràng của vấn đề phân tích mã nhị phân không có mã nguồn Thứ hai, mã nhị phân phụ thuộc vào quá trình biên dịch của chương trình Mà quá trình biên dịch có khả năng làm thay đổi hành vi của chương trình do quá trình tối ưu hóa mã [7] Chính vì nguyên nhân này, việc kiểm tra trên mã nhị phân sẽ cho ra các kết quả đáng tin cậy vì máy tính sẽ thực thi mã nhị phân thay vì mã nguồn như là kết quả duy nhất và cuối cùng Thứ ba, khi chương trình được phát triển từ nhiều ngôn ngữ khác nhau và được tích hợp nhiều module khác nhau, vấn đề phân tích mã nguồn sẽ trở nên hết sức khó khăn do vấn đề thiếu hụt đặc tả chi tiết các module

1.1.2 Những thách thức trong phân tích mã nhị phân

Tuy nhiên, trong phương pháp phân tích mã nhị phân, cũng nổi lên rất nhiều những thách thức:

 Thách thức đầu tiên là độ phức tạp của mã nhị phân Những kiến trúc CISC như x86 có rất nhiều các câu lệnh khác nhau để phục vụ các tác vụ hệ thống Chẳng hạn, trong kiến trúc x86, có hàng trăm câu lệnh và hàng ngàn khả năng kết hợp giữa các toán hạng [8] Ví dụ như, hơn 300 câu lệnh SIMD được sử dụng trong nền tảng x86 như MMX, SSE, SSE2, SSE3, SSSE3, và SSE4 [9] để hỗ trợ những tác vụ tính toán vector đồng thời trên nhiều bytes hoặc từ (word) Mặt khác, mỗi câu

3 lệnh lại có ngữ nghĩa phức tạp Một chương trình phân tích mã nhị phân phải nhận biết và biểu diễn một cách chính xác các câu lệnh này Đây là một vấn đề khó khăn

 Thách thức thứ hai đến từ vấn đề thiếu hụt các cấu trúc ngữ nghĩa bậc cao (high level semantic structure) trong mã nhị phân Mã nhị phân không chứa các hàm và các kiểu dữ liệu Trong mã nhị phân, biến toàn cục, biến cục bộ, kiểu mảng, và bảng ghi đều được biểu diễn thành một dãy liên tục các giá trị trong bộ nhớ Các biến có thể được lưu trữ trong các thanh ghi Kiểu dữ liệu khác nhau được biểu diễn bởi số lượng byte khác nhau Do đó, khi một giá trị mới được gán vào thanh ghi hay ô nhớ, giá trị của nó có thể ghi đè một phần hay toàn bộ những byte thuộc về các biến khác

 Thứ ba, chương trình phân tích mã nhị phân phải giải quyết các vấn đề về sự nhập nhằng giữa mã chương trình và dữ liệu (code and data ambituity) Có nhiều định dạng khác nhau để lưu trữ chương trình nhị phân trên máy tính, cho phép các mã nhị phân này có thể được nạp và thực thi dễ dàng bởi hệ điều hành Đối với hệ thống x86, định dạng thông dụng nhất là PE [10] được sử dụng trong Windows và ELF [11] được sử dụng trong Linux Cả hai định dạng này cho phép nhóm chương trình thực thi thành các phân vùng (section), nhằm lưu trữ mã thực thi hay dữ liệu Các phân vùng này có thể được thiết lập quyền đọc, ghi hay thực thi Tuy nhiên, sự phân chia giữa vùng dành cho mã thực thi và dữ liệu là không chặt chẽ Do đó, phân vùng chứa mã thực thi có thể chứa dữ liệu ví dụ như các chuỗi, hằng số Chỉ trong quá trình thực thi của chương trình, vi xử lý (processor) mới xác định chính xác những byte dành cho câu lệnh và những bye dành cho dữ liệu Vị trí điểm thực thi ban đầu của chương trình được gọi là điểm vào (entry point) và được đặc tả trong tiêu đề (header) của chương trình

 Thứ tư là vấn đề câu lệnh nhảy không trực tiếp (indirect jump) Một trong những vấn đề lớn khi phân tích mã nhị phân trong x86 là vấn đề xử lý các câu lệnh nhảy không trực tiếp Các lệnh này tương ứng với những lệnh Goto mà địa chỉ nhảy đến

4 chỉ được tính toán tại thời điểm chạy của chương trình như câu lệnh JMP EAX Địa chỉ nhảy của câu lệnh được lưu trong thanh ghi EAX và chỉ được xác định trong thời điểm thực thi của chương trình Trong phân tích mã nhị phân, mọi địa chỉ trong mã lệnh đều là những địa chỉ tiềm năng của của câu lệnh nhảy không trực tiếp Do đó, việc xử lý địa chỉ nhảy của những câu lệnh này không thành công trong có thể dẫn đến (i) phân tích chương trình không chính xác; (ii) vấn đề xấp xỉ quá mức (over-approximation) khi các câu lệnh nhảy không trực tiếp sẽ nhảy đến mọi địa chỉ có thể của chương trình Trong trường hợp này, độ phức tạp của chương trình phân tích sẽ bùng nổ

 Thứ năm là vấn đề các câu lệnh trùng lắp (overlapping instructions) Trong môi trường x86, các câu lệnh có độ dài thay đổi Mỗi câu lệnh chứa mã thực thi

(opcode), định nghĩa nội dung câu lệnh, kiểu dữ liệu của câu lệnh và danh sách các toán hạng Các toán hạng có thể là thanh ghi, các giá trị trung gian hay vị trí bộ nhớ Bản chất độ dài thay đổi của các lệnh x86 dẫn đến vấn đề các câu lệnh trùng nhau Cùng một chuỗi byte có thể được diễn dịch thành những câu lệnh khác nhau bởi bộ vi xử lý của chương trình Xem xét ví dụ trong Hình 1-1, chương trình bắt đầu tại địa chỉ 0000 và được dịch ngược (disassemble) thành câu lệnh mov eax, 0xBBC10300 Tại địa chỉ 000C, câu lệnh được giải mã thành jmp $-10 Câu lệnh jmp $-10 chiếm 2 bytes Do đó, câu lệnh kế tiếp sẽ được bắt đầu tại địa chỉ 000E và được giải mã thành add eax, ebx Tuy nhiên, câu lệnh jmp $-10 sẽ chuyển luồng thực thi của chương trình đến vị trí 0002 Do đó, câu lệnh kế tiếp sẽ bắt đầu tại địa chỉ 0002 và được biểu diễn thành add eax, ecx Câu lệnh mới này lồng với câu lệnh gốc ban đầu tại địa chỉ 0000 như mô tả trong Hình 1-2

Những khó khăn trên đã dẫn đến vấn đề bùng nổ độ phức tạp trong phân tích mã nhị phân của các chương trình lớn Vì thế có rất ít các công cụ phân tích mã nhị phân có khả năng phân tích các chương trình thực tế với độ phức tạp cao Đây là một nhu cầu bức thiết đặt ra trong thời điểm hiện tại và là nguyên nhân thúc đẩy của đề tài này

1.1.3 Bài toán xây dựng đồ thị luồng điều khiển

Trong ngành công nghiệp phần mềm, xu hướng kiểm tra phần mềm dựa trên mã nhị phân đang phát triển một cách mạnh mẽ Hình 1-3 mô tả bốn bước chính trong quá trình phân tích mã nhị phân Trong bước đầu tiên, chương trình tiến hành dịch ngược mã nhị phân Bước thứ hai là quá trình xây dựng biểu diễn trung gian (intermediate

Hình 1-1 Ví dụ về vấn đề các câu lệnh trùng lắp trong phân tích mã nhị phân

Hình 1-2 Luồng thực thi đúng của chương trình

0009: 05 03 C1 EB F4 add eax, 0xF4EBC103

6 representation) dựa trên kết quả bước 1 Trong bước 3, đồ thị luồng điều khiển (control flow graph) được xây dựng dựa trên kết quả của bước 2 Trong đó, các đỉnh đại diện cho các lệnh và các cạnh đại diện cho bước nhảy trong luồng điều khiển Dựa trên đồ thị luồng điều khiển được xây dựng, các chương trình phân tích sẽ kiểm tra tính độc hại của chương trình hoặc các tính năng chuyên sâu khác trong bước 4 Trong Hình 1-

Phát biểu vấn đề

Như đã phân tích trong phần trên, luận án này nêu lên bài toán cần phải giải quyết là phát triển một phương pháp kết hợp giữa phân tích tĩnh và kiểm tra động trong phân tích mã nhị phân, mà cụ thể là bài toán xây dựng đồ thị luồng điều khiển.

Câu hỏi nghiên cứu

Luận án vận dụng sự kết hợp giữa phương pháp phân tích tĩnh và kiểm tra động để giải quyết bài toán xây dựng đồ thị luồng điều khiển trong phân tích mã nhị phân Để thực hiện nghiên cứu này, luận án cần phải xem xét giải quyết và trả lời các câu hỏi sau:

[RQ1] Đã có một khung thức hay một công cụ tổng quát cho việc kết hợp giữa phương pháp phân tích tĩnh và kiểm tra động để xây dựng đồ thị luồng điều khiển trong mã nhị phân hay chưa? Khung thức phải giải quyết các thách thức trong phân tích mã nhị phân và đặc biệt là vấn đề lệnh nhảy động Đặc biệt, công cụ này có thể được sử dụng bởi người dùng thông thường, không có kiến thức về phân tích mã nhị phân

[RQ2] Làm sao để rút ngắn thời gian thực thi của chương trình trong bài toán xây dựng đồ thị luồng điều khiển?

[RQ3] Làm sao để khai thác tri thức dựa trên đồ thị luồng điều khiển của chương trình được sinh ra từ mã nhị phân?

Mục tiêu nghiên cứu

Mục tiêu của luận án là giải quyết và trả lời ba câu hỏi nghiên cứu mà luận án đã đề ra Trong đó, các mục tiêu cụ thể là:

[OB1] Đưa ra một khung thức tổng quát cho việc kết hợp hai kỹ thuật phân tích tĩnh và kiểm tra động nhằm xây dựng đồ thị luồng điều khiển trong phân tích mã nhị phân Khung thức này giải quyết các thách thức trong phân tích mã nhị phân và đặc biệt là vấn đề lệnh nhảy động Ngoài ra, khung thức còn cung cấp

9 giao diện để người dùng sử dụng chương trình của mình một cách trực quan Mục tiêu nghiên cứu này giải quyết câu hỏi nghiên cứu [RQ1] của luận án [OB2] Nghiên cứu này đưa ra một phương pháp tăng tốc thời gian thực thi của chương trình phân tích với cơ chế đa luồng (multithreading) và loại bỏ những đường đi dư thừa (redundant path) đã được xử lý trong chương trình Phương pháp này vừa không nặng về mặt toán học và phải đảm bảo tính đúng đắn của kết quả phân tích Mục tiêu này giải quyết câu hỏi nghiên cứu thứ hai [RQ2] của luận án

[OB3] Mục tiêu cuối cùng của nghiên cứu là khám phá tri thức dựa trên đồ thị luồng điều khiển của chương trình được sinh ra từ mã nhị phân Nghiên cứu này tập trung vào chủ đề phân tích mã nhị phân của mã độc Luận án thực hiện đồng thời hai việc, (i) nhận diện chương trình đóng gói (packer) được sử dụng trong mã độc bằng cách áp dụng kỹ thuật kiểm tra Chi bình phương (Chi square test) và mô hình Markov ẩn (Hidden Markov Model); (ii) nhận diện mã độc sử dụng phương pháp học sâu (deep learning) Câu hỏi nghiên cứu thứ ba [RQ3] được giải quyết bởi mục tiêu này.

Những đóng góp chính của nghiên cứu

Theo kết quả nghiên cứu, luận án đã xây dựng thành công một phương pháp kết hợp giữa kỹ thuật phân tích tĩnh và kiểm tra động trong bài toán xây dựng đồ thị luồng điều khiển từ mã nhị phân Việc kết hợp này giải quyết được các thách thức trong phân tích mã nhị phân và đặc biệt là vấn đề lệnh nhảy động Ý tưởng chính của phương pháp này là xây dựng đồ thị luồng điều khiển nội bộ thủ tục (intra-procedural CFG) cho đến khi gặp lệnh nhảy gián tiếp hoặc các lời gọi hàm giao diện lập trình ứng dụng (Application Programming Interface) xảy ra Khi đó, kỹ thuật kiểm tra động được áp dụng bằng cách mô phỏng quá trình thực thi với các dữ liệu kiểm tra để xác định điểm đến chính xác của câu lệnh nhảy Chúng tôi áp dụng kỹ thuật thực thi ký hiệu

(symbolic execution) để tạo ra dữ liệu kiểm tra phù hợp Các đóng góp chính của luận án được tóm tắt như sau: i Luận án đề xuất một khung thức tổng quát cho bài toán xây dựng đồ thị luồng điều khiển từ mã nhị phân của chương trình Khung thức này giải quyết các thách thức trong phân tích mã nhị phân và đặc biệt là vấn đề lệnh nhảy động Các công bố liên quan đến đóng góp này là [CT5] và [CT6] Đóng góp này đã đáp ứng cho mục tiêu [OB1] của luận án ii Luận án đưa ra giải pháp để tăng tốc quá trình thực thi của chương trình Đó là áp dụng giải thuật song song hóa với tính toán đa luồng để tăng tốc độ xử lý các nút Giải thuật đề xuất có yêu cầu rất nhỏ về vấn đề đồng bộ và giao tiếp giữa các luồng xử lý Ngoài ra, giải thuật kết hợp xử lý song song với kỹ thuật băm để giảm lượng bộ nhớ sử dụng cho việc lưu trữ thông tin về các nút đã được xử lý Hơn thế nữa, giải thuật sử dụng phương pháp phát hiện trùng lặp kết hợp với giải thuật di truyền để ngăn chặn sự phân tích dư thừa giữa các luồng xử lý Với phương pháp này, thời gian xử lý cũng như tài nguyên hệ thống được giảm đi đáng kể Công bố có liên quan đến đóng góp này là [CT3] và [CT9] Những đóng góp này đã thỏa mãn mục tiêu thứ hai [OB2] của luận án iii Luận án đề xuất cách khai thác tri thức dựa trên đồ thị luồng điều khiển của mã nhị phân Luận án tập trung vào vấn đề nhận diện chương trình đóng gói trên mã độc với hai hướng tiếp cận: (i) sử dụng kiểm tra Chi bình phương; (ii) sử dụng mô hình Markov ẩn Các công bố có liên quan đến đóng góp này là [CT1], [CT4], [CT7], [CT8], [CT10], [CT12] và [CT13] Những đóng góp trong việc nhận diện chương trình đóng gói đã góp phần thỏa mãn mục tiêu thứ ba [OB3] của luận án iv Luận án này đã đề xuất cách nhận diện mã độc dựa trên phương pháp học sâu Đồ thị luồng điều khiển của chương trình được chuyển đổi thành hình ảnh tương ứng và được học trong mô hình học sâu để tiến hành huấn luyện Việc sử dụng phương pháp học sâu giúp hệ thống có thể học và phân loại hiệu quả trên không gian trạng thái phức tạp được sinh ra bởi đồ thị luồng điều khiển của các mã độc Các công

11 bố có liên quan đến đóng góp này là [CT2] và [CT11] Đóng góp này đã góp phần hiện thực cho mục tiêu thứ ba [OB3] là khai thác tri thức dựa trên đồ thị luồng điều khiển sinh ra v Cuối cùng, luận án cũng đã xây dựng một công cụ hoàn chỉnh có tên là BE-PUM cho việc xây dựng đồ thị luồng điều khiển từ mã nhị phân Đây là đóng góp mang tính thực tế của luận án BE-PUM là sản phẩm cuối cùng, giải quyết được đồng thời ba câu hỏi nghiên cứu đã đề cập ở trên Công bố liên quan đến công cụ BE-PUM là [CT6] và [CT14].

Tầm quan trọng của nghiên cứu

Nghiên cứu trong luận án này có tầm quan trọng rất cao trong lĩnh vực an toàn thông tin nói chung và trong lĩnh vực phân tích mã độc nói riêng Phân tích chương trình, đặc biệt ở dạng mã nhị phân là bài toán quan trọng trong lĩnh vực an toàn thông tin, xuất phát từ nhu cầu thực tế để phân tích các ứng dụng chứa mã độc Vì vậy, việc xây dựng đồ thị luồng điều khiển để phục vụ phân tích mã nhị phân là bài toán có ý nghĩa khoa học và thực tiễn cao Tính độc đáo trong đề tài này là sự kết hợp giữa những kỹ thuật phân tích tĩnh và kiểm tra động Luận án này còn đóng góp vào cộng đồng nghiên cứu một khung thức tổng quát cho việc xây dựng đồ thị luồng điều khiển từ mã nhị phân.

Giới hạn của nghiên cứu

Các chương trình nhị phân có thể chạy trên nhiều kiến trúc khác nhau như nền tảng 32 bit, 64 bit, hệ điều hành Linux, Windows Về phương diện học thuật, luận án đã nghiên cứu, phát triển các phương pháp cũng như xây dựng khung thức một cách tổng quát để có thể áp dụng với tất cả các loại kiến trúc này Tuy nhiên, về mặt kỹ thuật và triển khai thực nghiệm, luận án tập trung vào việc áp dụng kết quả nghiên cứu lên các chương trình nhị phân 32 bit Windows Nguyên nhân là vì đa phần các mã độc luận án thu thập để phục vụ mục tiêu nghiên cứu được chạy trên nền tảng này

Bố cục của luận án

Trong Chương 1 này, chúng tôi đã trình bày về bối cảnh nghiên cứu cũng như đặt vấn đề nghiên cứu Câu hỏi nghiên cứu, mục tiêu nghiên cứu của luận án cũng đã được trình bày Chúng tôi cũng đã liệt kê những đóng góp chính, cũng như tầm quan trọng và giới hạn của luận án Cấu trúc tổng quan các phần của luận án được trình bày trong Hình 1-5

Chương 2 trình bày tổng quan về các kiến thức nền tảng, định hướng cho nghiên cứu của luận án Trong chương này, lý thuyết về các đồ thị luồng điều khiển, kỹ thuật thực thi ký hiệu và kỹ thuật kiểm tra thực thi ký hiệu động (concolic testing) được giới thiệu Kiến thức về chương trình đóng gói, đặc biệt là các kỹ thuật làm rối

(obfuscation) trong chương trình đóng gói cũng được trình bày chi tiết Ngoài ra, lý thuyết về kiểm tra Chi bình phương và mô hình Markov ẩn cũng được trình bày chi tiết trong chương này

Chương 3 trình bày về khung thức tổng quát cho bài toán xây dựng đồ thị luồng điều khiển từ mã nhị phân một cách tự động Kiến trúc tổng quát của khung thức sẽ được giới thiệu với các khối chức năng của nó Với khung thức này, chúng tôi có thể mở rộng để áp dụng quá trình xây dựng đồ thị luồng điều khiển của mã nhị phân trên nhiều nền tảng khác nhau

Chương 4 trình bày về đóng góp thứ hai của luận án, đó là phương pháp tăng tốc quá trình thực thi của chương trình với giải thuật tính toán đa luồng kết hợp với bảng băm Trong chương này, chúng tôi trình bày chi tiết về cách hiện thực của giải thuật với ví dụ minh họa Chúng tôi cũng tiến hành thí nghiệm trên tập mã độc thực để kiểm tra hiệu năng của giải thuật

Chương 5 trình bày về các phương pháp nhận diện chương trình đóng gói sử dụng kiểm tra Chi bình phương Trong quá trình xây dựng đồ thị luồng điều khiển, những kỹ thuật làm rối mã (obfuscation technique) được phát hiện dựa trên các tiêu chuẩn của từng kỹ thuật khác nhau Tiếp theo, chương trình đóng gói được nhận diện

13 dựa trên sự tương đồng sử dụng phương pháp kiểm tra Chi bình phương trên tập kỹ thuật làm rối mã Độ chính xác của giải thuật được tính toán với 12814 mã độc thực tế

Hình 1-5 Cấu trúc luận án Trong đó hơn 608 mẫu được phát hiện với kết quả nhận diện tốt hơn so với PeiD, CFF Explore, và VirusTotal

Chương 6 trình bày giải thuật áp dụng mô hình Markov ẩn vào việc phát hiện và phân loại chương trình đóng gói nhằm giải quyết những vấn đề trong kiểm tra Chi bình phương Trong chương này, chúng tôi trình bày chi tiết giải thuật xây dựng mô hình Markov ẩn Bên cạnh đó để đánh giá hiệu quả của phương pháp đề xuất, chúng tôi tiến

14 hành thí nghiệm trên tập 2126 mã độc thực và so sánh với các công cụ phát hiện chương trình nén phổ biến là PEiD, CFF Explorer, và VirusTotal

Trong chương 7, chúng tôi đưa ra một phương pháp nhận diện mã độc sử dụng phương pháp học sâu Để làm được điều này, chúng tôi đã đưa ra công thức chuyển đổi từ đồ thị luồng điều khiển của chương trình thành hình ảnh và tiến hành học trong phương pháp học sâu Kết quả thực nghiệm được trình bày ở cuối chương cho thấy tính hiệu quả thực tế của nghiên cứu

Chương 8 trình bày về công cụ BE-PUM Đây là công cụ hiện thực hóa tất cả các lý thuyết đã được trình bày trong luận án Trong chương này, mô hình đẩy xuống

(pushdown model) kết hợp với kỹ thuật kiểm tra thực thi ký hiệu động được giới thiệu để giải quyết vấn đề lệnh nhảy động Quá trình hiện thực các luật thực thi ngữ nghĩa trong thực thi động cũng được mô tả trong chương này Kết quả thực nghiệm so sánh công cụ BE-PUM với những công cụ phổ biến như IDA Pro và Jakstab chứng minh sự đúng đắn của các lý thuyết đã xây dựng trong luận án

Các kết luận của luận án và các định hướng nghiên cứu tiếp theo trong tương lai được chúng tôi trình bày trong Chương 9

KIẾN THỨC NỀN TẢNG

Đồ thị luồng điều khiển

Đồ thị luồng điều khiển (Control Flow Graph - CFG) [22] là một đồ thị có hướng và dùng để biểu diễn chương trình Trong đó, đỉnh của đồ thị bao gồm địa chỉ của câu lệnh và câu lệnh hợp ngữ tại địa chỉ đó Cạnh của đồ thị là thể hiện luồng thực thi của chương trình Hình 2-2 mô tả ví dụ về đồ thị luồng điều khiển tương ứng với đoạn mã trong Hình 2-1

Hình 2-1 Ví dụ minh họa đồ thị luồng điều khiển

Hình 2-2 Đồ thị luồng điều khiển tương ứng với Hình 2.1

Kỹ thuật thực thi ký hiệu

Kỹ thuật thực thi ký hiệu (symbolic execution) [23] là một cách tiếp cận thực tế để chứng minh tính đúng đắn của chương trình Khác với quá trình thực thi thông thường, chương trình được thực thi với đầu vào (input) là các ký hiệu (symbol) Ví dụ sau đây mô tả chương trình minh họa kỹ thuật thực thi ký hiệu

Với quá trình thực thi thông thường, khi chương trình được gọi, các biến A, B và

C được cung cấp với giá trị cụ thể Các giá trị này sẽ quyết định con đường mà chương trình sẽ đi qua trong thời gian thực thi Ngược lại, trong kỹ thuật thực thi ký hiệu, chương trình có thể đi qua bất kỳ con đường nào khả thi Tuy nhiên mỗi con đường thực thi sẽ có một điều kiện đường đi (path condition) tương ứng mô tả điều kiện phải thỏa mãn nếu con đường được lựa chọn Ví dụ, khi chương trình được chạy thông thường, các giá trị có thể được gán, A = 3, B = 7; C = 5 Đường thực thi chương trình tương ứng là và gán 7 đến MAX Trong kỹ thuật thực thi ký hiệu, tất cả 4 đường thực thi của chương trình được khám phá Khi đó, A, B và C được gán các giá trị ký hiệu, A = α, B = β, C = γ Hình 2-4 mô tả quá trình chạy của chương trình và các điều kiện đường đi tương ứng Ví dụ như, đường thực thi gán Max = γ với điều kiện đường đi là (α < β β < γ)

Hình 2-4 Quá trình thực thi ký hiệu của thủ tục MAX

Kỹ thuật kiểm tra thực thi ký hiệu động

Kỹ thuật kiểm tra thực thi ký hiệu động (concolic testing) [24] là một kỹ thuật kiểm chứng phần mềm lai ghép kết hợp hai phương pháp thực thi cụ thể (concrete execution) và thực thi ký hiệu [23] Kỹ thuật này được sử dụng trong một số công cụ kiểm tra phần mềm như PathCrawler [25], jCUTE [24] và SAGE [26] So sánh với phương pháp kiểm tra hộp trắng (whitebox testing) truyền thống, kỹ thuật kiểm tra thực thi ký hiệu động có ưu điểm là cho phép giảm số đường thực thi cần phải kiểm tra

Xem xét chương trình được mô tả trong Hình 2-5, có 2 điều kiện thực thi trong chương trình là (x != y) và (2 * x == x + 10) Với kỹ thuật kiểm tra hộp trắng truyền thống, để đạt được vị trí error(), chúng ta sẽ phải xem xét 3 đường thực thi tương ứng void foo (int x, int y) { 0: if (x ! = y) 1: if (2*x = x + 10)

Hình 2-5 Ví dụ về kiểm tra thực thi ký hiệu động

18 với các điều kiện thực thi là x == y, (x != y) (2 * x == x + 10), và (x != y) (2 * x

!= x + 10) Với kỹ thuật kiểm tra thực thi ký hiệu động, số đường thực thi sẽ được giảm xuống Áp dụng kiểm tra thực thi ký hiệu động, đầu tiên chúng ta sinh các giá trị ngẫu nhiên cho x và y, ví dụ (x = 1) và (y = 2) Trong quá trình thực thi cụ thể, Dòng 0 thỏa do điều kiện là (x != y) đúng Tuy nhiên Dòng 1 sai do điều kiện (2 * x = x + 10) không thỏa Khi đó, kỹ thuật thực thi ký hiệu sẽ được áp dụng trên cùng đường thực thi Lúc này x và y được gán các giá trị ký hiệu x = α, y = β Các điều kiện sinh ra

(α != β) (2 * α == α + 10), là điều kiện đường đi (path condition) của chương trình Để khám phá đường thực thi, công cụ chứng minh Z3.4.3 [27] được sử dụng để giải điều kiện đường đi (α != β) (2 * α= = α + 10) và sinh ra giá trị tương ứng (α = 10) và (β = 10) Áp dụng thực thi cụ thể với các giá trị mới được sinh ra, quá trình thực thi của chương trình sẽ đạt được vị trí error().

Chương trình đóng gói

Những phần mềm độc hại (malware) đã và đang dần trở thành mối đe doạ thực sự đối với mỗi quốc gia Để phân tích và phát hiện mã độc, đa phần những phần mềm trong công nghiệp sử dụng kỹ thuật nhận dạng chữ ký Trong kỹ thuật này, mỗi mã độc được biểu diễn dưới dạng một chuỗi bit nhị phân duy nhất đặc trưng Tuy nhiên, những mã độc ngày này sử dụng các chương trình đóng gói (packer) để tạo ra nhiều biến thể mới đã khiến kỹ thuật nhận dạng chữ ký trở nên không hiệu quả

Phần mềm đóng gói là một chương trình chuyển đổi mã nhị phân của chương trình gốc thành một chương trình thực thi khác Chương trình thực thi mới này vẫn gìn giữ những tính năng nguyên bản nhưng có nội dung hoàn toàn khác với chương trình gốc khi được lưu trữ Chính vì điều này đã làm cho kỹ thuật quét chữ ký không thể liên kết giữa hai phiên bản này Theo thống kê trên [28], hơn 80% mã độc sử dụng rất nhiều loại phần mềm đóng gói khác nhau và thông dụng nhất có thể kể đến UPX [29],

PECOMPACT [30] và ASPACK [31] Phần mềm đóng gói có các mục tiêu cụ thể được mô tả như sau:

 Giảm kích thước của tập tin gốc Đây cũng là mục tiêu mà rất nhiều chương trình hướng tới, bằng việc áp dụng các kỹ thuật đóng gói và mã hóa Kích thước của một tập tin được đóng gói qua đó sẽ giảm đi một cách đáng kể Tuy nhiên, những phần mềm đóng gói hiện đại ngày nay đã không còn đặt tiêu chí giảm kích thước tập tin lên hàng đầu Nguyên nhân là vì giảm kích thước đồng nghĩa với việc sử dụng những kỹ thuật bảo mật khác sẽ bị loại bỏ và do đó độ tin cậy của một chương trình cũng giảm đi Một số phần mềm đóng gói có cơ chế bảo mật tốt hiện nay như Themida [32] có thể làm tăng kích thước tập tin lên rất nhiều lần

 Chống dịch ngược Phần mềm đóng gói được sử dụng như một công cụ chống dịch ngược rất hiệu quả vì những giải thuật đóng gói tập tin phức tạp của chương trình này có thể khiến việc dịch ngược mã nhị phân trở nên vô cùng khó khăn

 Bảo vệ bản quyền của phần mềm Đây cũng là mục tiêu chính yếu nhất mà các phần mềm đóng gói ngày nay hướng tới Bằng cách nâng cao độ phức tạp của các giải thuật đóng gói, đồng thời áp dụng những kỹ thuật chống sửa lỗi, chống dịch ngược, các chương trình đóng gói giúp bảo vệ một phần mềm khỏi việc đánh cắp thông tin bất hợp pháp Mã độc cũng lợi dụng điểm mạnh này nhằm che dấu quá trình thực thi

2.4.2 Cấu trúc chương trình bị đóng gói

Tổng quan, chương trình bị đóng gói sẽ gồm thông tin về PE, đoạn mã thực thi để giải nén và nội dung đã bị nén Ví dụ như chương trình nén bởi UPX sẽ có cấu trúc được mô tả trong Hình 2-7 PE là định dạng file trong hệ điều hành Win32 và chứa các thông tin quan trọng như ngày tháng biên dịch, các hàm trong thư viện được chương trình gọi …

Hình 2-6 Cấu trúc của PE

Dựa trên cấu trúc chương trình gốc ban đầu (Hello.exe), chương trình đóng gói tạo ra nhiều phân vùng khác và thêm vào tập tin thực thi bị đóng gói (Hello_upx.exe) như mô tả trong Hình 2-7

Hình 2-7 Ví dụ về chương trình được đóng gói bởi UPX [72]

Chương trình đóng gói sử dụng rất nhiều kỹ thuật làm rối (obfuscation technique) nhằm mục tiêu làm cho quá trình phân tích trở nên rất khó khăn

2.4.3 Các kỹ thuật làm rối trong chương trình đóng gói

Nhóm kỹ thuật mã động (dynamic code) bao gồm hai kỹ thuật chính là ghi đè mã (code overwriting) và kỹ thuật nén/giải nén (packing/unpacking)

Kỹ thuật ghi đè mã còn được gọi là kỹ thuật mã tự thay đổi (self-modifying code) Theo đó, chương trình đóng gói sẽ sử dụng kỹ thuật này để thay đổi động mã thực thi của chương trình trong quá trình thực thi Mã thực thi thay đổi sẽ dẫn đến câu lệnh tại địa chỉ đó cũng được thay đổi Chương trình đóng gói sử dụng kỹ thuật này để có thể thay đổi chữ ký của bản thân nhằm mục tiêu đánh lừa những phần mềm nhận dạng chương trình đóng gói thông qua chữ ký Hình 2-8 mô tả kỹ thuật ghi đè mã được sử dụng trong chương trình YODA [33] Theo đó sau khi thực thi đoạn mã tại vị trí

004040C3 với giá trị EDI = 0x004040C6, câu lệnh CMP tại địa chỉ 004040C6 sẽ được thay đổi thành câu lệnh MOV

Hình 2-8 Kỹ thuật ghi đè mã sử dụng trong chương trình YODA

Kỹ thuật nén/giải nén còn được gọi là kỹ thuật mã hóa/giải mã Kỹ thuật này tương tự với kỹ thuật mã tự thay đổi đã được trình bày như trên Tuy nhiên, kỹ thuật này sử dụng vòng lặp để thay đổi một hoặc nhiều byte dẫn đến việc thay đổi nhiều câu lệnh liên tục trong suốt quá trình thực thi Hình 2-9 mô tả kỹ thuật nén/giải nén được sử dụng trong chương trình YODA

Hình 2-9 Kỹ thuật nén/giải nén sử dụng trong YODA

Thay đổi cấu trúc mã (code layout)

Nhóm kỹ thuật này được sử dụng để thay đổi cấu trúc của chương trình Có 3 kỹ thuật chính là hàm trùng lắp (overlapping functions), khối trùng lắp (overlapping blocks) và phân mảnh mã (code chunking)

Kỹ thuật hàm trùng lắp với ý tưởng chính là nhiều hàm có thể nằm trùng lắp trong một phân vùng Mỗi hàm được xác định với địa chỉ bắt đầu tại địa chỉ là tham số trong câu lệnh CALL và địa chỉ kết thúc chính là địa chỉ của câu lệnh RET trong cùng một hàm

Kỹ thuật khối trùng lắp có cùng ý tưởng với kỹ thuật hàm trùng lắp như trình bày ở trên Tuy nhiên, khác với kỹ thuật hàm trùng lắp, mỗi khối được xác định thông qua câu lệnh nhảy hoặc nhảy có điều kiện Hình 2-10 mô tả kỹ thuật khối trùng lắp được sử dụng trong YODA Theo đó tại vị trí 004040BD một câu lệnh nhảy sẽ nhảy tới địa chỉ 004040C0 và tại địa chỉ này sẽ được dịch ngược thành một câu lệnh hoàn toàn khác

Hình 2-10 Kỹ thuật khối trùng lắp sử dụng trong YODA

Kỹ thuật phân mảnh mã được sử dụng để có thể chia đoạn mã thực thi thành nhiều khối Mỗi khối này kết thúc với một câu lệnh nhảy và có kích thước là dưới 20 bytes Đoạn mã trong Hình 2-11 mô tả kỹ thuật phân mảnh mã trong YODA Trong đoạn mã trên, có thể thấy đoạn mã được chia nhỏ làm các khối 0040446E, 00404474,

Hình 2-11 Kỹ thuật phân mảnh sử dụng trong YODA

Kỹ thuật làm rối câu lệnh (instruction obfuscation)

Kỹ thuật làm rối câu lệnh hay còn gọi là kỹ thuật nhảy không trực tiếp (indirect jump) Kỹ thuật này được sử dụng rất nhiều trong các chương trình đóng gói Theo đó, địa chỉ của câu lệnh nhảy được lưu trữ trong thanh ghi, bộ nhớ hay stack và chỉ được xác định trong thời điểm thực thi của chương trình Hình 2-12 mô tả một ví dụ về việc sử dụng kỹ thuật nhảy không trực tiếp trong UPX Trong câu lệnh trên, giá trị đích đến được lưu trữ trong thanh ghi ESI

Hình 2-12 Kỹ thuật làm rối câu lệnh sử dụng trong UPX

Kỹ thuật chống lưu vết (anti-tracing)

Nhóm kỹ thuật này bao gồm 2 kỹ thuật chính là quản lý ngoại lệ có cấu trúc

(structured exception handler - SEH) và hai APIs đặc biệt (two special APIs)

Kỹ thuật quản lý ngoại lệ có cấu trúc bao gồm 2 giai đoạn chính Trong giai đoạn đầu, chương trình đóng gói sẽ thiết lập một ngoại lệ (exception) bằng cách lưu trữ địa chỉ của hàm xử lý ngoại lệ trong bộ nhớ tại địa chỉ FS:[0] Giai đoạn này được gọi là thiết lập ngoại lệ (setup exception) Khi một ngoại lệ xảy ra do thực hiện câu lệnh chia cho 0, đọc hoặc ghi vào vùng bộ nhớ không hợp lệ hoặc khi sử dụng những câu lệnh ngắt như INT3, chương trình sẽ tự động chuyển điều khiển đến hàm xử lý ngoại lệ

Giai đoạn này được gọi là gây lỗi ngoại lệ (causing exception) Đoạn mã trong Hình 2-

13 mô tả một ví dụ về việc sử dụng kỹ thuật quản lý ngoại lệ có cấu trúc trong PETITE

Mô hình Markov ẩn

Mô hình Markov ẩn ((Hidden Markov Model)) [36] là mô hình chuyển trạng thái ngẫu nhiên và được ứng dụng thành công trong nhiều lĩnh vực về nhận dạng mẫu [37]

[38] Mô hình Markov ẩn = { , , } bao gồm các thành phần sau

 Tập hợp S tất cả các trạng thái: S = {s1, s2, …, sn} với n là số trạng thái

 Tập hợp O tất cả các ký hiệu quan sát được O = {o1, o2, …, om} với m là số ký hiệu quan sát

 Ma trận xác suất chuyển trạng thái A

= = ( = | = )} (2.1) với là xác suất chuyển đổi từ trạng thái sang trạng thái

 Ma trận xác suất quan sát B

= { ( )| ( ) = ( | = )} (2.2) Với ( ) là xác suất quan sát được ký hiệu tại trạng thái

 Một tập xác suất khởi đầu, = { | = ( = )}

Mô hình Markov ẩn phải thỏa mãn 2 điều kiện sau:

 Trạng thái hiện tại chỉ phụ thuộc vào trạng thái liền trước nó, đặc trưng cho tính nhớ của mô hình

 Quan sát được ở thời điểm t, chỉ phụ thuộc vào trạng thái hiện tại, độc lập với các trạng thái và quan sát được trong quá khứ.

Kiểm tra Chi bình phương

Phương pháp kiểm tra Chi bình phương (Chi-square test) [39] là một trong những phương pháp tiêu chuẩn để phân loại dựa trên các thuộc tính Dựa trên ý tưởng của [40], chúng tôi sử dụng phương pháp kiểm tra Chi bình phương trong bài toán phân loại Do đây là bài toán phân loại với số loại = 2 (tương ứng với trường hợp thuộc và không thuộc) nên bậc tự do (degree of freedom) được xác định ( − 1) = 1 Chúng tôi lựa chọn giá trị mất mát (loss) tiêu chuẩn là 0,05 Dựa trên bảng phân phối Chi bình phương [39], giá trị hệ số tương quan tương ứng = 3,84

Gọi = ( , , … , ) là những vectơ trong không gian chiều Với thuộc tính và f i là tần số xuất hiện của thuộc tính i Đầu tiên, chúng tôi chuẩn bị tập huấn luyện T r , đã được phân loại vào một tập C Tập vectơ trung bình = ( , , … , ) của tần số xuất hiện được định nghĩa theo công thức

Với mẫu (sample), = ( , , … , ), phương pháp Chi bình phương sẽ tiến hành kiểm tra trên như sau

( ) = | | (2.5) Bậc của thành phần ( ) sẽ thể hiện có thuộc về hay không

Tiếp theo, chuẩn bị tập , mà đã biết trước sẽ thuộc và ∩ = ∅ Phần tử ngưỡng ̅ bằng trung bình của bậc các phần tử trong , ̅ = ∑ ∈ ( )

| | (2.6) Khi mẫu mới được kiểm tra với ( ) ≥ ̅ sẽ kết luận rằng nằm trong

KHUNG THỨC TỔNG QUÁT XÂY DỰNG ĐỒ THỊ LUỒNG ĐIỀU KHIỂN 32

Giới thiệu

Lấy cảm hứng từ [19], chúng tôi đề xuất phương pháp kiểm tra thực thi ký hiệu động, kết hợp kỹ thuật phân tích tĩnh (static analysis) và kiểm tra động (dynamic testing) để xây dựng đồ thị luồng điều khiển từ mã nhị phân Ý tưởng chính của phương pháp này là áp dụng phân tích tĩnh để xây dựng đồ thị luồng điều khiển nội bộ thủ tục cho đến khi gặp lệnh nhảy gián tiếp hay các lời gọi hàm Khi đó, kỹ thuật kiểm tra động được áp dụng bằng cách sinh ra các dữ liệu kiểm tra (test-case) để xác định điểm đến chính xác của câu lệnh nhảy Tuy nhiên, khác với ý tưởng từ [19], chúng tôi áp dụng kỹ thuật thực thi ký hiệu để tạo ra dữ liệu kiểm tra thích hợp Phương pháp này cung cấp cho một đồ thị luồng điều khiển thực tế chính xác hơn (ngay cả với trường hợp lệnh nhảy động) so với phương pháp phân giải trừu tượng (abstract interpretation) [21] dựa trên phân tích tĩnh Trong [19], các tác giả cũng đề xuất việc kết hợp giữa phân tích tĩnh và kiểm tra động để phân tích mã nhị phân Tuy nhiên, các lệnh nhảy động được giải quyết sử dụng phân tích ngược (backward analysis) với kỹ thuật gán tĩnh đơn (single static assignment)

Hình 3-1 mô tả khung thức tổng quát của phương pháp Trong đó, vai trò của các thành phần này như sau

 Khối Static Analysis đảm nhận quá trình phân tích tĩnh với kỹ thuật thực thi ký hiệu Thành phần Disassembler dịch ngược mã thực thi (opcode) thành câu lệnh hợp ngữ Thành phần Path Condition Solving giải các điều kiện đường đi và sinh ra dữ liệu kiểm tra thích hợp

 Khối Dynamic Testing đảm nhận quá trình kiểm tra động Đây là một thành phần quan trọng trong tổng thể kiến trúc của khung thức nhằm giả lập và mô phỏng hoạt động các thành phần của hệ thống với khối Binary Emulation

 Khối CFG storage lưu trữ đồ thị luồng điều khiển sau khi được tính toán chính xác CFG storage sẽ được sử dụng để xây dựng mô hình thực thi cuối cùng của tập tin được phân tích

 Thành phần Frontier lưu trữ thông tin về đường đi trong quá trình phân tích

Trong khung thức này, chương trình được chia thành các khu vực (area) Mỗi khu vực bao gồm một khối các câu lệnh hợp ngữ (assembly code) được dịch ngược

(disassemble) từ mã thực thi thông qua khối Disassembler Trong giai đoạn phân tích tĩnh, chúng tôi áp dụng kỹ thuật thực thi ký hiệu để xây dựng đường thực thi trong một khu vực và tạo ra các đồ thị luồng điều khiển phụ tương ứng Quá trình thực thi ký hiệu này được thực hiện cho đến khi gặp phải một câu lệnh nhảy động

Khi gặp phải một bước nhảy động, chúng tôi giải điều kiện đường đi (path condition) tương ứng với đường thực thi trong khu vực này thông qua khối Path Condition Solving Sau đó, các trường hợp kiểm tra được sinh ra để bao phủ tất cả các đường thực thi Trong lúc đó, đồ thị luồng điều khiển của khu vực sẽ được cập nhật Sau đó, giai đoạn phân tích động sẽ được thực hiện Trong giai đoạn này, chương trình sẽ tiến hành thực thi chương trình sử dụng các trường hợp kiểm tra được sinh ra ở bước trên thông qua khối Binary Emulation Điều này cho phép xác định các mục tiêu

Hình 3-1 Kiến trúc tổng quát của khung thức

34 thực sự của lệnh nhảy động và cập nhật các đồ thị luồng điều khiển hiện hành trong khối CFG Storage Nếu lệnh nhảy này nhảy vào một vùng mới mà chưa được khám phá, giai đoạn phân tích tĩnh được thực thi tiếp tục Hai quá trình phân tích tĩnh và động được lặp đi lặp lại cho đến khi không có khu vực mới được phát hiện.

Các nghiên cứu liên quan

Có rất nhiều các công cụ xây dựng mô hình cho phân tích mã nhị phân Để giải quyết vấn đề lệnh nhảy động, các công cụ này có thể đi theo hướng, phân tích tĩnh hay kiểm tra động Các công cụ CodeSurfer/x86 [41], McVeto [14], và JakStab [15] sử dụng kỹ thuật phân tích tĩnh Trong khi đó OSMOSE [16], BIRD [42], Renovo [18], Syman [19], Codiasm [43]và SAGE [20] sử dụng phân tích động Một cách tổng quát, kiểm tra động hiệu quả hơn phân tích tĩnh trong vấn đề phân tích mã độc [44] Khung thức của chúng tôi sử dụng phương pháp kết hợp cả 2 cách trên

Phân tích tĩnh sử dụng kỹ thuật phân giải trừu tượng để xấp xỉ quá mức địa chỉ nhảy trong câu lệnh nhảy không trực tiếp Đây là ý tưởng chính được hiện thực trong JakStab Tuy nhiên, công cụ này có nhược điểm là không thể bảo đảm các địa chỉ sinh ra là chính xác

McVeto sử dụng thực thi ký hiệu để kiểm tra các đường đi khả thi (concrete trace) Công cụ này xử lý vấn đề lệnh nhảy động bằng phân tích tĩnh, chọn một và kiểm tra các điều kiện khả thi của đường đi Do đó, McVecto không thể bao phủ hết các đường thực thi của chương trình

X-Force [45] thực thi động dựa trên công cụ PIN [46] được hỗ trợ bởi Intel Công cụ này tìm kiếm các đường thực thi khác nhau một cách hệ thống bằng cách ép (force) kết quả trả về dựa trên điều kiện đường đi Moser [47] phát triển một hệ thống cho Windows để thực thi các đường đi khác nhau Công cụ này có hỗ trợ vấn đề mã tự thay đổi (self-modification code)

MineSweeper [48] sử dụng giá trị ký hiệu cho APIs để phát hiện các hành vi kích hoạt (triggerbased behavior) Công cụ Syman [19] mô phỏng toàn bộ Windows OS

Tuy nhiên, công cụ này gặp phải vấn đề bùng nổ độ phức tạp ngay cả khi phân tích những chương trình nhỏ OSMOSE và CodeSurfer/x86 sử dụng mô hình 32-bit vector, gọi là DBA (Dynamic Bit-vector Automaton) [49]

CoDisasm dựa trên phân tích các hành vi thực thi gọi là các sóng (wave) Công cụ này có thể xử lý vấn đề lệnh trùng lắp (overlapping instructions) và mã tự thay đổi Một cách tổng quát, khung thức của chúng tôi tương tự với McVeto Tuy nhiên, McVeto xử lý vấn đề lệnh nhảy động bằng phân tích tĩnh, chọn một và kiểm tra các điều kiện khả thi của đường đi Khung thức của chúng tôi đề xuất giải điều kiện đường đi và ứng dụng kiểm tra động (dựa trên khối binary emulator) để xác định đích đến.

Ví dụ minh họa

Xử lý câu lệnh nhảy động Để mô tả hoạt động của khung thức, chúng tôi đã xây dựng một ví dụ đơn giản được mô tả trong Hình 3-2 Chương trình được bắt đầu tại vị trí start và chứa câu lệnh lệnh nhảy gián tiếp tại vị trí L10 Sử dụng phương pháp phân tích tĩnh, chúng ta có thể xác định được hai đường thực thi dẫn đến lệnh nhảy động này, P 1 = (start  0  1 

7  8  9  10) và P 2 = (start  0  1  2  3  4  5  9  10) Với giá trị ký hiệu ban đầu của thanh ghi eax là ∝, các điều kiện đường đi tương ứng của P 1 và P 2 là (∝ 0)

Giải điều kiện đường đi bằng SMT, chúng ta có thể sinh ra 2 trường hợp kiểm tra tương ứng với các điều kiện đường đi này, ∝ = -1 và ∝ = 2 Bằng cách mô phỏng quá trình thực thi với những điều kiện này, địa chỉ nhảy của câu lênh nhảy gián tiếp được xác định là start và L8 Tiếp tục thực thi đường đi từ L8 và L6 được sinh ra như là một điểm đến mới của câu lệnh nhảy gián tiếp CFG kết quả được trình bày trong

Hình 3-2 Ví dụ xử lý câu lệnh nhảy động

Hình 3-3 Trong Hình 3-3, chúng tôi trình bày kết quả phân tích của Jakstab (hình bên phải) và BE-PUM (hình bên trái) BE-PUM là công cụ hiện thực khung thức của chúng tôi và được trình bày chi tiết trong chương 8 Jakstab thất bại với lệnh nhảy gián tiếp tại L10 nhưng BE-PUM đã xử lý được

Sự kết hợp của nhiều vùng và xử lý vùng mã không thể đến được (dead code)

Trong ví dụ này, chúng tôi mở rộng Ví dụ 1 để minh họa cho một kịch bản phức tạp hơn Đoạn mã trong Hình 3.4 trình bày chương trình cần phân tích, trong đó có hai lệnh nhảy động tại vị trí L7 và L16 Ngoài ra, chương trình này chèn mã không thể đến được (dead code) từ vị trí L17 đến L19

Hình 3-3 So sánh CFG sinh ra bởi Jakstab (phải) và BE-PUM (trái)

Ví dụ này mô tả ý tưởng của chúng tôi là mỗi bước nhảy động khi được thực thi sẽ tạo ra một khu vực mới trong chương trình Hình 3-5 minh họa quá trình xây dựng CFG tuân thủ chiến lược này Đầu tiên, CFG của khu vực 1 (tương ứng với L0 đến L7) được xây dựng theo phương pháp như mô tả trong Ví dụ 1 Bằng cách sinh ra dữ liệu kiểm tra và thực thi các lệnh nhảy gián tiếp tại L7 , chúng tôi có thể phát hiện ra một khu vực mới tại L8

Lưu ý rằng nếu áp dụng kỹ thuật phân giải trừu tượng, kết quả thu được là một khoảng bao gồm tất cả các giá trị có thể có của câu lệnh L7, ví dụ, lệnh start và lệnh L8 Vì vậy, kết quả là khoảng [offsetlstart, offsetll + 12] Vì khoảng này cũng bao gồm địa chỉ mã không thể đến được, quá trình phân tích này đã tạo ra lệnh nhảy sai từ câu lệnh L7 đến những vùng mã không thể đến được ở trên

4: mov ax, offset lcont2 – lcont1

Hình 3-4 Ví dụ về xử lý đoạn mã không thể đến

Kết luận

Trong chương này, chúng tôi đã đề xuất một khung thức tổng quát cho việc xây dựng đồ thị luồng điều khiển từ mã nhị phân Trong khung thức này, chúng tôi đề xuất kết hợp phân tích tĩnh và kiểm tra động để giải quyết vấn đề lệnh nhảy động trong phân tích mã nhị phân Chúng tôi đã trình bày 2 ví dụ minh họa cho cơ chế hoạt động của khung thức Trong chương tiếp theo, chúng tôi trình bày về giải thuật song song

39 hóa kết hợp với bảng băm và giải thuật di truyền để tăng tốc quá trình thực thi trong chương trình của chúng tôi

Hình 3-5 Kết quả chiến thuật xây dựng CFG liên vùng

ÁP DỤNG KỸ THUẬT SONG SONG HÓA KẾT HỢP VỚI BẢNG BĂM VÀ GIẢI THUẬT DI TRUYỀN ĐỂ GIẢM THỜI GIAN THỰC THI CỦA CHƯƠNG TRÌNH

NHẬN DIỆN CHƯƠNG TRÌNH ĐÓNG GÓI SỬ DỤNG KỸ THUẬT CHI BÌNH PHƯƠNG

NHẬN DIỆN CHƯƠNG TRÌNH ĐÓNG GÓI SỬ DỤNG MÔ HÌNH

NHẬN DIỆN MÃ ĐỘC SỬ DỤNG PHƯƠNG PHÁP HỌC SÂU

CÔNG CỤ XÂY DỰNG ĐỒ THỊ LUỒNG ĐIỀU KHIỂN BE-PUM 111

Ngày đăng: 16/06/2021, 22:09

Nguồn tham khảo

Tài liệu tham khảo Loại Chi tiết
[1] J.- M. Jézéquel and B. Meyer, "Design by Contract: The Lessons of Ariane," Journal Computer, vol. 30, no. 1, pp. 129-130, 1997 Sách, tạp chí
Tiêu đề: Design by Contract: The Lessons of Ariane
[4] T. Linz and H. Schaefer. A. Spillner, Software Testing Foundations, Santa Barbara, Ed.: Rocky Nook Inc., 2006 Sách, tạp chí
Tiêu đề: Software Testing Foundations
[5] E. M. Clarke and J. M. Wing., "Formal methods: State of the art and future directions.," Journal ACM Computing Surveys, vol. 28, no. 4, pp. 626-643, 1996 Sách, tạp chí
Tiêu đề: Formal methods: State of the art and future directions
[6] J. W. Backus, ""The Syntax and Semantics of the Proposed International Algebraic Language of Zürich ACM-GAMM Conference," in Proceedings of the International Conference on Information Processing, Zurich, Switzerland, 1959, pp. 1-21 Sách, tạp chí
Tiêu đề: The Syntax and Semantics of the Proposed International Algebraic Language of Zürich ACM-GAMM Conference
[7] T. Reps, D. Melski, T. Teitelbaum and G. Balakrishnan, "WYSINWYX:What You See Is Not What You eXecute.," in Transactions on Programming Languages and Systems (TOPLAS), New York, USA, 2010 Sách, tạp chí
Tiêu đề: WYSINWYX:What You See Is Not What You eXecute
[8] Intel Corporation, "Intel 64 and IA-32 Architectures Software Developer’s Manual," 2009 Sách, tạp chí
Tiêu đề: Intel 64 and IA-32 Architectures Software Developer’s Manual
[2] Tricentis. (2017, Oct.) Tricentis. [Online]. https://www.tricentis.com/wp- content/uploads/2017/01/20161231SoftwareFails2016.pdf Link
[30] J. Collake. (2017, January) PECompact – Windows (PE) Executable Compressor. [Online]. https://bitsum.com/portfolio/pecompact/ Link
[32] Oreans Technologies. (2017, October) Themida Advanced Windows Software Protection System. [Online]. https://www.oreans.com/themida.php Link
[34] Un4seen. PETITE Win32 Executable Compressor. [Online]. http://www.un4seen.com/petite/ Link
[35] Telock Packer. [Online]. http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/Telock.shtml Link
[46] S. Naftaly (2012, June) Pin - A Dynamic Binary Instrumentation Tool. [Online]. https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool Link
[53] Y. Guillot and J. Tinnes. (2007, April) The METASM assembly manipulation suite. [Online]. http://metasm.cr0.org/ Link
[54] V. Bénony. Hopper v4 The macOS and Linux Disassembler. [Online]. http://www.hopperapp.com Link
[55] Java User Group. Java Native Access (JNA). [Online]. https://github.com/java- native-access/jna Link
[67] D. Pistelli. (2009, May) NTCore-CFF Explorer. [Online]. http://www.ntcore.com/exsuite.php Link
[76] D. Song. TEMU: The BitBlaze Dynamic Analysis Component. [Online]. http://bitblaze.cs.berkeley.edu/temu.html Link
[91] CERT. (2017) THE WANNACRY RANSOMWARE. [Online]. http://www.ey.com/Publication/vwLUAssets/ey-wannacry-ransomware-attack/$File/ey-wannacry-ransomware-attack.pdf Link
[106] Software Freedom Conservancy. QEMU the FAST! processor emulator. [Online]. https://www.qemu.org/ Link
[107] M. Russinovich. (2017, September) Process Monitor v3.40. [Online]. https://docs.microsoft.com/en-us/sysinternals/downloads/procmon Link

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w