首页
社区
课程
招聘
十多年前未公开的反调试 - WindowByte反调试
发表于: 2024-6-27 23:44 4037

十多年前未公开的反调试 - WindowByte反调试

2024-6-27 23:44
4037
typedef LONG (WINAPI* WINDOWSBYTE)(int, int);
bool CheckDebug()
{
    DWORD dwRet = 0;
    char szModuleName[15] = {0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C}; // user32.dll
    PWCHAR lpModuleName = NULL;
    PWCHAR lpModuleNameTemp = NULL;
    PCHAR lpSrc = szModuleName;
    DWORD dwAPI = 0;
    DWORD dwFunName = 0;
    DWORD dwBase = 0;
    
    _asm
    {
        xor ecx, ecx
        mov esi, fs: [0x30]
        mov esi, [esi + 0x0c]
        mov esi, [esi + 0x1c]
next_module:
        
        mov eax, [esi+0x8]
        cmp eax, 0
        je end
        mov edi,[esi+0x20]
        mov esi ,[esi]

        mov dwBase, eax
        mov lpModuleName, edi
        mov lpModuleNameTemp, edi
    }
    
    lpSrc = szModuleName;
    while(*lpModuleNameTemp != 0 && *lpSrc != 0)
    {
        if(*lpModuleNameTemp >= 'A' && *lpModuleNameTemp <= 'Z')
        {
            if(*lpModuleNameTemp != *lpSrc-0x20)
            {
                _asm
                {
                    jmp next_module
                }
            }
            else
            {
                lpSrc++;
                lpModuleNameTemp++;
            }
        }
        else if(*lpModuleNameTemp != *lpSrc)
        {
            _asm
            {
                jmp next_module
            }
        }
        else
        {
            lpSrc++;
            lpModuleNameTemp++;
        }
    }

end:

    
    PIMAGE_DOS_HEADER pDosHeader;
    PIMAGE_NT_HEADERS pNtHeader;
    PIMAGE_EXPORT_DIRECTORY pExportDirectory;
    
    char szFunName[15] = {0x47, 0x65, 0x74, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x4C, 0x6F, 0x6E, 0x67, 0x41, 0x00}; // GetWindowLongA
    
    
    pDosHeader = (PIMAGE_DOS_HEADER)dwBase;
    pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)dwBase + pDosHeader->e_lfanew);
    pExportDirectory = PIMAGE_EXPORT_DIRECTORY(pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress + (PBYTE)dwBase);
    
    PDWORD pAddressName = PDWORD((PBYTE)dwBase+pExportDirectory->AddressOfNames);
    PWORD pAddressOfNameOrdinals = (PWORD)((PBYTE)dwBase+pExportDirectory->AddressOfNameOrdinals);
    PDWORD pAddresOfFunction = (PDWORD)((PBYTE)dwBase+pExportDirectory->AddressOfFunctions);
    
    for(DWORD i = 0; i < pExportDirectory->NumberOfNames; i++)
    {
        PCHAR pFunc = (PCHAR)((PBYTE)dwBase + *pAddressName++);
        
        // printf("%s\r\n", pFunc);
        
        if (0 == strcmp(pFunc, szFunName))
        {
            dwAPI = (DWORD)dwBase + pAddresOfFunction[*pAddressOfNameOrdinals];
            break;
        }
        
        pAddressOfNameOrdinals++;
    }

    WINDOWSBYTE WindowsByte = (WINDOWSBYTE)dwAPI;

    for(int j = 0; j < 0xffffff; j++)
    {
        dwRet = WindowsByte(j, 0);
        
        // 1.x OD
        if(0x4cd6a8 == dwRet ||
            0x4cda75 == dwRet ||
            0x4cde42 == dwRet)
        {
            return TRUE;
        }
        
        // 2.x OD
        if(0x5e63c4 == dwRet ||
            0x5e6ab8 == dwRet ||
            0x5e6d24 == dwRet ||
            0x5e6fa8 == dwRet ||
            0x5e76b4 == dwRet)
        {
            return TRUE;
        }
    }

    return false;
}


