Tools

Reverse Engineering (3/5): phân tích động với strace, GDB và Frida

Tóm tắt

Giả thuyết ở Ghidra, bằng chứng ở debugger. Bắt đầu bằng ltrace/strace, dùng GDB để xác nhận, và Frida để hook hàm mà không cần biên dịch lại.

Phân tích tĩnh cho biết code có thể làm gì; phân tích động cho thấy nó thực sự làm gì với input thật. Người làm chuyên nghiệp chuyển qua lại liên tục: đặt giả thuyết trong Ghidra, xác nhận bằng debugger trong vài chục giây. Bài 3 trong loạt Reverse Engineering cho lập trình viên đi qua tracing hộp đen, debugger và instrumentation với Frida.

Bắt đầu bằng tracing hộp đen

Trước khi gắn debugger, hãy quan sát chương trình từ bên ngoài:

Công cụNền tảngCho thấy
strace -fLinuxSystem call: file mở, socket, tiến trình con
ltraceLinuxLời gọi thư viện động (strcmp, malloc, SSL_write)
Process MonitorWindowsHoạt động file, registry, mạng
fs_usage, dtrussmacOSFile và system call (SIP có thể giới hạn)

Chỉ một lệnh ltrace ./crackme AAAA nhiều khi đã lộ ra strcmp("AAAA", "s3cr3t") — chiến thắng rẻ nhất trong dịch ngược.

Debugger

  • GDB + pwndbg hoặc GEF (Linux): plugin hiển thị thanh ghi, stack, disassembly trên một màn hình.
  • x64dbg (Windows): chuẩn miễn phí cho user-mode.
  • LLDB (macOS, iOS): debugger gốc của Apple.
  • WinDbg cho kernel/crash dump; rr trên Linux ghi lại và phát lại, chạy ngược về đúng lúc bộ nhớ bị hỏng.
break *0x401a30          # breakpoint theo địa chỉ
break strcmp             # breakpoint theo tên hàm
watch *(int*)0x404040    # dừng khi bộ nhớ đổi
run AAAA
ni / si                  # đi từng lệnh
x/16gx $rsp              # xem stack
finish                   # chạy tới khi hàm trả về
set $rax = 1             # sửa giá trị trả về

Binary PIE đổi địa chỉ mỗi lần chạy: dùng starti rồi vmmap (pwndbg) để tìm base, hoặc tắt ASLR trong lab bằng setarch -R ./target.

Instrumentation với Frida

Frida tiêm một engine JavaScript vào tiến trình đang chạy, cho phép hook hàm bất kỳ mà không cần biên dịch lại. Chạy trên Windows, macOS, Linux, Android, iOS.

// hook.js — log mọi lời gọi strcmp
Interceptor.attach(Module.getGlobalExportByName('strcmp'), {
  onEnter(args) {
    this.a = args[0].readUtf8String();
    this.b = args[1].readUtf8String();
  },
  onLeave(ret) {
    console.log(`strcmp("${this.a}", "${this.b}") = ${ret.toInt32()}`);
  }
});
frida -f ./target -l hook.js       # khởi chạy và hook
frida-trace -i "recv*" -p 1234     # tự sinh hook cho PID đang chạy

Dùng Frida để dump buffer đã giải mã sau khi hàm decrypt trả về, log tham số của hàm nội bộ tìm được trong Ghidra (địa chỉ base của module + offset), hoặc thay giá trị trả về. Tên API có thể đổi giữa các phiên bản Frida — kiểm tra tài liệu cho bản bạn cài.

Vòng lặp tĩnh + động

  1. Tìm hàm ứng viên trong Ghidra (ví dụ hàm tham chiếu chuỗi "invalid license").
  2. Ghi offset của nó so với image base.
  3. Đặt breakpoint hoặc hook Frida, đưa input có kiểm soát.
  4. Xem tham số và giá trị trả về; đổi tên, gán kiểu lại trong Ghidra.
  5. Lặp lại với hàm kế tiếp trong chuỗi gọi.

Rủi ro và lưu ý

  • Chạy là có rủi ro: mẫu lạ chỉ chạy trong máy ảo có snapshot, tắt thư mục chia sẻ, cô lập mạng (host-only hoặc giả lập dịch vụ). FLARE-VM và REMnux có sẵn bộ công cụ.
  • Chống debug: nhiều chương trình phát hiện debugger và đổi hành vi — xem bài 5.
  • Quyền: chỉ instrument phần mềm bạn sở hữu hoặc được phép kiểm thử.

Áp dụng thế nào?

  • Dev: giải lại crackme ở bài 2 theo ba cách — chỉ ltrace, breakpoint tại lệnh so sánh trong GDB, và một script Frida 10 dòng in giá trị đúng.
  • Tech Lead: Frida và strace cũng là công cụ debug production tuyệt vời cho chính app của team: xem app gọi file/mạng gì mà không cần build lại.
  • PM: chuẩn bị máy ảo lab dùng chung (snapshot sẵn công cụ) giúp người mới bắt đầu trong vài giờ thay vì vài ngày.

Nguồn & tham khảo

  1. Frida documentation — frida.re
  2. pwndbg — GitHub
  3. OpenSecurityTraining2 — OST2