对Rav2005中HOOK的初步分析

对Rav2005中HOOK的初步分析   
MicrosoftCTO 

 
昨天升级了一下RAV2004。本以为很快就完,但升级程序却拖了近一个小时。启动后发现,RAV已经被升级到了2005。这事本应该就这么完了,但恰巧我对各种软件的内存占用非常敏感,弄了个empty.exe放在bat里,定期清理一下内存。执行了一遍bat却发现empty报错,说无法清理ravmond.exe!于是本能地觉得有名堂。赶紧分析了一下empty。
从出错信息入手,可以找到下面的代码(注释是我加的):
.text:01001603 loc_1001603:
.text:01001603                 call    sub_1001D1B
.text:01001608                 mov     eax, dword_12D3180 ; EAX里应该是PID
.text:0100160D                 test    eax, eax
.text:0100160F                 jz      short loc_100163D
.text:01001611                 push    eax
.text:01001612                 call    sub_1001F2C     ; 清理内存
.text:01001617                 test    eax, eax
.text:01001619                 jnz     short loc_1001636
.text:0100161B                 push    dword_12D3180
.text:01001621                 push    offset aCouldNotEmptyW ; "could not empty working set for process"...
.text:01001626                 call    ds:printf
.text:0100162C                 pop     ecx

  OK,到sub_1001F2C去看看:

.text:01001F2C                 push    ebp
.text:01001F2D                 mov     ebp, esp
.text:01001F2F                 push    ecx
.text:01001F30                 push    esi
.text:01001F31                 push    edi
.text:01001F32                 push    [ebp+MaximumWorkingSetSize] ; dwProcessId
.text:01001F35                 xor     edi, edi
.text:01001F37                 push    edi             ; bInheritHandle
.text:01001F38                 push    1F0FFFh         ; dwDesiredAccess
.text:01001F3D                 call    ds:OpenProcess
.text:01001F43                 mov     esi, eax
.text:01001F45                 cmp     esi, edi
.text:01001F47                 jnz     short loc_1001F4D
.text:01001F49                 xor     eax, eax
.text:01001F4B                 jmp     short loc_1001F77

首先是以PROCESS_ALL_ACCESS权限调用OpenProcess。但就是在这里,esi=edi,跳到出口loc_1001F77。

好,于是写段调用OpenProcess的程序。结果发现,对ravmond的操作结果是返回ERROR_INVALID_PARAMETER??!!但是我的参数没有写错啊!然后开始怀疑bInheritHandle参数,但改了还是一样。那么,换PID。换了SMSS的PID,说没有权限,很正常。换delphi32的PID,可以正常打开。那么,就是说,参数绝对是正确的,只是RAV玩了个花样。那样,按照系统给的PID去找就找不到了。

既然这样,那就拿RAV开刀。先翻了一下RAV的目录,有几个驱动文件引起了我的注意:

Hooksys.sys
hookbase.sys
HOOKREG.sys
HookCont.sys
HookApi.sys

难道是OpenProcess被HOOK了?于是先在HookApi里查import,没有可疑的API。hookbase?Hooksys?HookCont?都没有。

还是写程序看看……GetProcAddress却报告说没有异常。

没办法,查找ravmond吧……HOOKREG里居然有ravmond的字样!改之,重新启动RAV的服务,bingo!在任务管理器里k进程时显示没有权限!那么很明显是被HOOK了。

以前玩过rootkit(只是玩而已,写不来),本来是应该想到的……

那么反汇编HOOKREG,查找ravmond的xref……在00011BEF有一个push,向上找到函数入口,得到整个函数:

.text:00011B74 sub_11B74       proc near
.text:00011B74
.text:00011B74 var_2C          = dword ptr -2Ch
.text:00011B74 var_28          = byte ptr -28h
.text:00011B74 var_9           = byte ptr -9
.text:00011B74 var_8           = dword ptr -8
.text:00011B74 var_4           = dword ptr -4
.text:00011B74 arg_0           = dword ptr  8
.text:00011B74
.text:00011B74                 push    ebp
.text:00011B75                 mov     ebp, esp
.text:00011B77                 sub     esp, 2Ch
.text:00011B7A                 mov     [ebp+var_2C], 0
.text:00011B81                 mov     [ebp+var_28], 0
.text:00011B85                 call    ds:IoGetCurrentProcess
.text:00011B8B                 mov     [ebp+var_8], eax
//指向当前进程开头的指针
.text:00011B8E                 mov     eax, [ebp+var_8]
.text:00011B91                 add     eax, dword_12F48
//dword_12F48的真实偏移
.text:00011B97                 mov     [ebp+var_4], eax
.text:00011B9A                 mov     ecx, [ebp+var_4]
.text:00011B9D                 push    ecx
.text:00011B9E                 lea     edx, [ebp+var_28]
//缓冲的长度是$1F
.text:00011BA1                 push    edx
.text:00011BA2                 call    strcpy
.text:00011BA7                 add     esp, 8
//复制
.text:00011BAA 

我们可以看到,这个东西有点象call/pop的手法。好处就是可以不要数据段(反正特征字符串是只读的)。

那么,这只是一个判断。判断dword_12F48是否含有特定的字符串,若是RAV的核心就返回3,主程序返回2,外围程序返回4,其他返回0。

那么来看看sub_11B74的xref,有三处:11D27、119E6、115E2,对应的sub分别是sub_11D00、sub_119D0、sub_115BC。

sub_115BC有4个xref,全部是code引用,sub_119D0只有1个data引用的xref,而11D00,有3个xref,data引用。

