看流星社区

 找回密码
 注册账号
查看: 1921|回复: 0

使用 Native API 创建进程

[复制链接]

该用户从未签到

发表于 2017-6-1 14:50:17 | 显示全部楼层 |阅读模式
使用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;
ULONGConsoleFlags;
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/source/1585086



参考文章:
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.
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-19 12:26

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表