吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13012|回复: 56
收起左侧

[调试逆向] 几种反调试手法及自写OD插件对其进行绕过

  [复制链接]
镇北看雪 发表于 2020-10-9 23:29
本帖最后由 镇北看雪 于 2020-10-9 23:34 编辑

BeginDebugged

利用调试器加载程序时调试器会通过CreateProcess()创建调试进程,同时会创建调试内核对象并保存在当前线程环境块的DbgSsReserved[1]字段中,此时此线程就不同于普通线程了(一般称为调试器线程)。接着CreateProcess()会判断是否有调试器,无则直接返回,有则调用PspCreateProcess(),此函数会根据DbgSsReserved[1]字段设置创建进程的EPROCESS的DebugPort字段,这样此被创建进程就可以称为被调试进程。接着PspCreateProcess()会调用MmCreatePeb(),此函数会根据EPROCESS的Debugport字段设置PEB的BeingDebuged字段。(无调试器时其值为0)
G5K5HKOMZ}BSA92_5`7DP63.png

我们可以直接通过内联汇编来访问BeingDebuged字段,也可以通过IsDebuggerPresent()这个API来得到此字段的值。下面是示例程序。

int main(int argc, char *argv[])
{
        DWORD        dwBeingDebuged;
        TCHAR        szTest[]        = TEXT("已检测到调试器!");
        TCHAR        szSuccess[] = TEXT("运行正常!");

    dwBeingDebuged           = IsDebuggerPresent();
        if(0 != dwBeingDebuged)
        {
                MessageBox(NULL, szTest, NULL, MB_OK);
                ExitProcess(NULL);
        }
        MessageBox(NULL, szSuccess, NULL, MB_OK);
        return 0;
}

NtGlobalFlag

当BeingDebuged被设为“TRUE”后会将PEB的NtGlobalFlag设置0x70h标志,我们通过内联汇编检测进程环境快的NtGlobalFlag字段。

int main(int argc, char *argv[])
{
        DWORD        dwNtGlobalFlag;
        TCHAR        szTest[]        = TEXT("已检测到调试器!");
        TCHAR        szSuccess[] = TEXT("运行正常!");

    dwNtGlobalFlag           = _AntiDebug();
        if(0 != dwNtGlobalFlag)
        {
                MessageBox(NULL, szTest, NULL, MB_OK);
                ExitProcess(NULL);
        }
        MessageBox(NULL, szSuccess, NULL, MB_OK);
        return 0;
}

//反调试
DWORD _AntiDebug()
{
        _asm{
        mov eax,fs:[0x30]
        mov eax,[eax + 0x68]
        and eax,0x70
        }
}

ProcessHeap的Flags和ForceFlags

当NtGlobalFlag字段被设置0x70标志后,其会改变PEB的字段ProcessHeap所指向的Flags和ForceFlags的值。
对于x86平台而言Flags和ForceFlags偏移地址分别是相对于ProcessHeap指向地址的0x40和0x44处。当程序未被调试器调试时Flags的值应包含0x00000002标志,ForceFlags的值应为0,下面是通过内联汇编检测二者的值。

int main(int argc, char *argv[])
{
        DWORD        dwReturn;
        TCHAR        szTest[]        = TEXT("已检测到调试器!");
        TCHAR        szSuccess[] = TEXT("运行正常!");

    dwReturn                         = _AntiDebug();
        if(0 != dwReturn)
        {
                MessageBox(NULL, szTest, NULL, MB_OK);
                ExitProcess(NULL);
        }

        MessageBox(NULL, szSuccess, NULL, MB_OK);
        return 0;
}

//反调试
DWORD _AntiDebug()
{
        _asm{
        push ebx
        mov eax,fs:[0x30]
        mov eax,[eax + 0x18]

        mov ebx,dword ptr [eax + 0x40]                   //Flags
        and ebx,0x00000002
        cmp ebx,0
        je        end0
        mov ebx,dword ptr [eax + 0x44]                   //ForceFlags
        cmp ebx,0
        jne end0
        xor eax,eax
        jmp end
end0:
        mov eax,1
end:
        pop ebx
        }
}

自写OD插件绕过

此插件时基于OD1.10版本的,当然也可以参考此插件写法编写基于OD2.0版本的。插件思路为:我们通过IATHOOK   OD的WaitForDebugEvent( )函数,将WaitForDebugEvent函数替换为我们的MyWaitForDebugEvent(),当检测到第一次接收到EXCEPTION_DEBUG_EVENT异常调试事件时将BeginDebugged,
NtGlobalFlag,Flags和ForceFlags清除。
替换WaitForDebugEvent()的函数即MyWaitForDebugEvent()代码如下。

BOOL _stdcall MyWaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent, DWORD dwMilliseconds)
{

        static DWORD        stPid;                                                 //进程PID
        static DWORD        dwFlag = 0;
        BOOL Return;

        Return = WaitForDebugEvent(lpDebugEvent,dwMilliseconds);                   //调用原WaitForDebugEvent

        switch(lpDebugEvent->dwDebugEventCode)
        {
        case CREATE_PROCESS_DEBUG_EVENT:                                           //创建进程
                stPid = lpDebugEvent->dwProcessId;
                break;
        case EXCEPTION_DEBUG_EVENT:                                                //调试异常
                dwFlag++;
                if(dwFlag == 1)
                        _DetourAnti(stPid);         //清除BeingDebugged,NtGlobalFlag,HeapFlags,ForceFlags
                break;
        case EXIT_PROCESS_DEBUG_EVENT:                                             //程序退出       
                dwFlag = 0;
        }
        return Return;

}

_DetourAnti( )函数利用OD接口将BeingDebugged,NtGlobalFlag,HeapFlags,ForceFlags标志清除。

//绕过反调试
void _DetourAnti(DWORD dwPid)
{
        HANDLE hProcess;                                                                                                                //进程句柄
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);                           //获取权限

        DWORD dwFlag = 0;
        t_thread * stMainThread ;
        stMainThread = _Findthread(_Plugingetvalue(VAL_MAINTHREADID));

        DWORD dwTibAddress = stMainThread->datablock;
        DWORD dwPebAddress;
        DWORD dwAddress;

        _Readmemory(&dwPebAddress,(dwTibAddress + 0x30), 4, MM_RESTORE);                    //PEB
        _Writememory(&dwFlag,(dwPebAddress + 0x02), 1, MM_RESTORE);                         //DebugPresent

        _Writememory(&dwFlag,(dwPebAddress + 0x68), 4, MM_RESTORE);                         //NtGlobalFlag

        _Readmemory(&dwAddress,(dwPebAddress + 0x18), 4, MM_RESTORE);                       //ProcessHeap

        _Readmemory(&dwFlag,(dwAddress + 0x40), 4, MM_RESTORE);
        dwFlag = dwFlag | 0x2;                                                                                                       
        _Writememory(&dwFlag,(dwAddress + 0x40), 4, MM_RESTORE);                            //HeapFlags

        _Readmemory(&dwFlag,(dwAddress + 0x44), 4, MM_RESTORE);
        dwFlag = 0;
        _Writememory(&dwFlag,(dwAddress + 0x44), 4, MM_RESTORE);                            //ForceFlags
}

IATHook代码在这里就不贴出了,可自行查看附件代码。将插件DLL放入OD1.10版本的plugin目录中运行OD会弹出DLL成功加载。

VQ8_DH1NPXUO{3)W~NLGPUC.png

我们利用BeingDebugged,NtGlobalFlag,HeapFlags,ForceFlags标志写了一个综合反调试程序,将测试程序用OD加载其将绕过所有反调试正常运行。
8Z433C9RQA3LA(T0G9TL4%B.png
实际我们相当于实现了和知名插件HideOD的HideNtDebugBit选项的功能

)(`C(7HK{]{NI{~_Z(0BF.png
参考资料:《软件调试》《加密与解密》

测试程序和源代码和插件DLL.zip

35.92 KB, 下载次数: 513, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 14吾爱币 +18 热心值 +14 收起 理由
atom_warhead + 1 谢谢@Thanks!
youku2020 + 1 热心回复!
ccn1974 + 1 + 1 用心讨论,共获提升!
Hmily + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
shng + 1 + 1 用心讨论,共获提升!
xiuji + 1 + 1 谢谢@Thanks!
victos + 1 + 1 谢谢@Thanks!
anlovedong + 1 + 1 谢谢@Thanks!
Temet-only + 1 我很赞同!
冥界3大法王 + 1 懂得分析内因,因适制造工具才牛逼!
绝无神 + 1 + 1 我很赞同!
qaz003 + 1 + 1 谢谢分享,这个玩得6.。
Lucifer_BW + 1 + 1 热心回复!
yAYa + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

雨露心 发表于 2020-10-10 00:29

佩服高手,,,拿来试试效果
hurryLow 发表于 2022-8-1 08:41
macolma 发表于 2022-7-20 18:28
在win7 x64下没有办法使用,将插件解压放到plug目录下,执行olldbg,打开文件一直在加载中,无法正常使用ol ...

我win10也用不了,咱还是乖乖用提供的xp系统吧
287166966 发表于 2020-10-10 00:23
Dboykey 发表于 2020-10-10 01:09

牛AC的大大,膜拜呀!
dongwuleyuan 发表于 2020-10-10 03:20
马上人肉测试
莎莎啦啦 发表于 2020-10-10 07:05
我很赞同
Eaglecad 发表于 2020-10-10 07:06
有点猛,感谢分享
lifz888 发表于 2020-10-10 08:04
非常好的实践练习,支持分享
tan567421 发表于 2020-10-10 08:23
不错不错,楼主很棒
云中燕 发表于 2020-10-10 08:32
实践是最好的学习方法……膜拜大神
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-31 01:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表