设为首页 友情链接
在线留言 发表文章
加入收藏 广告联系

刺猬首页

| 专案技术 | 网络技术 | 图形图象 | 网络编程 | 网页设计 | 操作系统 | 服务器 | 技术白皮书 | 在线实验室 | 刺猬论坛 |
小说专版  | 数据库 | 设计赏析 | 存储频道 | 网络安全 | 私服架设 |  Solaris | 网站评估 | PC维护技巧 | 下载中心 | 博 客 |
专   题: | Linux | java | cisco | 防病毒 | 刀片 | SOA | iscsi | ASP.NET | SQL | Oracle |
您现在的位置: IT公社 IT community >> 网络安全 >> IDSIPS >> 文章正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
深入浅出 分析Linux系统…
从dos到linux内核学习心…
安全的破绽:Linux内核漏…
Linux内核漏洞浅析
黑客经验之杂谈PHP4内核…
Linux操作系统内核抢占补…
内核级Rootkit技术入门(…
在Linux下用gdb检测内核…
内核级Rootkit的加载和调…
Linux 2.4 内核中的ipta…
  内核级利用通用Hook函数方法检测进程         ★★★★★
内核级利用通用Hook函数方法检测进程
 

介绍通用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!\n");

  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.\n"));

    return Status;

  }

    Status = IoCreateSymbolicLink (&devLinkUnicd, &devNameUnicd);

    if( !NT_SUCCESS(Status)) 

    {

      DbgPrint(("Cannot create link.\n"));

      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,(char*)OrgDestFunction,5);

  HookDestFunction();

  

  return STATUS_SUCCESS;

}



void DriverUnload (IN PDRIVER_OBJECT pDriverObject)

{

  NTSTATUS         status;

  ResumeDestFunction();

  if(pDriverObject->DeviceObject != NULL)

    {

      status=IoDeleteSymbolicLink( &devLinkUnicd );

    if ( !NT_SUCCESS( status ) )

        {

            DbgPrint(( "IoDeleteSymbolicLink() failed\n" ));

        }

        IoDeleteDevice( pDriverObject->DeviceObject );

    }

}



void DisplayName(PKTHREAD Thread)

{

  PKPROCESS Process = Thread->ApcState.Process;

  PEPROCESS pEprocess = (PEPROCESS)Process;

  DbgPrint("ImageFileName = %s \n",pEprocess->ImageFileName);

  sprintf(OutBuf[Count++],"%s",pEprocess->ImageFileName);

}



void cfunc (void)

{

  ULONG PKHeader=0;

  __asm

  {

    mov PKHeader,ecx //ecx寄存器是KiReadyThread中的PRKTHREAD参数

  }

  ResumeDestFunction();

  

  if ( PKHeader != 0 && Count < 128 )

  {

    DisplayName((PKTHREAD)PKHeader);   

  }   

}



void HookDestFunction()

{

  DisableWriteProtect(&orgcr0);

  memcpy((char*)OrgDestFunction,JmpMyCode,5);

  EnableWriteProtect(orgcr0);   

}



void ResumeDestFunction()

{

  DisableWriteProtect(&orgcr0);

  memcpy((char*)OrgDestFunction,OrgCode,5);

  EnableWriteProtect(orgcr0);

}



NTSTATUS DeviceIoControlDispatch(

                      IN PDEVICE_OBJECT DeviceObject,

                      IN PIRP         pIrp

                      )

