频道栏目
首页 > 程序开发 > 综合编程 > 安全编程 > 正文
内核级利用通用Hook函数方法检测进程
2005-05-20 09:49:10           
收藏   我要投稿

作者:    LionD8
QQ:    10415468
Email: LionD8@126.com
Blog:    http://blog.csdn.net/LionD8     or http://liond8.126.com

介绍通用Hook的一点思想:
    在系统内核级中,MS的很多信息都没公开,包括函数的参数数目,每个参数的类型等。在系统内核中,访问了大量的寄存器,而很多寄存器的值,是上层调用者提供的。如果值改变系统就会变得不稳定。很可能出现不可想象的后果。另外有时候对需要Hook的函数的参数不了解,所以不能随便就去改变它的堆栈,如果不小心也有可能导致蓝屏。所以Hook的最佳原则是在自己的Hook函数中呼叫原函数的时候,所有的寄存器值,堆栈里面的值和Hook前的信息一样。这样就能保证在原函数中不会出错。一般我们自己的Hook的函数都是写在C文件里面的。例如Hook的目标函数KiReadyThread。
那么一般就自己实现一个:
MyKiReadyThread(...)
{
    ......
    call KiReadyThread
    ......
}
但是用C编译器编译出来的代码会出现一个堆栈帧:
Push ebp
mov  ebp,esp
这就和我们的初衷不改变寄存器的数违背了。所以我们可以自己用汇编来实现MyKiReadyThread。

_func@0 proc
    pushad        ;保存通用寄存器
    call _cfunc@0  ;这里是在进入原来函数前进行的一些处理。
    popad         ;恢复通用寄存器
    push eax  
    mov eax,[esp+4] ;得到系统在call 目标函数时入栈的返回地址。
    mov ds:_OrgRet,eax ;保存在一个临时变量中
    pop eax
    mov [esp],retaddr  ;把目标函数的返回地址改成自己的代码空间的返回地址,使其返回                后能接手继续的处理
    jmp _OrgDestFunction ;跳到原目标函数中
retaddr:
    pushad         ;原函数处理完后保存寄存器
    call _HookDestFunction@0 ;再处理
    popad      ;回复寄存器
    jmp ds:_OrgRet ;跳到系统调用目标函数的下一条指令。
_func@0 endp

当我们要拦截目标API的时候,只要修改原函数头5个字节的机器为一个JMP _func就行了。
然后把原来的5字节保存。在跳入原函数时,恢复那5个字节即可。

Hook KiReadyThread检测系统中的进程:
在线程调度抢占的的时候会调用KiReadyThread,它的原型为
VOID FASTCALL KiReadyThread (IN PRKTHREAD Thread)
在进入KiReadyThread时,ecx指向Thread。
所以完全可以Hook KiReadyThread 然后用ecx的值得到但前线程的进程信息。
KiReadyThread没被ntosknrl.exe导出,所以通过硬编码来。在2000Sp4中地址为0x8043141f

具体实现:
////////////////////////////////
// 1.cpp
////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif

#include "ntddk.h"
#include "string.h"
#include "ntifs.h"
#include "stdio.h"

#define FILE_DEVICE_EVENT  0x8000

#define IOCTL_PASSBUF
    CTL_CODE(FILE_DEVICE_EVENT, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)

void DriverUnload (IN PDRIVER_OBJECT pDriverObject);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);

void cfunc ();

void HookDestFunction();
NTSTATUS DeviceIoControlDispatch(IN  PDEVICE_OBJECT  DeviceObject,
                                 IN  PIRP            pIrp);
extern void func();

void ResumeDestFunction();

const WCHAR devLink[]  = L"\??\MyEvent";
const WCHAR devName[]  = L"\Device\MyEvent";
UNICODE_STRING          devNameUnicd;
UNICODE_STRING          devLinkUnicd;   

ULONG OrgDestFunction = (ULONG)0x8043141f; //KiReadyThread

char JmpMyCode [] = {0xE9,0x00,0x00,0x00,0x00};
char OrgCode [5];

char OutBuf[128][16];

int Count = 0;

ULONG orgcr0;
#ifdef __cplusplus
}
#endif

VOID DisableWriteProtect( PULONG pOldAttr)
{

     ULONG uAttr;

     _asm
    {
          push eax;
          mov  eax, cr0;
          mov  uAttr, eax;
          and  eax, 0FFFEFFFFh; // CR0 16 BIT = 0
          mov  cr0, eax;
          pop  eax;
    };

     *pOldAttr = uAttr; //保存原有的 CRO 属性

}

VOID EnableWriteProtect( ULONG uOldAttr )
{

  _asm
  {
       push eax;
       mov  eax, uOldAttr; //恢复原有 CR0 属性
       mov  cr0, eax;
       pop  eax;
  };

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath)
{
    NTSTATUS                Status;
    PDEVICE_OBJECT            pDevice;

    DbgPrint("DriverEntry called! ");
    RtlInitUnicodeString (&devNameUnicd, devName );
    RtlInitUnicodeString (&devLinkUnicd, devLink );
    Status = IoCreateDevice ( pDriverObject,
    0,
         &devNameUnicd,
    FILE_DEVICE_UNKNOWN,
       0,
       TRUE,
       &pDevice );
        if( !NT_SUCCESS(Status))
        {
        DbgPrint(("Can not create device. "));
        return Status;
    }
       Status = IoCreateSymbolicLink (&devLinkUnicd, &devNameUnicd);
       if( !NT_SUCCESS(Status))
       {
           DbgPrint(("Cannot create link. "));
           return Status;
       }
       pDriverObject->DriverUnload  = DriverUnload;
       pDriverObject->MajorFunction[IRP_MJ_CREATE] =
    pDriverObject->MajorFunction[IRP_MJ_CLOSE] =
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =    DeviceIoControlDispatch;
     
    pDriverObject->DriverUnload = DriverUnload;
    * ( (ULONG*) (JmpMyCode+1) ) = (ULONG)func - (ULONG)OrgDestFunction - 5;
    memcpy(OrgCode,(

点击复制链接 与好友分享!回本站首页
上一篇:Delphi编程中在状态栏动态添加进度条
下一篇:防止全局钩子的侵入
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站