char szCheckDebug[] =
"u\"Unpublicized anti-debug by cpudbg 冭貾YIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BB"
"ABXP8ABuJI3eLKZLOsZL1hscRvaGkwBezlGpS05Pwpo6g5jL3Ekv3uHmpszfg5ZNREKv75zORRZfqU8pUc"
"IVReya7BIVqUkBVNjfaUhs2Do6reKD2L9VG5huPlvSKpniReXvMXW5kJo7SuYtUPePwpS0YWRekXs0s0uP"
"EPLMPM8lMYrmMxKwreoPS0GpuPwpjgaUoLWpWpuPePo7SuyPgpUPWpuPUcKyrDlKtuDpc0GpUPLK1fVlNk"
"0v5LnkQVwxNcXxs06olDOUwpWpwpLK1nUpNkvVlICu9PoyQmItoySMYxLMRuzLNi65lhNkPExh6SKy0flK"
"Vhouky4OotOqUPuPC0lKPU98VoMnC2nekpD4QglKpMM8ecKbE6LKtQMSzZg1alvZLKsuKXucjiavnk4HNc"
"l9PZ3O4mlK3eyxuckpBFlKfblKPMoXdOMnDQMSJJ7P7KYRadwtHkOeJKUBlKW5LhMSkpwqk9qUMxNkPMKX"
"ncKqgrnibmKXZKfKLKqEKXecKpQvlKS2lKRmoX6oONtQekO244uWM9Qxyo9o9oZKvrLKreY8mSIPGqK9Cu"
"OXNkpMJHosKquRmY0MYxYy2OIokOyokvpEN4CwIVQUzupeJfpEZvsDKv75XW67KvsuzxQyjfW5Jy0nkvQU"
"KjsTKvaUKkbOhFSuYLBW8FpEyMpLHFSuyN2OhFCuKo2No6BekP0g8FQUyqQQHFre8b7pnkru9PoyBuN0LK"
"QUN0nkRmkp4CqXUlmYPMx4lKceMdlK2ekpS3g2d8k9w5OTNkpMMtlKPUKp6cpQQ0k9buNLNkSuy4lKrmiP"
"C3bhVDk9rmlpNkSei4NkqUKpfcqRELk9QUZdKwPEXHUPS05PUPjKuYnk0MKxmSzaUQMYPMZhlK65mtlKSu"
"JhgKpBVxvoNcZ5UPuP30nkRmLllKaEO0VcTQMYPUOlnkg5nLOsKpvdmYG5NLlM2mZtLIpMnxlKQEolK9qE"
"ntNkrez4Nj38mX2mNsNk0UlXujTJ2UFNop3MNs7pQdUOlKBeodMZW8UQMXPMLRnk3enxDzQZUQPu4Wk3w5"
"odeRLCqUlXwrOpsMZ2Gp2UxLJgw5lLePgpwps0xks8EKiPNcJx9oMYW5lLLK0MnlMY2mMXMSQmNhwp3Ewf"
"LKRuNPgCKpqvNkS2nkpMhDnkV5KpvcTTK1Oyv590zKVnNkQUnPK3kp4BMYaU80KY0SkOIo9oLKPMOPOypM"
"KL8GqULxS0uPePWpxkTInkV5LxOszbGqoyruX8MQcMMhkOkODOePSMSnrJUPnkG5MhPPkOrukLLIRezlOq"
"cMXLnHkfBlePbTdRna1mzl0uzzRlePPtUYmQQmZlcrYNblgpQeGtLpeQZKp5k13MxLITQsSns0qdEtk1SM"
"xLoHsZqNWp44eKNaQmzlvDrMsngpt4gbmQQmXLlhpo3nwpD4WyoqSMZlMdrVsngppugtnPuQzKWtZKNpgB"
"KpsoSnqKLKm53mQKjcz0LPLPlPEPHappy birthday, my brave girl :)lmYPMx4lKceMdlK2ekpS3g";

