首页
社区
课程
招聘
[求助]新手Hook IoCallDriver的问题
发表于: 2013-9-26 16:31 14691

[求助]新手Hook IoCallDriver的问题

2013-9-26 16:31
14691
代码如下:
但是一旦执行到MyIoCallDriver就蓝屏,通过Windbg 调试在调用旧的IofCallDriver的时候出错,提示BugCheck 50的错误,各位能帮我找找是什么原因么,谢谢
#include<ntddk.h>

typedef NTSTATUS (FASTCALL* PMY_IOFCALLDRIVER_FP)(IN PDEVICE_OBJECT,IN OUT PIRP);
typedef unsigned char BYTE;
static PMY_IOFCALLDRIVER_FP oldcallerbody=NULL;
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);

PMY_IOFCALLDRIVER_FP XP_HOOK_IoCallDriver(PMY_IOFCALLDRIVER_FP newCaller,BOOLEAN hook)
{
        UNICODE_STRING funName;
        BYTE *addr;
        RtlInitUnicodeString(&funName,L"IofCallDriver");
        addr=MmGetSystemRoutineAddress(&funName);
        if(hook)
        {
           oldcallerbody=(PMY_IOFCALLDRIVER_FP)(*(PLONG)(addr+2));
           InterlockedExchange((PLONG)(addr+2),newCaller);
           return oldcallerbody;
        }
        else
        {
                if (oldcallerbody!=NULL)
                {
                        InterlockedExchange((PLONG)(addr+2),oldcallerbody);
                        return oldcallerbody;
                }
        }
}

NTSTATUS FASTCALL MyIoCallDriver(IN PDEVICE_OBJECT pDev,IN OUT PIRP pIrp )
{
        DbgPrint("Hook Is called \n");
        return oldcallerbody(pDev,pIrp);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN IN PUNICODE_STRING pReg_Path)
{
        PMY_IOFCALLDRIVER_FP pfn=MyIoCallDriver;
        XP_HOOK_IoCallDriver(MyIoCallDriver,TRUE);
        pDriverObject->DriverUnload=DriverUnload;
}

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
        XP_HOOK_IoCallDriver(MyIoCallDriver,FALSE);
        DbgPrint("close hook \n");
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (21)
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
google “Inline Hook”
2013-9-26 17:07
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
cr0 寄存器没修改,代码段只读不可写
2013-9-26 17:45
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
能说得详细点么
2013-9-26 18:11
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
5
LZ的问题在于没有仔细看IofCallDriver,一起看看:
kd> u IofCallDriver
nt!IofCallDriver:
804eefea ff2500c65480    jmp     dword ptr [nt!pIofCallDriver (8054c600)]

IofCallDriver这里的ff25是jmp到一个指针变量所保存的值里去,也就是说不是jmp到8054c600,而是jmp到这里:
kd> dd 8054c600 l1
8054c600  804eefb2

kd> u 804eefb2
nt!IopfCallDriver:
804eefb2 fe4a23          dec     byte ptr [edx+23h]
804eefb5 8a4223          mov     al,byte ptr [edx+23h]
804eefb8 84c0            test    al,al
804eefba 7f0e            jg      nt!IopfCallDriver+0x18 (804eefca)
804eefbc 6a00            push    0
804eefbe 6a00            push    0
804eefc0 6a00            push    0
804eefc2 52              push    edx

同样,LZ写进入的值也不能直接是你的MyIoCallDriver,而应该做如下修改:
        if(hook)
        {
                oldcallerbody=(PMY_IOFCALLDRIVER_FP)(*(PLONG)(addr+2));
                oldcallerbody=(PMY_IOFCALLDRIVER_FP)(*(ULONG*)oldcallerbody);
                static PMY_IOFCALLDRIVER_FP newcallerbody = newCaller;
                InterlockedExchange((PLONG)(addr+2),(LONG)&newcallerbody);
                return oldcallerbody;
        }
2013-9-26 18:21
0
雪    币: 11
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
相对跳转问题吧
2013-9-26 18:22
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=星逝;1225301]LZ的问题在于没有仔细看IofCallDriver,一起看看:
kd> u IofCallDriver
nt!IofCallDriver:
804eefea ff2500c65480    jmp     dword ptr [nt!pIofCallDriver (8054c600)]

IofCa...[/QUOTE]

话说这个问题修改了以后还蓝屏,还用了全局的,也用过ExAllocatePoolWithTag申请不分页内存,呼呼,Hook在windbg下查看完全OK,F9依旧蓝屏,哎~~~
2013-9-26 18:25
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
我去啊,你DriverEntry都没return success,难怪蓝屏了,驱动都没加载成功,而跳转被修改了,函数MyIoCallDriver 不可读
2013-9-26 18:28
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
#include<ntddk.h>

typedef NTSTATUS (FASTCALL* PMY_IOFCALLDRIVER_FP)(IN PDEVICE_OBJECT,IN OUT PIRP);
typedef unsigned char BYTE;
static PMY_IOFCALLDRIVER_FP* oldcallerbody = NULL;

