使用Native API 创建进程
使用 Native API 创建进程
最近几个星期一直在研究这个题目。因为关于方面的资料比较多(可以看下面的参考文章),所以开始时以为很快就结束了。谁知道真正动起手来才发现有很多要考虑的地方,不过还好今天终于成功了,还是很高兴的。写下来,做个小结吧。(纸上得来终觉浅 , 须知此事要躬行。)
我们一般是使用 CreateProcess 来创建进程的,而使用 Native API 来创建进程其实说白了就是模拟 CreateProcess 的实现。一开始我以为 CreateProcess 就是调用 NtCreateProcess 的(毕竟和 CreateProcess 名称一样嘛),但是读了许多文章后才知道NtCreateProcess 只是完成了 CreateProcess 一小部分工作。 CreateProcess 是由下面几个步骤完成的:
1. 使用 ZwOpenFile 打开文件,创建映射 ZwCreateSection.
本步骤打开文件,并创建一个属性为 SEC_IMAGE 的 SECTION 对象。
2. 调用 ZwCreateProcess
本步骤主要是创建进程的 PEB 、 EPROCESS 、 VAD 等核心内核结构。
3. 创建堆栈、 CONTEXT 、进程参数等,并创建主线程 ZwCreateThread(SUSPEND)
尽管 ZwCreateProcess 创建了进程对象,但是并没有同时创建一个主线程。主线程需要调用函数 ZwCreateThread 来创建,这个过程同时会建立堆栈、 CONTEXT 、进程的参数等等。有点要注意的是:创建的进程 CreateSuspended 为 TRUE ,于是线程创建后是不能立即执行的。
1) 堆栈的创建
一般情况我们都会从可执行文件( PE )文件头中取出需要堆栈的大小,这个大小是在程序编译的时候指定的。
我们将需要堆栈的结构放到一个 INITIAL_TEB 结构中:
|
typedef struct _INITIAL_TEB{ PVOID OldStabckBase; PVOID OldStackLimit; PVOID StackBase; PVOID StackLimit; PVOID StackAllocationBase; }INITIAL_TEB, *PINITIAL_TEB; |
分配堆栈内存后,将地址填入上面的结构中,下面是堆栈的结构 :
2) 进程参数
我们使用 RtlCreateProcessParameters 来建立一个数据结构:
|
ULONG NTSYSAPI WINAPI RtlCreateProcessParameters( OUT PRTL_USER_PROCESS_PARAMETERS *pProcessParameters, IN PUNICODE_STRING ImagePathName, IN PUNICODE_STRING DllPath OPTIONAL, IN PUNICODE_STRING CurrentDirectory OPTIONAL, IN PUNICODE_STRING CommandLine OPTIONAL, IN PVOID Environment OPTIONAL, IN PUNICODE_STRING WindowTitle OPTIONAL, IN PUNICODE_STRING DesktopInfo OPTIONAL, IN PUNICODE_STRING ShellInfo OPTIONAL, IN PUNICODE_STRING RuntimeData OPTIONAL ); |
结构如下:
|
typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; ULONG Length; ULONG Flags; ULONG DebugFlags; HANDLE ConsoleHandle; ULONG ConsoleFlags; HANDLE StandardInput; HANDLE StandardOutput; HANDLE StandardError; CURDIR CurrentDirectory; // ProcessParameters UNICODE_STRING DllPath; // ProcessParameters UNICODE_STRING ImagePathName; // ProcessParameters UNICODE_STRING CommandLine; // ProcessParameters PVOID Environment; // NtAllocateVirtualMemory ULONG StartingX; ULONG StartingY; ULONG CountX; ULONG CountY; ULONG CountCharsX; ULONG CountCharsY; ULONG FillAttribute; ULONG WindowFlags; ULONG ShowWindowFlags; UNICODE_STRING WindowTitle; // ProcessParameters UNICODE_STRING DesktopInfo; // ProcessParameters UNICODE_STRING ShellInfo; // ProcessParameters UNICODE_STRING RuntimeData; // ProcessParameters RTL_DRIVE_LETTER_CURDIR CurrentDirectores[ RTL_MAX_DRIVE_LETTERS ]; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; |
调用这个函数后返回一个当前进程(非新建的进程)的内存块,该内存中除了上面的这个结构还包括该结构中指针成员所指向的内容。只有一个成员除外: Environment 。函数仅仅将参数拷贝进这个指针成员中,并没有分配其他空间。所以你需要在新建进程中调用 ZwAllocateVirtualMemory 分配 Environment 内容的内存空间,然后调用 ZwWriteVirtualMemory 写进去,并将内存空间更新到 Environment 成员。
由于函数返回的内存空间是在当前进程中,所以下面需要调用 ZwAllocateVirtualMemory 分配一块内存空间,并调用 ZwWriteVirtualMemory 将函数的返回空间拷贝进去,最后还得调用 RtlDestroyProcessParameters 来清除内存空间。
4. 通知 Csrss.exe
每个新创建的进程都需要通知 Csrss.exe 子系统。使用的参数结构如下:
5. 调用 ZwResumeThread 恢复线程的执行。
上面的一切都完成了,就可以调用 ZwResumeThread 恢复线程的执行了。
代码下载:
http://download.csdn.net/detail/swanabin/6582277
参考文章:
1. 利用 Native API 创建进程 , 炉子 [0GiNr], < 黑客防线 >2008.12
2. CreateProcess 进程创建的内核跟踪分析 ,gz1X
3. gloomy ——研究 CreateProcess
4. 浅谈 CreateProcess
5. Windows NT/2000 本机 API 参考手册
6. 一段 CreateProcess 的强悍代码
7. Window via C/C++ 第四章 Process
8. Microsoft windows Internals, Fourth Edition (深入解析 Windows 操作系统 第 4 版) , Chapter 6.
使用Native API 创建进程的更多相关文章
- Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)
文章目录: 1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Ap ...
- 用Windows Native API枚举所有句柄及查找文件句柄对应文件名的方法
枚举所有句柄的方法 由于windows并没有给出枚举所有句柄所用到的API,和进程所拥有的句柄相关的只有GetProcessHandleCount这个函数,然而这个函数只能获取到和进程相关的句柄数,不 ...
- 从创建进程到进入main函数,发生了什么?
前几天,读者群里有小伙伴提问:从进程创建后,到底是怎么进入我写的main函数的? 今天这篇文章就来聊聊这个话题. 首先先划定一下这个问题的讨论范围:C/C++语言 这篇文章主要讨论的是操作系统层面上对 ...
- android,JNI创建进程,使用fork()
long add(long x,long y) { pid_t fpid; //fpid表示fork函数返回的值 int count=0; fpid=fork(); if (fpid < 0) ...
- Java中如何创建进程(转)
在Java中,可以通过两种方式来创建进程,总共涉及到5个主要的类. 第一种方式是通过Runtime.exec()方法来创建一个进程,第二种方法是通过ProcessBuilder的start方法来创建进 ...
- 使用hbase的api创建表时出现的异常
/usr/lib/jvm/java-7-openjdk-amd64/bin/java -Didea.launcher.port=7538 -Didea.launcher.bin.path=/usr/l ...
- Java并发编程:如何创建进程?
转载自:http://www.cnblogs.com/dolphin0520/p/3913517.html 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程 ...
- Java 多线程详解(二)------如何创建进程和线程
Java 多线程详解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html 在上一篇博客中,我们已经介绍了并发和并行的区别,以及进程和 ...
- 关于Windows创建进程的过程
之前有听到别人的面试题是问系统创建进程的具体过程是什么,首先想到的是CreateProcess,但是对于具体过程却不是很清楚,今天整理一下. 从操作系统的角度来说 创建进程步骤: 1.申 ...
随机推荐
- 《转》python基础下
转自http://www.cnblogs.com/BeginMan/archive/2013/04/12/3016323.html 一.数字 在看<Python 核心编程>的时候,我就有点 ...
- 增量+全量备份SVN服务器
#!/bin/bash # 获取当前是星期几 DAY=$(date +%w) # 获取当前的日期 DATE=$(date '+%Y-%m-%d-%H-%M') # 获取当前版本库中最新的版本 CURR ...
- 现代软件工程HW2:结对编程-生成五则运算式-Core10组 [PB16110698+PB16120162]
作业具体要求点 这里 Core组要求: 1.Calc() 这个Calc 函数接受字符串的输入(字符串里就是算术表达式,例如 “5*3.5”,“7/8 - 3/8 ”,“3 + 90 * 0.3”等等) ...
- .net Core开源框架NetModular记录
NetModular 源码: https://github.com/iamoldli/NetModular 文档: https://nm.iamoldli.com/docs/guide/
- C#学习笔记----反射基础
反射基础 反射用于在程序运行过程中,获取类里面的信息或发现程序集并运行的一个过程.通过反射可以获得.dll和.exe后缀的程序集里面的信息.使用反射可以看到一个程序集内部的类,接口,字段,属性,方法, ...
- stelller插件与background-attachment配合使用,制作滚动页面
stelller插件与background-attachment:fixed配合使用,制作滚动页面
- [JZOJ1901] 【2010集训队出题】光棱坦克
题目 题目大意 给你个平面上的一堆点,问序列\({p_i}\)的个数. 满足\(y_{p_{i-1}}>y_{p_i}\)并且\(x_{p_i}\)在\(x_{p_i-1}\)和\(x_{p_i ...
- Windows 获取控制台窗口句柄
详细信息 因为多个窗口可能具有相同的标题,您应该更改当前的控制台窗口标题为唯一的标题.这将有助于防止返回不正确的窗口句柄.使用 SetConsoleTitle() 来更改当前的控制台窗口标题.下面是此 ...
- 0926CSP-S模拟测试赛后总结
又一次垫底.持续低迷.20分. 赛时状态还可以.但是过于保守而不思进取.三道题目打了暴力就滚粗了. 暴力还挂掉了. T1暴力因为开小了数组挂成了0.1000的点,子序列个数我开了1e5以为足够了.结果 ...
- vue语法糖
加冒号,就是个语法糖 两点: 例如 export default { data(){ return { item: { src: 'xxxxx' } } } } <img :src='item ...