吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 32814|回复: 99
收起左侧

[调试逆向] 反调试之遍历驱动名

  [复制链接]
JoyChou 发表于 2014-3-14 21:54
本帖最后由 JoyChou 于 2014-3-16 19:40 编辑

一、如何遍历驱动   
       在内核中,可以通过大概下面几种方法获取,
       0x1. 遍历驱动对象(Driver_Object)的DriverSection域
       0x2. 遍历KPCR结构体的PsLoadedModuleList域
       0x3. ZwQuerySystemInformation的11号功能
       0x4. 内存暴力搜索

       在应用层中,可以通过psapi的EnumDeviceDrivers API来获取,其关键是调用ZwQuerySystemInformation。

二、Anti原理
       平时在用OD调试的时候,肯定会用到很多OD的插件。可以发现,这些插件都是dll文件,然后被OD加载调用。那既然OD加载了这么多插件,为何不直接遍历所有进程模块,如果发现有可疑的模块(例如:stringOD模块),那就可以直接判断调试器正在运行。但是,OD的进程被SOD隐藏了,如果不借助ARK工具,在任务管理器里面是看不到的。图1是XueTr观察到的。

图1

图1


       但是可以遍历系统驱动模块,因为驱动模块是没有隐藏的,所以可以通过程序遍历得到。如图2所示。但是,要排除掉系统的dbghelp.dll的干扰。

图2

图2

       可见,只要将驱动路径向上2个目录,来到OllyDbg目录,判断是否存在dbghelp.dll,即可确定是否有调试器的存在。如图3所示。

      

图3

图3



三、代码

[C++] 纯文本查看 复制代码
#include "stdafx.h"
 
#include <stdio.h>
#include <windows.h>
#include <Psapi.h>
#include <shlwapi.h>  //PathFileExists
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "shlwapi.lib")
#define  ARRAY_SIZE 1024
 
int main(int argc, char *argv[])
{
    DWORD cbNeeded = 0;
    LPVOID drivers[ARRAY_SIZE] = {0};
    int cDrivers = 0, i = 0;
    if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) &&
        cbNeeded < sizeof(drivers))
    {
        char szDriver[ARRAY_SIZE] = {0};
        char szPath[ARRAY_SIZE] = {0};
        char szDbgHelp[ARRAY_SIZE] = {0};
        char szSystemPath[ARRAY_SIZE] = {0};
        cDrivers = cbNeeded / sizeof(LPVOID);
        bool bDetect = FALSE;  
        //得到C:\Windows\system32\dbghelp.dll
        GetSystemDirectory(szSystemPath, sizeof(szSystemPath));
        strcat_s(szSystemPath, "\\dbghelp.dll");
        //printf("There are %d drivers\n", cDrivers);
        for (i = 0; i < cDrivers; i++)
        {
            // 驱动名
            if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(LPVOID)))
            {
                printf("%d:%s\n", i+1, szDriver);
                // 驱动完整路径
                GetDeviceDriverFileName(drivers[i], szPath, sizeof(szPath));
                //只判断非系统驱动
                if (szPath[1] == '?')  
                {
                    int len = strlen(szPath);
                    //printf("%d:%s\n", i+1, szPath);
                    // 得到驱动上一级目录
                    do
                    {
                        len--; 
                    } while (szPath[len] != '\\');
                    // 得到驱动上 上一级目录
                    do
                    {
                        len--; 
                    } while (szPath[len] != '\\');
                    szPath[len + 1] = '\0'; // 字符串截断
                    // 去除驱动路径的前4个字符"\??\"
                    for (int j = 0; j < len; j++)
                    {
                        szPath[j] = szPath[j + 4];
                    }
                    sprintf_s(szDbgHelp, "%sdbghelp.dll", szPath);
                    // 判断文件是否存在
                    if (PathFileExists(szDbgHelp))
                    {
                        // 排除系统的dbghelp.dll
                        if (_strcmpi(szSystemPath, szDbgHelp) != 0)
                        {
                            bDetect = TRUE;
                            break;
                        }          
                        else
                        {
                            bDetect = FALSE;
                        }
                    }
                }
            }
        }
        if (bDetect)
        {
            printf_s("Detect OD\n");
            printf_s("Path: %s\n", szPath);
            printf_s("SOD Name: %s\n", szDriver);
        }
        else
        {
            printf_s("Do not Detect OD\n");
        }
        getchar();
    }
}


四、效果

