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ảng | Cho thấy |
|---|---|---|
strace -f | Linux | System call: file mở, socket, tiến trình con |
ltrace | Linux | Lời gọi thư viện động (strcmp, malloc, SSL_write) |
| Process Monitor | Windows | Hoạt động file, registry, mạng |
fs_usage, dtruss | macOS | File 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
- Tìm hàm ứng viên trong Ghidra (ví dụ hàm tham chiếu chuỗi "invalid license").
- Ghi offset của nó so với image base.
- Đặt breakpoint hoặc hook Frida, đưa input có kiểm soát.
- Xem tham số và giá trị trả về; đổi tên, gán kiểu lại trong Ghidra.
- 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à
stracecũ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
- Frida documentation — frida.re
- pwndbg — GitHub
- OpenSecurityTraining2 — OST2