码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-08-19 20:18:18      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:

一、如何遍历驱动   
       在内核中,可以通过大概下面几种方法获取,
       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的驱动没有进行隐藏。反调试手段很多,大家可以随意发挥,只要能检测到。

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

标签:

原文地址:http://www.cnblogs.com/kangxiaopao/p/4743000.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!