Xác định xem tiến trình hiện tại có bị debugging bởi trình debugger (ollyDbg, x64dbg) không? Bằng cách kiểm tra cờ BeingDebugged
trong PEB. (Tiến trình bị debug sẽ được spawn từ tiến trình debugger).
API cũng hoạt động khi process đang bị attached
isDebuggerPresent() | 32bit | 64bit |
---|---|---|
Get PEB struct | mov eax, dword ptr fs:[30h] | mov rax, qword ptr gs:[60h] |
Get Being Debuged flag | movzx eax, byte ptr [eax+2h] | movzx eax, byte ptr [rax+2h] |
Return | ret | ret |
Bypass: set BeingDebugged flag trong PEB thành 0
Kiểm tra xem có trình debugger nào (tiến trình khác trên cùng máy) attach tới tiến trình hiện tại (CheckRemoteDebuggerPresent).
cũng hoạt động khi được spawn từ trình debugger.
bypass: bypass được NtQueryInformationProcess
ProcessInformationClass
Hàm này được gọi bên trong của
CheckRemoteDebuggerPresent
ProcessDebugPort
bằng 7. Giá trị trả về sẽ được lưu vào tham số thứ 3.Retrieves a DWORD_PTR value that is the port number of the debugger for the process. A nonzero value indicates that the process is being run under the control of a ring 3 debugger.
hoạt động cả khi spawn từ debbuger hoặc bị attached
NOTE: chỉ hoạt động với build x86
bypass: hook NtQueryInformationProcess và set giá trị trả về khác -1
Tương tự với undocumented ProcessDebugFlags (= 0x1F) class sẽ trả về giá trị trường NoDebugInherit trong cấu trúc EPROCESS.
Cấu trúc kernel EPROCESS, bao gồm trường NoDebugInherit. Nếu giá trị trả về là 0 -> có sự tồn tại của trình debugger. (= 1 Nếu không bị attached/debugging).
bypass: hook NtQueryInformationProcess và set giá trị trả về khác 0.
Khi quá trình debug được bắt đầu, một đối tượng kernel được gọi là debug object
được tạo. Có thể truy vấn tới handle của đối tượng này bởi undocument class ProcessDebugObjectHandle = 0x1E.
NOTE: chỉ hoạt động với build x86
bypass: hook NtQueryInformationProcess và set giá trị trả về = 0.
Có thể sử dụng để đọc các cờ heap của bộ nhớ tiến trình hiện tại.
build x86:
spawn từ VisualStudio -> HeapFlags = 2 -> not detect.
spawn từ debugger (IDA) -> HeapFlags = 0x40000062 -> detect.
attach từ debugger (IDA) -> HeapFlags = 2 -> not detect.
bypass: hook RtlQueryProcessHeapInformation và set giá trị trả về thành HEAP_GROWABLE (0x2h).
Đọc một số trường từ bộ nhớ tiến trình, bao gồm cả HeapFlags.
build x86:
spawn từ VisualStudio -> HeapFlags = 2 -> not detect.
spawn từ debugger (IDA) -> HeapFlags = 0x40000062 -> detect
attach từ debugger (IDA) -> HeapFlags = 2 -> not detect.
bypass: hook RtlQueryProcessHeapInformation và set giá trị trả về thành HEAP_GROWABLE (0x2h).
Tham số đầu tiên của hàm là SYSTEM_INFORMATION_CLASS
, từ enumerate class SYSTEM_INFORMATION_CLASS
sẽ quyết định thông tin được truy vấn. Nếu thành công, kết quả sẽ được lưu tại biến được khai báo thủ công SystemInformation
.
Cái ta sử dụng sẽ là 0x23
(SystemKernelDebuggerInformation class). Class này sẽ trả về 2 flags:
- KdDebuggerEnabled
là thanh ghiAH
- KdDebuggerNotPresennt
là thanh ghi AL
.
-> Do đó, nếu thanh ghi AH
= 0 -> có sự tồn tại của trình debugger.
Phương pháp này chỉ hoạt động trên phiên bản WinXP
bypass: hook RtlQueryProcessHeapInformation và set giá trị trả về DebuggerEnabled = 0 và DebuggerNotPresent = 1.
bypass: set flag này thành 0, bằng cách DLL injection. Hay sử dụng ScyllaHide plugin.
HEAP_GROWABLE
(0x2).Không hoạt động khi attach process.
bypass: set Flags thành HEAP_GROWABLE (0x2) và ForgeFlags thành 0. Sử dụng DLL Injection hay ScyllaHide plugin.
Khi vùng nhớ heap được khởi tạo,
Nếu cờ HEAP_TAIL_CHECKING_ENABLED
(0x20) được set trong NtGlobalFlag, 0xABABABAB (32bit)/ 0xBABABABBABABAB (64 bit) sẽ được set tại cuối khối heap được khởi tạo.
Nếu cờ HEAP_FREE_CHECKING_ENABLED
được set trong NtGlobalFlag, 0xFEEEFEEE sẽ được thêm nếu chuỗi bytes bổ sung được yêu cầu để fill vào không gian trống đến khối nhớ tiếp theo.
Không hoạt động khi attach process.
windows-internal
anti-debug