[TOC]ide
特色:通常在调试开始时阻拦调试者,调试只须要找到缘由后就能够一次性突破函数
PEB
:star:工具
BeginDebug
: 调试标志位// 经过检查 PEB.BeingDebuged 字段判断是否被调试 // 能够在目标程序运行以前修改对应的字段为 0 进行反反调试 bool CheckBeingDebugged() { __asm { ; 获取到 PEB 的内容 mov eax, fs:[0x30] ; 获取 PEB 内偏移为 2 大小为 1 字节的字段 movzx eax, byte ptr[eax + 2] } } int main() { if (CheckBeingDebugged()) printf("当前处于[被]调试状态\n"); else printf("当前处于[非]调试状态\n"); system("pause"); return 0; }
// 使用 IsDebuggerPresent 原理一样是判断 PEB.BeingDebuged // 经过 HOOK 函数和修改对应字段的方式能够进行反调试 int main() { if (IsDebuggerPresent()) printf("当前处于[被]调试状态\n"); else printf("当前处于[非]调试状态\n"); system("pause"); return 0; }
Ldr
内存状态Heap
(Flags
, Force Flags
): 堆状态NtGlobalFlag
: 内核全局标记
PEB.NtGlobalFlag
判断是否被调试,当处于被调试状态时PEB.NtGlobalFlag
保存的是 0x70
,能够经过修改标志反反调试bool CheckNtGlobalFlag() { __asm { ; 获取到 PEB, 保存在 FS :[0x30] mov eax, fs : [0x30] ;获取到 NtGlobalFlag 字段的内容 mov eax, [eax + 0x68] } } int main() { if (CheckNtGlobalFlag()) printf("当前处于[被]调试状态\n"); else printf("当前处于[非]调试状态\n"); system("pause"); return 0; }
TEB
spa
StaticUnicodeString
:静态缓冲区使用原始 API
插件
NtQuerySystemInformationProcess()
ProcessDebugPort(0x07)
: 获取调试端口ProcessDebugObjectHandle(0x1E)
: 获取调试句柄ProcessDebugFlag(0x1F)
: 获取调试标记NtQuerySystemInformation()
:
SystemKernelDeBuggerInformation(0x23)
:获取系统调试状态 (双机)NtQueryObject()
: 遍历系统内核攻击调试器调试
NtSetInformationThread()
ThreadHideFormDebugger(0x11)
打开进程检查code
SetDebugPrivilege
:arrow_right: 检查进程是否具备调试权限利用**TLS
**回调函数orm
使用普通API
进程
Explorer.exe
,也就是资源管理器,若是判断不是,就可能被调试,提供参考。bool CheckParentProcess() { struct PROCESS_BASIC_INFORMATION { ULONG ExitStatus; // 进程返回码 PPEB PebBaseAddress; // PEB 地址 ULONG AffinityMask; // CPU 亲和性掩码 LONG BasePriority; // 基本优先级 ULONG UniqueProcessId; // 本进程PID ULONG InheritedFromUniqueProcessId; // 父进程PID }stcProcInfo; // 查询到目标进程的对应信息,主要是 父进程 ID NtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &stcProcInfo, sizeof(stcProcInfo), NULL); // 查询资源管理器对应的 PID DWORD ExplorerPID = 0; DWORD CurrentPID = stcProcInfo.InheritedFromUniqueProcessId; GetWindowThreadProcessId(FindWindow(L"Progman", NULL), &ExplorerPID); // 比对两个 PID 的值,相同就OK,不一样就可能被调试 return ExplorerPID == CurrentPID ? false : true; } int main() { if (CheckParentProcess()) printf("当前处于[被]调试状态\n"); else printf("当前处于[非]调试状态\n"); system("pause"); return 0; }
int main() { if (FindWindow(NULL, L"OllyDbg")) printf("存在调试器\n"); else printf("没检测到调试器\n"); return 0; }
EPROCESS
结构体中相关的字段,由于不能在 R3
修改 R0
的数据,因此只能 HOOK
bool CheckProcessDebugPort() { int nDebugPort = 0; NtQueryInformationProcess( GetCurrentProcess(), // 目标进程句柄 ProcessDebugPort, // 查询信息类型(7) &nDebugPort, // 输出查询信息 sizeof(nDebugPort), // 查询类型大小 NULL); // 实际返回数据大小 // 若是返回的是 -1 ,那么就被调试了 return nDebugPort == 0xFFFFFFFF ? true : false; } int main() { if (CheckProcessDebugPort()) printf("当前处于[被]调试状态\n"); else printf("当前处于[非]调试状态\n"); system("pause"); return 0; }
SEH
SetUnhandleedExceptionFilter()
OllyDbg
插件编写一般以DLL
的方式存在的,可是后缀名可能会有变化内存
全部的插件都应该被保护到具体的路径中