前言

以下内容我也不知道写没写全就这样吧,主要是面试时候当时问我反调试都有啥,就说了个TLS,当时是一个都没想起来,这下得好好总结一下

内容参考

合理的分类有助于学习和理解各种反调试技术的原理

以下就分为静态反调试方法与动态反调试方法两大类:

其中静态反调试的分类原理为:程序启动时,系统会根据正常运行和调试运行分配不同的进程环境,通过检测进程环境来检测进程是否处于调试状态;根据逆向人员的工作环境和程序的正常运行环境不同,可以通过检测调试器或逆向分析工具实现反调试。

动态反调试技术的分类原理是:进程运行时的执行流程是否正常,执行状态是否正常。

本文测试环境:

测试代码: https://github.com/alphaSeclab/anti-debug

原版OD

测试环境,这有影响吗,win7和win10和win11都试试

PE编辑器:LordPE

静态反调试

IsDebuggerPresent

首先试了一下调试,有插件的根本不影响

IsDebuggerPresent函数,该函数会检查用户模式调试器是否正在调试该进程。示例代码如下:

int main()
{
if (IsDebuggerPresent())
{
std::cout << "Stop debugging program!" << std::endl;
exit(-1);
}
return 0;
}

如果进一步观察IsDebuggerPresent函数,我们可以找到如下代码:

0:000< u kernelbase!IsDebuggerPresent L3
KERNELBASE!IsDebuggerPresent:
751ca8d0 64a130000000 mov eax,dword ptr fs:[00000030h]
751ca8d6 0fb64002 movzx eax,byte ptr [eax+2]
751ca8da c3 ret

对于x64进程:

0:000< u kernelbase!IsDebuggerPresent L3
KERNELBASE!IsDebuggerPresent:
00007ffc`ab6c1aa0 65488b042560000000 mov rax,qword ptr gs:[60h]
00007ffc`ab6c1aa9 0fb64002 movzx eax,byte ptr [rax+2]
00007ffc`ab6c1aad c3 ret

可以用内联汇编写

bool IsDebuggerR()
{
bool bRet = false;
__asm {
mov eax, fs: [0x30] ; // fs=TEB+0x30
mov al, byte ptr[eax + 2]; // FS:[0x30] = PEB
mov bRet, al
}
return bRet;
}
BOOL IsDebuggerPresent();
作用
确定调用进程是否由用户模式的调试器调试。
返回值
如果当前进程在调试器的上下文中运行,则返回值非零。
如果当前进程未在调试器的上下文中运行,则返回值为零。

je跳转进行跳转就可以了,那么直接修改jmp

OD进行分析,运行程序,断下点来到如下

7C81F424 >  64:A1 18000000  MOV EAX,DWORD PTR FS:[18]                ; 将7FFDD018地址中的值7FFDD00赋值给eax
7C81F42A 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30] ; 将7FFDD30的地址的机器码7FFDE000赋值给eax
7C81F42D 0FB640 02 MOVZX EAX,BYTE PTR DS:[EAX+2] ; 将7FFDE02的第一字节机器码赋值给eax,这里的第一字节的机器码也就是01
7C81F431 C3 RETN ; 那么返回值中的eax值也就是01,判断为被调试,结束程序

eax中的值改为00000000,所以就可以绕过了

所以