PMY_IOFCALLDRIVER_FP* jmp_addr = NULL;

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);

PMY_IOFCALLDRIVER_FP XP_HOOK_IoCallDriver(PMY_IOFCALLDRIVER_FP* newCaller,BOOLEAN hook)
{
  UNICODE_STRING funName;
  BYTE *addr;
  RtlInitUnicodeString(&funName,L"IofCallDriver");
  addr=MmGetSystemRoutineAddress(&funName);
  if(hook)
  {
     oldcallerbody = (PMY_IOFCALLDRIVER_FP*)(*(PLONG)(addr+2));
	  
	__asm{
		cli
		mov  eax,cr0
		push eax
		and  eax,not 10000h
		mov  cr0,eax
	}
	InterlockedExchange((PLONG)(addr+2), newCaller);
	__asm{  
		pop  eax
		mov  cr0,eax
		sti
	}
     
     return oldcallerbody;
  }
  else
  {
    if (oldcallerbody!=NULL)
    {
		__asm{
			cli
			mov  eax,cr0
			push eax
			and  eax,not 10000h
			mov  cr0,eax
		}
		InterlockedExchange((PLONG)(addr+2),oldcallerbody); 
		__asm{  
			pop  eax
			mov  cr0,eax
			sti
		}
		
      return oldcallerbody;
    }
  }
}

NTSTATUS FASTCALL MyIoCallDriver(IN PDEVICE_OBJECT pDev,IN OUT PIRP pIrp )
{
	DbgPrint("Hook Is called \n");
	return (*oldcallerbody)(pDev,pIrp);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN IN PUNICODE_STRING pReg_Path)
{
	PMY_IOFCALLDRIVER_FP pfn = MyIoCallDriver;
	
	// 方法一:自己申请内存
//	jmp_addr = (PMY_IOFCALLDRIVER_FP*)ExAllocatePoolWithTag(NonPagedPoolCacheAligned, sizeof(PMY_IOFCALLDRIVER_FP), 'KNUJ'); 
//	*jmp_addr = MyIoCallDriver;
//	XP_HOOK_IoCallDriver(jmp_addr, TRUE);
	
	// 方法二:全局变量
	jmp_addr = MyIoCallDriver;
	XP_HOOK_IoCallDriver(&jmp_addr, TRUE);

	pDriverObject->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
	// 这里反正第一个参数没用,就取地址吧
	XP_HOOK_IoCallDriver(&jmp_addr, FALSE);
//	ExFreePoolWithTag(jmp_addr, 'KNUJ');	
	DbgPrint("close hook \n");
} 
2013-9-26 18:47
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
10
我试过了,不会蓝。DriverEntry里没return应该是LZ copy代码疏忽了,编译器肯定是编不过的。
2013-9-26 19:21
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
额,好吧,我这编译通过了 ,也无情的蓝了,win7 x64 sp1 ,7600的wdk 用 x86 checked。平时写代码还有强转来强转去的,这次这么干脆过了

.text:0001058C                 mov     _jmp_addr, eax
.text:00010591                 mov     eax, _jmp_addr
.text:00010596                 mov     dword ptr [eax], offset MyIoCallDriver(x,x)
.text:0001059C                 push    1               ; hook
.text:0001059E                 mov     ecx, _jmp_addr
.text:000105A4                 push    ecx             ; newCaller
.text:000105A5                 call    XP_HOOK_IoCallDriver(x,x)
.text:000105A5
.text:000105AA                 mov     edx, [ebp+pDriverObject]
.text:000105AD                 mov     dword ptr [edx+34h], offset DriverUnload(x)
.text:000105B4                 mov     esp, ebp
.text:000105B6                 pop     ebp
.text:000105B7                 retn    8
.text:000105B7
.text:000105B7 __stdcall DriverEntry(x, x) endp

结果就这样,eax 最后返回了 自己申请的内存地址
2013-9-26 19:50
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
[QUOTE=星逝;1225301]LZ的问题在于没有仔细看IofCallDriver,一起看看:
kd> u IofCallDriver
nt!IofCallDriver:
804eefea ff2500c65480    jmp     dword ptr [nt!pIofCallDriver (8054c600)]

IofCa...[/QUOTE]
能请教你个问题么,我把驱动编译之后,实际上文件中存在的是机器码,然后我通过InterLockedExchange这个函数修改之后,也是直接修改机器码是不是?还是修改汇编代码?
2013-9-26 20:35
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
[QUOTE=星逝;1225301]LZ的问题在于没有仔细看IofCallDriver,一起看看:
kd> u IofCallDriver
nt!IofCallDriver:
804eefea ff2500c65480    jmp     dword ptr [nt!pIofCallDriver (8054c600)]

IofCa...[/QUOTE]

