# Các kĩ thuật Anti-Debug cơ bản
## *1. IsDebuggerPresent()*
Hàm kernel32! `IsDebuggerPresent()` xác định rằng khi nào mà chương trình hiện tại đang được debug bằng 1 công cụ debug được sử dụng bởi con người ví dụ như là `OllyDbg` hay `x64dbg`. Nói tóm lại, hàm này chỉ check `BeingDebugged flag` trong môi trường ngăn chặn thực thi chương trình.
Dưới đây là code 2 code ví dụ về cách thức mà hàm này hoạt động
#### Code C
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
int main()
{
int check;
int mot = 1;
int sau = 3;
int hai;
scanf("%d", &check);
if(check != 1)
{
printf("Em chao` anh Ajomix\n");
}
hai = mot + sau;
if (IsDebuggerPresent())
{
printf("Adu ko debug duoc roi huhu\n");
ExitProcess(-1);
}
}
```
---
## *2. CheckRemoteDebuggerPresent()*
Hàm kernel32! `CheckRemoteDebuggerPresent()` kiểm tra rằng nếu 1 trình debug đang chạy(trong 1 chương trình khác trên cùng 1 thiết bị) gắn với trình thực thi hiện tại
#### Code C++
```
#include <iostream>
#include "windows.h"
using namespace std;
int main()
{
BOOL HasDebugPort = FALSE;
cout << "Em chao` anh Ajomix" << endl ;
if(CheckRemoteDebuggerPresent(GetCurrentProcess(), &HasDebugPort))
{
cout << "Buon vay khong debug duoc roi :<<<<" << endl;
ExitProcess(0);
}
return 0;
}
```
## 3. *NtQueryInformationProcess()*
Hàm ntdll!`NtQueryInformationProcess()` có thể lấy ra một loại thông tin khác của chương trình. Nó chấp thuận 1 thông số `ProcessInformationClass` thứ mà chỉ định thông tin mà bạn muốn lấy ra và định dạng nó kiểu thông tin đầu ra của tham số `ProcessInformationClass`.
### *3.1 ProcessDebugPort*
Ta hoàn toàn có thể lấy được `port number` của trình debug
cho quá trình sử dụng hàm ntdll! `NtQueryInformationProcess()`. Ở đây có 1 `documented class ProcessDebugPort`, thứ mà lấy giá trị có bộ nhớ 4 bytes(DWORD) có giá trị bằng 0xFFFFFFFF(decimal -1) khi chương trình được debug
#### Code C++
```
#include <iostream>
#include "windows.h"
#include "winternl.h"
using namespace std;
typedef NTSTATUS(NTAPI* pfnNtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength
);
int main(int argc, char* argv[])
{
pfnNtQueryInformationProcess NtQueryInformationProcess = NULL;
NTSTATUS status;
DWORD isDebuggerPresent = 0;
HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
PROCESSINFOCLASS *ProcessDebugPort = (PROCESSINFOCLASS*)malloc(sizeof(PROCESSINFOCLASS));
cout << "EM chao` anh Ajomix" << endl;
if (NULL != hNtDll)
{
NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(hNtDll, "NtQueryInformation");
if (NULL != NtQueryInformationProcess)
{
status = NtQueryInformationProcess(
GetCurrentProcess(),
*ProcessDebugPort,
&isDebuggerPresent,
sizeof(DWORD),
NULL);
if (status == 0 && isDebuggerPresent != 0)
{
cout << "Dcm van ko the debug noi :<<" << endl;
ExitProcess(-1);
}
}
}
return 0;
}
```
---
### *3.2NtQuerySystemInformation()*
Hàm ntdll! NtQuerySystemInformation() chấp thuận 1 thông số nằm trong lớp thông tin được truy vấn. Hầu hết các lớp ko được dẫn chứng. Nó bao gồm lớp `SystemKernelDebuggerInformation (0x23)`. Lớp `SystemKernelDebuggerInformation` trả về giá trị của 2 cờ: `KdDebuggerEnabled` trong thanh ghi 8-bit al và `KdDebuggerNotPresent` trong thanh ghi 8-bit ah. Vì thế, giá trị trả về trên thanh ghi 8-bit ah là 0 nếu như trình debug kernel đang hoạt động
#### Code C++
```
#include <iostream>
#include "windows.h"
#include "winternl.h"
using namespace std;
enum { SystemKernelDebuggerInformation = 0x23};
typedef NTSTATUS(NTAPI* TNtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN DWORD ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength
);
typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION {
BOOLEAN DebuggerEnabled;
BOOLEAN DebuggerNotPresent;
} SYSTEM_KERNEL_DEBUGGER_INFORMATION, * PSYSTEM_KERNEL_DEBUGGER_INFORMATION;
bool Check()
{
NTSTATUS status;
SYSTEM_KERNEL_DEBUGGER_INFORMATION SystemInfo;
status = NtQuerySystemInformation(
(SYSTEM_INFORMATION_CLASS)SystemKernelDebuggerInformation,
&SystemInfo,
sizeof(SystemInfo),
NULL);
return SUCCEEDED(status)
? (SystemInfo.DebuggerEnabled && !SystemInfo.DebuggerNotPresent)
: false;
}
```
#### Cách khắc phục
Đối với `IsDebuggerPresent()`: Đặt cờ BeingDebugged của Process Environment Block (PEB) thành 0 Đối với `CheckRemoteDebuggerPresent()` và `NtQueryInformationProcess():`
Khi `CheckRemoteDebuggerPresent()` gọi `NtQueryInformationProcess()`, cách duy nhất là nối `NtQueryInformationProcess()` và đặt các giá trị sau trong bộ đệm trả về:
0 (hoặc bất kỳ giá trị nào ngoại trừ -1) trong trường hợp truy vấn ProcessDebugPort.
Giá trị khác 0 trong trường hợp truy vấn `ProcessDebugFlags`.
0 trong trường hợp truy vấn ProcessDebugObjectHandle.
Cách duy nhất để giảm thiểu những kiểm tra này với các hàm `RtlQueryProcessHeapInformation()`, `RtlQueryProcessDebugInformation()` và `NtQuerySystemInformation()` là nối chúng và sửa đổi các giá trị trả về:
`RTL_PROCESS_HEAPS :: HeapInformation :: Heaps [0] `:: Gắn cờ cho `HEAP_GROWABLE` cho `RtlQueryProcessHeapInformation()` và `RtlQueryProcessDebugInformation()`.
SYSTEM_KERNEL_DEBUGGER_INFORMATION :: DebuggerEnabled thành 0 và SYSTEM_KERNEL_DEBUGGER_INFORMATION :: DebuggerNotPresent thành 1 cho hàm NtQuerySystemInformation () trong trường hợp truy vấn SystemKernelDebuggerInformation.
---
### *3.3ProcessDebugFlags()*
Khi việc kiểm tra cờ đang diễn ra, nó trả về giá trị nghịch đảo của `NoDebugInherit` bit thuộc cấu trúc kernel `EPROCESS`. Nếu giá trị trả về của hàm `NtQueryInformationProcess` bằng với 0, thì khí đó, chương trình tiếp tục được debug
#### Code C++
```
status = NtQueryInformationProcess(
GetCurrentProcess(),
ProcessDebugObjectHandle,
&debugFlags,
sizeof(ULONG),
NULL);
if (0x00000000 == status && NULL != debugFlags)
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
```