先看11D00,xref全在start里:

.text:00010453 8B 45 08                          mov     eax, [ebp+DriverObject]
.text:00010456 C7 40 38 00 1D 01+                mov     dword ptr [eax+38h], offset sub_11D00
.text:0001045D 8B 4D 08                          mov     ecx, [ebp+DriverObject]
.text:00010460 C7 41 40 00 1D 01+                mov     dword ptr [ecx+40h], offset sub_11D00
.text:00010467 8B 55 08                          mov     edx, [ebp+DriverObject]
.text:0001046A C7 82 80 00 00 00+                mov     dword ptr [edx+80h], offset sub_11D00

下面就dump一下和DriverObject有关的代码(eax,ecx,edx都是临时使用的):

.text:00010308                   ; int __stdcall start(PDRIVER_OBJECT DriverObject)
.text:00010308                                   public start
.text:00010308                   start           proc near
.text:00010308
.text:00010308                   var_64          = dword ptr -64h
.text:00010308                   var_60          = dword ptr -60h
.text:00010308                   SymbolicLinkName= UNICODE_STRING ptr -5Ch
.text:00010308                   DeviceObject    = dword ptr -54h
.text:00010308                   DeviceName      = UNICODE_STRING ptr -50h
.text:00010308                   SourceString    = word ptr -48h
.text:00010308                   var_28          = dword ptr -28h
.text:00010308                   DriverObject    = dword ptr  8
.text:00010308
.text:00010308 55                                push    ebp
.text:00010309 8B EC                             mov     ebp, esp
.text:0001030B 83 EC 64                          sub     esp, 64h
.text:0001030E 56                                push    esi
.text:0001030F 57                                push    edi
.text:00010310 C7 45 AC 00 00 00+                mov     [ebp+DeviceObject], 0
.....
.text:0001036A 8D 55 AC                          lea     edx, [ebp+DeviceObject]
.text:0001036D 52                                push    edx             ; DeviceObject
.text:0001036E 6A 00                             push    0               ; Exclusive
.text:00010370 6A 00                             push    0               ; DeviceCharacteristics
.text:00010372 68 00 84 00 00                    push    8400h           ; DeviceType
.text:00010377 8D 45 B0                          lea     eax, [ebp+DeviceName]
.text:0001037A 50                                push    eax             ; DeviceName
.text:0001037B 6A 00                             push    0               ; DeviceExtensionSize
.text:0001037D 8B 4D 08                          mov     ecx, [ebp+DriverObject]
.text:00010380 51                                push    ecx             ; DriverObject
.text:00010381 FF 15 DC 26 01 00                 call    ds:IoCreateDevice
.....
.text:000103BD 8B 45 08                          mov     eax, [ebp+DriverObject]
.text:000103C0 8B 48 04                          mov     ecx, [eax+4]
.text:000103C3 51                                push    ecx             ; DeviceObject
.text:000103C4 FF 15 D4 26 01 00                 call    ds:IoDeleteDevice
.text:000103CA 8B 45 9C                          mov     eax, [ebp+var_64]
.....
.text:00010453 8B 45 08                          mov     eax, [ebp+DriverObject]
.text:00010456 C7 40 38 00 1D 01+                mov     dword ptr [eax+38h], offset sub_11D00
.text:0001045D 8B 4D 08                          mov     ecx, [ebp+DriverObject]
.text:00010460 C7 41 40 00 1D 01+                mov     dword ptr [ecx+40h], offset sub_11D00
.text:00010467 8B 55 08                          mov     edx, [ebp+DriverObject]
.text:0001046A C7 82 80 00 00 00+                mov     dword ptr [edx+80h], offset sub_11D00
.text:00010474 8B 45 08                          mov     eax, [ebp+DriverObject]
.text:00010477 C7 40 70 BF 1D 01+                mov     dword ptr [eax+70h], offset sub_11DBF
.text:0001047E 8B 4D 08                          mov     ecx, [ebp+DriverObject]
.text:00010481 C7 41 34 68 05 01+                mov     dword ptr [ecx+34h], offset sub_10568
就是填充PDRIVER_OBJECT,其他没有什么。这里的大概意思是创建一个内核Device,然后定义几个Function。问题是,这个驱动的Type是自定义的,而我又不懂Driver……

不过还好,119D0的xref有点意思:

.text:00010CBA                 mov     eax, ds:ZwSetValueKey
.text:00010CBF                 mov     ecx, [eax+1]
.text:00010CC2                 mov     edx, ds:KeServiceDescriptorTable
.text:00010CC8                 mov     eax, [edx]
.text:00010CCA                 mov     dword ptr [eax+ecx*4], offset sub_119D0

那么,这里是修改ServiceDescriptorTable里ZwSetValueKey的入口。联想一下,应该是不允许修改RAVMOND服务的Key。

最后看看115BC,xref对应的sub有111A0,112F0,11360和119D0。而它们都是只有一个data的xref,应该是function了:

.text:00010CD1                 mov     ecx, ds:ZwCreateKey
.text:00010CD7                 mov     edx, [ecx+1]
.text:00010CDA                 mov     eax, ds:KeServiceDescriptorTable
.text:00010CDF                 mov     ecx, [eax]
.text:00010CE1                 mov     dword ptr [ecx+edx*4], offset sub_111A0
.text:00010CE8                 mov     edx, ds:ZwDeleteValueKey
.text:00010CEE                 mov     eax, [edx+1]
.text:00010CF1                 mo
...
未完待续

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值