Bài 7: Anti Dynamic Analysis
1. Anti-Debugging
Tổng quan
Anti-debugging là kỹ thuật chống phân tích động được mã độc sử dụng nhằm:
- Nhận biết khi nào nó đang bị kiểm soát bởi một debugger.
- Cản trở hoạt động của debugger để làm chậm quá trình phân tích.
Khi mã độc phát hiện ra đang bị debug, nó có thể:
- Thay đổi luồng thực thi bình thường (rẽ sang code path khác).
- Chỉnh sửa code gây ra crash, làm cho nhà phân tích tốn thêm thời gian và công sức.
2. Windows Debugger Detection
2.1 Sử dụng Windows API
Windows cung cấp một số hàm API có thể được chương trình dùng để xác định xem nó có đang bị debug hay không. Một số hàm được thiết kế chuyên cho việc phát hiện debugger, một số khác được dùng lại (repurpose) cho mục đích này.
2.1.1 IsDebuggerPresent
BOOL WINAPI IsDebuggerPresent(void);Cơ chế hoạt động:
- Kiểm tra trường
BeingDebuggedtrong cấu trúc Process Environment Block (PEB) của tiến trình hiện tại. - Nếu tiến trình đang chạy trong ngữ cảnh của debugger → trả về khác 0 (nonzero).
- Nếu tiến trình KHÔNG bị debug → trả về 0.
Ghi chú:
- Hàm này cho phép ứng dụng tự biết mình có đang bị debug không để thay đổi hành vi.
- Ví dụ: ứng dụng có thể gọi
OutputDebugStringđể in thêm thông tin nếu phát hiện có debugger. - Để kiểm tra tiến trình khác (remote process), dùng
CheckRemoteDebuggerPresent.
2.1.2 CheckRemoteDebuggerPresent
BOOL WINAPI CheckRemoteDebuggerPresent(
_In_ HANDLE hProcess,
_Inout_ PBOOL pbDebuggerPresent
);Tham số:
hProcess: Handle của tiến trình cần kiểm tra.pbDebuggerPresent: Con trỏ đến biến boolean — hàm sẽ đặt thànhTRUEnếu tiến trình đang bị debug,FALSEnếu không.
Lưu ý quan trọng:
- Từ “remote” ở đây không có nghĩa là debugger nằm trên máy khác.
- “Remote” ở đây nghĩa là debugger nằm trong một tiến trình song song, tách biệt.
IsDebuggerPresentchỉ dùng cho tiến trình đang gọi;CheckRemoteDebuggerPresentdùng cho bất kỳ tiến trình nào thông qua handle.
2.1.3 NtQueryInformationProcess
NTSTATUS WINAPI NtQueryInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);Cơ chế hoạt động:
- Truy xuất thông tin về một tiến trình được chỉ định.
- Tham số
ProcessInformationClassxác định loại thông tin cần lấy. - Giá trị
ProcessDebugPort(=0x7) sẽ trả về:- 0 nếu tiến trình không bị debug.
- Port number (khác 0) nếu tiến trình đang bị debug.
2.1.4 OutputDebugString
void WINAPI OutputDebugString(_In_opt_ LPCTSTR lpOutputString);Cơ chế phát hiện debugger:
DWORD errorValue = 12345;
SetLastError(errorValue);
OutputDebugString("Test for Debugger");
if (GetLastError() == errorValue) {
ExitProcess(); // Không có debugger → hàm thất bại → error code không đổi
} else {
RunMaliciousPayload(); // Có debugger → hàm thành công → error code bị thay đổi
}Logic:
- Gán một giá trị lỗi tùy ý bằng
SetLastError. - Gọi
OutputDebugString. - Nếu có debugger đính kèm: hàm thành công → error code sẽ bị thay đổi →
GetLastError()≠errorValue→ chạy payload độc hại. - Nếu không có debugger: hàm thất bại → error code giữ nguyên →
GetLastError()==errorValue→ thoát.
2.2 Kiểm tra Cấu trúc Thủ công (Manually Checking Structures)
Mã độc thường không tin tưởng vào Windows API vì:
- API có thể bị hook bởi rootkit để trả về thông tin giả.
- Do đó, tác giả mã độc thường tự thực hiện kiểm tra tương đương API một cách thủ công ở cấp độ assembly.
2.2.1 Kiểm tra BeingDebugged Flag
Cấu trúc PEB (Process Environment Block):
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged; // <-- Flag quan trọng (offset 0x2)
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;- PEB được trỏ tới qua địa chỉ
fs:[30h]trong khi tiến trình chạy. BeingDebuggednằm tại offset 0x2 trong PEB.
Assembly kiểm tra (hai cách):
mov eax, dword ptr fs:[30h] ; EAX = địa chỉ PEB
mov ebx, byte ptr [eax+2] ; EBX = BeingDebugged flag
test ebx, ebx
jz NoDebuggerDetected ; Nếu = 0 thì không bị debugpush dword ptr fs:[30h] ; Đẩy địa chỉ PEB vào stack
pop edx ; EDX = địa chỉ PEB
cmp byte ptr [edx+2], 1 ; So sánh BeingDebugged với 1
je DebuggerDetected2.2.2 Kiểm tra ProcessHeap Flag
ProcessHeapnằm tại offset 0x18 trong PEB — trỏ tới heap đầu tiên của tiến trình.- Trong heap header, trường
ForceFlags:- Windows XP: offset
0x10 - Windows 7 (32-bit): offset
0x44
- Windows XP: offset
- Khi có debugger:
ForceFlags≠ 0. - Khi không có debugger:
ForceFlags= 0.
mov eax, large fs:30h ; EAX = PEB
mov eax, dword ptr [eax+18h] ; EAX = ProcessHeap (offset 0x18)
cmp dword ptr ds:[eax+10h], 0 ; Kiểm tra ForceFlags (offset 0x10)
jne DebuggerDetected2.2.3 Kiểm tra NtGlobalFlag
NtGlobalFlagnằm tại offset 0x68 trong PEB.- Khi không có debugger: giá trị =
0x0. - Khi có debugger: giá trị thường =
0x70, bao gồm các flag:FLG_HEAP_ENABLE_TAIL_CHECKFLG_HEAP_ENABLE_FREE_CHECKFLG_HEAP_VALIDATE_PARAMETERS
mov eax, large fs:30h ; EAX = PEB
cmp dword ptr ds:[eax+68h], 70h ; Kiểm tra NtGlobalFlag
jz DebuggerDetected2.3 Tìm kiếm Dấu vết Hệ thống (Checking for System Residue)
Khi phân tích mã độc, các công cụ debug để lại dấu vết trên hệ thống. Mã độc có thể tìm kiếm những dấu vết này để nhận biết môi trường phân tích.
Các phương pháp:
- Registry keys: Tìm kiếm khóa registry liên quan đến debugger, ví dụ:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug - File/thư mục: Tìm kiếm file thực thi của các debugger phổ biến.
- Process listing: Duyệt danh sách tiến trình đang chạy để tìm debugger.
- FindWindow API: Tìm kiếm cửa sổ của debugger theo tên class:
HWND WINAPI FindWindow(
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName
);
if (FindWindow("OLLYDBG", 0) == NULL) {
// Debugger Not Found
} else {
// Debugger Detected
}2.4 Nhận Diện Hành Vi Debugger (Identifying Debugger Behavior)
Debugger sử dụng breakpoint và single-step để theo dõi thực thi. Mã độc có thể phát hiện các hành vi này qua:
- INT scanning
- Checksum checks
- Timing checks
2.4.1 INT Scanning
- INT 3 (opcode
0xCC) là software interrupt mà debugger dùng để đặt breakpoint. - Khi đặt breakpoint tại một địa chỉ, debugger thay thế byte đầu tiên của lệnh tại đó bằng
0xCC. - Mã độc có thể quét vùng code của chính mình để tìm byte
0xCC:
call next_line ; Đẩy địa chỉ tiếp theo vào stack
next_line:
pop edi ; EDI = địa chỉ hiện tại
sub edi, 5 ; Điều chỉnh về đầu vùng cần quét
mov ecx, 400h ; Độ dài vùng quét
mov eax, 0CCh ; Tìm byte 0xCC
repne scasb ; Quét
jz DebuggerDetected ; Nếu tìm thấy → có breakpoint → có debugger2.4.2 Code Checksums
- Mã độc tính CRC hoặc MD5 checksum trên một đoạn code của chính mình.
- Nếu debugger đặt breakpoint (thay byte bằng
0xCC), checksum sẽ thay đổi so với giá trị gốc. - Phát hiện sự thay đổi checksum → kết luận có debugger.
2.4.3 Timing Checks
Tiến trình chạy chậm hơn đáng kể khi bị debug. Mã độc khai thác điều này.
Hai chiến lược:
- Ghi timestamp → thực hiện vài thao tác → ghi timestamp → so sánh độ chênh lệch.
- Ghi timestamp trước và sau khi raise exception — exception không có debugger xử lý rất nhanh, còn qua debugger thì chậm hơn nhiều.
rdtsc (Read Time-Stamp Counter, opcode 0x0F31) trả về số tick kể từ lần reboot cuối dưới dạng giá trị 64-bit trong EDX:EAX.
rdtsc ; Lần đọc 1
xor ecx, ecx
add ecx, eax
rdtsc ; Lần đọc 2
sub eax, ecx ; Tính hiệu
cmp eax, 0xFFF0 ; Nếu hiệu lớn → debugger làm chậm
jb NoDebuggerDetecteda = GetTickCount();
MaliciousActivityFunction();
b = GetTickCount();
delta = b - a;
if (delta > 0x1A) {
// Debugger Detected
} else {
// Debugger Not Found
}GetTickCount() trả về số millisecond kể từ lần reboot cuối.
GetTickCount.2.5 Can Thiệp Chức Năng Debugger (Interfering with Debugger Functionality)
Mã độc có thể sử dụng các kỹ thuật sau để cản trở hoạt động bình thường của debugger:
- TLS Callbacks
- Exceptions
- Interrupt insertion
2.5.1 TLS Callbacks
- TLS (Thread Local Storage) callbacks là các subroutine được thực thi trước entry point của chương trình.
- Thông tin về TLS callback được mô tả trong PE header.
- Mã độc dùng TLS callback để thực thi code bí mật trước khi debugger đặt breakpoint tại entry point.
- Analyst cần chú ý đặt breakpoint ngay từ đầu quá trình load, không chỉ tại entry point.
2.6 Khai thác Lỗ hổng Debugger (Debugger Vulnerabilities)
2.6.1 PE Header Vulnerabilities
- Mã độc chỉnh sửa PE header theo cách khiến OllyDbg crash khi tải file.
- OllyDbg báo lỗi: “Bad or Unknown 32-bit Executable File”.
- Tuy nhiên chương trình vẫn chạy bình thường bên ngoài debugger.
2.6.2 OutputDebugString Vulnerability
- Khai thác format string vulnerability trong OllyDbg v1.1.
- Gọi
OutputDebugStringvới chuỗi chứa toàn%s:
OutputDebugString("%s%s%s%s%s%s%s%s%s%s%s%s%s%s");- Nếu được thực thi, OllyDbg sẽ crash do cố gắng đọc chuỗi format không hợp lệ.
3. Anti-Virtual Machine (Anti-VM) Techniques
3.1 VMware Artifacts
VMware để lại nhiều dấu vết trên hệ thống, đặc biệt khi VMware Tools được cài đặt:
Tiến trình VMware:
VMwareService.exeVMwareTray.exeVMwareUser.exe
Mã độc có thể duyệt danh sách tiến trình và tìm chuỗi “VMware”.
3.1.1 VMwareService.exe
- Chạy VMware Tools Service, là tiến trình con của
services.exe. - Có thể phát hiện qua registry hoặc lệnh:
net start | findstr VMwareKết quả:
VMware Physical Disk Helper Service
VMware Tools Service3.1.2 File System và Registry
- Thư mục:
C:\Program Files\VMware\VMware Tools - Registry keys đặc trưng:
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\...]
"Identifier" = "VMware Virtual IDE Hard Drive"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Reinstall\...]
"DeviceDesc" = "VMware Accelerated AMD PCNet Adapter"
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{...}]
"LocationInformationOverride" = "plugged into PS/2 mouse port"
"ProviderName" = "VMware, Inc."3.2 Vulnerable Instructions
Một số lệnh x86 truy xuất thông tin phần cứng nhưng không sinh ra interrupt trong môi trường ảo hóa, tạo ra sự khác biệt có thể phát hiện:
sidt— Store Interrupt Descriptor Table Registersgdt— Store Global Descriptor Table Registersldt— Store Local Descriptor Table Registercpuid— CPU Identification
3.2.1 sidt — Red Pill Technique
- Lệnh
sidtghi 6-byte IDTR (Interrupt Descriptor Table Register) ra vùng nhớ chỉ định. - Mỗi processor chỉ có một IDTR, một GDTR, một LDTR.
- Địa chỉ base của IDT khác nhau giữa các môi trường:
| Môi trường | IDT Base Address |
|---|---|
| Windows thật | 0x8effffff |
| Virtual PC | 0xe8xxxxxxx |
| VMware | 0xffxxxxxxx |
lea eax, [ebp+Dst]
sidt fword ptr [eax] ; Lưu IDTR vào bộ nhớ
mov al, [eax+5] ; Lấy byte thứ 5 (byte cao của base address)
cmp al, 0FFh ; VMware signature
jnz short loc_401E19 ; Không phải VMware → bỏ quaCountermeasures:
- Chạy trên máy multi-core processor (IDT có thể khác nhau mỗi core).
- NOP-out lệnh
sidt. - Patch lệnh jump phía sau kiểm tra.
3.2.2 Querying I/O Communication Port
- Lệnh
inđọc dữ liệu từ I/O port. - VMware giám sát lệnh
invà bẫy I/O đến port0x5668(chuỗi “VX” — VMware backdoor).
mov eax, 'VMXh' ; Magic number
mov ecx, 0ah ; Command: get VMware version
mov dx, 'VX' ; Port 0x5668
in eax, dx ; Đọc từ port
cmp ebx, 'VMXh' ; Nếu EBX = 'VMXh' → đang trong VMware
je detectedCountermeasure: NOP-out lệnh in hoặc patch conditional jump.
3.2.3 ScoopyNG
ScoopyNG là công cụ phát hiện VMware miễn phí thực hiện 7 loại kiểm tra:
- Kiểm tra lệnh
sidt(Red Pill) - Kiểm tra lệnh
sgdt - Kiểm tra lệnh
sldt(No Pill) - Kiểm tra lệnh
str - I/O backdoor port option
0xa - I/O backdoor port option
0x14 - Bug trong VMware cũ chạy ở emulation mode
3.2.4 Tweaking VMware Settings
VMware có một số tính năng không có tài liệu (undocumented) giúp giảm thiểu các kỹ thuật anti-VM. Thêm vào file .vmx:
isolation.tools.getPtrLocation.disable = "TRUE"
isolation.tools.setPtrLocation.disable = "TRUE"
isolation.tools.setVersion.disable = "TRUE"
isolation.tools.getVersion.disable = "TRUE"
monitor_control.disable_directexec = "TRUE"
monitor_control.disable_chksimd = "TRUE"
monitor_control.disable_ntreloc = "TRUE"
monitor_control.disable_selfmod = "TRUE"
monitor_control.disable_reloc = "TRUE"
monitor_control.disable_btinout = "TRUE"
monitor_control.disable_btmemspace = "TRUE"
monitor_control.disable_btpriv = "TRUE"
monitor_control.disable_btseg = "TRUE"4. Packers và Unpacking
4.1 Packer Anatomy
- Packer nhận một file thực thi làm đầu vào và xuất ra một file thực thi đã được đóng gói.
- Hầu hết packer sử dụng thuật toán nén để nén code gốc.
- Mục đích: ẩn nội dung thực sự của mã độc khỏi phân tích tĩnh.
4.2 The Unpacking Stub
Entry point của file đã packed trỏ tới unpacking stub, không phải code gốc.
Ba bước của unpacking stub:
- Giải nén (unpack) code gốc vào memory.
- Resolve tất cả imports của code gốc.
- Chuyển thực thi sang OEP (Original Entry Point).
4.3 Quá trình Unpacking chi tiết
Bước 1: Loading the Executable
- File thực thi thông thường: OS loader đọc PE header, cấp phát memory cho từng section, copy sections vào memory.
- File đã packed: PE header vẫn được format để loader cấp phát memory → Unpacking stub sau đó giải nén code vào vùng nhớ đó.
Bước 2: Resolving Imports
- Windows loader không thể đọc thông tin import bị đóng gói.
- Unpacking stub tự resolve imports:
- Gọi
LoadLibrarycho mỗi DLL. - Gọi
GetProcAddresscho từng hàm. - Điền địa chỉ vào import table.
- Gọi
Bước 3: The Tail Jump
- Sau khi hoàn tất, stub thực hiện jump tới OEP.
- Đây là bước chuyển giao thực thi cuối cùng.
4.4 Hình ảnh cấu trúc trước/sau packing
4.5 Nhận Diện Chương Trình Đã Packed
Các dấu hiệu nhận biết:
- Rất ít imports, đặc biệt nếu chỉ có
LoadLibraryvàGetProcAddress. - Mở trong IDA Pro: chỉ một lượng nhỏ code được phân tích tự động.
- Mở trong OllyDbg: có cảnh báo chương trình có thể bị packed.
- Tên section đặc trưng: ví dụ
UPX0,UPX1. - Kích thước section bất thường: ví dụ
.textsection cóSize of Raw Data = 0nhưngVirtual Size ≠ 0.
4.6 Các Phương Pháp Unpacking
- Chương trình tự động giải nén/giải mã file thực thi mà không cần chạy nó.
- Nhanh nhất khi áp dụng được.
- PE Explorer hỗ trợ plug-in static unpacker cho:
- NSPack
- Upack
- UPX
- Chạy file thực thi và để unpacking stub tự làm việc.
- Hiện tại không có công cụ automated dynamic unpacker tốt công khai.
Hai phương pháp thủ công:
Phương pháp 1 – Reverse Engineer thuật toán:
- Tìm hiểu thuật toán đóng gói.
- Viết chương trình chạy ngược thuật toán đó để giải nén.
Phương pháp 2 – Dump từ memory:
- Chạy file packed → để stub tự giải nén vào memory.
- Dump tiến trình ra khỏi memory.
- Sửa PE header thủ công để hoàn thiện file.
Câu hỏi Trắc nghiệm
Câu 1. Anti-debugging là gì?
- A. Kỹ thuật tối ưu hóa hiệu suất chương trình
- B. Kỹ thuật chống phân tích động giúp mã độc nhận biết và cản trở debugger
- C. Công cụ dùng để debug phần mềm
- D. Phương pháp mã hóa dữ liệu trong mã độc
Câu 2. Hàm IsDebuggerPresent() kiểm tra trường nào trong cấu trúc PEB?
- A.
NtGlobalFlag - B.
ProcessHeap - C.
BeingDebugged - D.
ForceFlags
Câu 3. IsDebuggerPresent() trả về giá trị nào khi tiến trình KHÔNG bị debug?
- A. -1
- B. 1
- C. Nonzero
- D. 0
Câu 4. Điểm khác biệt chính giữa IsDebuggerPresent và CheckRemoteDebuggerPresent là gì?
- A.
CheckRemoteDebuggerPresentchỉ hoạt động trên Windows 10 - B.
IsDebuggerPresentkiểm tra tiến trình hiện tại;CheckRemoteDebuggerPresentkiểm tra bất kỳ tiến trình nào qua handle - C.
CheckRemoteDebuggerPresentphát hiện debugger trên máy tính khác qua mạng - D. Hai hàm hoàn toàn giống nhau về chức năng
Câu 5. Khi dùng NtQueryInformationProcess với tham số ProcessDebugPort (0x7), giá trị nào được trả về khi tiến trình KHÔNG bị debug?
- A.
0x7 - B.
0xFF - C.
0 - D. Port number
Câu 6. Trong kỹ thuật phát hiện debugger bằng OutputDebugString, logic hoạt động như thế nào?
- A. Nếu
GetLastError()== giá trị tùy ý đã đặt → có debugger - B. Nếu
GetLastError()!= giá trị tùy ý đã đặt → không có debugger - C. Nếu
GetLastError()== giá trị tùy ý đã đặt → KHÔNG có debugger (hàm thất bại → code không đổi) - D.
OutputDebugStringluôn thay đổi error code
Câu 7. Tại sao mã độc thường kiểm tra cấu trúc PEB thủ công thay vì dùng Windows API?
- A. API chạy chậm hơn so với truy cập trực tiếp
- B. API có thể bị hook bởi rootkit để trả về thông tin giả
- C. API không tồn tại trên một số phiên bản Windows
- D. Truy cập thủ công chính xác hơn
Câu 8. BeingDebugged flag nằm ở offset nào trong cấu trúc PEB?
- A.
0x0 - B.
0x2 - C.
0x18 - D.
0x68
Câu 9. Thanh ghi nào được dùng để tham chiếu vị trí PEB khi tiến trình đang chạy?
- A.
gs:[30h] - B.
ds:[30h] - C.
fs:[30h] - D.
es:[30h]
Câu 10. Trường NtGlobalFlag trong PEB thường có giá trị bao nhiêu khi tiến trình đang bị debug?
- A.
0x0 - B.
0x18 - C.
0x70 - D.
0xFF
Câu 11. NtGlobalFlag nằm ở offset nào trong PEB?
- A.
0x2 - B.
0x18 - C.
0x44 - D.
0x68
Câu 12. ProcessHeap trong PEB nằm ở offset nào?
- A.
0x2 - B.
0x10 - C.
0x18 - D.
0x68
Câu 13. Trường ForceFlags trong heap header nằm ở offset nào trên Windows 7 (32-bit)?
- A.
0x10 - B.
0x18 - C.
0x44 - D.
0x68
Câu 14. Mã độc có thể tìm kiếm dấu vết của debugger trong registry ở key nào?
- A.
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run - B.
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug - C.
HKLM\SYSTEM\CurrentControlSet\Services - D.
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
Câu 15. Hàm FindWindow("OLLYDBG", 0) trả về NULL có nghĩa là gì?
- A. OllyDbg đang chạy và được phát hiện
- B. OllyDbg không được tìm thấy — không có debugger
- C. Hàm gặp lỗi
- D. OllyDbg bị ẩn
Câu 16. INT 3 được dùng bởi debugger để làm gì?
- A. Kết thúc tiến trình
- B. Tạm thời thay thế một lệnh bằng software breakpoint và gọi debug exception handler
- C. Đọc thanh ghi CPU
- D. Ghi log ra file
Câu 17. Opcode của INT 3 là gì?
- A.
0x0F31 - B.
0xCC - C.
0x90 - D.
0xFF
Câu 18. Kỹ thuật Code Checksums trong anti-debugging hoạt động như thế nào?
- A. Tính checksum của toàn bộ file trên đĩa
- B. Tính CRC/MD5 của một đoạn code trong bộ nhớ; nếu debugger đặt breakpoint, checksum sẽ thay đổi
- C. Kiểm tra hash của DLL hệ thống
- D. So sánh file thực thi với database virus
Câu 19. Lệnh rdtsc trả về điều gì?
- A. Thời gian hệ thống hiện tại
- B. Số tick kể từ lần reboot cuối, dưới dạng 64-bit trong EDX:EAX
- C. Tần số CPU
- D. Số tiến trình đang chạy
Câu 20. Opcode của lệnh rdtsc là gì?
- A.
0xCC - B.
0x90 - C.
0x0F31 - D.
0x5668
Câu 21. Hàm GetTickCount() trả về điều gì?
- A. Số tick CPU
- B. Số millisecond kể từ lần reboot cuối
- C. Timestamp Unix
- D. Số giây kể từ lần reboot cuối
Câu 22. Tại sao timing check là phương pháp phổ biến để phát hiện debugger?
- A. Debugger thay đổi hệ thống clock
- B. Tiến trình chạy chậm hơn đáng kể khi bị debug do debugger xử lý các sự kiện
- C. Debugger tốn nhiều RAM khiến hệ thống chậm
- D. Timing check không bị ảnh hưởng bởi phần cứng
Câu 23. TLS Callback là gì và tại sao mã độc sử dụng chúng?
- A. Callback gọi khi DLL được load; dùng để inject code
- B. Subroutine thực thi TRƯỚC entry point; dùng để thực thi code bí mật trước khi debugger đặt breakpoint tại OEP
- C. Hàm xử lý thread kết thúc; dùng để cleanup
- D. Callback của Windows scheduler
Câu 24. PE Header Vulnerability trong OllyDbg gây ra hiệu ứng gì?
- A. OllyDbg bỏ qua các breakpoint
- B. OllyDbg crash khi tải file với thông báo lỗi về PE header không hợp lệ
- C. OllyDbg chạy file trong sandbox
- D. OllyDbg tự động patch file
Câu 25. Lỗ hổng OutputDebugString trong OllyDbg v1.1 được khai thác như thế nào?
- A. Gọi với chuỗi rất dài để gây buffer overflow
- B. Gọi với chuỗi chứa toàn format specifier
%sgây format string vulnerability làm crash debugger - C. Gọi nhiều lần liên tục để chiếm tài nguyên
- D. Gọi với null pointer
Câu 26. Ba tiến trình VMware điển hình mà mã độc tìm kiếm là gì?
- A.
VMware.exe,VMtools.exe,VMhost.exe - B.
VMwareService.exe,VMwareTray.exe,VMwareUser.exe - C.
vmrun.exe,vmnat.exe,vmnetdhcp.exe - D.
vmplayer.exe,vmware-vmx.exe,vmware-authd.exe
Câu 27. Lệnh nào dùng để kiểm tra VMware Tools Service có đang chạy không?
- A.
sc query VMware - B.
tasklist | findstr VMware - C.
net start | findstr VMware - D.
wmic service list | findstr VMware
Câu 28. Registry key nào là dấu hiệu điển hình của VMware virtual hard drive?
- A.
HKLM\SOFTWARE\VMware, Inc. - B.
HKLM\HARDWARE\DEVICEMAP\Scsi\...với Identifier = “VMware Virtual IDE Hard Drive” - C.
HKLM\SYSTEM\CurrentControlSet\Services\VMware - D.
HKCU\SOFTWARE\VMware
Câu 29. Lệnh x86 nào KHÔNG sinh ra interrupt khi truy xuất thông tin phần cứng, tạo ra sự khác biệt có thể phát hiện trong VM?
- A.
int 3,int 1,int 0 - B.
sidt,sgdt,sldt,cpuid - C.
in,out,cli,sti - D.
rdmsr,wrmsr,hlt
Câu 30. Lệnh sidt làm gì?
- A. Store Instruction Descriptor Table
- B. Ghi nội dung 6-byte IDTR (Interrupt Descriptor Table Register) ra vùng nhớ chỉ định
- C. Kiểm tra IDT có hợp lệ không
- D. Set Interrupt Descriptor Table Register
Câu 31. Địa chỉ base IDT đặc trưng của VMware là gì?
- A.
0x8exxxxxx - B.
0xe8xxxxxx - C.
0xffxxxxxx - D.
0x00xxxxxx
Câu 32. Ba countermeasure để vô hiệu hóa kỹ thuật phát hiện VM qua sidt là gì?
- A. Cài đặt firewall, tắt mạng, dùng NAT
- B. Chạy trên multi-core, NOP-out lệnh sidt, patch lệnh jump sau kiểm tra
- C. Dùng 64-bit VM, tăng RAM, dùng SSD
- D. Cập nhật VMware, dùng VMware Workstation Pro, bật VT-x
Câu 33. VMware I/O backdoor sử dụng port nào?
- A.
0x1234 - B.
0x5658(VX) - C.
0x5668(VX) - D.
0x5566
Câu 34. ScoopyNG thực hiện bao nhiêu loại kiểm tra phát hiện VM?
- A. 3
- B. 5
- C. 7
- D. 10
Câu 35. Packer làm gì với một file thực thi?
- A. Mã hóa file và yêu cầu password để chạy
- B. Nhận file thực thi làm đầu vào, nén/biến đổi và xuất ra file thực thi mới chứa code đã được đóng gói
- C. Tách file thành nhiều phần nhỏ
- D. Thêm digital signature vào file
Câu 36. Entry point của file đã packed trỏ đến đâu?
- A. Code gốc (Original Code)
- B. Unpacking stub
- C. Import table
- D. PE header
Câu 37. Unpacking stub thực hiện ba bước theo thứ tự nào?
- A. Resolve imports → Giải nén code → Nhảy tới OEP
- B. Giải nén code → Nhảy tới OEP → Resolve imports
- C. Giải nén code gốc vào memory → Resolve imports → Nhảy tới OEP (Tail Jump)
- D. Load DLL → Giải nén → Copy sections
Câu 38. Tại sao Windows loader không thể tự resolve imports của file packed?
- A. File packed dùng định dạng import table khác
- B. Thông tin import bị nén/mã hóa cùng với code — Windows loader không thể đọc thông tin đã bị đóng gói
- C. File packed không có import table
- D. Windows loader bị vô hiệu hóa bởi packer
Câu 39. “Tail Jump” trong quá trình unpacking là gì?
- A. Lệnh jump ở cuối file thực thi
- B. Lệnh jump cuối cùng của unpacking stub để chuyển thực thi sang OEP sau khi hoàn tất giải nén
- C. Jump để thoát chương trình
- D. Jump đến exception handler
Câu 40. Dấu hiệu nào KHÔNG phải là dấu hiệu nhận biết file đã packed?
- A. Chỉ có
LoadLibraryvàGetProcAddresstrong import table - B. Tên section là
UPX0hoặcUPX1 - C. File có nhiều imports từ nhiều DLL khác nhau
- D.
.textsection cóSize of Raw Data = 0nhưngVirtual Size ≠ 0
Câu 41. Ba phương pháp unpacking chính là gì?
- A. Manual, automatic, hybrid
- B. Automated static unpacking, Automated dynamic unpacking, Manual dynamic unpacking
- C. Reverse engineering, memory dump, file patching
- D. IDA Pro, OllyDbg, PE Explorer
Câu 42. Công cụ nào hỗ trợ static unpacking plug-in cho NSPack, Upack, UPX?
- A. IDA Pro
- B. OllyDbg
- C. PE Explorer
- D. x64dbg
Câu 43. Hai phương pháp manual unpacking phổ biến là gì?
- A. Dùng IDA Pro và OllyDbg
- B. Reverse engineer thuật toán packing và viết chương trình giải nén; HOẶC chạy để stub tự giải nén rồi dump memory
- C. Phân tích tĩnh và phân tích động
- D. Dùng antivirus và sandbox
Câu 44. Khi mã độc phát hiện đang bị debug, nó có thể làm gì? (Chọn tất cả đúng)
- A. Thay đổi luồng thực thi sang code path khác
- B. Tự xóa file khỏi đĩa
- C. Gây crash tiến trình
- D. Thực thi payload độc hại bình thường
Câu 45. Kỹ thuật “INT scanning” trong anti-debugging quét tìm điều gì?
- A. Tất cả lệnh INT trong file thực thi
- B. Byte
0xCCtrong vùng code của chính mã độc để phát hiện breakpoint đã được đặt - C. Số lần INT 3 được gọi
- D. Các interrupt handler bất thường
Câu 46. Lệnh repne scasb trong đoạn code INT scanning làm gì?
- A. Lặp và so sánh từng byte trong chuỗi với giá trị trong AL, dừng khi tìm thấy
- B. Lặp và copy dữ liệu
- C. Lặp và xóa byte
- D. Lặp và tính tổng các byte
Câu 47. Trong kỹ thuật Timing Check, tại sao raising an exception cũng có thể dùng để phát hiện debugger?
- A. Exception gây crash debugger
- B. Tiến trình không bị debug xử lý exception rất nhanh; debugger xử lý chậm hơn nhiều do phải xử lý event
- C. Exception thay đổi hành vi của debugger
- D. Exception không thể xảy ra khi có debugger
Câu 48. Thư mục nào là artifact điển hình của VMware Tools trên hệ thống Windows?
- A.
C:\Windows\System32\VMware - B.
C:\Program Files\VMware\VMware Tools - C.
C:\VMware\Tools - D.
C:\Users\Public\VMware
Câu 49. Kỹ thuật phát hiện VM qua I/O port, magic number nào được dùng để xác nhận đang trong VMware?
- A.
'VBOX' - B.
'VXxx' - C.
'VMXh' - D.
'VMWR'
Câu 50. Điều gì xảy ra với IDA Pro khi phân tích file đã packed so với file bình thường?
- A. IDA Pro không thể mở file packed
- B. IDA Pro chạy chậm hơn bình thường
- C. Chỉ một lượng nhỏ code được IDA Pro nhận diện và phân tích tự động — phần lớn code vẫn bị ẩn
- D. IDA Pro tự động giải nén file
Câu 51. VMwareService.exe là tiến trình con của tiến trình nào?
- A.
explorer.exe - B.
winlogon.exe - C.
services.exe - D.
svchost.exe
Câu 52. Phương pháp manual unpacking bằng memory dump yêu cầu bước nào sau khi dump?
- A. Mã hóa lại file dump
- B. Sửa PE header thủ công để hoàn thiện file thực thi
- C. Compress lại file
- D. Ký số file
Câu 53. Tại sao CheckRemoteDebuggerPresent được gọi là “remote” dù debugger có thể ở cùng máy?
- A. Vì hàm này ban đầu được thiết kế cho remote debugging qua mạng
- B. “Remote” chỉ đơn giản nghĩa là debugger nằm trong một tiến trình song song, tách biệt — không nhất thiết là máy khác
- C. Vì hàm chỉ hoạt động khi debug qua mạng
- D. Đây là lỗi đặt tên trong Windows API
Câu 54. Khi IDA Pro chỉ nhận diện được một lượng nhỏ code, điều đó gợi ý điều gì về file đang phân tích?
- A. File bị hỏng
- B. File rất nhỏ
- C. File có thể đã được packed, và phần code lớn vẫn đang ở dạng nén
- D. IDA Pro phiên bản cũ không hỗ trợ file này
Câu 55. Trong cấu trúc PEB, trường nào chứa thông tin về heap đầu tiên của tiến trình?
- A.
BeingDebugged - B.
NtGlobalFlag - C.
ProcessHeap - D.
Ldr