Bài 3: Static Analysis với IDA Pro


1. Tổng quan về Công cụ Reverse Engineering

Trước khi đi vào IDA Pro, cần biết “bức tranh toàn cảnh” — có nhiều công cụ phục vụ reverse engineering, mỗi cái có lý do tồn tại riêng.

Khái niệm & lý thuyết

Disassembler — công cụ chuyển đổi mã máy (binary) thành assembly code có thể đọc được.

Debugger — công cụ cho phép chạy từng bước chương trình, theo dõi trạng thái memory/register.

Các công cụ chính trong reversing community:

Công cụLoạiPhíĐiểm mạnhĐiểm yếu
IDA ProDisassembler + DebuggerCó phíHỗ trợ đa nền tảng, tính năng vượt trộiGiá cao, learning curve dốc
Radare2 (r2)Disassembler + DebuggerMiễn phíOpen source, cross-platformLearning curve dốc
x64dbgDebuggerMiễn phíx64-oriented, plugin ecosystemCòn phát triển
OllyDbgDebuggerMiễn phíDễ dùng, nhiều tutorialKhông hỗ trợ x64, phát triển chậm
GhidraDisassemblerMiễn phíNSA-backed, mạnh ngang IDA

Ví dụ thực tế & Analogy

Analogy: Nếu một binary là căn nhà đã bị khóa cửa, thì disassembler là bản vẽ kiến trúc giúp bạn hiểu cấu trúc bên trong — còn debugger là chìa khóa vạn năng cho phép bạn bước vào từng phòng theo thời gian thực.

Thực tế: ESET Labs dùng IDA Pro để reverse engineer malware phục vụ xây dựng signature cho AV.

⚠️ Điểm hay gặp sai

Câu hỏi thực tế

  1. Khi bạn nhận được một file .exe bị nghi là malware và cần phân tích nhanh mà không cần chạy — bạn dùng disassembler hay debugger trước?
  2. Team bạn cần reversing cả binary 32-bit lẫn 64-bit, nhưng ngân sách bằng 0 — bạn chọn công cụ gì và tại sao?

💡 Chốt nhanh: IDA Pro = vua disassembler, đắt nhưng đỉnh. Radare2/Ghidra = miễn phí, đủ mạnh cho học tập và CTF. x64dbg = debugger hiện đại nhất cho Windows binary.


2. IDA Pro — Giao diện & Chế độ hiển thị

Khái niệm & lý thuyết

IDA Pro có hai chế độ hiển thị chính:

Graph Mode (mặc định) — hiển thị control flow graph (CFG) dưới dạng các block nối với nhau bằng mũi tên màu sắc.

Text Mode — hiển thị disassembly dạng dòng tuần tự như text editor truyền thống, kèm địa chỉ và section label.

Phím Spacebar chuyển đổi qua lại giữa hai chế độ.

Cách hoạt động — Màu sắc mũi tên trong Graph Mode

