[转]反调试之遍历驱动名

一、如何遍历驱动   
       在内核中,可以通过大概下面几种方法获取,
       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观察到的。

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

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

三、代码

   1: #include "stdafx.h"
   2:   
   3: #include <stdio.h>
   4: #include <windows.h>
   5: #include <Psapi.h>
   6: #include <shlwapi.h>  //PathFileExists
   7: #pragma comment(lib, "psapi.lib")
   8: #pragma comment(lib, "shlwapi.lib")
   9: #define  ARRAY_SIZE 1024
  10:   
  11: int main(int argc, char *argv[])
  12: {
  13:     DWORD cbNeeded = 0;
  14:     LPVOID drivers[ARRAY_SIZE] = {0};
  15:     int cDrivers = 0, i = 0;
  16:     if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) &&
  17:         cbNeeded < sizeof(drivers))
  18:     {
  19:         char szDriver[ARRAY_SIZE] = {0};
  20:         char szPath[ARRAY_SIZE] = {0};
  21:         char szDbgHelp[ARRAY_SIZE] = {0};
  22:         char szSystemPath[ARRAY_SIZE] = {0};
  23:         cDrivers = cbNeeded / sizeof(LPVOID);
  24:         bool bDetect = FALSE;  
  25:         //得到C:\Windows\system32\dbghelp.dll
  26:         GetSystemDirectory(szSystemPath, sizeof(szSystemPath));
  27:         strcat_s(szSystemPath, "\\dbghelp.dll");
  28:         //printf("There are %d drivers\n", cDrivers);
  29:         for (i = 0; i < cDrivers; i++)
  30:         {
  31:             // 驱动名
  32:             if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(LPVOID)))
  33:             {
  34:                 printf("%d:%s\n", i+1, szDriver);
  35:                 // 驱动完整路径
  36:                 GetDeviceDriverFileName(drivers[i], szPath, sizeof(szPath));
  37:                 //只判断非系统驱动
  38:                 if (szPath[1] == ‘?‘)  
  39:                 {
  40:                     int len = strlen(szPath);
  41:                     //printf("%d:%s\n", i+1, szPath);
  42:                     // 得到驱动上一级目录
  43:                     do
  44:                     {
  45:                         len--; 
  46:                     } while (szPath[len] != ‘\\‘);
  47:                     // 得到驱动上 上一级目录
  48:                     do
  49:                     {
  50:                         len--; 
  51:                     } while (szPath[len] != ‘\\‘);
  52:                     szPath[len + 1] = ‘\0‘; // 字符串截断
  53:                     // 去除驱动路径的前4个字符"\??\"
  54:                     for (int j = 0; j < len; j++)
  55:                     {
  56:                         szPath[j] = szPath[j + 4];
  57:                     }
  58:                     sprintf_s(szDbgHelp, "%sdbghelp.dll", szPath);
  59:                     // 判断文件是否存在
  60:                     if (PathFileExists(szDbgHelp))
  61:                     {
  62:                         // 排除系统的dbghelp.dll
  63:                         if (_strcmpi(szSystemPath, szDbgHelp) != 0)
  64:                         {
  65:                             bDetect = TRUE;
  66:                             break;
  67:                         }          
  68:                         else
  69:                         {
  70:                             bDetect = FALSE;
  71:                         }
  72:                     }
  73:                 }
  74:             }
  75:         }
  76:         if (bDetect)
  77:         {
  78:             printf_s("Detect OD\n");
  79:             printf_s("Path: %s\n", szPath);
  80:             printf_s("SOD Name: %s\n", szDriver);
  81:         }
  82:         else
  83:         {
  84:             printf_s("Do not Detect OD\n");
  85:         }
  86:         getchar();
  87:     }
  88: }

四、效果

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