在XP和32位的win7下面,驱动是不需要签名的,载入OD即可加载驱动。

      

图4

图4


五、反调试之策

可以通过断链隐藏SOD的驱动名,一般是fengyue0.sys
       隐藏代码:

      
[C++] 纯文本查看 复制代码
VOID HideDriver(PDRIVER_OBJECT pDriverObject)
{
    PLDR_DATA_TABLE_ENTRY pLdrData = NULL;
    PLIST_ENTRY pCur, pHead = NULL;
    UNICODE_STRING uDriverName;
 
    // 初始化要隐藏的驱动名
    RtlInitUnicodeString(&uDriverName, L"fengyue0.sys");
 
    pLdrData = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
 
    // 得到当前sys模块,并设置为第一个(head)以及当前(cur)模块
    pCur = pHead = pLdrData->InLoadOrderLinks.Flink;
 
    __try
    {
 
        do
        {
            // 这句pLdrData = (PLDR_DATA_TABLE_ENTRY)pCur是等价的
            // 因为pCur在LDR_DATA_TABLE_ENTRY结构体的第一个域(成员)
            pLdrData = CONTAINING_RECORD(pCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
            if (pLdrData->BaseDllName.Length > 0 &&
                pLdrData->BaseDllName.Buffer != NULL)
            {
                if (RtlCompareUnicodeString(&uDriverName, &(pLdrData->BaseDllName), FALSE) == 0)
                {
                    KdPrint(("驱动隐藏\n"));
                    // 断链
                    pLdrData->InLoadOrderLinks.Blink->Flink =
                        pLdrData->InLoadOrderLinks.Flink;
 
                    pLdrData->InLoadOrderLinks.Flink->Blink =
                        pLdrData->InLoadOrderLinks.Blink;
 
                    // 断掉的链指向自己
                    pLdrData->InLoadOrderLinks.Flink =
                        (PLIST_ENTRY)&pLdrData->InLoadOrderLinks.Flink;
 
                    pLdrData->InLoadOrderLinks.Blink =
                        (PLIST_ENTRY)&pLdrData->InLoadOrderLinks.Flink;
 
                    KdPrint(("PsLoadedModuleList success \r\n"));
                    break;
                }
            }
 
            pCur = pCur->Flink;
        } while (pCur != pHead);
    }
 
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        KdPrint(("PsLoadedModuleList Error \r\n"));
    }

       驱动载入后,再次运行之前的anti程序,就找不到驱动名了,反调试已经没用了。如图5。

图5

图5


六、总结

这种anti手法,局限性比较低,因为StrongOD的驱动没有进行隐藏。反调试手段很多,大家可以随意发挥,只要能检测到。



反调试之遍历驱动名.zip (160.55 KB, 下载次数: 175)






免费评分

参与人数 6热心值 +6 收起 理由
Jack丶雷 + 1 用心讨论,共获提升!!!!
fire8223069 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
currwin + 1 分全给愿意分享优秀教材的人
无名L + 1 都是大牛!
神圣剑帝 + 1 我很赞同!
H2o + 1 分是给愿意分享的人的!

查看全部评分

本帖被以下淘专辑推荐:

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

吾爱扣扣 发表于 2014-3-14 23:29
原来看雪上也是你发的?

免费评分

参与人数 1热心值 +1 收起 理由
Jack丶雷 + 1 发现一枚扣扣,

查看全部评分

bnbyc 发表于 2014-5-27 08:53
wodezuiaiyxm 发表于 2014-5-26 09:17
头像被屏蔽
892644330 发表于 2014-3-14 23:23
oh,No  这不是真的:
(, 下载次数: 5)

www52pojiecn 发表于 2014-3-15 17:47
谢谢,能看!
Hmily 发表于 2014-3-16 18:26
这个算一个方法介绍吧,加精鼓励,JoyChou有空可以把文章直接贴上来,方便大家阅读。
门卫冰 发表于 2014-3-16 18:38
下载收藏之
不知道新人能不能看懂
 楼主| JoyChou 发表于 2014-3-16 19:15
Hmily 发表于 2014-3-16 18:26
这个算一个方法介绍吧,加精鼓励,JoyChou有空可以把文章直接贴上来,方便大家阅读。

恩,好的。H大大
℡Black星辰 发表于 2014-3-16 20:17
又学习了,支持楼主
wp2664392 发表于 2014-3-16 20:23
标记学习!
凌云9 发表于 2014-3-16 20:52
模拜大神
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-23 12:32

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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