零基础逆向工程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);        

//获取入口点
DWORD dwEntryPoint = contx.Eax;     

//获取ImageBase
char* baseAddress = (CHAR *) contx.Ebx+8;       

memset(szBuffer,0,256);     

ReadProcessMemory(ie_pi.hProcess,baseAddress,szBuffer,4,NULL);      

ResumeThread(ie_pi.hThread);        
时间: 2024-10-12 00:17:47

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

sql面试题(学生表_课程表_成绩表_教师表)

sql面试题(学生表_课程表_成绩表_教师表) 原帖链接:http://bbs.csdn.net/topics/280002741 表架构 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 建表语句 CREATE TABLE student ( s# INT, sname nvarchar(32), sage INT, ssex nvarchar(8)

零基础逆向工程40_Win32_14_枚举窗口_模拟鼠标键盘

1 查找窗口 1.1 代码案例 //查找指定窗口 TCHAR szTitle[MAX_PATH] = {0}; HWND hwnd = ::FindWindow(TEXT("#32770"),TEXT("飞鸽传书 IP Messenger")); if(hwnd != NULL) { //修改窗口标题 ::SetWindowText(hwnd,"新的窗口标题"); } else { ::MessageBox(NULL,TEXT("窗口没

零基础逆向工程34_Win32_08_线程控制_CONTEXT结构

线程控制 实验 挂起线程 ::SuspendThread(hThread); 恢复线程 ::ResumeThread(hThread); 终止线程 (这里讲了同步调用与异步调用) 方式一: 此方法结束线程会自动清理堆栈 ::ExitThread(DWORD dwExitCode); 方式二: 线程函数返回 方式三: 而此方法结束线程不会自动清理堆栈 ::TerminateThread(hThread,2); ::WaitForSingleObject(hThread,INFINITE); 判断线

网易云课堂_艾叔:零基础一站式C语言|C程序设计精讲_章节12:指针_课时63指针操作数组

二维数组 #include <stdio.h> #include <stdlib.h> int main() { int age[2][4] = { 1,2,3,4,5,6,7,8 }; int* p = &(age[0][0]); int i = 0; int j = 0; for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { printf("age[%d][%d] %p %d\n", i,

菜鸟零基础学习HTML5 &nbsp; ----- 1.5、HTML5表单和PHP环境搭建

一.HTML5表单 1.表单用于获取不同类型的用户输入 2.常用表单标签 例: <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>表单</title> </head> <body>     <form>         用户名:         <i

salesforce零基础学习(七十一)级联表DML操作

曾经做项目没有考虑那么多,对于级联表操作都是正常的一步一步操作,没有考虑过失败情况,最近项目遇见了失败的情况,导致碰到了相应的情况,特此mark一下,免得后期继续踩坑. 需求如下:新建页面,页面中包含1.新建企业,2.新建联系人,3.新建机会.任何一步的逻辑或者DML操作失败都会导致整体的回滚.只有当三步都正常插入成功了以后才会跳转到新生成的机会的标准页面. 1.NewOpportunityController:这里做了一个逻辑判断,当联系人为空情况下,不允许新建联系人.当然,现实场景不会在这里

salesforce 零基础学习(三十二)通过Streams和DOM方式读写XML

有的时候我们需要对XML进行读写操作,常用的XML操作主要有Streams和DOM方式. 一.Streams方式 Streams常用到的类主要有两个XmlStreamReader 以及XmlStreamWriter. XmlStreamReader:此种读取方式的读的特点为从上而下读,下图是根据reader的EventType自上而下的运行步骤. 我们将此xml读取后封装到一个Goods的List中,Goods包括item,name以及type属性,代码如下: /* * 假定目前XML数据样式为

数据结构_线性表_链表实现

之前已经完全忘了指针怎么用了.复习了一下,目前只写了一点点. #include<iostream> #include<cstdio> #include<malloc.h> using namespace std; struct Node { int e; double c; Node* next; }; struct Head { int cnt; Node* elem; }; Head* inilHead() { Head *head; head=(Head*)mal

SQL常见面试题(学生表_课程表_成绩表_教师表)

表架构 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 建表语句 CREATE TABLE student ( s# INT, sname nvarchar(32), sage INT, ssex nvarchar(8) ) CREATE TABLE course ( c# INT, cname nvarchar(32), t# INT ) CREA