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模式
添加必要的静态库。
这样就可以了。
本文略水。
看官见谅。
201401-基于驱动遍历的一种OD检测方案-kido[4st TeAm],布布扣,bubuko.com
201401-基于驱动遍历的一种OD检测方案-kido[4st TeAm]
原文地址:http://www.cnblogs.com/ReverseSec/p/3824819.html