给游戏或代码增加反调试功能(应用层级)

前言:

感谢:易道云学院 tiger老师指导:

调试分为:打开一个调试进程和调试一个现有的进程。

DebugByCreate为真时调用CreateProcess()函数打开一个调试进程,当DebugByCreate为假时调用DebugActiveProcess(dwPID)函数调试一个现有的程序。

一、调用CreateProcess()函数打开一个调试进程:

调用CreateProcess()函数实际底层调用:

二、调用DebugActiveProcess(dwPID)函数调试一个现有的程序

 总结:

一个进程被调试,内核状态下EPROCESS结构的DebugProt 一定不为0,用户态模式下PEB结构的BeinDebuged一定不为0.

NT TP等驱动反调试原理:

 使用打开模式调试:

        驱动反调试可以在NTCreateProcess()处设置回调函数,如果发现创建调试的进程是自己要保护的进程时就让函数返回失败。

附件现有进程调试时

        驱动反调试可以接管NtOpenProcess函数发现是自己要保护的进程时就直接返回失败,还可以把后面的每一步都破坏掉来实现跳过反调试的复杂度。

因为要建立调试关系就必须把DebugPort与DEBUG_OBJECT进行关联,那么就可以直接把DebugPort的值设置为0,也能实现反调试。

在用户层实现反调试

一、设置主线程为隐藏调试破坏调试通道

使用windows未公开的函数实现该函数位于ntdll实现代码:

typedef NTSTATUS(NTAPI* zwsetImformationThreadPtr)(DWORD, DWORD, DWORD, DWORD); //该函数原型

auto hNtDll=LoadLibrary("ntdll.dll"); //加载支持模块

if(hNtDll)

{

zwsetImformationThreadPtr  zwsetImformationThread;                                        zwsetImformationThread=(zwsetImformationThreadPtr)GetProcAddress(hNtDll,"zwsetImformationThread")

zwsetImformationThread((DWORD)GetCurrentThread(),0x11,0x0,0x0);//第一个参数时传入当前线程,第二各参数0X11就表示把当前线程设置为隐藏调试

}

实现逻辑:

调试器调试程序时,下断点实际时在断点处写入int3,然后进程走到这里会断下来然后由调试器来处理,我们使用这个函数可以使当前线程为不调试模式。当调试器下断点时依然会在断点位置写入int3,可是因为我们设置了当前线程为不调试模式,所以当程序走到这里就会崩溃,实现反调试共功能。

在用户层实现调试检测

一、通过BeinDebuged检测是否被调试                                                                                                    通过用户态模式下PEB结构的BeinDebuged一定不为0.我们只用检测PEB结构的BeinDebuged是否为0即可检测当前程序是否被调试。                                                                       通过汇编方法获取PEB结构:                                                                                                            因为TEB结构地址存放在FS段寄存器中。                                                                                          typedef struct _TEB { PVOID Reserved1[12]; PPEB ProcessEnvironmentBlock; PVOID Reserved2[399]; BYTE Reserved3[1952]; PVOID TlsSlots[64]; BYTE Reserved4[8]; PVOID Reserved5[26]; PVOID ReservedForOle; PVOID Reserved6[4]; PVOID TlsExpansionSlots; } TEB, *PTEB;  TEB结构体原型。

可以看到TEB结构体偏移48位刚好就是PEB结构体指针,48的十六进制是0X30 所以我们可以写如下汇编来实现获取PEB结构

PPEB _peb;

_asm                                                                                                                                                  { mov eax,fs:[0x30]     //获取PEB指针地址                                                                                            mov _peb,eax          // 把地址传给变量_peb                                                                                    }

然后判断_peb->BeingDebugged  是否位0 即可实现调试检测。

通过API函数获取BeingDebugged的值:

CheckRemoteDebuggerPresent():

IsDebuggerPresent();

通过上面两个函数进行检测,函数具体使用不再做介绍。

二、通过内核信息检测是否被调试          

typedef NTSTATUS(NTAPI* NtQueryInformationProcessPtr)(HANDLE, DWORD, PVOID,ULONG, PULONG);  

使用该函数,该函数是微软未公开函数 使用前需要导入。

auto hNtdll = LoadLibrary(L"ntdll.dll");                                                                  NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hNtdll, "NtQueryInformationProcess"); 

然后调用该函数第一个参数需要传入当前线程句柄,第二个参数我门需要知道的三个值:

 0x07 :取debugport值。   debugport !=0时说明正在被调试                                                                0x01E:取debugobject值    debugobject !=0时说明正在被调试                                                         0x01F:取debugflages值,debugflages=0时说明正在被调试

检测方法:

、DWORD debug_port = 0;
    NtQueryInformationProcess(proce, 0x07, &debug_port, sizeof(debug_port), 0x0);
    if (debug_port)return TRUE;
    HANDLE debug_object = 0;
    NtQueryInformationProcess(proce, 0x01E, &debug_object, sizeof(debug_object), 0x0);
    if (debug_object)return TRUE;
    BOOL debug_flages = 1;
    NtQueryInformationProcess(proce, 0x01F, &debug_flages, sizeof(debug_flages), 0x0);
    if (!debug_flages)return TRUE;
    return FALSE;

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值