你好改成这样当跟踪到红色这一句就蓝了,我的系统是XP DDK 为 7600
PMY_IOFCALLDRIVER_FP XP_HOOK_IoCallDriver(PMY_IOFCALLDRIVER_FP newCaller,BOOLEAN hook)
{
        UNICODE_STRING funName;
        BYTE *addr;
        static PMY_IOFCALLDRIVER_FP newcallerbody=NULL;
        RtlInitUnicodeString(&funName,L"IofCallDriver");
        addr=MmGetSystemRoutineAddress(&funName);
        if(hook)
        {
           oldcallerbody=(PMY_IOFCALLDRIVER_FP)(*(PLONG)(addr+2));
           newcallerbody=newCaller;
           InterlockedExchange((PLONG)(addr+2),(LONG)&newcallerbody);
           return oldcallerbody;
        }
        else
        {
                if (oldcallerbody!=NULL)
                {
                        InterlockedExchange((PLONG)(addr+2),oldcallerbody);
                        return oldcallerbody;
                }
        }
}
2013-9-26 21:41
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
见Intel手册卷三,应该是第3章内存管理里面有详细说明。


上面很清楚的标记了CR0第16位是写保护位,如果为1的时候代码内存是不能写的,一写就蓝屏,必须把它清零先

9L代码不是可以运行了么~~~~~~~~~~~~~~
2013-9-27 08:31
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
15
你是用命令行编译的吗?
2013-9-27 11:17
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
16
是直接修改机器码,也可以说修改了汇编代码,因为汇编代码只是机器码的一种等价表示,就如中文的你好用英文表示为hello一样。
2013-9-27 11:20
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
17
要具体看了,提供下源码我试下?
2013-9-27 11:22
0
雪    币: 293
活跃值: (287)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
wdk自带的命令行编译的。


LZ贴的就是完整代码,你不是说你试过了么?
2013-9-27 12:41
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
19
我是VS+DDKWizard生成的,DriverEntry部分没用LZ的,所以是有return的。
2013-9-27 13:16
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
20
目测没有去掉写保护.
2013-9-27 13:49
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
以下是完整代码,去除读写保护之后,InterLockedExchange就不蓝屏了,不过执行HOOK函数就蓝了

#include<ntddk.h>

typedef NTSTATUS (FASTCALL* PMY_IOFCALLDRIVER_FP)(IN PDEVICE_OBJECT,IN OUT PIRP);
typedef unsigned char BYTE;
static PMY_IOFCALLDRIVER_FP oldcallerbody=NULL;
//static PMY_IOFCALLDRIVER_FP newcallerbody=NULL;
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);

PMY_IOFCALLDRIVER_FP XP_HOOK_IoCallDriver(PMY_IOFCALLDRIVER_FP newCaller,BOOLEAN hook)
{
        UNICODE_STRING funName;
        BYTE *addr;
        static PMY_IOFCALLDRIVER_FP newcallerbody=NULL;
        RtlInitUnicodeString(&funName,L"IofCallDriver");
        addr=MmGetSystemRoutineAddress(&funName);
        if(hook)
        {
           oldcallerbody=(PMY_IOFCALLDRIVER_FP)(*(PLONG)(addr+2));
           newcallerbody=newCaller;
             __asm{
                                cli
                                mov  eax,cr0
                                push eax
                                and  eax,not 10000h
                                mov  cr0,eax
              }
           InterlockedExchange((PLONG)(addr+2),(LONG)&newcallerbody);
             __asm{  
                                pop  eax
                                mov  cr0,eax
                                sti
              }
           return oldcallerbody;
        }
        else
        {
                if (oldcallerbody!=NULL)
                {
                 __asm{
                                cli
                                mov  eax,cr0
                                push eax
                                and  eax,not 10000h
                                mov  cr0,eax
              }
                        newcallerbody=oldcallerbody;
                        InterlockedExchange((PLONG)(addr+2),&oldcallerbody);
            __asm{  
                                pop  eax
                                mov  cr0,eax
                                sti
              }
                        return oldcallerbody;
                }
        }
}

NTSTATUS FASTCALL MyIoCallDriver(IN PDEVICE_OBJECT pDev,IN OUT PIRP pIrp )
{
        DbgPrint("Hook Is called \n");
        return (*oldcallerbody)(pDev,pIrp);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN IN PUNICODE_STRING pReg_Path)
{
        PMY_IOFCALLDRIVER_FP pfn=MyIoCallDriver;
        XP_HOOK_IoCallDriver(MyIoCallDriver,TRUE);
        pDriverObject->DriverUnload=DriverUnload;
        return STATUS_SUCCESS;
}

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
        XP_HOOK_IoCallDriver(MyIoCallDriver,FALSE);
        DbgPrint("close hook \n");
}
2013-9-28 10:34
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
22
仔细对比下我或者瀚海云烟贴出来的代码,目测现在的问题在oldcallerbody的定义,瀚海云烟的定义如下:static PMY_IOFCALLDRIVER_FP* oldcallerbody = NULL;
2013-9-29 12:16
0
游客
登录 | 注册 方可回帖
返回
//