Giải pháp bảo vệ, che giấu chương trình Windows chống lại nguy cơ phân tích, dịch ngược
NGUY CƠ PHÂN TÍCH, DỊCH NGƯỢC CÁC THUẬT TOÁN MẬT MÃ
An toàn thông tin (ATTT) có 3 đặc trưng quan trọng là bảo vệ tính bí mật, toàn vẹn và sẵn sàng của thông tin. Trong bối cảnh ngày nay, khi ATTT trở thành mối quan tâm hàng đầu thì các kỹ thuật mật mã đóng một vai trò vô cùng quan trọng trong phát triển và triển khai sản phẩm phần mềm. Tích hợp mật mã không chỉ là một biện pháp bảo mật để bảo vệ các thông tin quan trọng mà còn là một phần không thể thiếu của việc xây dựng một sản phẩm phần mềm an toàn, tin cậy và đáp ứng các tiêu chuẩn an toàn cao, từ đó quyết định sự tin cậy và thành công của sản phẩm.
Tuy nhiên, có một thách thức đáng kể mà các nhà phát triển và chuyên gia bảo mật phải đối mặt khi xây dựng sản phẩm phần mềm có tích hợp mật mã, đó là nguy cơ dịch ngược các thuật toán mật mã. Dịch ngược mật mã là quá trình phân tích và hiểu rõ lại thuật toán mật mã đã được sử dụng trong ứng dụng, có thể dẫn đến việc loại bỏ các biện pháp bảo mật [1]. Khi sản phẩm phần mềm không được bảo vệ đủ tốt, tin tặc có thể dễ dàng truy cập và phân tích mã chương trình. Kỹ thuật dịch ngược có thể tiết lộ chi tiết cấu trúc của thuật toán, các khóa mã hóa và cách thông tin được xử lý trong quá trình thực hiện mã hóa và giải mã.
Một số phương pháp dịch ngược thông dụng bao gồm sử dụng debuggers, disassemblers và các công cụ tương tự để theo dõi và phân tích quá trình thực thi của chương trình. Khi đã hiểu rõ thuật toán mật mã, tin tặc có thể tìm cách đánh lừa hoặc tấn công hệ thống một cách hiệu quả hơn, thậm chí có thể giả mạo chữ ký số hoặc giải mã thông tin nhạy cảm.
MỘT SỐ KỸ THUẬT BẢO VỆ PHẦN MỀM CHỐNG LẠI NGUY CƠ PHÂN TÍCH, DỊCH NGƯỢC
Một phần mềm có thể được phân tích bằng phương pháp phân tích tĩnh, phân tích động hoặc kết hợp cả hai. Phân tích tĩnh là quá trình sử dụng các công cụ disaseembly để phân tích mà không cần thực thi mã của chương trình [2]. Trong khi đó, sử dụng phương pháp phân tích động giúp xác định hành vi thực sự khi chương trình đang chạy và theo dõi các giá trị biến, lưu trữ trung gian của chương trình. Để phân tích động, các chương trình phần mềm được thực thi trong một công cụ trình gỡ lỗi. Bằng cách này, mọi thứ xảy ra trong quá trình thực thi chương trình đều có thể được kiểm soát bởi trình gỡ lỗi. Trong quá trình phân tích động, tin tặc có thể sử dụng chế độ gỡ lỗi để lần lượt bỏ qua tất cả các thuật toán bảo vệ của chương trình, đặc biệt là các quy trình tạo và kiểm tra khóa đăng ký [1]. Để khắc phục việc phân tích dịch ngược chương trình, có một số phương pháp mà các nhà phát triển có thể sử dụng để bảo vệ phần mềm như:
- Làm xáo trộn mã (Code Obfuscation): Làm xáo trộn mã liên quan đến việc sửa đổi để làm cho mã của một chương trình phần mềm trở nên khó hiểu hơn hoặc khó sử dụng kỹ thuật dịch ngược hơn. Kỹ thuật này có thể bao gồm một loạt các biến đổi, chẳng hạn như đổi tên biến/hàm/đối số, loại bỏ chuỗi, thay đổi thứ tự các khối mã và thêm mã “rác” (mã không có chức năng và các biến đổi khác). Mã nguồn sau đó trở nên khó đọc hơn nhưng vẫn hoạt động chính xác như trước khi được sửa đổi.
- Kỹ thuật chống giả mạo: Kỹ thuật chống giả mạo được sử dụng để ngăn chặn sửa đổi trái phép của một chương trình phần mềm. Kỹ thuật này có thể bao gồm các biện pháp như sử dụng checksum hoặc chữ ký số để đảm bảo rằng mã không bị thay đổi.
- Quản lý giấy phép: Quản lý giấy phép liên quan đến việc kiểm soát việc phân phối và sử dụng chương trình phần mềm thông qua các thỏa thuận cấp phép. Kỹ thuật này có thể bao gồm các biện pháp như kích hoạt sản phẩm, xác minh khóa cấp phép hoặc giám sát việc sử dụng. Quản lý giấy phép có thể giúp ngăn chặn việc sử dụng và phân phối trái phép chương trình phần mềm, từ đó có thể giúp bảo vệ chống lại kỹ thuật dịch ngược.
- Mã hóa: Mã hóa bao gồm việc sử dụng các thuật toán để xáo trộn mã phần mềm sao cho không thể đọc hoặc hiểu được nếu không có khóa giải mã. Đây có thể là một phương pháp hiệu quả để ngăn chặn kỹ thuật dịch ngược, vì việc hiểu mã nếu không có khóa là gần như không thể.
Các trình bảo vệ thay đổi cấu trúc mã thực thi của chương trình và thêm vào các phần mã hóa, nén làm mờ đi chức năng cụ thể khiến cho mã thực thi gốc sẽ bị ẩn đi khi tệp thực thi được nạp vào các công cụ phân tích, từ đó giúp ngăn chặn các kỹ thuật dịch ngược. Khả năng bảo vệ mà hầu hết các trình bảo vệ cung cấp là dựa trên việc đóng gói hoặc mã hóa tệp thực thi ban đầu: Chương trình ban đầu được nén hoặc mã hóa thành dữ liệu được đóng gói và liên kết với quy trình giải nén, giải mã mà không làm thay đổi chức năng nhằm mục đích khiến người tấn công hoặc người dịch ngược gặp khó khăn và tốn thời gian hơn trong việc bẻ khóa hoặc dịch ngược phần mềm. Phần dữ liệu thực sự chứa các dữ liệu nhạy cảm hoặc bí mật nằm ở đoạn dữ liệu được che giấu, dữ liệu này chỉ được giải mã khi chạy chương trình.
GIẢI PHÁP BẢO VỆ, CHE GIẤU CHƯƠNG TRÌNH WINDOWS CHỐNG LẠI NGUY CƠ PHÂN TÍCH, DỊCH NGƯỢC
Để bảo vệ chương trình phần mềm trước nguy cơ phân tích, dịch ngược, nhóm tác giả đề xuất mô hình giải pháp như Hình 1.
Hình 1. Mô hình mã hóa bảo vệ chương trình
Trong cấu trúc của một tệp thực thi, phần .text là phần chứa các mã lệnh thực thi của chương trình còn phần .data là phần khai báo các dữ liệu khởi tạo, các hằng số, các giá trị không thay đổi trong quá trình chạy. Trong mô hình mã hóa này, phần .text và .data sẽ được được nén bằng thuật toán LZMA (Lempel-Ziv Markov chain Algorithm) nhằm giảm kích thước của tệp thực thi rồi mã hóa từng phần bằng thuật toán AES-256 chế độ CBC với khóa được dẫn xuất từ một mật khẩu được cấp phát từ phía người quản trị. Hàm dẫn xuất được triển khai theo tiêu chuẩn PBKDF2 với tham số Salt được sinh ngẫu nhiên và được lưu lại trong phần dữ liệu được che giấu. Để chương trình có thể tự động giải nén và giải mã khi thực thi, đoạn dữ liệu được che giấu cần một đoạn mã shellcode gọi là đoạn mã stub đính kèm. Mô hình hoạt động của đoạn mã stub như Hình 2.
Hình 2. Mô hình hoạt động của đoạn mã stub
Khi một chương trình đã bảo vệ được thực thi, bản chất là đoạn mã stub thực thi đầu tiên sẽ thực hiện nhận mật khẩu từ phía người dùng thông qua hộp thoại được hiển thị rồi tiến hành giải nén, giải mã chương trình thật, nạp lên bộ nhớ và chuyển điều khiển luồng thực thi về cho chương trình chính. Dữ liệu sau khi được giải mã và giải nén hoàn toàn sẽ được kiểm tra tính toàn vẹn rồi cảnh báo phía người dùng nếu người dùng nhập sai mật khẩu.
Để đảm bảo chương trình vẫn hoạt động bình thường, cấu trúc PE của tệp thực thi mới được xây dựng lại sau khi đóng gói đoạn dữ liệu đã được che giấu và đoạn mã shellcode tự động giải nén giải mã chương trình như Hình 3.
Hình 3. Cấu trúc PE của tệp trước và sau khi bảo vệ
Dữ liệu được che giấu sẽ được đóng gói vào phần mới có tên là BCY1 trong khi đó, phần BCY0 được dùng để lưu trữ dữ liệu sau khi được giải nén và giải mã thành công. Để chương trình có thể thực thi, việc khó khăn cần thực hiện đó là xây dựng header mới theo các phần mới với một kích thước mới và thứ tự, số lượng các phần đã bị thay đổi. Trong khi xây dựng header mới, cần thiết lập điểm thực thi đầu tiên (OEP) vào đoạn mã stub, sau khi giải mã thành công tiến hành trả quyền thực thi về đoạn mã gốc (Hình 4).
Hình 4. Mô hình thực thi của tệp đã bảo vệ
Giải pháp đã tiến hành chạy thử trên phần mềm VSE VPN Server có sử dụng các thuật toán của Ngành trong bộ thư viện OpenSSL 3.x. Sử dụng công cụ CFF-Explorer so sánh cấu trúc của chương trình trước và sau khi áp dụng giải pháp thu được kết quả như Hình 5.
Hình 5. Cấu trúc tệp trước và sau khi tích hợp giải pháp
Sau khi áp dụng giải pháp, cấu trúc của chương trình đã hoàn toàn thay đổi nhưng vẫn đảm bảo chương trình thực thi đúng chức năng như chương trình gốc. Nếu như ở chương trình gốc, chương trình có 5 phần (.text, .data, .rdata, .rsrc, .reloc) thì ở chương trình sau chỉ có 3 phần là BCY0, BCY1 và .rsrc; đặc biệt là kích thước của các phần cũng đã giảm đáng kể. Đồng thời các hàm sử dụng trong chương trình cũng được che giấu và chỉ được hiển thị như Hình 6.
Hình 6. Các hàm trong chương trình sau khi bảo vệ
Toàn bộ chương trình đã được che giấu và hiển thị với các tên phần là BCY1. Chương trình sau khi che giấu thực hiện các chức năng giống như chương trình gốc và không cần tệp nào khác đính kèm để khôi phục chương trình.
KẾT LUẬN
Có thể nói, bảo vệ phần mềm chống lại kỹ thuật phân tích dịch ngược đang là mối quan tâm hàng đầu của các nhà phát triển phần mềm trên toàn thế giới vì phương pháp này có thể ngăn chặn truy cập trái phép vào phần mềm, giúp bảo đảm tính toàn vẹn của sản phẩm cũng như bảo vệ tài sản trí tuệ của họ. Bài báo đã giới thiệu một số kỹ thuật bảo vệ phần mềm phổ biến, từ đó đề xuất giải pháp cụ thể nhằm bảo vệ các chương trình Windows trước nguy cơ phân tích dịch ngược có thể được áp dụng cho các sản phẩm phần mềm nói chung và đặc biệt là các sản phẩm phần mềm mật mã yêu cầu cấp độ mật cao của ngành Cơ yếu nói riêng.
TÀI LIỆU THAM KHẢO [1]. Reginald Wong, "Mastering Reverse Engineering: Your Practical guide to master the art of Malware Reversing", October 2018. [2]. Bùi Đình Cường, Các kỹ thuật phân tích tĩnh cơ bản. [Online]: Accessed on 15 Feb. 2024. |
Nguyễn Đình Đại, Hoàng Thu Phương (Viện Khoa học - Công nghệ mật mã)