Cheatsheet
Trang tra cứu nhanh — gom lại các bảng/kiến thức mình hay phải lật lại tìm trong chính các bài viết của mình. Mỗi mục đều có link về bài gốc để đọc đầy đủ ngữ cảnh. Chia theo nhóm lớn (chọn tab bên dưới) để đỡ phải cuộn qua thứ không liên quan tới thứ đang cần tra.
Reverse Engineering
x86 Data Types
| Tên | Kích thước | Windows API | Kiểu C tương đương | Directive khai báo |
|---|---|---|---|---|
| Byte | 8 bit | BYTE | unsigned char | db |
| Word | 16 bit | WORD | unsigned short | dw |
| Dword | 32 bit | DWORD | unsigned long | dd |
| Qword | 64 bit | QWORD | unsigned long long | dq |
x86 Registers (32-bit)
8 thanh ghi mục đích chung: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP. Chỉ 4 thanh ghi đầu chia được thành sub-register:
EAX (32-bit) └─ AX (16-bit) ─┬─ AH (8-bit cao)
└─ AL (8-bit thấp)ESI, EDI, EBP, ESP chỉ chia được tới 16-bit (SI, DI, BP, SP), không có dạng 8-bit cao/thấp riêng.
3 loại operand:
| Loại | Mô tả | Ví dụ |
|---|---|---|
| Immediate | Giá trị là chính operand đó | 8, 10h, -123, 'A' |
| Register | Giá trị nằm trong thanh ghi | eax, si, ecx, esp |
| Memory | Tham chiếu tới một địa chỉ bộ nhớ | [00020001], [ebp+08h], [eax+esi] |
Công thức địa chỉ hiệu dụng: Effective Address = Base + Index × Scale + Displacement
Stack & PUSH/POP
Stack phát triển về phía địa chỉ thấp hơn. ESP luôn trỏ đỉnh hiện tại.
; PUSH tương đương:
sub esp, 4
mov [esp], <operand>
; POP tương đương:
mov <đích>, [esp]
add esp, 4CALL / RET / Vòng đời Function Call
CALL target = push <địa chỉ lệnh kế tiếp> rồi jmp target. RET pop giá trị đó ra rồi nhảy tới. RET n (vd ret 8) tự cộng thêm n byte vào ESP sau khi pop — đây là callee cleanup.
Vòng đời: chuẩn bị tham số (push phải→trái) → CALL (push return address) → hàm chạy → RET (pop return address) → dọn stack (tùy convention).
String trong binary: ASCII (1 byte/ký tự, kết 0x00) vs Unicode UTF-16LE (2 byte/ký tự, kết 0x00 0x00).
Stack Frame (Prologue/Epilogue)
; Prologue
push ebp
mov ebp, esp
sub esp, N ; cấp N byte cho biến cục bộ
; Epilogue
mov esp, ebp
pop ebp
ret [n]- Tham số → offset dương từ EBP:
[ebp+8]= tham số 1,[ebp+0xC]= tham số 2… - Biến cục bộ → offset âm từ EBP:
[ebp-4],[ebp-8]…
Calling Conventions
| STDCALL | CDECL | __fastcall (x64) | |
|---|---|---|---|
| Ai dọn stack | Callee (RET n) | Caller (ADD ESP, n) | Callee |
| Thường thấy ở | Windows API (WINAPI) | Hàm C chuẩn, printf | Windows x64 mặc định |
| Tham số qua thanh ghi | Không | Không | 4 đầu: RCX, RDX, R8, R9 |
Conditional Jumps
CMP a,b tính a-b nội bộ; TEST a,b tính a AND b nội bộ — chỉ set EFLAGS, không ghi kết quả.
| Signed | Ý nghĩa | Unsigned | Ý nghĩa | Chung | Ý nghĩa |
|---|---|---|---|---|---|
JL | < | JB | < | JZ/JE | == |
JLE | ≤ | JBE | ≤ | JNZ/JNE | != |
JG | > | JA | > | ||
JGE | ≥ | JAE | ≥ |
Mẹo đọc nhanh: dịch mnemonic thành toán tử rồi đọc “nhảy nếu [operand1] toán_tử [operand2]”. Compiler thường đảo ngược điều kiện khi dịch if (nhảy nếu false để bỏ qua thân if).
Debugging & Patching
| Kỹ thuật | Tồn tại | Rủi ro |
|---|---|---|
| Sửa Register/Flag | Tạm thời (mất khi restart) | Thấp |
| Sửa Instruction Pointer (Set IP) | Tạm thời | Có thể làm lệch stack nếu bỏ qua đoạn dọn stack |
| Patch code vào file | Vĩnh viễn | Làm hỏng chữ ký số, phải đúng số byte lệnh cũ/mới |
| NOP’ing-out | Vĩnh viễn | Phải biết đúng độ dài byte lệnh gốc, thiếu/thừa đều crash |
MUL / IMUL
| Lệnh | Kích thước | Phép tính | Kết quả |
|---|---|---|---|
MUL (unsigned) | 32-bit | EAX × r/m32 | EDX:EAX |
IMUL (signed, 1 toán hạng) | 32-bit | EAX × r/m32 | EDX:EAX |
IMUL (2 toán hạng) | — | đích = đích × nguồn | cắt bớt nếu tràn |
IMUL (3 toán hạng) | — | đích = nguồn × hằng số | cắt bớt nếu tràn |
String Instructions & Repeat Prefix
Dùng ESI (nguồn)/EDI (đích), tự tăng/giảm theo Direction Flag (CLD=tăng, STD=giảm):
| Lệnh | Tác dụng |
|---|---|
MOVS | Copy [ESI] → [EDI] |
STOS | Ghi EAX/AL → [EDI] (zero hóa buffer nếu EAX=0 trước) |
SCAS | So EAX/AL với [EDI], chỉ set flag |
REP (lặp theo ECX), REPE/REPZ (lặp khi ZF=1 và ECX>0), REPNE/REPNZ (lặp khi ZF=0 và ECX>0).
Intrinsic hay gặp: memcpy()→rep movs*, memset()→rep stos*, strlen()→repne scasb — lý do nhiều khi không thấy CALL nào tới các hàm này trong disassembly.
Structs & Switch/Jump Table
Struct biến mất hoàn toàn sau compile — nhận ra qua: 1 lệnh memset/STOS khởi tạo nguyên vùng nhớ liên tục, hoặc nhiều lệnh cộng các offset cố định vào cùng 1 base.
Switch nhiều case liên tiếp → compiler dùng jump table:
cmp eax, 4
ja default_case
jmp [jump_table + eax*4]
jump_table:
dd case_0, case_1, case_2, case_3, case_4x86-64 Registers & __fastcall
Mở rộng 8 thanh ghi gốc lên 64-bit (tiền tố R), thêm R8-R15.
| Thứ tự tham số | Thanh ghi |
|---|---|
| 1 | RCX |
| 2 | RDX |
| 3 | R8 |
| 4 | R9 |
Tham số thứ 5 trở đi ra stack tại [RSP+0x20]. Home space = 32-byte caller luôn chừa sẵn ngay dưới return address, để callee spill 4 tham số thanh ghi ra bộ nhớ khi cần. RBP ở x64 không bắt buộc làm frame pointer nữa vì RSP không đổi suốt thân hàm.
MOVSX/MOVSXD giữ dấu khi mở rộng; MOVZX lấp số 0. Không có MOVZXD vì MOV vào thanh ghi 32-bit đã tự zero-extend nửa cao của thanh ghi 64-bit.
Windows API & Internals
Hungarian Notation
| Kiểu Windows | Tiền tố | Ví dụ | Ý nghĩa |
|---|---|---|---|
WORD | w | wYear | số nguyên 16-bit unsigned |
DWORD | dw | dwSize | số nguyên 32-bit unsigned |
LPCSTR | lp | lpFileName | con trỏ tới chuỗi ASCII hằng |
SAL Annotation (trong function prototype)
| Annotation | Ý nghĩa |
|---|---|
_In_ | Caller cung cấp, hàm chỉ đọc |
_Out_ | Hàm ghi ra |
_Inout_ | Cả hai chiều |
_In_opt_ | Tùy chọn, được truyền NULL |
Handles
Handle = index vào bảng handle riêng của từng process — cùng giá trị handle ở 2 process khác nhau có thể trỏ tới 2 object hoàn toàn khác nhau. Vòng đời điển hình: CreateFile → dùng handle (ReadFile…) → CloseHandle.
File API Workflow
I/O: CreateFile → ReadFile / WriteFile → CloseHandle
Enumeration: FindFirstFile → FindNextFile → FindCloseWindows Registry
| Root Key | Viết tắt | Mô tả |
|---|---|---|
HKEY_CURRENT_USER | HKCU | Dữ liệu user đang đăng nhập |
HKEY_USERS | HKU | Thông tin mọi account trên máy |
HKEY_CLASSES_ROOT | HKCR | Liên kết loại file, COM object |
HKEY_LOCAL_MACHINE | HKLM | Cấu hình toàn hệ thống |
HKEY_CURRENT_CONFIG | HKCC | Hardware profile hiện tại |
Malware nhắm nhiều nhất: HKLM và HKCU.
RegCreateKeyEx / RegOpenKeyEx → RegQueryValueEx / RegSetValueEx → RegCloseKeyProcess Loading (PE Loader)
Khi 1 file .exe chạy, code đầu tiên thực thi không phải entry point của chương trình — mà là Windows loader (ntdll.dll):
- Parse PE header
- Dựng virtual memory, map section vào bộ nhớ
- Đệ quy resolve import table (load DLL → resolve import của chính DLL đó)
- Chuyển quyền thực thi tới
AddressOfEntryPoint
LoadLibrary + GetProcAddress = resolve hàm thủ công lúc runtime (Runtime Dynamic Linking) — malware hay dùng để né import table tĩnh.
DLL Usage (ví dụ thực tế)
LoadLibraryA("msvcrt.dll") -> trả về HMODULE (địa chỉ base DLL)
GetProcAddress(hModule, "printf") -> trả về địa chỉ thật của hàmGọi hàm gián tiếp qua con trỏ vừa lấy — không thấy CALL printf tường minh trong disassembly, chỉ thấy CALL [con trỏ].
Windows Networking
| Tầng | Luồng gọi |
|---|---|
| Winsock (client) | socket → connect |
| Winsock (server) | socket → bind → listen → accept |
| WinInet (HTTP) | InternetOpen → InternetConnect → HttpOpenRequest → HttpSendRequest → InternetReadFile → InternetCloseHandle |
Chuỗi gọi WinInet là dấu vết rất rõ để lần ra C2 domain/IP qua import + xref.
SOC / Threat Hunting
Ưu tiên theo dõi đầu tiên
- 1102 — audit log bị xóa (luôn luôn khẩn cấp)
- 4625 hàng loạt rồi 4624 thành công — brute-force trót lọt
- 4688 / Sysmon 1 với command line đáng ngờ (
-enc,IEX,DownloadString…) - Sysmon 10 nhắm
lsass.exe— credential dumping - 4769 số lượng lớn, encryption type yếu — Kerberoasting
- 7045 với binary path lạ — persistence/lateral movement
- 4104 — nội dung PowerShell script sau khi deobfuscate
Logon / Logoff
| Event ID | Ý nghĩa |
|---|---|
| 4624 | Đăng nhập thành công |
| 4625 | Đăng nhập thất bại |
| 4634 | Đăng xuất |
| 4648 | Đăng nhập bằng credential tường minh (runas) |
| 4672 | Tài khoản đặc quyền vừa đăng nhập |
Logon Type (đi kèm 4624):
| Type | Ý nghĩa |
|---|---|
| 2 | Interactive — tại máy |
| 3 | Network — SMB… |
| 4 | Batch — scheduled task |
| 5 | Service |
| 7 | Unlock |
| 8 | NetworkCleartext |
| 9 | NewCredentials (runas /netonly) |
| 10 | RemoteInteractive — RDP |
| 11 | CachedInteractive |
Account Management
| Event ID | Ý nghĩa |
|---|---|
| 4720 | Tạo user mới |
| 4722 | Enable account |
| 4724 | Reset password account khác |
| 4728/4732/4756 | Thêm vào nhóm global/local/universal |
| 4738 | Thuộc tính account bị đổi |
Pattern đáng ngờ: 4720 → 4732 vào Administrators = backdoor account.
Kerberos
| Event ID | Ý nghĩa | Liên quan |
|---|---|---|
| 4768 | Request TGT | Bước đầu xác thực |
| 4769 | Request Service Ticket | Kerberoasting |
| 4771 | Pre-auth thất bại | Brute-force / AS-REP Roasting |
Process / Object / Audit
| Event ID | Ý nghĩa |
|---|---|
| 4688 | Process mới (cần bật audit command-line riêng) |
| 4663 | Hành động cụ thể lên object (đọc/ghi/xóa) |
| 5140/5145 | Truy cập network share |
| 4719 | Audit policy bị đổi |
| 1102 | Audit log bị xóa sạch |
| 7045 | Service mới cài (System log) |
| 4103/4104 | PowerShell module log / Script Block Log |
Sysmon Event IDs
| ID | Ý nghĩa | Vì sao quan trọng |
|---|---|---|
| 1 | Process Create | Thay 4688, kèm hash/cmdline/parent |
| 3 | Network Connect | Phát hiện C2 beaconing |
| 6 | Driver Load | Driver độc hại/rootkit |
| 7 | Image Load | DLL injection/sideloading |
| 8 | CreateRemoteThread | Process injection kinh điển |
| 10 | Process Access | Target lsass.exe = credential dumping |
| 11 | File Create | |
| 12/13/14 | Registry Event | Theo dõi key persistence |
| 15 | FileCreateStreamHash | Alternate Data Stream |
| 22 | DNS Query | DNS tunneling |
Trang này mình sẽ cập nhật dần mỗi khi có bảng tra cứu mới đáng gom vào.