graph TD A["Block A
cmp eax, 0Ah
jle short loc_X"] -->|"🟢 Green — Jump taken (True)"| B["Block B
Good!"] A -->|"🔴 Red — Jump NOT taken (False)"| C["Block C
No problem."] D["Block D
loop body"] -->|"🔵 Blue — Unconditional jmp"| E["Block E"] F["Block F"] -->|"⬆️ Upward arrow = LOOP"| F
MàuÝ nghĩa
🟢 Xanh láConditional jump được thực hiện (condition = true)
🔴 ĐỏConditional jump không được thực hiện (condition = false)
🔵 Xanh dươngUnconditional jump (jmp)
⬆️ Mũi tên đi lênLoop — nhảy ngược về địa chỉ cao hơn

Trong Text Mode, convention khác:

  • Solid arrow = unconditional jump
  • Dashed arrow = conditional jump
  • Arrow đi lên = loop

Thanh màu nằm phía trên IDA cho biết loại code:

  • 🔵 Xanh nhạt — Library code (không cần phân tích sâu)
  • 🔴 Đỏ — Compiler-generated code
  • 🔵 Xanh đậmUser-written code → đây là phần cần tập trung phân tích

Ví dụ thực tế & Analogy

Analogy: Graph mode giống bản đồ metro — bạn thấy ngay ga nào nối ga nào, rẽ trái hay rẽ phải. Text mode giống đọc lịch trình chuyến tàu từng dòng — chi tiết hơn nhưng mất nhiều thời gian để hiểu tổng thể.

// Source code gốc
if (abc > 10) {
    printf("\n Good!");
} else {
    printf("\n No problem.");
}

Trong Graph Mode, IDA tạo ra 3 block:

  • Block điều kiện (cmp, jle)
  • Block “Good!” → mũi tên xanh lá từ block điều kiện
  • Block “No problem.” → mũi tên đỏ từ block điều kiện

⚠️ Điểm hay gặp sai

Câu hỏi thực tế

  1. Bạn đang phân tích một hàm trong Graph Mode và thấy một mũi tên màu đỏ đi lên — điều đó nói lên gì về cấu trúc code?
  2. Trong Navigation Band, phần nào bạn nên click vào đầu tiên khi bắt đầu phân tích malware và tại sao?

💡 Chốt nhanh: Graph Mode = nhìn tổng thể control flow; Text Mode = đọc chi tiết từng instruction. Màu mũi tên = ngôn ngữ riêng của IDA — phải thuộc lòng.


3. Các cửa sổ phân tích quan trọng

Khái niệm & lý thuyết

IDA Pro cung cấp nhiều sub-window, mỗi cái phục vụ một mục đích khác nhau trong quá trình phân tích.

Functions Window

Liệt kê tất cả hàm được IDA nhận diện, kèm:

  • Segment (.text, .data…)
  • Start address
  • Length — hàm có length lớn thường chứa logic phức tạp hơn → ưu tiên phân tích
  • Flags: L = Library function (bỏ qua), R, S, B, T

Tip: Sort theo Length giảm dần để tìm hàm “béo” nhất — thường là nơi chứa logic chính của malware.

Names Window

Liệt kê mọi địa chỉ có tên, bao gồm: functions, named code, named data, strings.

PrefixÝ nghĩa
FFunction (user-defined)
LLibrary function

Strings Window

Hiển thị tất cả chuỗi tìm thấy trong binary — đây là điểm khởi đầu tuyệt vời khi phân tích malware vì strings thường tiết lộ: URL C2, registry key, tên file, thông điệp lỗi.

Imports & Exports Window

  • Imports: Danh sách API/DLL mà binary gọi → biết ngay khả năng của malware (network? registry? file system?)
  • Exports: Hàm mà binary expose ra ngoài

Structures Window

Hiển thị tất cả data structures đang active. Hover để xem pop-up màu vàng hiện chi tiết từng field.

Cách hoạt động — Luồng phân tích từ Strings đến Code

sequenceDiagram participant A as Analyst participant S as Strings Window participant D as Disassembly View participant X as XREF Dialog A->>S: Mở Strings Window A->>S: Double-click "Error 1.1: No Internet" S->>D: Jump đến vị trí string trong disassembly A->>D: Hover over DATA XREF comment D-->>A: Pop-up hiện nơi string được dùng A->>D: Nhấn X (Ctrl+X) D->>X: Hiện toàn bộ cross-references A->>X: Double-click để jump đến caller

Ví dụ thực tế & Analogy

Analogy: Strings Window giống việc lật sách ra xem mục lục và phần chú thích — bạn chưa đọc toàn bộ sách nhưng đã biết sách nói về gì. Sau đó dùng XREF để tìm trang nào nhắc đến keyword đó.

Ví dụ thực tế: Thấy string "InternetGetConnectedState" trong Imports → malware có khả năng kiểm tra kết nối internet trước khi thực hiện hành động độc hại.

⚠️ Điểm hay gặp sai

Câu hỏi thực tế

  1. Khi mở một binary trong IDA, bạn thấy Imports có RegSetValueExW, CreateFileA, InternetOpenA — bạn suy luận gì về hành vi của binary?
  2. Làm thế nào để từ một string thú vị trong Strings Window, bạn tìm được hàm main() đang dùng string đó?

💡 Chốt nhanh: Strings → XREF → Code = luồng phân tích cơ bản nhất. Functions Window sort theo size để tìm điểm vào. Imports tiết lộ “vũ khí” của malware.


4. Điều hướng trong IDA Pro

Khái niệm & lý thuyết

Cross-Reference (XREF) — cơ chế IDA theo dõi mọi nơi một symbol (hàm, data, string) được sử dụng hoặc được gọi đến.

Hai loại XREF:

  • Code XREF — hàm A gọi hàm B → XREF từ A đến B
  • Data XREF — instruction tại địa chỉ X đọc/ghi data tại địa chỉ Y

Các phím tắt quan trọng

PhímTác dụng
Double-clickJump đến địa chỉ/symbol được click
Esc / Back buttonQuay lại vị trí trước (như browser history)
GJump to address — nhập hex address hoặc tên symbol
X (hoặc Ctrl+X)Hiện tất cả cross-references đến symbol đang chọn
SpacebarToggle Graph ↔ Text mode
Alt+TSearch text
Alt+BSearch sequence of bytes

Cách hoạt động — XREF trong thực tế

graph LR subgraph "Code XREF" main["_main()"] -->|"call"| sub["sub_401000()"] start["start()"] -->|"call"| main end subgraph "Data XREF" instr["mov ecx, offset aError1_1NoInte"] -->|"DATA XREF"| str["'.data:aError1_1NoInte'
'Error 1.1: No Internet'"] end

XREF comment trong disassembly view có dạng:

.text:00401440 _main  proc near    ; CODE XREF: start+DE↓p
  • start+DE = địa chỉ trong hàm start gọi đến main
  • ↓p = direction down, type p (call instruction)

Để xem tất cả XREF (không chỉ 1-2 cái mặc định): click vào tên hàm → nhấn X.

Graphing Options — XREF Visualization

  • View → Graphs → Xrefs to: Hiển thị tất cả đường đi dẫn vào một hàm
  • View → Graphs → Xrefs from: Hiển thị tất cả hàm mà một hàm gọi ra
  • View → Graphs → Function calls: Toàn bộ call graph của chương trình

Ví dụ thực tế & Analogy

Analogy: XREF giống tính năng “Find all references” trong IDE như VS Code — bạn click vào một function, IDE hiện tất cả nơi gọi function đó. IDA làm điều tương tự nhưng với binary đã compiled.

⚠️ Điểm hay gặp sai

Câu hỏi thực tế

  1. Bạn muốn tìm tất cả nơi trong binary gọi đến CreateFileA — bạn làm theo bước nào trong IDA?
  2. Phím G trong IDA có thể nhận input là gì — chỉ hex address hay còn gì khác?

💡 Chốt nhanh: Double-click để navigate, Esc để quay lại, X để xem tất cả XREF. Navigation Band màu đậm = user code = phần cần đọc.


5. Tùy chỉnh và Nâng cao chất lượng Disassembly

Khái niệm & lý thuyết

IDA Pro cho phép annotaterename để biến assembly khó hiểu thành code có ý nghĩa — đây là kỹ năng cốt lõi của reverse engineer.

FLIRT (Fast Library Identification and Recognition Technology) — hệ thống nhận diện library code của IDA dựa trên code signature. Cả free và paid version đều có FLIRT.

Các thao tác nâng cao disassembly

1. Renaming

Click vào tên (sub_401000) → nhấn N → nhập tên có ý nghĩa (DecryptPayload).

IDA sẽ tự động cập nhật tên này ở tất cả XREF — không cần sửa thủ công từng nơi.

Trước khi rename:

004013C8  mov   eax, [ebp+arg_4]
004013D4  mov   [ebp+var_598], ax

Sau khi rename arg_4port_strvar_598port:

004013C8  mov   eax, [ebp+port_str]
004013D4  mov   [ebp+port], ax

2. Comments

PhímTác dụng
: (colon)Thêm comment tại dòng hiện tại (chỉ xuất hiện 1 nơi)
; (semicolon)Thêm repeatable comment — echo đến tất cả XREF

3. Formatting Operands

Mặc định IDA hiển thị số theo hexadecimal. Right-click vào operand để chuyển sang:

  • Decimal (4896)
  • Octal (11440o)
  • Binary (1001100100000b)
  • Named constant (quan trọng nhất!)

4. Named Constants

IDA tự động gợi ý Windows API constants. Trước:

push  80h         ; dwFlagsAndAttributes
push  3           ; dwCreationDisposition
push  0           ; lpSecurityAttributes
push  1           ; dwShareMode

Sau khi apply symbolic constants:

push  FILE_ATTRIBUTE_NORMAL   ; dwFlagsAndAttributes
push  OPEN_EXISTING           ; dwCreationDisposition
push  NULL                    ; lpSecurityAttributes
push  FILE_SHARE_READ         ; dwShareMode

5. Options → General

Có thể bật Auto comments — IDA tự thêm comment giải thích mỗi instruction:

jz   short loc_40102B  ; Jump if Zero (ZF=1)
call sub_40105F        ; Call Procedure
xor  eax, eax         ; Logical Exclusive OR

Cách hoạt động — Quy trình phân tích hàm

flowchart TD A["Mở Functions Window"] --> B["Sort by Length, chọn hàm lớn"] B --> C["Xem Graph Mode — hiểu control flow tổng thể"] C --> D["Đọc Strings và Imports liên quan"] D --> E["Rename variables/functions theo ý nghĩa"] E --> F["Add comments tại điểm quan trọng"] F --> G["Dùng XREF để trace caller/callee"] G --> H["Lặp lại với hàm tiếp theo"]

Ví dụ thực tế & Analogy

Analogy: Renaming trong IDA giống việc dùng bút highlight và ghi chú vào lề sách giáo khoa — sách vẫn vậy nhưng bạn đã thêm context của mình vào, lần sau đọc lại nhanh hơn nhiều.

⚠️ Điểm hay gặp sai

Câu hỏi thực tế

  1. Bạn thấy hàm sub_401000 được gọi ở 30 nơi khác nhau, và sau phân tích bạn biết nó decrypt string. Bạn sẽ làm gì để việc phân tích các caller sau này dễ hơn?
  2. Khi thấy push 3 trước một call đến CreateFileA, làm thế nào để IDA tự hiển thị push OPEN_EXISTING thay vì con số?

💡 Chốt nhanh: Rename + Comment = đầu tư thời gian ban đầu để tiết kiệm thời gian phân tích về sau. Named constants biến số hex vô nghĩa thành Windows API constant có ý nghĩa rõ ràng.


6. Mở rộng IDA với Scripts & Plugins

Khái niệm & lý thuyết

IDA Pro hỗ trợ hai ngôn ngữ scripting:

  • IDC — ngôn ngữ scripting nội bộ của IDA (C-like syntax)
  • IDAPython — Python binding cho IDA API (phổ biến hơn nhiều trong cộng đồng hiện đại)

Paid version còn cung cấp SDK để viết plugin native.

Ứng dụng thực tế của scripts

# Ví dụ IDAPython: Tự động rename tất cả function bắt đầu bằng sub_
import idc
import idautils

for func_ea in idautils.Functions():
    name = idc.get_func_name(func_ea)
    if name.startswith("sub_"):
        # Thêm prefix để dễ nhận biết
        idc.set_name(func_ea, f"UNKNOWN_{name}", idc.SN_NOCHECK)

⚠️ Điểm hay gặp sai


💡 Chốt nhanh: IDAPython là cầu nối giữa IDA Pro và Python ecosystem — cho phép tự động hóa mọi thao tác thủ công. Đây là kỹ năng phân biệt reverse engineer cơ bản và chuyên nghiệp.


Quiz — IDA Pro & Static Analysis


Tầng 1 — Ghi nhớ

Câu 1. IDA Pro lần đầu được phát hành vào khoảng thời gian nào?

  • Đầu những năm 2000
  • Giữa những năm 1990
  • Năm 2006
  • Năm 2013

Câu 2. Phím tắt nào dùng để chuyển đổi giữa Graph Mode và Text Mode trong IDA Pro?

  • Tab
  • Enter
  • Spacebar
  • Ctrl+G

Câu 3. Trong Graph Mode của IDA Pro, mũi tên màu xanh lá (green) thể hiện điều gì?

  • Unconditional jump
  • Conditional jump không được thực hiện
  • Conditional jump được thực hiện (taken)
  • Loop

Câu 4. FLIRT trong IDA Pro là viết tắt của gì?

  • Fast Library Integration and Runtime Technology
  • Fast Library Identification and Recognition Technology
  • Function Label Identification and Reverse Tooling
  • File Loading and Instruction Recognition Tool

Câu 5. Trong Navigation Band của IDA Pro, màu xanh đậm (dark blue) đại diện cho loại code nào?

  • Library code
  • Compiler-generated code
  • User-written code
  • Import table

Câu 6. Phím nào trong IDA Pro dùng để xem tất cả cross-references đến một symbol?

  • C
  • R
  • N
  • X

Câu 7. Trong IDA Pro, pressing : (colon) thực hiện hành động gì?

  • Thêm comment tại dòng hiện tại (single comment)
  • Thêm repeatable comment echo đến tất cả XREF
  • Rename symbol
  • Format operand

Tầng 2 — Hiểu & phân tích

Câu 8. Analyst đang phân tích một malware và thấy mũi tên đi ngược lên (upward arrow) trong Graph Mode. Điều này có nghĩa là gì?

  • Hàm đang gọi một hàm khác từ thư viện
  • Có unconditional jump đến đầu file
  • Có vòng lặp (loop) trong code
  • Control flow trở về hàm caller

Câu 9. Tại sao analyst nên ưu tiên phân tích các hàm có length lớn trong Functions Window?

  • Hàm dài hơn chạy chậm hơn và dễ debug hơn
  • IDA Pro phân tích hàm dài chính xác hơn
  • Hàm lớn thường chứa nhiều logic phức tạp hơn và có nhiều khả năng là code quan trọng
  • Hàm dài thường là library function dễ nhận diện

Câu 10. So sánh XREF toXREF from trong graphing options của IDA — sự khác biệt cốt lõi là gì?

  • Xrefs to hiển thị graph của toàn bộ chương trình; Xrefs from chỉ hiển thị 1 level
  • Xrefs to hiển thị đường đi DẪN VÀO hàm; Xrefs from hiển thị hàm nào được gọi RA từ hàm đó
  • Xrefs to chỉ hoạt động với code references; Xrefs from hoạt động với data references
  • Không có sự khác biệt thực tế

Câu 11. Tại sao việc apply Named Constants trong IDA lại quan trọng khi phân tích Windows binary?

  • Giúp IDA phân tích nhanh hơn
  • Thay thế việc đọc tài liệu Windows API
  • Biến các giá trị số vô nghĩa thành tên constant có ý nghĩa, giúp hiểu ngay Windows API được gọi với parameter nào
  • Chỉ quan trọng khi phân tích malware, không cần cho binary thông thường

Câu 12. Radare2 khác IDA Pro ở điểm cốt lõi nào?

  • Radare2 chỉ hỗ trợ Linux, IDA Pro chỉ hỗ trợ Windows
  • Radare2 là debugger thuần túy, không có disassembler
  • Radare2 là open source còn IDA Pro là proprietary — nhưng cả hai có khả năng tương đương nhau
  • Radare2 không hỗ trợ plugin

Tầng 3 — Vận dụng

Câu 13. Bạn nhận được một file .exe bị nghi là malware. Trong Imports window của IDA, bạn thấy: InternetOpenA, InternetConnectA, HttpSendRequestA, RegSetValueExW, CreateProcessA. Bạn kết luận malware này có khả năng làm gì?

  • Chỉ đơn giản là một web browser
  • Chỉ có khả năng đọc/ghi registry
  • Có khả năng kết nối internet (C2 communication), ghi vào registry (persistence), và tạo process mới (execution)
  • Đây là một installer thông thường, không phải malware

Câu 14. Trong quá trình phân tích, bạn tìm thấy string "cmd.exe /c whoami" trong Strings Window. Bước tiếp theo hiệu quả nhất để hiểu string này được dùng như thế nào là gì?

  • Đóng IDA và chạy binary trong sandbox để xem output
  • Search toàn bộ disassembly bằng Text search
  • Double-click vào string để jump đến vị trí nó được định nghĩa, sau đó nhấn X để xem tất cả nơi nó được referenced trong code
  • Mở Structures window để tìm struct chứa string này

Câu 15. Team của bạn cần phân tích một malware family với 50+ variant. Mỗi variant có hàm decrypt strings tại địa chỉ khác nhau nhưng logic giống nhau. Cách nào là scalable nhất để xử lý tình huống này trong IDA?

  • Phân tích thủ công từng variant một
  • Chỉ phân tích variant đầu tiên và assume các variant khác giống nhau
  • Viết IDAPython script để tự động nhận diện và rename hàm decrypt dựa trên pattern (byte signature hoặc import list), apply cho tất cả variant
  • Dùng FLIRT để tạo signature cho hàm decrypt