吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 33004|回复: 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++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#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++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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, 2025-3-30 18:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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