第51章:静态反调试技术——API查询

NtQueryInformationProcess( )

将第二个参数设置为不同的特定值并调用该函数,就能将不同的数据写入到第三个参数。

该枚举类型与调试器探测有关的成员有 ProcessDebugPort ( 0x7 )ProcessDebugObjectHandle ( 0x1E ),ProcessDebugFlags ( 0x1F )

ProcessDebugPort ( 0x7 )

当进程处于调试状态时,系统就会给它分配一个调试端口(Debug Port),当 ProcessInformationClass 被设置为 0x7 时,调用 NtQueryInformationProcess( ) 就能获取调试端口。若进程处于非调试状态,则变量 dwDebugPort 的值设置为0,否则为 FFFFFFFF

CheckRemoteDebuggerPresent()API IsDebuggerPresent()类似,但是它还可以用来检测其它进程是否处于被调试状态。其内部代码:

ProcessDebugObjectHandle ( 0x1E )

调试进程时会生成调试对象(Debug Object),进程处于调试状态时,调试对象的句柄就存在,否则为 NULL 

ProcessDebugFlags ( 0x1F )

若第三个参数返回值为0,则处于被调试状态;为1,则处于非调试状态。

调试-钩取API

改变函数运行流程到自己的代码中,并修改函数返回值:

NtQuerySystemInformation()

此 API 是用于基于调试环境检测的反调试技术。注意:此方法仅仅只显示当前系统是否处于调试模式!

第一个参数用于指定需要的系统信息类型,API 将返回的信息放在第二个参数

向 SystemInformationClass 参数传入 SystemKernelDebuggerInformation( 0x23 ) ,即可判断处 OS 是否处于调试模式下运行.

破解之法:在 XP 系统中编辑 boot.ini 文件,删除 值,在 Win 7 中只能关闭调试模式。

NtQueryObject

同样的,第二个参数是枚举类型,第三个参数返回要查询的信息。调用该 API 有点麻烦:

然后还需要一个循环找到 “DebugObject”,并对当中的某个元素进行查验。应对方法是,钩取该 API ,将其第二个参数的值设为 0 .

ZwSetInformationThread()

利用此 API 可以将被调试者从调试器中分离出来。

第一个参数为当前线程的句柄,第二个参数 ThreadInformationClass 表示线程信息类型,若其值设置为 ThreadHideFromDebugger(0x11) ,调用后即可分离,并终止它们的运行,若无调试器,则不影响。

应对方法:在函数调用函数前将第二个参数设置为 0 即可,或者钩取 API 改。

TLS回调函数

前面有

ETC

FindWindow & GetWindowText

探测是否存在指定名称(OllyDbg、IDA Pro、WinDbg)的调试窗口。

主要的思路是:先利用 GetDesktopWindow() 返回桌面窗口句柄,再通过 GetWindow() 返回其子窗口句柄及子窗口的兄弟窗口句柄,然后利用 GetWindwosText() 返回窗口的标题,并与程序内的字符串进行对比。

应对方法:直接在 GetDesktopWindow()  调用后将其返回值(EAX)置 0,即可跳过。

原文地址:https://www.cnblogs.com/Rev-omi/p/13681422.html