首页 > 代码库 > 201401-基于驱动遍历的一种OD检测方案-kido[4st TeAm]

201401-基于驱动遍历的一种OD检测方案-kido[4st TeAm]

基于驱动遍历的一种OD检测方案

Kido[C.L.G][4.s.T]

好久没写过文章了,这次写一篇关于OD检测方面的科普文。

个人浅薄之见,不喜勿喷。

众所周知,OllyDbg是一款普及度很高的Windows下32位免费Ring3级别的调试工具。

以其插件丰富,操作便捷,功能强大深受广大程序猿,灰客,安全砖家等各种生物喜爱。

自有了软件开发这个概念伊始,调试器就一直存在。随着时代的进步,众多乡非青年对灰客技术的向往,软件安全、加密解密也越来越受众人注视。

人们为了优化,逆向,二次开发,找寻漏洞,修改,破解某一程序,而对其进行的猥琐动作就被叫做调试。

调试又分为黑盒、白盒两种,不过有时候也会引出灰盒这种概念。

所谓黑盒就是去调戏一个不认识的小姑娘。白盒就是夫妻之间恩恩爱爱。灰盒是一种居中的概念,大概就是情人之间那些神奇的事情了。

本文因为笔者的个人兴趣,主要着重探讨调戏陌生小姑娘(Debugee)的事情。

人们为了调试陌生小姑娘,开发了各式各样的调试器(调戏器? Debugger),本文重点关注OllyDbg这个调戏必备神器。而并不是每个小姑娘都是金莲,有些就会自备一些很NB的防狼工具(Anti-Debug)。

例如IsDebuggerPresent是一个通过光明正大观察调戏器是否存在来防止被调戏的方法。

猥琐的二次元人类为了成功的调戏,对目标进行完整的了解,自然也有一些反防狼手段(Anti-Anti-Debug),其中最高端洋气上档次的就属一款叫做StrongOD的工具了。为了少打几个字,人们通常亲切的称呼它为SOD。

SOD不仅从用户层对OD进行了一系列的改造升级,在驱动层也对OD进行了一些保护。例如:隐身术(隐藏OD进程),易容术(Hook 函数使得Debugee对Debugger的检测显示为正常运行的状态)等等。

SOD对自身的驱动也进行了一些保护,使得该驱动文件不可见,且除非暴力穷举不可被识别。

所幸我们利用XT还是可以对他进行观察的:

File Not Found代表驱动文件已经被隐藏起来,看不到了。

我的OD被我改名叫做HolyShit了。红色代表着他已经被隐藏起来了。

Ring3 Access State是Deny代表不可被操作。

让我们看看SOD对驱动层做了一些什么操作把!

SSDT hook了10个函数。

ShadowSSDT hook了6个函数。

正是这些钩子保证了OD不可被通过hwnd遍历出来,并且OD进程不可被操作。

保证了调试器的地位。

本文要介绍的这个方法其实是一个老生常谈的东西。一个很老的手段。

通过暴力获取驱动,判断是否为StrongOD驱动来进行是否被调试的判断。

笔者是一个文艺装逼小青年,花了一天时间下载了VS2013。

下面上代码:

///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////

#include <stdio.h>

#include <tchar.h>

include <Shlwapi.h>

#include <Psapi.h>

#pragma comment(lib,"psapi")

#define ARRAY_SIZE 1024

int _tmain(int argc, _TCHAR* argv[])

{

LPVOID drivers[ARRAY_SIZE];

DWORD cbNeeded;

int cDrivers, i;

if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)

&& cbNeeded < sizeof(drivers))

{

CHAR szDriver[ARRAY_SIZE];

CHAR szPath[ARRAY_SIZE];

CHAR szDbgHelp[ARRAY_SIZE];

CHAR szSystem[ARRAY_SIZE];

size_t len = 0;

BOOL file = false;

GetSystemDirectory(szSystem, sizeof(szSystem));

strcat_s(szSystem, "\\dbghelp.dll");

cDrivers = cbNeeded / sizeof(drivers[0]);

for (i = 0; i < cDrivers; i++)

{

if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0])))

{

GetDeviceDriverFileName(drivers[i], szPath, sizeof(szPath));

if (szPath[1] == ‘?‘)

{

len = strlen(szPath);

do{

len--;

} while (szPath[len] != ‘\\‘);

do{

len--;

} while (szPath[len] != ‘\\‘);

szPath[len + 1] = 0;

for (UINT i = 0; i < len; i++)

{

szPath[i] = szPath[i + 4];

}

sprintf_s(szDbgHelp, "%sdbghelp.dll", szPath);

if (PathFileExists(szDbgHelp))

{

if (strcmp(szSystem, szDbgHelp) == 0)

{

continue;

}

printf_s("OllyDbg Detected:\n"

"Path:%s\n"

"StrongOD Driver Name:%s\n", szPath, szDriver);

}

}

}

}

}

return 0;

}

///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////

上面的代码主要是利用EnumDeviceDrivers 获取出来所有的驱动

然后利用GetDeviceDriverFileName暴力取出驱动路径

去掉开头的”\\??\”之后,去掉驱动名并向上退一个目录。

然后检测该目录下是否存在dbghelp.dll文件

如果存在 且 该目录不为 %system%目录 那么就判定这是个调试器。

然后输出检测到的OD路径以及SOD的驱动名(ollydbg.ini中可自定义)。

如图:

一旦获取到了OD目录。SOD驱动名,那么卸载驱动,破坏OD,利用CMD调用OD来附加现在的这个调试器,恢复SSDT钩子等等。这就不是本文所关注的内容了。

注意:使用VS2012/VS2013编译时需要进行的修改:

兼容XP且试用Ansi模式

添加必要的静态库。

这样就可以了。

本文略水。

看官见谅。