Win32 进程创建_句柄表

目录

1.进程的创建过程

一、进程的创建过程

二、CreateProcess的做了什么

​编辑

2.创建进程

1.创建进程函数的第一个参数 

2.第二个参数

3.两个结构体

3.进程终止

4.句柄的继承

1.然后我们创建一个可以被继承的内核对象,CreateEvent创建事件

2.再使用sprintf函数将数字转换为字符串

3.然后初始化创进程需要的结构体,而后创建结构体

4.再创建进程,注意:将创建结构体函数的第五个参数传参为TRUE,表示需要继承,否则即使前面指定了结构体来表示继承,也无法在子进程中继承到父进程的句柄表

5.SetEvent来修改状态,我们在子进程中接受命令行参数,并将命令行参数赋值给HANDLE类型的事件,来检测是否能WaitForSingleObject到


1.进程的创建过程

一、进程的创建过程

进程就是一个 4GB的空间,因为32位系统里面的寻址范围是2的32次方。Explorer.exe程序也是被操作系统的内核程序创建的,只不过该程序在创建完毕桌面程序后就退出了。

二、CreateProcess的做了什么

当要创建出一个进程时,会创建出一个内核对象,内核对象在内存中分配了4GB的虚拟内存空间,在高2G位置中,有一个句柄表。该句柄表在刚创建的时候是空的,但是在该进程中的主线程或子线程中有CreateProcess、CreateThread等创建内核对象的函数时,就会在句柄表的位置中添加句柄编号。 

句柄标号其实是系统给内核对象地址的一个编号,因为不可能把内核对象真正的地址传递出去。

一个进程的创建就是在4GB中贴入各种exe、dll文件,因为一开始装载的地址是写死的,所以有可能会发生位置被占用的情况,因此需要重定位表来记录哪些需要被修改的位置,然后由操作系统来进行绝对地址的修改,并且有些exe或者dll中会调用其他dll中的函数,但是地址却没有写死,因此需要修改IAT表。

当贴块完毕后,就会创建一个主线程,再将EIP的初始值修改为ImageBase+OEP后就可以开始跑了 

2.创建进程

// CreateProcess.cpp : Defines the entry point for the console application.
//

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

int main(int argc, char* argv[])
{
	STARTUPINFO si={0};
	PROCESS_INFORMATION pi={0};

	si.cb=sizeof(STARTUPINFO);

	TCHAR szApplicationName[]=TEXT("c://program files//internet explorer//iexplore.exe");

	BOOL ret=CreateProcess(
		szApplicationName,
		TEXT(" http://www.ifeng.com"),
		NULL,
		NULL,
		FALSE,
		CREATE_NEW_CONSOLE,
		NULL,
		NULL,&si,&pi);

	printf("%x\t%x\t%x\t&x\n",pi.dwProcessId,pi.dwThreadId,pi.hProcess,pi.hThread);

	return 0;
}

1.创建进程函数的第一个参数 

第一个参数是进程模块的名字,在我们打开进程时,可以将进程名传参(可以是详细的也可以是单独一个进程名,系统会自动加上exe后缀名,但是会一层一层的在系统文件中查找),也可以传参为NULL,通过第二个参数进行打开进程

2.第二个参数

第二个参数时命令行参数,我们也可以将第一个参数传NULL,通过第二个参数进行传参

也可以第一个参数传参路径,第二个参数可以向进程传递参数,比如:打开网站某个网页

3.两个结构体

第一个结构体初始化后需要将第一个成员进行赋值

第二个结构体是一个out型参数,我们可以通过结构体得知进程的相关信息

3.进程终止

 进程终止时的相关操作是操作系统在为我们做,我们只需大概了解

4.句柄的继承

现在我们创建两个进程来查看继承是否成功

父进程:Part_A:

// Patr_A.cpp : Defines the entry point for the console application.
//

#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_Event=CreateEvent(&sa,true,false,NULL);
	sprintf(szHandle,"%x",g_Event);
	sprintf(szBuffer,"C:/Part_B %s",szHandle);

	STARTUPINFO si={0};
	PROCESS_INFORMATION pi={0};

	si.cb=sizeof(si);

	BOOL ret=CreateProcess(
		NULL,
		szBuffer,
		NULL,
		NULL,
		true,
		CREATE_NEW_CONSOLE,
		NULL,
		NULL,&si,&pi);

	SetEvent(g_Event);
	CloseHandle(g_Event);

	return 0;
}

 我们要想实现父进程中的句柄表能够继承到子进程中,我们需要定义一个结构体并对齐进行初始化。

 此处第三个成员赋值为TRUE表示父进程句柄表可以被继承(在后面创建子进程中还有个参数要定义,以此来表示需要继承父进程的句柄表)

1.然后我们创建一个可以被继承的内核对象,CreateEvent创建事件
2.再使用sprintf函数将数字转换为字符串
3.然后初始化创进程需要的结构体,而后创建结构体
4.再创建进程,注意:将创建结构体函数的第五个参数传参为TRUE,表示需要继承,否则即使前面指定了结构体来表示继承,也无法在子进程中继承到父进程的句柄表
5.SetEvent来修改状态,我们在子进程中接受命令行参数,并将命令行参数赋值给HANDLE类型的事件,来检测是否能WaitForSingleObject到

子进程:

// Part_B.cpp : Defines the entry point for the console application.
//

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

int main(int argc, char* argv[])
{
	TCHAR szBuffer[256]={0};
	memcpy(szBuffer,argv[1],8);
	DWORD Handle=0;
	sscanf(szBuffer,"%x",&Handle);

	printf("%s\n",argv[0]);
	printf("%x\n",Handle);

	HANDLE g_Event=(HANDLE)Handle;
	printf("Lording.......\n");

	WaitForSingleObject(g_Event,-1);

	DWORD Code=GetLastError();

	printf("Waiting successful!\n");

	getchar();


	return 0;
}

注意:我们在创建一个内核对象的时候会有一个计数器,当被使用的时候会+1,当我们CloseHandle的时候,只是计数器-1了,但是已成任然存在,Wai依旧能够等待到

连续两次Close Handle是无效的,因为第一次Close后就将句柄在句柄表当中抹除了,所以第二次关闭是无效的

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值