五、反调试之策

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

       隐藏代码:

 

   1: VOID HideDriver(PDRIVER_OBJECT pDriverObject)
   2: {
   3:     PLDR_DATA_TABLE_ENTRY pLdrData = NULL;
   4:     PLIST_ENTRY pCur, pHead = NULL;
   5:     UNICODE_STRING uDriverName;
   6:   
   7:     // 初始化要隐藏的驱动名
   8:     RtlInitUnicodeString(&uDriverName, L"fengyue0.sys");
   9:   
  10:     pLdrData = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
  11:   
  12:     // 得到当前sys模块,并设置为第一个(head)以及当前(cur)模块
  13:     pCur = pHead = pLdrData->InLoadOrderLinks.Flink;
  14:   
  15:     __try
  16:     {
  17:   
  18:         do
  19:         {
  20:             // 这句pLdrData = (PLDR_DATA_TABLE_ENTRY)pCur是等价的
  21:             // 因为pCur在LDR_DATA_TABLE_ENTRY结构体的第一个域(成员)
  22:             pLdrData = CONTAINING_RECORD(pCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  23:             if (pLdrData->BaseDllName.Length > 0 &&
  24:                 pLdrData->BaseDllName.Buffer != NULL)
  25:             {
  26:                 if (RtlCompareUnicodeString(&uDriverName, &(pLdrData->BaseDllName), FALSE) == 0)
  27:                 {
  28:                     KdPrint(("驱动隐藏\n"));
  29:                     // 断链
  30:                     pLdrData->InLoadOrderLinks.Blink->Flink =
  31:                         pLdrData->InLoadOrderLinks.Flink;
  32:   
  33:                     pLdrData->InLoadOrderLinks.Flink->Blink =
  34:                         pLdrData->InLoadOrderLinks.Blink;
  35:   
  36:                     // 断掉的链指向自己
  37:                     pLdrData->InLoadOrderLinks.Flink =
  38:                         (PLIST_ENTRY)&pLdrData->InLoadOrderLinks.Flink;
  39:   
  40:                     pLdrData->InLoadOrderLinks.Blink =
  41:                         (PLIST_ENTRY)&pLdrData->InLoadOrderLinks.Flink;
  42:   
  43:                     KdPrint(("PsLoadedModuleList success \r\n"));
  44:                     break;
  45:                 }
  46:             }
  47:   
  48:             pCur = pCur->Flink;
  49:         } while (pCur != pHead);
  50:     }
  51:   
  52:     __except(EXCEPTION_EXECUTE_HANDLER)
  53:     {
  54:         KdPrint(("PsLoadedModuleList Error \r\n"));
  55:     }

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

六、总结

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

时间: 2024-08-02 08:46:54

[转]反调试之遍历驱动名的相关文章

过反调试

重所周知,有破解就必有防破解,二者本为一体 破解技术就不要我多介绍了,下面我来介绍反调试技术 也就是所谓的防破解技术 反调试技术可以简单通俗的理解为:防止OD分析软件的技术,也就是反调试技术 那么反调试技术又有几种呢? 下面我介绍几种常用反调试技术 首先声明,下面有一部分内容来源百度,若有喷子觉得恶心,请自觉删除 1.       最常用的便是调用windows API 那么 windows API又如何检测OD呢?每一个API的作用是什么呢 2.       小编在百度上搜寻了一些文章来引用

【转】反调试技巧总结-原理和实现

总结: 1.  FindWindow.比如 FindWindowA("OLLYDBG", NULL); 2.  EnumWindow函数调用后,系统枚举所有顶级窗口,为每个窗口调用一次回调函数.在回调函数中用 GetWindowText得到窗口标题,进行检测. 3.  GetForeGroundWindow返回前台窗口(用户当前工作的窗口).当程序被调试时,调用这个函数将获得Ollydbg的窗口句柄,再用GetWindowTextA检测. 4.枚举进程列表,看是否有调试器进程(OLLY

修改Android手机内核,绕过反调试

0x1.手机设备环境 Model number: Nexus 5 OS Version: Android 4.4.4 KTU84P Kernel Version: 3.4.0-gd59db4e 0x2.Android内核提取 查找Android设备的boot分区文件.高通芯片的设备可以通过下面的命令进行查找. cd /home/androidcode/AndroidDevlop/modifyNexus5Boot adb shell ls -al /dev/block/platform/msm_s

源码编译绕过反调试

参考师弟的贴子修改的, 基本我一次就弄好了, 没有遇到啥问题, 下面我主要是补充下他的帖子 http://bbs.pediy.com/showthread.php?t=213481 一. 环境搭建 (1). 环境介绍: 手机:nexus 5 ubuntu版本:15.10 android版本:4.4.4 android源码官网(这里有很多相关的资料,基本上按照官网的来就可以编译想编译的任何版本了) http://source.android.com/source/ (2). 环境配置 配置环境得好

强大反调试cm的奇葩破解

系统 : Windows xp 程序 : Crackme-xp 程序下载地址 :http://pan.baidu.com/s/1slUwmVr 要求 : 编写注册机 使用工具 : OD & IDA 可在看雪论坛中查找关于此程序的破文:传送门 这是一个拥有强大反调试机制的cm,无法查询到关键子串.下获取窗口文本的断点没用,设置对按钮下消息断点都没用. 然后用IDA打开后却发现了函数表里有: .................. 这个懂点英文的人都能看出来是 注册按钮的处理函数吧?所以前面那么多防护

TLS (Thread Local Storage)反调试原理

TLS的特别之处在于使得程序的入口点EP不是第一条执行的指令,所以常常用于反调试检测之中. 用一个已经开启的TLS的程序来做说明. 数据结构 TLS存在于PE文件格式之中.IMAGE_DATA_DIRECTORY DataDirectory[9] 存放了TLS目录的地址. winNT.h [F12 可得到定义位置] #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory 同其他目录表数组一样,也是8字节结构 (VA+Size) typedef s

反调试-去除各种反调试

前不久破解一个软件的时候遇到了各种反调试,折腾的自己各种难受,最终爆破了之后感觉心情大快就顺手写下了这篇文章 使用工具 十六进制分析工具:winhex 查壳工具:PEID 脱壳工具:ollydump插件或者LordPE 脱壳修复工具:ImportREC 逆向工具:OllyDbg 分析过程 PE修复 打开源程序所在文件夹,发现有一个crackme,双机运行程序发现有这个提示: 应该是文件的PE结构被修改了,winhex载入分析发现: 果然是PE结构的问题,在DOS头后面的PE头的16进制应该为50

WIN10 X64下通过TLS实现反调试

目录(?)[-] TLS技术简介 1 TLS回调函数 2 TLS的数据结构 具体实现及原理 1 VS2015 X64 release下的demo 2 回调函数的具体实现 21 使用IsDebuggerPresent检测调试器 22 使调DebugPort检测调试器 实际测试 1 测试直接执行 2 测试用调试器加载 总 结 1 TLS技术简介 Thread Local Storage(TLS),是Windows为解决一个进程中多个线程同时访问全局变量而提供的机制.TLS可以简单地由操作系统代为完成

从破解实例到探讨反调试

系统 : Windows xp 程序 : KeyGenMe 1 by Taliesin 程序下载地址 :http://pan.baidu.com/s/1c2HTuqk 要求 : 注册机编写 使用工具 : OD 可在看雪论坛中查看关于此程序的讨论:传送门 老规矩,先查看下字符串,定位关键代码: 004014DF |. B8 6C304000 mov eax, 0040306C ; great job! 004014E4 |. 8BD8 mov ebx, eax 004014E6 |. 83C3 0