Reverse Engineering (5/5): obfuscation, angr và cách bảo vệ phần mềm của bạn
Tóm tắt
Không có bảo vệ phía client nào không phá được, chỉ làm tăng chi phí. angr giải nhanh bài kiểm tra input; còn với sản phẩm của bạn, hãy chuyển niềm tin về server.
Không có cơ chế bảo vệ phía client nào là không thể phá; nó chỉ làm tăng chi phí phân tích. Hiểu obfuscation từ cả hai phía giúp bạn trở thành người phân tích giỏi hơn và quyết định đúng sản phẩm của mình cần bảo vệ tới mức nào. Bài cuối trong loạt Reverse Engineering cho lập trình viên: các kỹ thuật chống dịch ngược, thực thi ký hiệu với angr, so sánh binary, và chiến lược bảo vệ thực tế.
Kỹ thuật bảo vệ và cách xử lý
| Kỹ thuật | Tác dụng | Cách người phân tích xử lý |
|---|---|---|
| Strip symbol | Xoá tên hàm | Chữ ký thư viện, xref từ chuỗi, khôi phục kiểu (bài 2) |
| Packing (UPX, Themida, VMProtect) | Nén/mã hoá code, giải nén khi chạy | upx -d với UPX; còn lại chạy tới điểm vào gốc (OEP) rồi dump bộ nhớ |
| Mã hoá chuỗi | Ẩn chuỗi cho tới khi dùng | Hook hàm giải mã bằng Frida hoặc giả lập (Unicorn, emulator của Ghidra) |
| Làm phẳng luồng điều khiển | Biến hàm thành một vòng switch điều phối khổng lồ | Trace thực thi thật, script deobfuscation, thực thi ký hiệu |
| Opaque predicate | Chèn nhánh luôn đúng/luôn sai | Dùng SMT solver chứng minh nhánh là hằng rồi bỏ đi |
| Ảo hoá code | Dịch code sang bytecode riêng chạy trên VM nhúng | Khó nhất: lập bản đồ handler của VM, viết disassembler cho bytecode |
| Chống debug | IsDebuggerPresent, ptrace, đo thời gian | Plugin ẩn debugger, patch đoạn kiểm tra, hoặc hook bằng Frida |
Thực thi ký hiệu với angr
Thay vì đoán input, bạn mô tả input là ký hiệu và để solver tìm giá trị dẫn tới địa chỉ mong muốn. angr là framework Python làm điều này trên binary thật:
import angr, claripy
proj = angr.Project('./crackme', auto_load_libs=False)
pw = claripy.BVS('pw', 8 * 16) # 16 byte ký hiệu
state = proj.factory.entry_state(args=['./crackme', pw])
simgr = proj.factory.simulation_manager(state)
simgr.explore(find=0x401234, avoid=0x401250) # in "Correct" / in "Wrong"
if simgr.found:
print(simgr.found[0].solver.eval(pw, cast_to=bytes))
Hai địa chỉ find/avoid là ví dụ — lấy từ Ghidra cho binary của bạn. angr rất mạnh với bài kiểm tra input và hàm ngắn, nhưng gặp bùng nổ đường đi với chương trình lớn. Khi đó, mô hình hoá riêng đoạn kiểm tra rồi giải bằng Z3 thường nhanh hơn.
So sánh binary (diffing)
Khi nhà cung cấp phát hành bản vá bảo mật, so sánh binary cũ và mới bằng BinDiff hoặc Diaphora cho thấy đúng hàm nào đã đổi. Đây là cách giới nghiên cứu phân tích lỗ hổng vừa được vá, và cũng là cách bạn kiểm chứng một bản cập nhật thực sự thay đổi gì.
Bảo vệ phần mềm của bạn — quan điểm thực tế
- Giả định client đọc được hoàn toàn. Không đưa bí mật (API key có quyền ghi, khoá ký, endpoint quản trị) vào app.
- Chuyển niềm tin về server: license, giá, quyền dùng tính năng, chống gian lận phải được xác thực ở server.
- Dùng dịch vụ toàn vẹn của nền tảng (Play Integrity API, Apple App Attest) để server đánh giá request có đến từ app thật không.
- Obfuscate vừa đủ: R8/ProGuard cho Android; obfuscator thương mại chỉ khi tài sản trí tuệ thực sự cần, và đo chi phí hiệu năng/debug.
- Giữ debug symbol riêng (upload lên hệ thống báo cáo crash), strip bản release.
Rủi ro và đạo đức
- Kỹ năng phân tích mã độc cũng có thể dùng để vượt bản quyền. Làm việc trong phạm vi được phép, báo cáo lỗ hổng có trách nhiệm cho nhà cung cấp, không phân phối phần mềm đã bẻ khoá.
- Obfuscation nặng làm crash report khó đọc và có thể bị cửa hàng ứng dụng hoặc antivirus nghi ngờ.
Áp dụng thế nào?
- Dev: lấy một crackme có luồng điều khiển bị làm phẳng trên crackmes.one, thử đọc trong Ghidra, rồi giải bằng script angr ở trên; so sánh thời gian hai cách.
- Tech Lead: threat model trước khi chọn obfuscator: kẻ tấn công lợi gì nếu đọc được code? Thường câu trả lời dẫn tới kiểm tra phía server chứ không phải thêm lớp mã hoá.
- PM: ngân sách bảo vệ nên tỉ lệ với thiệt hại thật (gian lận, mất doanh thu); đừng mua giải pháp "chống crack tuyệt đối" — không tồn tại.
Nguồn & tham khảo
- angr — angr.io
- angr documentation — angr
- google/bindiff — GitHub
- joxeankoret/diaphora — GitHub
- Flare-On Challenge — flare-on.com
- OWASP MASTG — OWASP