1.前言
StrongOD驱动是加了VM的,前段时间逛论坛看到一个前辈还原了这个驱动,详见此贴:
http://bbs.pediy.com/showthread.php?t=171729 ,闲来无事就分析了下。这个还原的版本应该不是StrongOD驱动的最新版本,因为新版本的支持更改设备名,更改通信key,而我并没有在驱动中看到相关代码。附件中有我还原的代码以及IDB文件(IDA版本6.1.110315),代码编译后可以替换最新版本的StrongOD驱动(在XP及win7上简单测过),前提是你不要修改设备名(fengyue0)和通信key(-82693034)。另外原驱动中有一部分函数驱动并没有引用,那部分函数我就没分析,还有某些地方VM还原的貌似不太正确,主要是一些数字,比如那个IRP_MJ_DEVICE_CONTROL的处理函数里面的一个switch跳转表应该有点错,我patch了下IDB以方便分析,还有些其它的数字不影响分析的就没patch,我直接在代码里面改了,代码后面的注释以"[Warning:xxx]"开头就表示此处与汇编代码有些出入,可能是VM还原错了,也可能是我弄错了,大家对照着看!
2.驱动功能简单说明
驱动中东西并没有多少,但是作者为了兼容性和稳定性写了很多代码(驱动的兼容性和稳定性那是灰常的重要),整个驱动编译后有30多KB。
重要的数据结构:
typedef struct _LIST_NODE
{
HANDLE hProcId;
PEPROCESS pEProcess;
DWORD dwType; // 1:black process(the debuggee) 2:white process(the debugger)
PVOID pPool; // the pool of the shared memory
PMDL pMdl; // the mdl of the shared memory
PVOID pUserAddrOfSharedMem; // the user mode address of shared memory
}LIST_NODE, *PLIST_NODE;
驱动中有一个如上结构的结构体数组(100个元素),保存着调试器和被调试程序的相关信息供后面Hook查询使用。Hook了Shadow表内窗体相关的一些函数用来隐藏窗体,Hook了SSDT表中相关的一些函数来anti反调试和保护进程,隐藏进程之类的。另外还有1个IDT Hook,这里面有点意思,后面说。驱动共有6个接口,添加/删除白名单(The debugger),添加/删除黑名单(The debuggee),开启/关闭IDT Hook。如果有人要给其它调试器写类似的插件,插件的驱动部分可以直接拿这个驱动来使用,只需要调用前面4个接口就行了。
3.有点意思的几个地方
1>应用层传给驱动的数据都会先加密,驱动收到数据后先解密,解密后取出第一个双字当作通信Key(就是OD目录配置文件里面的那个Key),与驱动中保存的Key比较,不对的话驱动直接传回参数错误(如我前面说的,我并没有看到修改Key的相关代码,所以这个版本应该不是最新版,驱动中的Key初始化为-82693034==0xFB123456,与OD目录的配置文件里面的那个初始Key是一样的)。
2>里面有一个IDT Hook,Hook的是与调试异常相关的1号中断(硬件断点和单步都走这个),并设置了调试控制寄存器(0x1d9)的BTF(Branch Trace Flag)位和LBR(Last Branch Record)位,开启按分支单步执行和LBR功能(开启这个功能后,CPU会将最后一次控制转移写到特定的寄存器里面,包括From Ip和To Ip),然后在自己的中断处理函数里面将这个From Ip和To Ip写到驱动创建的一个共享内存里面(每次添加黑名单后,即被调试程序,驱动会创建一块共享内存,并将这块共享内存映射到被调试程序的用户空间中去),然后StrongOD.dll负责通过调试接口从被调试进程内读出来(这个是我猜的)。不过我用XT看了一下这个IDT Hook并没有启用,可能是不稳定或者作者自己测试用的吧,这个其实也有些缺点,驱动创建了一块比较大的共享内存,却只写了8个字节(From Ip和To Ip)到里面去(共享内存的前面8个字节记录From Ip和To Ip),如果是多核的话还会存在竞争。更多的关于LBR(一对寄存器记录一次转移信息),LBR栈(多对寄存器记录多次转移信息),Debug Store(转移信息写到内存里,可以记录更多)等资料请参考软件调试(这本书非常好)中Cpu对调试的支持这一章!
4.驱动的几个小问题
分析中发现了驱动的几处小问题,作者最新版本可能已经修复了这些问题。
1>驱动没有Hook NtSetContextThread,在恢复Hook的时候却有一个恢复操作。
2>MyQuerySystemInformation(自己的用于替换系统的NtQuerySystemInformation函数)中有一处调用ObDereferenceObject调用位置不对导致可能泄漏。
3>IRP_MJ_DEVICE_CONTROL的处理里没检查buffer长度就引用,如果传递一个空buffer会导致蓝屏(勿喷
)。
4>MySetContextThread参数检查用的MmIsAddressValid,这个不太对(Try+ProbeXXX),这个函数没Hook,不会有啥大影响。
5>针对ProcessDebugFlags反调试没处理(最新版本我看了下这个是处理了),我已经加上了。
6>......详细见代码。
本人水平菜,以上说的可能有问题,大家勿喷!
5.最后
借看雪宝地打个小小的广告,不知道有木有招人的啊
,本人情况说明:
1>工作地点:北京
2>工作经验:12年本科毕业,一年实习+二年正式 端茶倒水经验
For more information, email to me, thanks! Email:295680460@qq.com
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: