首页
社区
课程
招聘
[原创]Rootkit Unhooker驱动逆向分析
发表于: 2008-6-19 00:31 21458

[原创]Rootkit Unhooker驱动逆向分析

2008-6-19 00:31
21458

这个驱动本来准备端午节搞的,但后来端午节去了躺北京玩了几天,也就搁置了...最近连续花了4个晚上,大致把它搞的差不多了,有些收获...初学window驱动,水平很菜,有些东西我也未必清明,加上3环的代码还没有吃透,期间也没有用调试器跟踪,全是IDA(F5)静态分析的,谬误在所难免,高手请飘过,希望对菜鸟学习有点帮助.

1.SSDT检测

这个功能有三个IoControlCode与之对应,他们分别是22000fh(拷贝KeServiceDescriptorTable);220007h(拷贝KeServiceDescriptorTable->ServiceTable);22000bh(恢复一个ssdt hook),这个功能目前还不具备检测和恢复inline hook的功能

2.Shadow SSDT检测

这个功能实现和SSDT差不多,都是从KeSystemServiceDescriptorTableShadow入手,不过3环需要为每个平台配置一张函数名表(ssdt可以不配置函数名表,可以从ntdll.dll中收集),详细文章可以参见zhuwg兄弟写的<<shadow ssdt学习笔记>>一文

3.进程

3.1 进程检测

IoControlCode是22001Bh,在检测之前会设置检测方式,然后根据检测方式进行检测.这个功能主要由irp_mj_device_control_dispatch_function函数的is_22001Bh_list_process分支完成,这里集成了4种检测方法,大致如下:

3.1.1 基于PspCidTalbe的检测,这里rku对句柄表做了解析,对每个Object判定是不是EPROCESS,是则插入到输出列表(icesword也有这中检测,不过在1.22中没有解析句柄表,而是用ExEnumHandleTable搞定这些) 详细代码见list_process_in_2k_by_handle_table/list_process_in_not_2k_by_handle_table函数
3.2.1 基于KiWaitListHead/KiWaitOutListHead的检测,这个检测方法很简单,关键是KiWaitListHead/KiWaitOutListHead两个链表的获取, 详细代码见list_process_by_list_head函数
3.3.1 如果是xp系统则还会采用*淫**荡*的内存暴力搜索进程进行检测,这段代码看debugman的yykingking发过, 详细代码在list_process_by_search_memory_in_xp函数
3.4.1 rku还会inline hook SwapContext函数,在这个函数里会记录当前的活动进程情况,经过上面三种方法的洗礼后,对在SwapContext的记录里的,但不在输出列表里的继续加入,当然是有判定条件的(条件就是EPROCESS不能在ntoskrnl模块内,即不为idle进程). BTW:这里有个逻辑我觉得有问题:

.text:000134A7                   loc_134A7:                              ; CODE XREF: irp_mj_device_control_dispatch_function+233j
.text:000134A7 3B 05 34 4E 01 00                 cmp     eax, g_nCurrentProcessCount
.text:000134AD 7D 5A                             jge     short loc_13509
这个检测方法的代码就在loc_134A7开始位置

上面获取的只是EPROCESS,要获取进程路径信息,还需要IoControlCode(220047h)的代码, 详细功能代码在get_image_path_by_eprocess函数里,在这个函数里,我们可以看到rku先走peb获取进程全路径,然后对非2k系统再走一次我们更为熟悉的SectionObject获取路径

3.2 杀进程 rku提供了两种杀进程的方法

3.2.1 IoControlCode(22001Fh) ZwOpenProcess/ZwTerminateProcess/ZwClose杀进程 这种杀法比较的弱
3.2.2 ioControlCode(22004fh) 内存清0杀进程 具体代码是kill_process_by_fill_zero函数,这个代码看debugman的yykingking也发过

3.3 Dump All Process Memory

IoControlCode是22008bh, 没什么可说的, 详细代码在dump_all_process_memory函数

3.4 Dump Seleted

这个就是拷贝主程序的内存镜象, IoControlCode是220083h, 先获取文件大小(对xp及其以上系统,通过EPROCESS->SectionObject->segmentObject->SizeOfSegment获取主程序内存镜象大小,对2k系统,由于手头缺乏资料,那段代码什么意思不知道,详细代码在get_main_file_size_by_eprocess函数), 然后输出缓冲区足够大就进入dump_selected函数拷贝内存

4.内核模块和Stealth Code检测

IoControlCode是0x220023h,在检测之前也会设置检测方式,然后根据检测方式进行检测.这个功能主要由list_kernel_module函数完成,这个函数里面集成了很多检测方法,很多方法都比较*淫**荡*,大致的检测方法有:

4.1 用IoDriverObjectType指向的OBJECT_TYPE.TypeList链表检测,遍历这个链表中的每一项,并会取每个DriverObject上的DeviceObject,并向上扫描这个设备所在的设备栈(注意这里没有向下扫描),尝试发现其它的DriverObject  详细代码见list_module_by_IoDriverObjectType函数
4.2 用IoDeviceObjectType指向的OBJECT_TYPE.TypeList链表检测,遍历这个链表中的每一个设备,并也会向上扫描这个设备所在的设备栈(注意这里没有向下扫描),尝试发现其它的DriverObject 详细代码见list_module_by_IoDeviceObjectType
4.3 用目录对象树(ZwOpenDirectoryObject("\\"))检测,遍历这棵树,对叶子节点(具体对象)看其OBJECT_HEADER.Type字段是否指向IoDriverObjectType/IoDeviceObjectType,如果是的话,则会采用4.1/4.2相似的措施;对目录对象子树则递归处理之(内核堆栈空间太小,递归搞始终给人一种不安全感,看SnipeSword里面处理注册表部分也大量递归,比较汗) 详细代码见list_module_by_OpenDirectoryObject函数
4.4 用DriverSection(PsLoadedModuleList链表)检测,这个方法大家都比较熟悉, 详细代码见list_module_by_DriverSection函数

经过上面4个方法,DriverObject就获取完毕了,他们对应的都是有详细信息的内核模块(这项检测初步给人的感觉是比icesword可靠些,icesword则是先尝试恢复NtQuerySystemInformation,设置KernelMode,然后调用NtQuerySystemInformation获取内核模块信息),下面的检测主要是对一些零星的能执行代码的内存块进行检测(Stealth Code)

4.5 用上面几种方法已经找到了一些DriverObject,这里就对这些DriverObject下手,检测这些DriverObject的DriverStartIo/MajorFunction是否被hook,如果被hook且新地址不在我们已经找到的模块里,则说明是那种分内存,写代码似的hook,记录这块内存信息 详细代码见list_module_by_DriverStartIo_and_MajorFunction函数
4.6 暴力搜索内存, 找到PE头部,并判定OptionalHeader.Subsystem是否是Native 详细代码见list_module_by_scan_memory函数
4.7 利用句柄表检测,这个的具体原理我未能理解, 详细代码在list_module_use_suspicious_thread_by_handle_table_in_not_2k/list_module_use_suspicious_thread_by_handle_table_in_2k这两个函数,感觉跟内核模块检测无关......知道的请说一声
4.8 rku会inline hook三个调用频度很高的函数(ExAllocatePool/ExAllocatePoolWithTag/KeDelayExecutionThread),在这三个函数里会记录它们的返回地址,并利用这些地址来检测一些模块,如果返回地址不在某具体模块范界则会记录其内存信息 详细代码见list_module_by_return_address函数
4.9 检测KiSystemService/KiFastCallEntry是否在某具体模块范界,如果不在也记录其内存信息

到这里检测就完成了,上面的检测方法太多,有些检测获取的信息不足,rku会进行一些额外的修正处理,这些代码都在list_kernel_module的结尾部分,详细请参见源码,我都做了一些注释

5.File检测

由于目前一直在用IDA反,并没有使用调试器,主程序目前还只反了一点,这个部分具体做什么的,我不太清楚,不过在驱动里看到一个IoControlCode(2200A7)是在做扇区级别的操作......

6.Code Hooks检测

在驱动里并没有看到分析code hooks的代码, 只看到一些拷贝内存到3环的功能函数,把一些系统关键手工load展开后,进行内存对照比较就可以搞定这个了,当然这个里面还具备KiSystemService/KiFastCallEntry hook的检测和恢复代码,详细可以看IDB文件

7.rku的进程保护

7.1 ssdt上的保护,在ssdt上对三个函数(NtOpenProcess, NtOpenThread, NtDuplicateObject)进行了inline hook
                NtOpenProcess 防止打开rku进程
                NtOpenThread 防止打开rku的线程
                NtDuplicateObject 防止复制rku进程的句柄
               
7.2 shadow ssdt上的保护,在shadow上对四个函数(NtUserQueryWindow, NtUserFindWindowEx, NtUserWindowFromPoint, NtUserNotifyIMEStatus)进行了inline hook,防止其它程序通过FindWindow,WindowFromPoint等函数来枚举rku的窗口,你可以看到spy++对rku已经失效

8.逆向这个的过程中,参考了网上很多大牛的文章,
    IceSword&Rootkit Unhooker驱动简析
   zhuwg  <<shadow ssdt学习笔记>>
    prince 翻译的<<侦测隐藏进程的强文>>
    yykingking 发在debugman上的两个代码片段
   还有些文章,无法一一列举,再次一并表示感谢
   
大致就是这样了.
                                                                                                                                                                                                                                        linxer  2008-06-19 于哈尔滨


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (31)
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
2
辛苦了
2008-6-19 00:37
0
雪    币: 1946
活跃值: (248)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
3
我就是进来膜拜linxer的
2008-6-19 01:13
0
雪    币: 334
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
慕拜中......
2008-6-19 07:15
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
5
从 debugman 赶过来顶~~~
2008-6-19 08:33
0
雪    币: 12
活跃值: (595)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
顶啊顶     
2008-6-19 09:16
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
7
分析得不错。。
2008-6-19 09:18
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
8
膜拜 啊  啊
2008-6-19 09:27
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
牛,膜拜一下
2008-6-19 09:30
0
雪    币: 200
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
强帖必须要顶(够6个字了
2008-6-19 09:59
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
11
进来膜拜linxer
2008-6-19 10:54
0
雪    币: 347
活跃值: (25)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
12
我也是来膜拜的
2008-6-19 14:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
听闻老衲要放血,故特来观摩....
2008-6-19 17:57
0
雪    币: 272
活跃值: (143)
能力值: ( LV15,RANK:930 )
在线值:
发帖
回帖
粉丝
14
顶,
收藏学习
2008-6-19 18:20
0
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
好强大 膜拜ing......
2008-6-19 19:08
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
奇怪,怎么我的ida5.2打不开这个idb呢?
2008-6-19 19:51
0
雪    币: 622
活跃值: (65)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
17
IDB打不开,有办法没。
2008-6-21 01:08
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
ding
2008-6-21 05:03
0
雪    币: 1746
活跃值: (287)
能力值: (RANK:450 )
在线值:
发帖
回帖
粉丝
19
IDA5.2打不开的 请先运行DarkNess0ut的补丁(http://bbs.pediy.com/showthread.php?t=55813) 然后再打开 就可以了
2008-6-21 14:22
0
雪    币: 191
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
哇塞。又是一牛人。。努力了
2008-6-21 16:50
0
雪    币: 250
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
好强悍,膜拜ing
2008-6-21 17:02
0
雪    币: 622
活跃值: (65)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
22
分析的很详细的说,很帅。
2008-6-21 17:41
0
雪    币: 311
活跃值: (124)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
牛人+好文,我也加入膜拜队伍.
2008-6-22 01:14
0
雪    币: 249
活跃值: (63)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
我装的是DataRescue IDA Pro Advanced v5.2 英文版 打开idb时提示这个文件是用盗版ida生成的,无法打开。。。没有看到19楼的,不好意思
2008-6-22 10:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
idb弄的真工整
谢谢
2008-6-22 12:25
0
游客
登录 | 注册 方可回帖
返回
//