零基础逆向工程39_Win32_13_进程创建_句柄表_挂起方式创建进程

1 进程的创建过程

打开系统 --> 双击要运行的程序 --> EXE开始执行

步骤一:
当系统启动后,创建一个进程:Explorer.exe(也就是桌面进程)

步骤二:
当用户双击某一个EXE时,Explorer 进程使用CreateProcess函数创建被双击的EXE,也就是说,我们在桌面上双

击创建的进程都是Explorer进程的子进程.

CreateProcess

BOOL CreateProcess(
  LPCTSTR lpApplicationName,                 // name of executable module
  LPTSTR lpCommandLine,                      // command line string
  LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // SD
  BOOL bInheritHandles,                      // handle inheritance option
  DWORD dwCreationFlags,                     // creation flags
  LPVOID lpEnvironment,                      // new environment block
  LPCTSTR lpCurrentDirectory,                // current directory name
  LPSTARTUPINFO lpStartupInfo,               // startup information
  LPPROCESS_INFORMATION lpProcessInformation // process information
);

1 创建内核对象

2 分配4GB的虚拟空间(Windows 32位)

3 创建进程的主线程

当进程的空间创建完毕,EXE与导入表中的DLL都正确加载完毕后,会创建一个线程。

当线程得到CPU的时候,程序就正开始指向了,EIP的初始值设定为:ImageBase+OEP。

HANDLE CreateThread(
   PSECURITY_ATTRIBUTES psa,
   DWORD cbStack,
   PTHREAD_START_ROUTINE pfnStartAddr,
   PVOID pvParam,
   DWORD fdwCreate,
   PDWORD pdwThreadID);

当进程创建成功后,会将进程句柄、主线程句柄、进程ID以及主线程ID存储在下面结构中:

typedef struct _PROCESS_INFORMATION
{
   HANDLE hProcess;				//进程句柄
   HANDLE hThread;				//主线程句柄
   DWORD dwProcessId;				//进程ID
   DWORD dwThreadId;				//线程ID
} PROCESS_INFORMATION;

也就是,CreateProcess的最后一个 OUT 参数

到此,整个进程创建结束了.

关于句柄和ID

1、都是系统分配的一个编号,句柄是客户程序使用 ID主要是系统调度时使用.
2、调用CloseHandle关闭进程或者线程句柄的时候,只是让内核计数器减少一个,并不是终止进程或者线程.进程或线程将继续运行,直到它自己终止运行。
3、进程ID与线程ID 是不可能相同。但不要通过进程或者线程的ID来操作进程或者线程,因为,这个编号是会重复使用的,也就是说,当你通过ID=100这个编号去访问一个进程的时候,它已经结束了,而且系统将这个编号赋给了另外一个进程或者线程.

2 进程终止

2.1 进程终止的三种方式:

VOID ExitProcess(UINT fuExitCode)							//进程自己调用
BOOL TerminateProcess(HANDLE hProcess, UINT fuExitCode);	//终止其他进程
ExitThread													//终止进程中的所有线程,进程也会终止

2.2 获取进程的退出码:

BOOL GetExitCodeProcess(HANDLE hProcess,PDWORD pdwExitCode);

进程终止时相关操作:
1、进程中剩余的所有线程全部终止运行
2、进程指定的所有用户对象均被释放,所有内核对象均被关闭
3、进程内核对象的状态变成收到通知的状态
4、进程内核对象的使用计数递减1

3 句柄的继承

3.1 命令行参数的使用

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);
getchar();

3.2 句柄的继承

进程A中的代码:

char szBuffer[256] = {0};
char szHandle[8] = {0};
//若要创建能继承的句柄,父进程必须指定一个SECURITY_ATTRIBUTES结构并对它进行初始化
//三个成员的意义:大小、默认安全属性、是否可以继承
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:/z2.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);

//设置事件为已通知
SetEvent(g_hEvent);

//关闭句柄 内核对象是否会被销毁?
CloseHandle(g_hEvent);

进程B中的代码:

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();

4 以挂起方式创建进程

4.1 以挂起的方式创建进程,观察创建后的结果

STARTUPINFO ie_si = {0};   	
PROCESS_INFORMATION ie_pi;	
ie_si.cb = sizeof(ie_si);	
	
TCHAR szBuffer[256] = "C:\\notepad.exe";	
CreateProcess(	
	NULL,                  
	szBuffer,                
	NULL, 
	NULL,  
	FALSE,                   
	CREATE_SUSPENDED,     
	NULL,                    
	NULL,                    
	&ie_si,                  
	&ie_pi                  
	);

//恢复执行
ResumeThread(ie_pi.hThread);

4.2 以挂起的方式创建进程,获取进程的ImageBase和AddressOfEntryPoint

STARTUPINFO ie_si = {0};   		
PROCESS_INFORMATION ie_pi;		
ie_si.cb = sizeof(ie_si);		
		
//以挂起的方式创建进程		
TCHAR szBuffer[256] = "C:\\ipmsg.exe";		
CreateProcess(		
	NULL,                    // name of executable module	
	szBuffer,                // command line string	
	NULL, 	
	NULL,  	
	FALSE,                   // handle inheritance option	
	CREATE_SUSPENDED,     	 // creation flags  
	NULL,                    // new environment block	
	NULL,                    // current directory name	
	&ie_si,                  // startup information	
	&ie_pi                   // process information	
	);	

//获取外壳程序的入口点
CONTEXT contx;  		
contx.ContextFlags = CONTEXT_FULL;  		
		
GetThreadContext(ie_pi.hThread, &contx);  //将ipmsg.exe的线程句柄写到contx中
		
//获取入口点		
DWORD dwEntryPoint = contx.Eax;		
		
//获取ImageBase		
char* baseAddress = (CHAR *) contx.Ebx+8;		
		
memset(szBuffer,0,256);		
		
ReadProcessMemory(ie_pi.hProcess,baseAddress,szBuffer,4,NULL);	 //参数:要读的进程,从哪里开始读,存放到哪里,大小是多少,[out]真正读了多少个字节
		
ResumeThread(ie_pi.hThread);		
posted @ 2017-11-24 19:51  flatcc  阅读(476)  评论(0编辑  收藏  举报