首页
社区
课程
招聘
win_7 64位HOOK NTDeviceIoControlFile函数 遇到点问题
发表于: 2016-6-6 10:58 16202

win_7 64位HOOK NTDeviceIoControlFile函数 遇到点问题

2016-6-6 10:58
16202
//作者:Tesla.Angela [www.vb-asm.com]

#include <ntddk.h>

typedef struct _SYSTEM_SERVICE_TABLE{
	PVOID  		ServiceTableBase; 
	PVOID  		ServiceCounterTableBase; 
	ULONGLONG  	NumberOfServices; 
	PVOID  		ParamTableBase; 
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

typedef struct _SERVICE_DESCRIPTOR_TABLE{
	SYSTEM_SERVICE_TABLE ntoskrnl;  // ntoskrnl.exe (native api)
	SYSTEM_SERVICE_TABLE win32k;    // win32k.sys   (gdi/user)
	SYSTEM_SERVICE_TABLE Table3;    // not used
	SYSTEM_SERVICE_TABLE Table4;    // not used
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;
//
typedef NTSTATUS ( __stdcall *NTDeviceIoControlFile)(//__stdcall  // _cdcel  //fastcall  三种模式都试过,都没有正常
	IN HANDLE FileHandle,
	IN HANDLE Event OPTIONAL,
	IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
	IN PVOID ApcContext OPTIONAL,
	OUT PIO_STATUS_BLOCK IoStatusBlock,
	IN ULONG IoControlCode,
	IN PVOID InputBuffer OPTIONAL,
	IN ULONG InputBufferLength,
	OUT PVOID OutputBuffer OPTIONAL,
	IN ULONG OutputBufferLength);

NTKERNELAPI
UCHAR *
PsGetProcessImageFileName(PEPROCESS Process);

PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
NTDeviceIoControlFile NtDeviceIoControlFile=NULL;
ULONG OldTpVal;

NTSTATUS __stdcall Fake_NtDeviceIoControlFile(//__stdcall  // _cdcel  //fastcall  三种模式都试过,都没有正常
	IN HANDLE FileHandle,
	IN HANDLE Event OPTIONAL,
	IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
	IN PVOID ApcContext OPTIONAL,
	OUT PIO_STATUS_BLOCK IoStatusBlock,
	IN ULONG IoControlCode,
	IN PVOID InputBuffer OPTIONAL,
	IN ULONG InputBufferLength,
	OUT PVOID OutputBuffer OPTIONAL,
	IN ULONG OutputBufferLength
	)
{
	//HOOK已经正确执行到了这里
	NTSTATUS rc;
	rc = NtDeviceIoControlFile (
		FileHandle,
		Event,
		ApcRoutine,
		ApcContext,
		IoStatusBlock,
		IoControlCode,
		InputBuffer,
		InputBufferLength,
		OutputBuffer,
		OutputBufferLength
		);//这个函数没调用正常,数据类型没有错,API功能出问题了

		return(rc);
	//DbgPrint("Fake_NtDeviceIoControlFile call_end!");


}



/*
NTSTATUS __fastcall Fake_NtDeviceIoControlFile(IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus)//新的函数地址
{
	PEPROCESS Process;
	NTSTATUS st = ObReferenceObjectByHandle (ProcessHandle, 0, *PsProcessType, KernelMode, &Process, NULL);
	DbgPrint("Fake_NtDeviceIoControlFile called!");
	if(NT_SUCCESS(st))
	{
		if(!_stricmp(PsGetProcessImageFileName(Process),"loaddrv.exe")||!_stricmp(PsGetProcessImageFileName(Process),"calc.exe"))
			return STATUS_ACCESS_DENIED;
		else
			return NtDeviceIoControlFile(ProcessHandle,ExitStatus);
	}
	else
		return STATUS_ACCESS_DENIED;
}
*/
KIRQL WPOFFx64()
{
	KIRQL irql=KeRaiseIrqlToDpcLevel();
	UINT64 cr0=__readcr0();
	cr0 &= 0xfffffffffffeffff;
	__writecr0(cr0);
	_disable();
	return irql;
}

void WPONx64(KIRQL irql)
{
	UINT64 cr0=__readcr0();
	cr0 |= 0x10000;
	_enable();
	__writecr0(cr0);
	KeLowerIrql(irql);
}

ULONGLONG GetKeServiceDescriptorTable64() //鬼佬的方法
{
	char KiSystemServiceStart_pattern[13] = "\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00";	//睇唔明系么春特征码
	ULONGLONG CodeScanStart = (ULONGLONG)&_strnicmp;
	ULONGLONG CodeScanEnd = (ULONGLONG)&KdDebuggerNotPresent;
	UNICODE_STRING Symbol;
	ULONGLONG i, tbl_address, b;
	for (i = 0; i < CodeScanEnd - CodeScanStart; i++)
	{
		if (!memcmp((char*)(ULONGLONG)CodeScanStart +i, (char*)KiSystemServiceStart_pattern,13))
		{ 
			for (b = 0; b < 50; b++)
			{
				tbl_address = ((ULONGLONG)CodeScanStart+i+b);
				if (*(USHORT*) ((ULONGLONG)tbl_address ) == (USHORT)0x8d4c)
					return ((LONGLONG)tbl_address +7) + *(LONG*)(tbl_address +3);
			}
		}
	}
	return 0;
}

ULONGLONG GetSSDTFuncCurAddr(ULONG id)
{
	LONG dwtmp=0;
	PULONG ServiceTableBase=NULL;
	ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
	dwtmp=ServiceTableBase[id];
	dwtmp=dwtmp>>4;
	return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;
}

ULONG GetOffsetAddress(ULONGLONG FuncAddr)
{
	ULONG dwtmp=0;
	PULONG ServiceTableBase=NULL;
	ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
	dwtmp=(ULONG)(FuncAddr-(ULONGLONG)ServiceTableBase);
	return dwtmp<<4;
}

VOID FuckKeBugCheckEx()
{
	KIRQL irql;
	ULONGLONG myfun;
	UCHAR jmp_code[]="\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0";
	myfun=(ULONGLONG)Fake_NtDeviceIoControlFile;
	memcpy(jmp_code+2,&myfun,8);
	irql=WPOFFx64();
	memset(KeBugCheckEx,0x90,15);
	memcpy(KeBugCheckEx,jmp_code,12);
	WPONx64(irql);
}

/*
填写KeBugCheckEx的地址
在KeBugCheckEx填写jmp,跳到Fake_NtDeviceIoControlFile
不能直接填写Fake_NtDeviceIoControlFile的地址,因为它们不再同一个4GB
*/
VOID HookSSDT()
{
	KIRQL irql;
	ULONGLONG dwtmp=0;
	PULONG ServiceTableBase=NULL;
	//get old address
	NtDeviceIoControlFile=(NTDeviceIoControlFile)GetSSDTFuncCurAddr(4);
	dprintf("Old_NtDeviceIoControlFile: %llx",(ULONGLONG)NtDeviceIoControlFile);
	//set kebugcheckex
	FuckKeBugCheckEx();
	//show new address
	ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
	OldTpVal=ServiceTableBase[4];	//record old offset value
	irql=WPOFFx64();
	ServiceTableBase[4]=GetOffsetAddress((ULONGLONG)KeBugCheckEx);
	WPONx64(irql);
	dprintf("KeBugCheckEx: %llx",(ULONGLONG)KeBugCheckEx);
	dprintf("New_NtDeviceIoControlFile: %llx",GetSSDTFuncCurAddr(4));
	
}

VOID UnhookSSDT()
{
	KIRQL irql;
	PULONG ServiceTableBase=NULL;
	ServiceTableBase=(PULONG)KeServiceDescriptorTable->ServiceTableBase;
	//set value
	irql=WPOFFx64();
	ServiceTableBase[4]=GetOffsetAddress((ULONGLONG)NtDeviceIoControlFile);	//OldTpVal;	//直接填写这个旧值也行
	WPONx64(irql);
	//没必要恢复KeBugCheckEx的内容了,反正执行到KeBugCheckEx时已经完蛋了。
	dprintf("NtDeviceIoControlFile: %llx",GetSSDTFuncCurAddr(4));
	
}


这是一份学习代码,win7_64的HOOK,原本代码上是HOOK:NtTerminateProcess的,用是fastcall模式,测试功能正常,经过修改后,HOOK会执行到Fake_NtDeviceIoControlFile,但是由于没有正常的掉用原来的函数,导致系统一会儿就出问题了,并没有蓝屏,测试的时候要谨慎,用的是WDK7.1版本编译的
__stdcall  // _cdcel  //fastcall  三种模式都试过,都没有正常

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 22
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
PG过了没?
2016-6-6 20:07
0
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这个粤语的注释有点意思,WIN7 X64你是不可以HOOK NTOSKNLR模块的
2016-6-6 20:43
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
那原本代码HOOK:NtTerminateProcess是成功的啊,没有问题啊
2016-6-7 01:18
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
PG我开始没过,现在才过的,你说了之后我去弄了一下午,才找到方法过,过了之后发现还不行,有一个疑问,原来的代码HOOK:NtTerminateProcess是成功的,测试过的,而且现在改成HOOK这个代码,也并非失败,成功执行到了新的函数,但是没有正常的调用系统的原函数,导致API功能上出了问题
2016-6-7 01:20
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
找不到问题就无法解决,附上源码,路过的看看[URL="http://pan.baidu.com/s/1o7G92wa"]http://pan.baidu.com/s/1o7G92wa[/URL
HOOK DeviceIoControlFile可以达到修改硬件信息的目的,让其他程序取硬件信息的时候,给他返回你想要的内容,这个框架修改一下,在64位下,你可以修改成其他函数的HOOK,非常容易,修改下SSDT的函数序列号,替换全部的函数名,最后修改下函数类型,就可以了
2016-6-7 11:18
0
雪    币: 135
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=耿康;1432828]找不到问题就无法解决,附上源码,路过的看看[URL="http://pan.baidu.com/s/1o7G92wa"]http://pan.baidu.com/s/1o7G92wa[/URL
HOOK DeviceIoControlFile可以达到修改硬件信息的目的,让其他程序取硬件信息的时候,给...[/QUOTE]

对于x64内核函数的原型,参数最好都换成64位的 , 会有想不到的效果。

别生搬x86的函数原型。。。。。
2016-6-12 04:39
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
32位的我用的是WRK-v1.2,微软开源的源码文件中找的函数原型,64位我就不知道去哪里找了
2016-6-12 23:37
0
雪    币: 135
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
双机直接WinDbg调试,逆出NTDeviceIoControlFile内部执行流程,看看是怎么处理传进去的参数的。注意参数长度。

<<<-----关键就是要逆,逆,逆,逆。。。。。。这就是<看雪>的宗旨!!!!
2016-6-13 01:19
0
雪    币: 3710
活跃值: (2669)
能力值: ( LV7,RANK:105 )
在线值:
发帖
回帖
粉丝
10
耿康 32位的我用的是WRK-v1.2,微软开源的源码文件中找的函数原型,64位我就不知道去哪里找了
64位下HOOK  NTDeviceIoControlFile函数调通了吗?
2018-1-29 14:00
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
yegu 64位下HOOK NTDeviceIoControlFile函数调通了吗?
有联系方式吗?有点问题需要请教一下
2018-1-31 17:26
0
雪    币: 3710
活跃值: (2669)
能力值: ( LV7,RANK:105 )
在线值:
发帖
回帖
粉丝
12
wx_旭日东升 有联系方式吗?有点问题需要请教一下
啥问题?https://bbs.pediy.com/thread-218009.htm(9楼,自己找找吧)
2018-2-2 22:59
0
雪    币: 42
活跃值: (208)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
目测你自己进入了死循环!NtDeviceIoControlFile->KeBugCheckEx->Fake_NtDeviceIoControlFile->NtDeviceIoControlFile
难道没发现你的代码一直在这样循环???
2018-10-24 19:45
0
游客
登录 | 注册 方可回帖
返回
//