特点:一般在调试开始时阻拦调试者,调试只需要找到原因后就可以一次性突破
PEB ?
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
StaticUnicodeString :静态缓冲区使用原始 API
NtQuerySystemInformationProcess()
ProcessDebugPort(0x07): 获取调试端口ProcessDebugObjectHandle(0x1E): 获取调试句柄ProcessDebugFlag(0x1F): 获取调试标记NtQuerySystemInformation():
SystemKernelDeBuggerInformation(0x23) :获取系统调试状态 (双机)NtQueryObject() : 遍历系统内核攻击调试器
NtSetInformationThread()
ThreadHideFormDebugger(0x11)打开进程检查
SetDebugPrivilege ?? 检查进程是否具有调试权限利用TLS回调函数
使用普通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 的数据,所以只能 HOOKbool 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的方式存在的,但是后缀名可能会有变化
所有的插件都应该被保护到具体的路径中
原文:https://www.cnblogs.com/TJTO/p/11374003.html