int main(int argc, char* argv[])
{
    bool bFound = false;

	// shellcode version
    _asm
    {
        lea eax, szCheckDebug
        call eax
        mov bFound, al
    }
	if(bFound)
    {
        MessageBox(NULL, "shellcode version, Found ollydbg!", ":(", MB_ICONERROR);
    }
    else
    {
        MessageBox(NULL, "shellcode version, Not found ollydbg!", ":)", MB_ICONINFORMATION);
    }


	// c version
    if(CheckDebug())
    {
        MessageBox(NULL, "c version, Found ollydbg!", ":(", MB_ICONERROR);
    }
    else
    {
        MessageBox(NULL, "c version, Not found ollydbg!", ":)", MB_ICONINFORMATION);
    }

    return 0;
}


还记得刚接触od那段时间,把od里三层外三层都研究了个遍,恨不得od的每一个字节都不放过.这个反调试也就是那时候发现的.
由于我对反调试不怎么感冒.这个反调试就慢慢的被遗忘了,直到前段时间,项目需求是必须要加上反调试.起初在网上找了许多反调试代码.
这些anti从环3到环0 从进程到内存 从窗口到特征 从嘀嗒差到debugapi 等等 各式各样的, 甚至还有检测进程目录下是否有 dbghelp plugin 等字样的.
这些anti有的很经典 有的检测环境苛刻 有的误判率过高  这些anti网上几乎都有相应的anti anti插件或方法绕过检测.
感觉都不尽如人意,这才让我想起了这个沉睡了10多年的反调试. WindowByte反调试.


<十多年前未公开的反调试 - WindowByte反调试>
优点: 误报率为0(代码写完善的情况下)
缺点: 只争对OD检测


不知od作者当初是有意栽花? 还是无意插柳?


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-6-28 23:19 被CpuDbg编辑 ,原因: 添加C语言版本
收藏
免费 1
支持
分享
最新回复 (8)
雪    币: 9686
活跃值: (1675)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
2
现在大多都用x64dbg了,od少了
2024-6-28 07:45
0
雪    币: 186
活跃值: (865)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
你这种方式 和搜索进程有啥区别啊 ,只要od打开了 就算嘛
2024-6-28 09:38
0
雪    币: 6
活跃值: (3465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
直接给给ASM源码吧, 另外检测的底层逻辑是什么,能不能先说一下?
2024-6-28 19:07
0
雪    币: 533
活跃值: (279)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
wx_冰川 你这种方式 和搜索进程有啥区别啊 ,只要od打开了 就算嘛
那还是不一样的, 搜索进程,有很多插件都会隐藏进程的.
2024-6-28 23:20
0
雪    币: 533
活跃值: (279)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
咖啡_741298 直接给给ASM源码吧, 另外检测的底层逻辑是什么,能不能先说一下?
我已经更新C语言代码 :)
2024-6-28 23:21
0
雪    币: 6
活跃值: (3465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
CpuDbg 我已经更新C语言代码 :)
关键是调用GetWindowLongA是把?  我记得vxk给了一个更隐蔽的方法一击必杀OD的, 类似于windowEventHook
2024-6-29 00:37
0
雪    币: 101
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
现在都是VT
2024-6-29 14:39
0
雪    币: 4496
活跃值: (4478)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9

优秀,发现的人用心了,感谢分享   


作者用SetWindowLong  DWL_MSGRESULT   保存了窗口的全局变量.       和 SetProp 之类的保存信息差不多. 

最后于 2024-6-29 20:24 被Mxixihaha编辑 ,原因:
2024-6-29 19:51
1
游客
登录 | 注册 方可回帖
返回
//