句柄表

一、句柄表

1、创建一个内核对象,会在高2G分配一个空间,里面有个结构体和一张句柄表,句柄表刚创建时是空的,当这个进程再创建一个内核对象时,会填充这个表

2、用户拿着句柄去句柄表扫描得到真正的地址(id),这是防止用户改了真正的地址导致错误蓝屏

二、句柄和ID

1、都是系统分配的一个编号,句柄是客户程序使用 ID主要是系统调度时使用.

2、调用CloseHandle关闭进程或者线程句柄的时候,只是让内核计数器减少一个,并不是终止进程或者线程.

3、进程ID与线程ID 是不可能相同。但不要通过进程或者线程的ID来操作进程或者线程,因为,这个编号是会重复使用的,也就是说,当你通过ID=100这个编号去访问一个进程的时候,它已经结束了,而且系统将这个编号赋给了另外一个进程或者线程.

三、句柄表的继承

1、继承是将父进程的句柄表,复制一份,允许继承的继承过来,不允许继承的填0

A进程

#include "stdafx.h"
#include <windows.h>



int main(int argc, char* argv[])
{
				
	char szBuffer[256] = {0};		
	char szHandle[8] = {0};		
						
	SECURITY_ATTRIBUTES sa;							
	sa.nLength = sizeof(sa);							
	sa.lpSecurityDescriptor = NULL;							
	sa.bInheritHandle = TRUE; 							
	//创建一个可以被继承的内核对象							
	HANDLE g_hEvent = CreateEvent(&sa, TRUE, FALSE, NULL);							
								
	//组织命令行参数							
	sprintf(szHandle,"%x",g_hEvent);							
	sprintf(szBuffer,"C:/b.exe %s",szHandle);							
								
	//定义创建进程需要用的结构体							
	STARTUPINFO si = {0};   							
	PROCESS_INFORMATION pi;							
	si.cb = sizeof(si);							
		
		
	//创建子进程							
	if(!CreateProcess(							
		NULL, 						
		szBuffer, 						
		NULL, 						
		NULL, 						
		TRUE, 				
		CREATE_NEW_CONSOLE, 						
		NULL, 						
		NULL, &si, &pi)						
		)
	{//打印错误信息
		printf("Error:%d\n",GetLastError());
		return FALSE;	
	}						
								
	//设置事件为已通知							
	SetEvent(g_hEvent);							
								
	//关闭句柄 内核对象是否会被销毁?							
	CloseHandle(g_hEvent);  							
															
	return 0;
}

B进程

#include "stdafx.h"
#include <windows.h>


int main(int argc, char* argv[])
{
	char szBuffer[256] = {0};					
						
	memcpy(szBuffer,argv[1],8);					
						
	DWORD dwHandle = 0;					
						
	sscanf(szBuffer,"%x",&dwHandle);					
						
	printf("%s\n",argv[0]);					
						
	printf("%x\n",dwHandle);					
						
	HANDLE g_hEvent = (HANDLE)dwHandle;					
						
						
	printf("开始等待.....\n");					
	//当事件变成已通知时 					
	WaitForSingleObject(g_hEvent, INFINITE);					
						
	DWORD dwCode = GetLastError();					
						
	printf("等到消息.....%x\n",dwCode);					
						
	getchar();					
						

	return 0;
}

2、继承进程

子进程的继承与其它内核对象不同,其他内核对象只有一个句柄,但是子进程内核对象有线程句柄和进程句柄,所以要继承这个子进程,需要对CreateProcess的第三个和第四个进行设置

A程序

#include "stdafx.h"
#include <windows.h>

int main(int argc, char* argv[])
{													
	char szBuffer[256] = {0};								
	char szHandle[8] = {0};								
								
	SECURITY_ATTRIBUTES ie_sa_p;	
        //设置大小							
	ie_sa_p.nLength = sizeof(ie_sa_p);	
        //安全描述符							
	ie_sa_p.lpSecurityDescriptor = NULL;	
        //进程句柄可以被继承							
	ie_sa_p.bInheritHandle = TRUE; 								
									
	SECURITY_ATTRIBUTES ie_sa_t;								
	ie_sa_t.nLength = sizeof(ie_sa_t);								
	ie_sa_t.lpSecurityDescriptor = NULL;	
        //线程句柄可以被继承							
	ie_sa_t.bInheritHandle = TRUE; 	
							
	//创建一个可以被继承的内核对象,此处是个进程								
	STARTUPINFO ie_si = {0};   								
	PROCESS_INFORMATION ie_pi;								
	ie_si.cb = sizeof(ie_si);								
									
	TCHAR szCmdline[] =TEXT("c://program files//internet explorer//iexplore.exe");								
	CreateProcess(								
		NULL, 							
		szCmdline, 							
		&ie_sa_p, 							
		&ie_sa_t, 							
		TRUE, 							
		CREATE_NEW_CONSOLE, 							
		NULL, 							
		NULL, &ie_si, &ie_pi); 							
	
	//组织命令行参数								
	sprintf(szHandle,"%x %x",ie_pi.hProcess,ie_pi.hThread);								
	sprintf(szBuffer,"C:/b.exe %s",szHandle);								
									
	//定义创建进程需要用的结构体								
	STARTUPINFO si = {0};   								
	PROCESS_INFORMATION pi;								
	si.cb = sizeof(si);								
									
	//创建子进程								
	BOOL res = CreateProcess(								
		NULL, 							
		szBuffer, 							
		NULL, 							
		NULL, 							
		TRUE, 							
		CREATE_NEW_CONSOLE, 							
		NULL, 							
		NULL, &si, &pi); 							
																							
	return 0;
}

B程序:

#include "stdafx.h"
#include <windows.h>

int main(int argc, char* argv[])
{
								
	DWORD dwProcessHandle = -1;							
	DWORD dwThreadHandle = -1;							
	char szBuffer[256] = {0};							
								
								
	memcpy(szBuffer,argv[1],8);	

	sscanf(szBuffer,"%x",&dwProcessHandle);	
	printf("%x\n",szBuffer);
								
	memset(szBuffer,0,256);							
	memcpy(szBuffer,argv[2],8);							
	sscanf(szBuffer,"%x",&dwThreadHandle);							
								
	printf("获取IE进程、主线程句柄\n");							
	Sleep(2000);							
	//挂起主线程							
	printf("挂起主线程\n");							
	::SuspendThread((HANDLE)dwThreadHandle);							
								
	Sleep(5000);							
								
	//恢复主线程							
	::ResumeThread((HANDLE)dwThreadHandle);							
	printf("恢复主线程\n");							
								
	Sleep(5000);							
								
	//关闭ID进程							
	::TerminateProcess((HANDLE)dwProcessHandle,1);							
	::WaitForSingleObject((HANDLE)dwProcessHandle, INFINITE);							
								
	printf("ID进程已经关闭.....\n");												

	return 0;
}
posted @ 2021-12-29 17:59  lnterpreter  阅读(55)  评论(0编辑  收藏  举报