CreateProcess

CreateProcessWindows进程创建完整过程(除去细节)当前流程是分析WinXPx86得到的,在最新版本Windows上不一定正确,但是可以做一个参考,由于我这里符号并不全,所以导致我这里有些东西看到的可能是错误的,误导了我,然后我就做了个错误的记录,有缘人如果看到的话,可以帮我指正一下,我会很高兴。

大家好,欢迎来到IT知识分享网。

Windows 进程创建完整过程(除去细节)

当前流程是分析WinXP x86得到的,在最新版本Windows上不一定正确,但是可以做一个参考,

由于我这里符号并不全,所以导致我这里有些东西看到的可能是错误的,误导了我,然后我就做了个错误的记录,

有缘人如果看到的话,可以帮我指正一下,我会很高兴。

工作挺忙的,三天的业余时间,哎,个人水平问题吧,还是没有办法详细地分析出完整套路,算是个简要分析吧。

 

差点忘记了,我这里分析的文件是 kernel32.dll 和 ntoskrnl.exe

 

 

1:入口  CreateProcessW

当我们在应用层调用CreateProcessW的时候,参数稍作整理,会直接调用到 CreateProcessInternalW

CreateProcess

(CreateProcessA,会调用 CreateProcessInternalA,然后整理了参数也会调用到CreateProcessInternalW)

 

 

2:CreateProcessInternalW

首先,开场是大概是2000来行的汇编指令,判断进程创建参数,以及文件安全属性等等乱七八糟没用的,

 

然后是 NtOpenFile NtCreateSection 一系列的函数,获取文件句柄和section句柄

CreateProcess

CreateProcess

 

中间经过一系列的文件类型判断,有效性判断,及属性判断,

 

调用 NtQuerySection 获取段属性,

CreateProcess

 

判断是否需要Debug方式启动,并且做对应的设置,

CreateProcess

 

加载 advapi32.dll ,然后获取 CreateProcessAsUserSecure 函数地址,但是并没有使用它,

CreateProcess

CreateProcess

 

很可能是根据这个函数是否存在,来判断当前操作系统版本,后面直接调用 NtQuerySystemInformation 来获取操作系统信息,参数很奇怪,0x47,可能就是特殊的情况,

CreateProcess

(有空再看)

 

中间判断了一个位,然后调用了DBG相关的函数,(可能是判断DBG相关吧)

CreateProcess

 

最后就是一个Nt函数,NtCreateProcessEx,进入内核了,(也可能是个Zw函数)

CreateProcess

 

 

3:NtCreateProcessEx

上一部分,调用ntdll 的ZwCreateProcessEx/NtCreateProcessEx 之后,

进入内核,走SSDT表,第48项,进入NtCreateProcessEx,

CreateProcess

 

判断当前执行模式,内核模式的话,就往下走,否则,改了模式往下走

调用PspCreateProcessEx,

CreateProcess

 

1)获取父进程信息,

CreateProcess

并且继承父进程的执行位置

 

2)给子进程创建一个EPROCESS,然后初步设置它

CreateProcess

 

3)初始化子进程的线程列表

CreateProcess

 

4)增加引用计数,并且继承父进程的QuotaBlock,如果父进程存在的话,否则用系统默认的

CreateProcess

 

5)继承父进程的DeviceMap,如果有父进程,否则用系统默认的

CreateProcess

 

6)如果父进程存在,那么再继承父进程的属性

CreateProcess

 

7)如果参数Section句柄存在,那么就获取对象,并且保存,后面需要用,保存到进程中

CreateProcess

这个Section,实际上是上面应用层CreateProcessInternalW函数创建的那个Section

 

8)如果Debug端口存在,那么就获取它的对象,如果不存在,则从父进程继承

CreateProcess

上面的第一个jnz跳转到下面,下面的最后一个jmp回到上面的cmp处

CreateProcess

 

9)初始化PrimaryToken

CreateProcess

 

10)中间继续初始化各种乱七八糟东西,包括

初始化进程地址空间

CreateProcess

如果当前进程EProcess不存在,就用另外一种方法,初始化进程空间

CreateProcess

PCB

CreateProcess

优先级组,因为后面直接就用EPROCESS了,所以我推断这里可能同时也初始化了EPROCESS剩下的部分

CreateProcess

 

11)如果 section存在,那么attach到子进程,

在很深的位置先循环调用了N次 MiMapViewOfPhysicalSection 函数来映射物理内存地址,然后

初始化section,根据section展开文件到子进程

CreateProcess

这里有else,但是一般来说,不会走到else里面,因为如果是有效PE,那么section肯定存在,这是应用层已经找到的,然后转化成的内核对象,

然后向自己内部再影射一个子进程模块的内存,映射了之后,就释放掉,只是判断是否成功,如果成功,什么都不干,不成功就返回到label_48

(走到else里面也是同样的操作,只不过目标section不存在,那么就只能映射自己的)

 

///中间有一块这段代码,个人能力问题,无法看出这里是做什么的,因为结构体识别可能是有一定的问题

CreateProcess

/// 

 

12)初始化PEB

PEB

CreateProcess

实际上这里有点问题,v74在前面的时候,是必须 hSection 存在的时候,才会 ==1,也就是说必须hSection存在,才会进入外层if

但是外层if进入了之后,反过来说,就是hSection肯定存在,肯定不会走else,但是为什么它这么写

 

13)初始化APC?不知道是否真的是这样,但是清理APC的功能,这里是第一次使用

CreateProcess

然后判断APC对列里面有没有APC,如果有的话,触发一个软中断,去运行它

 

