浅谈inline HOOk之ring0下的进程保护

来源:互联网 发布:mac 10.12 dns flush 编辑:程序博客网 时间:2024/06/05 01:01
浅谈inline HOOk之ring0下的进程保护

在上一篇中说了一下ring3下简单的inline HOOK,写函数开头的方法还是比较通用的,而Call钩子虽然有隐蔽的优点,却需要对目标函数进行反汇编,都不适合大规模使用,还有push 、ret的方法,熟习的API的压栈原理,就很简单的,这些问题以后再讨论,这次我将上一篇文章里的代码移植到了ring0下,用来实现进程保护,ring3下破环进程的方法大致有下面几种:NtTerminateProcess/Thread,NtDuplicateObject(你不断的Dup并关闭对方句柄,对方最后也会退出的),NtWriteVirtualMemory在这之后创建一个远程线程让其ExitProcess,或者直接写入垃圾数据,就是内存填0杀进程了,UnmapViewOfSection,或者直接释放对方内存,ring3下常见的就是这几种了……这些函数都毫不例外的调用了ObReferenceObjectByHandle,函数,直接返回错误是最简单的方法,但是很显然不人性化,比如人家就查查你的信息,这个权限还是要给的(如360),当然了木马病毒除外了……,经过我的查看,对于线程我们要拦截的两个DesiredAccess=2和DesiredAccess=1的情况,前者用于暂停线程,后者用于结束线程,但是进程却要处理4个情况,分别对应暂停,结束,复制句柄,和写内存,UnmapView如下

     //1 对应Terminate 800对应 Suspend 40对应Dumplicate 20对应ReadMemeory其中后面的UnMapView的权限和释放内存使用的是同样的权限,所以……
     if(DesiredAccess==1||DesiredAccess==0x800||DesiredAccess==0x40||DesiredAccess==0x20||8)

所以很容易写出一个过滤函数来了

typedef NTSTATUS (__stdcall *DObReferenceObjectByHandle)(
HANDLE Handle,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
     PVOID *Object,
    POBJECT_HANDLE_INFORMATION HandleInformation 
    );

NTSTATUS __stdcall Detour_ObReferenceObjectByHandle(DObReferenceObjectByHandle Fun,    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)
{
NTSTATUS Status;
PEPROCESS Eproc=0;
BOOLEAN Denied=FALSE;
if(*PsThreadType==ObjectType||*PsProcessType==ObjectType)
{
   Status=Fun(Handle,DesiredAccess,ObjectType,AccessMode,Object,HandleInformation);
   if(NT_SUCCESS(Status)&&(*Object)!=NULL)
   {
    if(*PsThreadType==ObjectType)
    {
     Eproc=IoThreadToProcess((PETHREAD)(*Object));
     if(DesiredAccess==2||DesiredAccess==1)
     {
      Denied=TRUE;
     }

    }
    else
    {
     //1 对应Terminate 800对应 Suspend 40对应Dumplicate 20对应ReadMemeory8对应UnMapViewOfSection
     if(DesiredAccess==1||DesiredAccess==0x800||DesiredAccess==0x40||DesiredAccess==0x20||DesiredAccess==8)
      Denied=TRUE;
     Eproc=(PEPROCESS)(*Object);

    }
    ULONG Pid=(ULONG)PsGetProcessId(Eproc);
    PPROCESS_NODE Node=LookupPid(Pid);
    if(Denied&&Node&&Node->Process!=PsGetCurrentProcess())
    {
      KdPrint(("Process:%d 尝试操作保护进程!!已拒绝\n",PsGetCurrentProcessId()));
      ObDereferenceObject(*Object);
      *Object=0;
      return STATUS_ACCESS_DENIED;

    }
   }
   return Status;
}
return Fun(Handle,DesiredAccess,ObjectType,AccessMode,Object,HandleInformation);
}

过滤函数很简单,可能和大家以前看到的带了好多汇编指令的裸函数有很大不同,是不是看上去很爽啊?代码编写也很简单,原因就是我上一篇的那个Hook方法,来到ring0依然可行,并且可以大幅降低自己处理堆栈的难度……至于那个代码的移植,相信只要你看懂了ring3的,移植自然不在话下了,可以写成一个Hook库,以后就方便……嗯试试效果,达到了预期效果,当然了对付冰刃也是可以的,关键在于怎么保护自己的钩子不被恢复……这个问题就仁者见仁了……

有点废话的是Windows7下微软已经提供保护方法了,这个也就是在XP和Vista下玩玩了,主要并不是说明怎么保护进程,而是说明上一篇的HOOK结构的用途,以及实现人性化的过滤处理,因为如果为了保护进程还是可以做得更底层的……

原创粉丝点击