执着成就未来 技术成就梦想
文字横幅以及760*60黄金广告位置招租,欢迎恰谈! 广告业务联系QQ:8019399 声明:在本站所投放广告内容均与本站立场无关!

您现在的位置: 中国安全在线 >> 攻防技术 >> 网络编程 >> 文章正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
了解Linux系统内核安全的入侵侦察系
SYN Cookie原理及其在Linux内核中的
入侵Windows揭秘 平台内核级文件访
内核级利用通用Hook函数方法检测进程
作者:佚名 来源:安全在线 更新时间:2007-1-15 【字体:
<%=(int(rnd()*1)+1)%>您当前的位置:中国安全在线cnsafer.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!\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 <windows.h>

#include <stdio.h>



#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

[1] [2] 下一页

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力

文章录入:ls1238    责任编辑:ls1238 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    | 设为首页 | 加入收藏 | 联系方式 | 友 情链接 | 关于我们 | 网站留言 |
    Copyright ?2003-2008 www.cnsafer.com All Rights Reserved.
    如有意见请与我们联系 Email:admin#mail.cnsafer.com 联系QQ:8589101
    中国安全在线友情提示:建议使用IE6.0或以上版本, 分辩率1024*768进行浏览
    敢想 敢做 挑战自我 努力做最好 打造最优秀的新手成长 第一起跑线
    中网科技有限公司 技术支持 鄂ICP备05006475号