欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]SSDT Hook 详细过程

[原创]SSDT Hook 详细过程

一。目标程序***********
//target.exe

int x=5;

int main()  

{  

 	while(1)

 	{

 		printf("%p %d",&x,x);

 		Sleep(20000);

 	}

}

//test.exe
int main()  

{  

	int pid=0;

	PROCESSENTRY32 pe32;

	pe32.dwSize = sizeof(pe32);

	HANDLE hProcessSnap =   

       ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

	if (hProcessSnap == INVALID_HANDLE_VALUE)

	{

		printf("CreateToolhelp32Snapshot 调用失败.\n");

		return -1;

	}

	BOOL bMore = ::Process32First(hProcessSnap,&pe32);

	while (bMore)

	{

		if(strcmp(pe32.szExeFile,"target.exe")==0)

		{

			pid=pe32.th32ProcessID;

			break;

		}

		bMore = ::Process32Next(hProcessSnap,&pe32);

	}

	::CloseHandle(hProcessSnap);

	HANDLE hOpen=OpenProcess(PROCESS_VM_READ, 0, pid);

	PVOID pbaseaddr=(PVOID)0x40bdc0;

	DWORD data=0;

	DWORD readlen=0;

	printf("%x",hOpen);

	ReadProcessMemory(hOpen,pbaseaddr,&data,4,&readlen);

	printf("%d",data);

	system("pause");

	return 0;  

}  

程序预览

本文通过ssdt hook 使test.exe读取内存的值为77
二。验证思路***********
用od打开test.exe看ReadProcessMemory



调用SSDT表中函数的编号为0xBA
windbg中加上断点
kd> bp nt!NtReadVirtualMemory
发现会停很多次
查看堆栈
kd> dd esp

其中esp+8为读内存起始地址
加上条件断点
kd> bc 0
kd> bp nt!NtReadVirtualMemory "j(poi(esp+8)==0x40bdc0)'!process;dd esp';'g'"

发现就是test.exe进程,接收缓冲区地址为0x0012fe48
运行至NtReadVirtualMemory的ret处
kd> ed 0012fe48 0x4d
运行结果

验证成功!
三。编程实现***********
这里说主要内容,附件有代码
这个是挂钩后调用的函数
获取进程名字用的地址是
kd> dt _EProcess获取的

NTSTATUS MyNtReadVirtualMemory (

	IN HANDLE ProcessHandle,

	IN PVOID BaseAddress,

	OUT PVOID Buffer,

	IN ULONG BufferSize,

	OUT PULONG NumberOfBytesRead

	)

{

	NTSTATUS ret=((NTREADVIRTUALMEMORY)g_pReadVirtualMemory)(ProcessHandle,BaseAddress,Buffer,BufferSize,NumberOfBytesRead);

	if(ret==STATUS_SUCCESS)

	{

		PEPROCESS Process;

		ret=ObReferenceObjectByHandle(ProcessHandle,EVENT_MODIFY_STATE,*PsProcessType,KernelMode,(PVOID*)&Process,NULL);

		if(ret==STATUS_SUCCESS && Process!=NULL)

		{

			PEPROCESS curProcess=IoGetCurrentProcess();

			if (_stricmp((char*)((char*)Process+0x174), "target.exe") == 0 )

			{

				if(_stricmp((char*)((char*)curProcess+0x174), "test.exe") == 0 )

				{

					*((CHAR*)Buffer)=77;

				}

			}

			ObDereferenceObject(Process);

		}

	}

	return ret;

}

这里是驱动入口
由于ssdt是只读内存,修改只读内存有2种常规方法,这里用的是修改cr0的WP位(问题:这样修改会不会在多CPU下出问题?????有什么好办法),另外一种是用Mdl
Hook的办法也有2种,这里用直接Hook SSDT,另外一种是inline Hook
extern "C"

NTSTATUS    DriverEntry(void* pModudleBase,int nNothing) {

	g_pNtKernelBaseAddr = FindKernelBaseAddr(&g_nNtKernelSizeOfImage);

	if (NULL == g_pNtKernelBaseAddr) {

		return -1;

	}

	ULONG   nNetIoSizeOfImage = 0;

	DWORD nServicesTableRVA=FindAPIRVAByName((PVOID)g_pNtKernelBaseAddr,"KeServiceDescriptorTable");

	if (NULL == nServicesTableRVA) {

		return FALSE;

	}

	PSERVICE_DESCRIPTOR_TABLE pServicesTable=(PSERVICE_DESCRIPTOR_TABLE)((PUCHAR)g_pNtKernelBaseAddr + nServicesTableRVA);

	PUCHAR pnSSDTVA = (PUCHAR)(pServicesTable->ServiceTableBase);

	//

	//SSDT Hook

	//

	PVOID* pReadVirtualMemory=(PVOID*)(pnSSDTVA+(0xba*4));

	__asm{

		cli

			mov  eax,cr0

			and  eax,not 10000h

			mov  cr0,eax

	}

	g_pReadVirtualMemory=*pReadVirtualMemory;

	*pReadVirtualMemory=(PVOID*)(DWORD)MyNtReadVirtualMemory;

	__asm{  

		mov  eax,cr0

			or   eax,10000h

			mov  cr0,eax

			sti

	}

    return STATUS_SUCCESS;

}

四。验证***********

第一次发帖
不知道截图附件有没有问题

上传的附件 QQ截图20131229135241.jpg
QQ截图20131228154456.jpg
QQ截图20131228154534.jpg
QQ截图20131228154738.jpg
dd esp.jpg
bp j.jpg
result.jpg
dt.jpg
SSDT.zip
SSdt.jpg

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功