{

  PIO_STACK_LOCATION         irpStack;

  NTSTATUS                 status;

  PVOID                   inputBuffer;

  ULONG                   inputLength;

  PVOID                   outputBuffer;

  ULONG                   outputLength;

  OBJECT_HANDLE_INFORMATION     objHandleInfo;



  status = STATUS_SUCCESS;

  // 取出IOCTL请求代码

  irpStack = IoGetCurrentIrpStackLocation(pIrp);



  switch (irpStack->MajorFunction)

  {

  case IRP_MJ_CREATE :

    DbgPrint("Call IRP_MJ_CREATE\n");

    break;

  case IRP_MJ_CLOSE:

    DbgPrint("Call IRP_MJ_CLOSE\n");

    break;

  case IRP_MJ_DEVICE_CONTROL:

    DbgPrint("IRP_MJ_DEVICE_CONTROL\n");

    inputLength=irpStack->Parameters.DeviceIoControl.InputBufferLength;

    outputLength=irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) 

    {

        case   IOCTL_PASSBUF:

        {

          RtlCopyMemory(pIrp->UserBuffer, OutBuf, 20*16);

          

          memset(OutBuf,0,128*16);

          Count = 0;

          break;

        }

        default:

          break;

    }



  default:

    DbgPrint("Call IRP_MJ_UNKNOWN\n");

    break;

  }

  pIrp->IoStatus.Status = status; 

  pIrp->IoStatus.Information = 0; 

  IoCompleteRequest (pIrp, IO_NO_INCREMENT);

  return status;

}



////////////////////////////////

// 1.asm

////////////////////////////////

.386

.model small



.data

_OrgRet dd 0



.code

public _func@0

extrn _cfunc@0:near

extrn _HookDestFunction@0:near

extrn _OrgDestFunction:DWORD



_func@0 proc

  pushad

  call _cfunc@0

  popad

  push eax

  mov eax,[esp+4]

  mov ds:_OrgRet,eax

  pop eax

  mov [esp],retaddr

  jmp _OrgDestFunction

retaddr:

  pushad

  call _HookDestFunction@0

  popad

  jmp ds:_OrgRet

_func@0 endp

END



//////////////////////////////////////////

// app.cpp

//////////////////////////////////////////



#include 

#include 



#define FILE_DEVICE_EVENT 0x8000

#define CTL_CODE( DeviceType, Function, Method, Access ) (           \

  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \

)



#define FILE_ANY_ACCESS           0

#define METHOD_BUFFERED           0

#define FILE_DEVICE_UNKNOWN         0x00000022



#define IOCTL_PASSBUF \

  CTL_CODE(FILE_DEVICE_EVENT, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)



int main()

{

    HANDLE     hDevice;   

    bool     status; 

    ULONG     dwReturn;

    char     outbuf[129][16];

    hDevice = NULL;

    m_hCommEvent = NULL;

    hDevice = CreateFile( "\\\\.\\MyEvent",

            GENERIC_READ|GENERIC_WRITE,

            FILE_SHARE_READ | FILE_SHARE_WRITE, 

            NULL,

            OPEN_EXISTING, 

            FILE_ATTRIBUTE_NORMAL, 

            NULL);

    if(hDevice == INVALID_HANDLE_VALUE)

    {

      printf("createfile wrong\n");

      getchar();

      return 0;

    }

  while(1)

  {

    memset(outbuf,0,129*16);

    status =DeviceIoControl(hDevice,

            IOCTL_PASSBUF,

            NULL,

            0,

            &outbuf,

            128*16,

            &dwReturn,NULL);

    if( !status)

    

[1] [2] 下一页

频道声明:本频道的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出出处和原始作者 文章版权归本频道与文章作者所有.对于被频道转载文章的个人和网站,我们表示深深的谢意。

原始作者:佚名 录入时间:2007-3-31 2:27:54
信息来源:不详 投稿信箱:itqoo@126.com
文章录入:itqoo    责任编辑:itqoo 
  • 上一个文章:

  • 下一个文章: 没有了
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    - 关于我们 - 合作伙伴 - 友情链接 - 广告刊登 - 投稿热线 - 在线留言版权声明联系方式 -
    IT公社版权所有 粤ICP备05127012号
    Copyrigh@2005-2006 itqoo.com.Inc All Rights Reserved  推荐分辨率 1024*768
    联系站长:E-Mail:itqoo@126.com     MSN:urchincc@hotmail.com    QQ:点击这里给我发消息
    特别感谢:亿太网络提供空间支持