14)做一个 AccessState ,然后使用它把子进程EPROCESS放到进程句柄表中,返回一个句柄

CreateProcess

然后AccessState就没用了,释放掉

最后设置一下进程优先级组

 

15)接近尾声,这里获取当前进程允许的访问权限位

CreateProcess

 

16)收尾

CreateProcess

设置进程创建时间,然后返回进程句柄,减掉自己的引用计数,防止泄露

 

 

4:CreateProcessInternalW,回到应用层了

CreateProcess

沿着第二部分的NtCreateProcessEx继续来看,这里已经回到应用层了,

继续往下,并且这里拿到了一个 新进程的句柄,也就是第一个参数

 

一大片代码,设置进程优先级和处理模式相关

NtSetInformationProcess

NtAllocateVirtualMemory

申请了一块内存,然后好像也没用过,

创建命令行参数,

初始化stdin stdout stderr

BasePushProcessParameters

就是直接dup出来,然后给对面进程用

CreateProcess

给目标进程创建一个栈

CreateProcess

给线程构建上下文

CreateProcess

然后,主线程就可以跑了

CreateProcess

(上下文构建中,其实有个小细节)

其实在 BaseInitializeContext 函数中,根据第五个参数,会判断走哪个启动函数

CreateProcess

如上,进程启动,最后一个参数,写死为0,则会走最下面的 BaseProcessStartThunk 函数

而 BaseProcessStartThunk 内部还调用了。。。

CreateProcess

再往里看,就是这样

CreateProcess

通过对比另外两个函数,可以推断,这里应该就是走主线程 _tmainCRTStartup / wWinMainCRTStartup 位置的了

 

 

5:NtCreateThread 开始主线程部分

应用层陷入内核,走SSDT,到了驱动里面的NtCreateThread,

进来还是模式校验,

然后走

CreateProcess

 

1)获取进程对象

CreateProcess

 

2)创建ETHREAD

CreateProcess

 

3)在进程句柄表中创建线程的handle

CreateProcess

 

4)创建TEB

CreateProcess

初始化TEB

 

5)中间使用了超级大篇幅来初始化这个ETHREAD

CreateProcess

初始化了之后,这一块,就是准备开跑了,

进程的活动线程数++,然后插入列表,然后启动线程,

CreateProcess

 

6)直到这里,这里是进程创建回调,注意哦,这里是在父进程里面调用的

CreateProcess

 

7)判断作业是否在工作,所在进程是否在作业中,如果在的话,特殊处理,让他去完成,并且清理APC

CreateProcess

 

8)压轴戏,线程创建回调

CreateProcess

 

9)两个回调结束之后,似乎就没什么好做得了,把线程对象插入句柄表

这里的插入和前面的创建不是一个东西,那个ExCreateHandle 是创建全局句柄表,

这里是插入进程句柄表

CreateProcess

 

10)后面就是枯燥乏味的收尾工作

写时间戳,写访问权限,解对象引用,

再清理一次APC,

然后把线程句柄返回,

 

11)补充一下吧

正常结束时,这里实际上是有个收尾的小工作的,

CreateProcess

这里面KeReadyThread 是关键操作,它把 ETHREAD 放到了进程 KPROCESS 的 ReadyListHead 里面,

这样应该就可以swapcontext了,

其实它内部还有众多关键函数,如 KiSetSwapEvent ,看名字和内部实现,似乎就是抢抢占时间片去了。

 

我所关心的整个部分,实际上就是,

进程、线程创建回调的触发时机,实际上触发的进程上下文都在父进程中,触发时机都在PspCreateThread中,

因为实际工作中,我们能用到的部分,也就这里了

 

 

6:回到应用层

这里直接判断返回值,有问题的话,直接错误返回,

没有问题的情况下,那么继续往下做判断

 

1)通知Csrss

CreateProcess

由于我这里符号不全,我想下面的ExitStatus 应该是 Csrss返回的吧。

一旦有问题,立刻退出

 

2)指派进程到一个作业中

CreateProcess

 

3)后面直到最后,通篇都是整理内存,释放空间了,

基本上就没有干别的活,

最后才是函数返回。

 

这样,整体流程结束。

 

 

补充一下,镜像加载回调的位置吧,

这个,实际上,镜像加载回调被调用的时候,已经和镜像没什么关系了,

而且镜像早早已经被铺到内存中了

在InitThread之前,是初始化TEB部分,这里初始化了TEB之后,设置了一个回调函数

创建应用层线程PspUserThreadStartup

进入这个函数里面,可以看到

CreateProcess

有这样一个判断,由于我实在没有找到那个6代表什么,可能是2|4,但是我没找到,所以无法知道它是什么,

进入函数之后,里面会进行一次镜像加载回调状态的判断,如果非隐藏状态,那么再经过一个函数,

CreateProcess

就会到这里,联系外面的函数,可以清晰地看出,这里就是镜像加载回调的调用位置,

总地来说,由于镜像加载回调有可能是异步调用的,所以无法确切地知道它的位置,

但是它的位置实际上是在前两个回调之后的(其实已知,这些都是废话)

 

 

 

重点:

在CreateProcess 函数中,会开辟子进程的进程空间,

然后同时会map子进程的主模块到进程空间中,这时不会调用镜像加载回调和进程创建回调,

到了CreateThread 里面,整理了线程各种信息之后,

会先调用进程创建回调,

然后调用线程创建回调,

这时,当前进程上下文还是在父进程中,

最后,当线程跑起来之后,

第一个回调会被触发,就是主模块的镜像加载回调,

这时剩下的就是其他模块的镜像加载回调了,

后面就不是很重要了,前面这个流程应该是最重要的。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30821.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信