首页
论坛
课程
招聘
[原创]简单inline hook ObReferenceObjectByHandle保护进程和屏蔽文件执行
2008-5-30 19:16 36803

[原创]简单inline hook ObReferenceObjectByHandle保护进程和屏蔽文件执行

2008-5-30 19:16
36803
// ***************************************************************
//  Author:  Sysnap     
//  Link:    http://hi.baidu.com/sysnap
//  
// ***************************************************************

   
   好久没弄hook了.最近看到还是很多人弄,而且蓝屏,就把我以前的inline hook的code改下,于是有此文,呵呵,给跟我一样的菜鸟科普用的,高手飘过
   现在一般工具的进程保护可能是hook NtOpenProcess和NtTerminateProcess...其实关于进程的话题很多,印象中Sudami同学对这方面面比较懂.下面的代码可以保护进程
   WsysCheck--->>>failed
   IceSword---->>>failed
   Gmer-->>>failed
   RUK--->>>failed
   SnipeSword---->>>failde(不包括内存清0)
   其实这只是简单的进程保护,唯一的好处就是hook导出函数ObReferenceObjectByHandle,稳定...而结束之的方法也有很多,比如内存清0..PspTerminateProcess...PspExitThread等等...其中很多很强大的办法很多anti-rootkit的工具没使用,我想可能就是为了稳定吧.的确
   另外,你可以用这个code来屏蔽某些程序的运行...其实这个code的效果就是已经运行的保护其进程,没有运行的屏蔽其运行....代码写得很草/.对系统性能也有一定影响,自己根据需要再改下吧...
   代码就是inline hook ObReferenceObjectByHandle使其跳到T_ObReferenceObjectByHandle中
   __declspec(naked)  T_ObReferenceObjectByHandle(
    IN HANDLE  Handle,
    IN ACCESS_MASK  DesiredAccess,
    IN POBJECT_TYPE  ObjectType  OPTIONAL,
    IN KPROCESSOR_MODE  AccessMode,
    OUT PVOID  *Object,
    OUT POBJECT_HANDLE_INFORMATION  HandleInformation  OPTIONAL
    )
{

        _asm
{

   mov     edi,edi------>>>执行被修改的前5个字节
   push    ebp
   mov     ebp,esp
   
   push   [ebp+0x1c]------>>>参数压栈
   push   [ebp+0x18]
   push   [ebp+0x14]
   push   [ebp+0x10]
   push   [ebp+0xc]
   push   [ebp+8]
  
   call   MyObReferenceObjectByHandle  -------->>>>调用我们的功能函数
   cmp   eax,1   
   jz     end
   
   mov   eax,ObReferenceObjectByHandle -------->>>>正常运行原来的函数  
   add   eax,5           
   jmp   eax   
end:
   mov   [ebp+8],-1------>>>>如果不想让这个函数正常运行..无效句柄就可以
   mov   eax,ObReferenceObjectByHandle     
   add   eax,5           
   jmp   eax   
   
}
  对原来函数是否要让其正常运行的判断由MyObReferenceObjectByHandle完成
   
  int  MyObReferenceObjectByHandle(
    IN HANDLE  Handle,
    IN ACCESS_MASK  DesiredAccess,
    IN POBJECT_TYPE  ObjectType  OPTIONAL,
    IN KPROCESSOR_MODE  AccessMode,
    OUT PVOID  *Object,
    OUT POBJECT_HANDLE_INFORMATION  HandleInformation  OPTIONAL
    )
{

        PEPROCESS Process;
        KIRQL  oldIrql;
        int JmpOffSet;
        unsigned char Code[5]={0x8b,0xff,0x55,0x8b,0xec};
        unsigned char JmpCode[5] = { 0xe9, 0x00, 0x00, 0x00, 0x00 };

       
        if(*PsProcessType==ObjectType)//判断句柄所属对象类型是不是*PsProcessType
{

                 oldIrql = KeRaiseIrqlToDpcLevel();
        __asm
        {
                CLI            
                MOV   eax, CR0     
                AND eax, NOT 10000H
                MOV   CR0, eax
        }
       

        RtlCopyMemory ( ObReferenceObjectByHandle, Code, 5 );//恢复inline hook以便正确调用ObReferenceObjectByHandle
///////////////////////////////////////////////////////////////////////////////////////////////////////////////       
       
       
        ObReferenceObjectByHandle(Handle,DesiredAccess,ObjectType,AccessMode,&Process,NULL);
        if (_stricmp((char*)((char*)Process+0x174), ProtectName) == 0 )//判断是不是我们要保护的进程
          {
                  JmpOffSet= (char*)T_ObReferenceObjectByHandle - (char*)ObReferenceObjectByHandle - 5;
                  RtlCopyMemory ( JmpCode+1, &JmpOffSet, 4 );
                  RtlCopyMemory ( ObReferenceObjectByHandle, JmpCode, 5 );
                         
                  
   __asm
   {
           MOV   eax, CR0
           OR   eax, 10000H
           MOV   CR0, eax
           STI
   }
                       
   KeLowerIrql(oldIrql);
   return 1;

          }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////       
       
        //否则再次HOOK这个函数
        JmpOffSet= (char*)T_ObReferenceObjectByHandle - (char*)ObReferenceObjectByHandle - 5;
        RtlCopyMemory ( JmpCode+1, &JmpOffSet, 4 );
        RtlCopyMemory ( ObReferenceObjectByHandle, JmpCode, 5 );
       
        __asm
        {
                MOV   eax, CR0
                OR   eax, 10000H
                MOV   CR0, eax
                STI
        }
       
        KeLowerIrql(oldIrql);

}

return 0;
}




[培训] 优秀毕业生寄语:恭喜id咸鱼炒白菜拿到远超3W月薪的offer,《安卓高级研修班》火热招生!!!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (38)
雪    币: 230
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
winnip 活跃值 1 2008-5-30 19:22
2
0
沙发 ............
雪    币: 205
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wowzjj 活跃值 2008-5-30 19:58
3
0
先占楼再看。
雪    币: 478
活跃值: 活跃值 (640)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2008-5-30 20:13
4
0
hook ObReferenceObjectByHandle可以拒绝很多东西,不光是进程方面,只要和对象相关的都可以过滤掉。。。

不过你的处理流程有点儿烦琐,里面的反复恢复有可能会出问题。

写的很好哦。顶下~~~
雪    币: 441
活跃值: 活跃值 (57)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2008-5-30 20:17
5
0
的确/////使用被自己HOOK的函数的确是比较麻烦....我也想不到更好的办法....呵呵
雪    币: 478
活跃值: 活跃值 (640)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2008-5-30 20:26
6
0
俺是这样处理的,不需要太烦琐:

--------------------------------------

VOID
fake_ObReferenceObjectByHandle (
    IN HANDLE Handle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_TYPE ObjectType,
    IN KPROCESSOR_MODE AccessMode,
    OUT PVOID *Object,
    OUT POBJECT_HANDLE_INFORMATION HandleInformation
    )
{
        NTSTATUS  status;
        WCHAR          Name[300];
        BOOL      bFuck = FALSE;
        PEPROCESS Process = NULL;
        PUCHAR    currentProcessName = NULL;
        HANDLE    ProcessID = NULL; // the owner process

        status = OldObReferenceObjectByHandle( Handle, DesiredAccess, ObjectType, AccessMode, Object, HandleInformation);

        _asm pushad
        _asm pushfd

              //
              //  过滤操作
              //

       
end:
        _asm popfd
        _asm popad

skip:
        _asm nop
}
雪    币: 441
活跃值: 活跃值 (57)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2008-5-30 20:50
7
0
谢谢sudami ........OldObReferenceObjectByHandle这应该是个地址吧....但inline hook后....ObReferenceObjectByHandle地址没变....只是前面几个字节变了...
雪    币: 109
活跃值: 活跃值 (134)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
combojiang 活跃值 26 2008-5-30 22:33
8
0
很好,很强大
雪    币: 207
活跃值: 活跃值 (16)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
hfyy 活跃值 2 2008-5-31 09:33
9
0
问个问题 MyObReferenceObjectByHandle 不会被page out么
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lOOp 活跃值 2008-5-31 15:57
10
0
  nice
雪    币: 207
活跃值: 活跃值 (16)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
hfyy 活跃值 2 2008-6-1 16:27
11
0
楼主没注意到我这个问题吧 重新发一下 希望解答一下 谢谢
雪    币: 441
活跃值: 活跃值 (57)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2008-6-1 17:18
12
0
照你那么说岂不是所有驱动程序都要自己分非分页内存.....一般不会拉....如果你要保险..也可以lock下....反正在我机器试了那么多次没事...
雪    币: 441
活跃值: 活跃值 (57)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2008-6-1 17:33
13
0
可能其他inline hook会把他们的函数放在非分页内存里...这样有一个最大的好处就是可以卸栽自己的驱动.....一般情况下我们的驱动程序不会被换出..你要换出可以加编译指令
#pragma alloc_text(PAGE, MyFunction)就好....还有一般驱动要运行在非分页是因为其代码运行于或高于DISPATCH_LEVEL的IRQL上的级别或者使用自旋锁的
雪    币: 478
活跃值: 活跃值 (640)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2008-6-1 18:30
14
0
MmProbeAndLockPages
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
loien 活跃值 2008-6-21 09:41
15
0
突然见发现为什么ObReferenceObjectByHandle(Handle,DesiredAccess,ObjectType,AccessMode,&Process,NULL);
不能用Process=PsGetCurrentProcess();代替呢
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
loien 活跃值 2008-6-21 11:25
16
0
sysnap为什么不能用Process=PsGetCurrentProcess();代替呢
雪    币: 303
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bluecode 活跃值 2008-11-8 00:45
17
0
Cool......
雪    币: 514
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
xacker 活跃值 1 2008-11-8 02:33
18
0
偶的双核下 蓝掉了。。
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
samisgod 活跃值 4 2008-11-12 14:52
19
0
我的也双核
可以退出进程,但退出后就BSOD

不错,反正要的效果也能达到,让别人不敢退了
雪    币: 189
活跃值: 活跃值 (50)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
choday 活跃值 2 2008-11-12 15:08
20
0
我就搞不懂,你们在inline hook的时候,为什么要反复的hook 恢复->hook 恢复->hook 恢复呢,

不觉得这样很烦很不稳定吗

为什么不用以下方案:
hook jmp to mycode

mycode:
处理事务
虚拟函数的头五个字节
jmp 函数地址+5

上面的方案不是很好吗?不用反复hook,
如果被HOOK函数头不是五字节,那你就多跳几个字节就是了
雪    币: 441
活跃值: 活跃值 (57)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 活跃值 14 2008-11-13 08:26
21
0
不好意思.............这份写得太燎草了.
__declspec(naked) T_ObReferenceObjectByHandle(
    IN HANDLE Handle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_TYPE ObjectType OPTIONAL,
    IN KPROCESSOR_MODE AccessMode,
    OUT PVOID *Object,
    OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
    ) {

     __asm
{
///////////////执行原先被修改的字节码
   mov     edi,edi
   push    ebp
   mov     ebp,esp
//因为调用了我们这个函数,所以栈现在的情况是
// 参数1-->>参数2-->>参数3-->>参数4-->>参数5-->>参数6-->>返回地址-->>老的EBP(push    ebp)
// 执行完mov     ebp,esp 后,ebp指向了栈顶,这个时候我们就可以用ebp来引用参数了
// 如下面的push   [ebp+0x1c]就是用ebp来引用栈中参数
// 保存相关寄存器的值
   pushad
   
   push   [ebp+0x1c]
   push   [ebp+0x18]
   push   [ebp+0x14]
         push   [ebp+0x10]
         push   [ebp+0xc]
         push   [ebp+8]
   
   call   FilterFunction   
   cmp   eax,1    //是否匹配
//上面的这个过程可以看做是透明的..虽然有很多push..但不会影响到我们的栈
   jz     end
//不匹配的..调用原来的地址+5个字节.ObReferenceObjectByHandle正常执行
   mov   eax,ObReferenceObjectByHandle      
   add   eax,5            
   jmp   eax
//否则   
end:
   popad
/*   mov   [ebp+8],-1 //--------->>无效句柄
   mov   eax,ObReferenceObjectByHandle      
   add   eax,5            
   jmp   eax    */
   //下面我们用栈会溯来解决问题
         mov esp,ebp //esp指向栈顶
         pop ebp      //ebp指向原来的栈底
   ret 0x18 //返回..0x18 == 24 == 6个参数*4个字节 这样esp才能指向正常.程序才不会崩溃
///这个地方也可以用来抵抗调试..这样肯定会到XX去..
}

}
雪    币: 70
活跃值: 活跃值 (127)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dnybz 活跃值 2009-1-31 06:28
22
0
好东东,很不错,双核退出,容易BSOD
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cjhuengame 活跃值 2009-2-1 21:41
23
0
好东西,好东西,
雪    币: 231
活跃值: 活跃值 (12)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
yaolibing 活跃值 2009-3-1 08:56
24
0
用ida 看下sysnap.sys,什么都看不到。请问sysnap它是不是加壳了是不是?
雪    币: 231
活跃值: 活跃值 (12)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
yaolibing 活跃值 2009-3-1 17:10
25
0
哪位大哥解释下extern POBJECT_TYPE *PsProcessType;这句是什么意思?

#include "ntddk.h"
//#include "hookiat.h"
#include <windef.h>

extern POBJECT_TYPE *PsProcessType;

VOID InlineHookObReferenceObjectByHandle();
VOID UnHook();
  T_ObReferenceObjectByHandle(
    IN HANDLE  Handle,
    IN ACCESS_MASK  DesiredAccess,
    IN POBJECT_TYPE  ObjectType  OPTIONAL,
    IN KPROCESSOR_MODE  AccessMode,
    OUT PVOID  *Object,
    OUT POBJECT_HANDLE_INFORMATION  HandleInformation  OPTIONAL
    );

char* ProtectName = "notepad.exe";

//////////////////////////////////////////////////////////////////////////////////////////////
// 我们的主要功能函数,基本功能是恢复和钩住ObReferenceObjectByHandle,对传递进来的HANDLE进行判断
//////////////////////////////////////////////////////////////////////////////////////////////
游客
登录 | 注册 方可回帖
返回