首页
论坛
课程
招聘
[原创]SSDT Hook 详细过程
2013-12-29 14:33 11597

[原创]SSDT Hook 详细过程

2013-12-29 14:33
11597
一。目标程序***********

//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;
}


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


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

2021 KCTF 秋季赛 防守篇-征题倒计时(11月14日截止)!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (17)
雪    币: 644
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
怕天亮 活跃值 2013-12-29 20:19
2
0
沙发我来做 好文章 多谢楼主
雪    币: 184
活跃值: 活跃值 (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whnet 活跃值 2013-12-30 11:21
3
0
"这里用直接Hook SSDT",                 为何截图成了inline了。 是截图 单独放的?
雪    币: 69
活跃值: 活跃值 (13)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
ztj 活跃值 2013-12-30 12:10
4
0
oh,截图弄错了,截图是后来弄的,后来是用inline hook的。
就假装截图上写的是ssdt hook吧
雪    币: 239
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
天行客 活跃值 2013-12-30 13:59
5
0
简单明了,好文章。
雪    币: 184
活跃值: 活跃值 (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whnet 活跃值 2013-12-30 16:03
6
0
那还是稍微注明一下。 对于新手,或者说没有接触过的人来说,分不清SSDT 和inline 的。

雪    币: 47
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jpys 活跃值 2013-12-30 16:18
7
0
mark
雪    币: 204
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
doa007 活跃值 1 2013-12-30 16:21
8
0
给个优秀也算是给初学点一点鼓励吧
雪    币: 79
活跃值: 活跃值 (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cqzj70 活跃值 2013-12-30 16:34
9
0
不错 ,辛苦了
雪    币: 882
活跃值: 活跃值 (345)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zquchs 活跃值 2013-12-30 19:42
10
0
思路很明确
雪    币: 42
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
scenic 活跃值 2013-12-31 12:29
11
0
mark
雪    币: 44
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
买啦个表 活跃值 2014-1-3 10:59
12
0
FindAPIRVAByName呢?
雪    币: 190
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mmkclub 活跃值 2014-1-3 11:09
13
0
前面还能看懂,从第三部分编程实现就看不懂了,基础差啊!
kd> dt _EProcess是什么意思,后面就不知道在干什么了
雪    币: 37
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
机器精灵 活跃值 2014-1-3 13:31
14
0
好文,强人
雪    币: 564
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lixupeng 活跃值 2014-1-4 00:36
15
0
学习 !
雪    币: 184
活跃值: 活跃值 (192)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
小木鱼 活跃值 2014-1-4 17:32
16
0
系统内核都被玩成这样了,只能膜拜了。
雪    币: 110
活跃值: 活跃值 (184)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ling林 活跃值 2014-1-4 19:24
17
0
mark一下
雪    币: 26
活跃值: 活跃值 (12)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Henzox 活跃值 2014-2-18 18:26
18
0
截图中的那个工具蛮好用的!
游客
登录 | 注册 方可回帖
返回