句柄表
一、句柄表
1、创建一个内核对象,会在高2G分配一个空间,里面有个结构体和一张句柄表,句柄表刚创建时是空的,当这个进程再创建一个内核对象时,会填充这个表
2、用户拿着句柄去句柄表扫描得到真正的地址(id),这是防止用户改了真正的地址导致错误蓝屏
二、句柄和ID
1、都是系统分配的一个编号,句柄是客户程序使用 ID主要是系统调度时使用.
2、调用CloseHandle关闭进程或者线程句柄的时候,只是让内核计数器减少一个,并不是终止进程或者线程.
3、进程ID与线程ID 是不可能相同。但不要通过进程或者线程的ID来操作进程或者线程,因为,这个编号是会重复使用的,也就是说,当你通过ID=100这个编号去访问一个进程的时候,它已经结束了,而且系统将这个编号赋给了另外一个进程或者线程.
三、句柄表的继承
1、继承是将父进程的句柄表,复制一份,允许继承的继承过来,不允许继承的填0
A进程
#include "stdafx.h"
#include
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
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
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
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;
}