函数原型:
NTSTATUS
NtCreateProcessEx(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in_opt POBJECT_ATTRIBUTES ObjectAttributes,
__in HANDLE ParentProcess,
__in ULONG Flags,
__in_opt HANDLE SectionHandle,
__in_opt HANDLE DebugPort,
__in_opt HANDLE ExceptionPort,
__in ULONG JobMemberLevel
);
函数主要功能:
函数大致操作分三部分:
1. 创建并初始化进程EPROCESS对象,
2. 创建并初始化进程地址空间,
3. 初始化内核进程块(KPROCESS)
4. 创建进程ID,创建PEB等操作。
函数参数:
ProcessHandle,输出参数,如果创建成功,则它返回所创建的进程的句柄。
DesiredAccess, 新进程的访问权限。
ObjectAttributes,可选参数,指定了新进程的对象属性。
ParentProcess:新进程的父进程句柄。如果这个参数没有设定,即新进程没有父进程,新进程使用系统地址空间创建。
Flags :进程创建的标志。
SectionHandle :内存区域映射句柄,用来创建进程的地址空间,如果这个参数没有设定,新进程的地址空间是一个简单的克隆父进程的地址空间。
DebugPort : 一个端口对象的句柄,被用于进程的调试端口。
ExceptionPort :一个端口对象的句柄,被用于进程的异常端口。
JobMemberLevel :新进程的在 jobset 中的等级。
函数具体分析:
NtCreateProcessEx函数的代码判断调用时状态是否为内核模式,内核模式不需要检查参数,而非内核模式要检查ProcessHandle参数代表的句柄是否可写,然后把真正的创建工作交给PspCreateProcess函数。需要注意的是,在反汇编中检查句柄是否可写的代码,会让人比较疑惑,就是一个相互赋值的语句,看似无用,其实是为了检查其地址是否可写,不是的话触发异常,trycase块捕获异常。具体看代码:
PAGE:005315DA mov eax, large fs:124h ; 得到当前线程 _KTHREAD 结构体的指针 PAGE:005315E0 xor edx, edx PAGE:005315E2 cmp [eax+0D7h], dl ; 比较当前线程之前模式是否为0环,比较_KTHREAD->PreviousMode中的值 PAGE:005315E8 jz short loc_53161F ; 之前运行模式在0环下,跳走 PAGE:005315EA mov [ebp+ms_exc.disabled], edx PAGE:005315ED mov ecx, [ebp+ProcessHandle] ; 取得句柄值地址 PAGE:005315F0 mov eax, _MmUserProbeAddress ; 获得允许的用户空间大小 PAGE:005315F5 cmp ecx, eax ; 比较句柄地址是否超过用户空间大小 PAGE:005315F7 jb short loc_5315FB PAGE:005315F9 mov [eax], edx PAGE:005315FB PAGE:005315FB loc_5315FB: ; CODE XREF: NtCreateProcessEx(x,x,x,x,x,x,x,x,x)+29 j PAGE:005315FB mov eax, [ecx] 检测地址是否可读 PAGE:005315FD mov [ecx], eax ; 检测地址是否可写 PAGE:005315FF or [ebp+ms_exc.disabled], 0FFFFFFFFh
函数的具体具体流程:
1. 首先是一些当前环境的获取,CurrentThread,PreviousMode,CurrentProcess等,
PAGE:005300DB mov eax, large fs:124h ; 得到 _KTHREAD 结构体指针 PAGE:005300E1 mov [ebp+CurrentThread], eax ; 保存到局部变量 CurrentThread 中 PAGE:005300E4 mov cl, [eax+_KTHREAD.___u33._s2.PreviousMode] ; 获得前一种运行模式 PAGE:005300EA mov byte ptr [ebp+PreviousMode], cl PAGE:005300ED mov eax, [eax+_KTHREAD.___u6.ApcState.Process] ; 得到 _KPROCESS 结构体指针 PAGE:005300F0 mov [ebp+CurrentProcess], eax
PAGE:0053010A cmp [ebp+ParentProcess], ebx ; 比较父进程句柄是否为0 PAGE:0053010D jz short loc_530161 PAGE:0053010F push ebx ; HandleInformation PAGE:00530110 lea eax, [ebp+ParentEPROCESS] ; 父进程 PEPROCESS PAGE:00530116 push eax ; Object PAGE:00530117 push [ebp+PreviousMode] ; AccessMode PAGE:0053011A push _PsProcessType ; ObjectType PAGE:00530120 push PROCESS_CREATE_PROCESS ; DesiredAccess PAGE:00530125 push [ebp+ParentProcess] ; Handle PAGE:00530128 call _ObReferenceObjectByHandle@24 ; 根据父进程句柄获取其EPROCESS PAGE:0053016B mov [ebp+Affinity], eax ; 可以运行在父进程job的各个处理器上 PAGE:0053016E mov eax, ds:_PsMinimumWorkingSet ; 设置工作集最小数 PAGE:00530173 mov [ebp+WorkingSetMinimum], eax PAGE:00530176 mov eax, ds:_PsMaximumWorkingSet ; 设置工作集最大数 PAGE:0053017B mov [ebp+WorkingSetMaximum], eax
程的EPROCESS 对象,创建的对象类型是在系统初始时通过ObCreateObjectType创建的。
PAGE:00530181 push eax ; Object PAGE:00530182 push ebx ; NonPagedPoolCharge PAGE:00530183 push ebx ; PagedPoolCharge PAGE:00530184 push 278h ; ObjectBodySize PAGE:00530189 push ebx ; ParseContext PAGE:0053018A push [ebp+PreviousMode] ; OwnershipMode PAGE:0053018D push [ebp+ObjectAttributes] ; ObjectAttributes PAGE:00530190 push _PsProcessType ; ObjectType PAGE:00530196 push [ebp+PreviousMode] ; ProbeMode PAGE:00530199 call _ObCreateObject@36 ; 创建进程 _EPROCESS
RundownProtect,和推锁(push lock)ProcessLock成员,初始化初始化EPROCESS线程链表头。将新进程的配额块设置为其父进程配额块地址,并且递增父进程配额块的引用计数,继承Windows的设备名称空间(包括驱动器字母的定义、COM端口、等等)。
PAGE:005301A8 mov ecx, 9Eh ; <- 设置Process指向的EPROCESS结构为全0 PAGE:005301AD xor eax, eax PAGE:005301AF mov ebx, [ebp+Process] PAGE:005301B2 mov edi, ebx PAGE:005301B4 rep stosd ; - > PAGE:005301B6 and dword ptr [ebx+_EPROCESS.RundownProtect.___u0], eax ; ExInitializeRundownProtection (&Process->RundownProtect); PAGE:005301BC and [ebx+_EPROCESS.ProcessLock.___u0.Value], eax ; PspInitializeProcessLock (Process); PAGE:005301BF lea eax, [ebx+_EPROCESS.ThreadListHead] ; <- 初始化EPROCESS线程链表头 PAGE:005301C5 mov [eax+4], eax PAGE:005301C8 mov [eax], eax ; - > PAGE:005301CA push esi ; ParentProcess PAGE:005301CB push ebx ; NewProcess PAGE:005301CC call _PspInheritQuota@8 ; 继承资源配额 PAGE:005301D1 push esi ; ParentProcess PAGE:005301D2 push ebx ; NewProcess PAGE:005301D3 call _ObInheritDeviceMap@8 ; 继承父进程的设备位图
PAGE:005301DC mov eax, [esi+_EPROCESS.DefaultHardErrorProcessing] PAGE:005301E2 mov [ebx+_EPROCESS.DefaultHardErrorProcessing], eax ; 子进程继承父进程的DefaultHardErrorProcessing PAGE:005301E8 mov eax, [esi+_EPROCESS.UniqueProcessId] PAGE:005301EE mov [ebx+_EPROCESS.InheritedFromUniqueProcessId], eax ; 子进程继承父进程的InheritedFromUniqueProcessId
PAGE:00530211 push 0 ; HandleInformation PAGE:00530213 lea eax, [ebp+SectionObj] PAGE:00530219 push eax ; Object PAGE:0053021A push [ebp+PreviousMode] ; AccessMode PAGE:0053021D push _MmSectionObjectType ; ObjectType PAGE:00530223 push 8 ; DesiredAccess PAGE:00530225 push [ebp+SectionHandle] ; Handle PAGE:00530228 call _ObReferenceObjectByHandle@24 ; PAGE:00530243 mov eax, [ebp+SectionObject] PAGE:00530246 mov [ebx+_EPROCESS.SectionObject], eax
对象中的 DebugPort 域。不存在的话继承父进程的调试端口。
PAGE:0053024C cmp [ebp+DebugPort], 0 ; 调试端口句柄不为空,说明处于调试状态 PAGE:00530250 jz DEBUGPORT_NULL PAGE:00530256 push 0 ; HandleInformation PAGE:00530258 lea eax, [ebp+DebugPortObj] PAGE:0053025B push eax ; Object PAGE:0053025C push [ebp+PreviousMode] ; AccessMode PAGE:0053025F push _DbgkDebugObjectType ; ObjectType PAGE:00530265 push 2 ; DesiredAccess = DEBUG_PROCESS_ASSIGN PAGE:00530267 push [ebp+DebugPort] ; Handle PAGE:0053026A call _ObReferenceObjectByHandle@24 ; 获取调试端口对象 PAGE:0053026F mov edi, eax PAGE:00530271 test edi, edi PAGE:00530273 jl exit_and_deref PAGE:00530279 mov eax, [ebp+DebugPortObj] PAGE:0053027C mov [ebx+_EPROCESS.DebugPort], eax ;初始化新进程调试端口
对象中的 ExceptionPort域。
PAGE:00530297 cmp [ebp+ExceptionPort], 0 ; 异常端口不为空获取异常端口对象 PAGE:0053029B jz short EXCEPTIONPORT_NULL PAGE:0053029D push 0 ; HandleInformation PAGE:0053029F lea eax, [ebp+ExceptionPortObject] PAGE:005302A2 push eax ; Object PAGE:005302A3 push [ebp+PreviousMode] ; AccessMode PAGE:005302A6 push _LpcPortObjectType ; ObjectType PAGE:005302AC push 0 ; DesiredAccess PAGE:005302AE push [ebp+ExceptionPort] ; Handle PAGE:005302B1 call _ObReferenceObjectByHandle@24 ; 获取异常端口对象 PAGE:005302B6 mov edi, eax PAGE:005302B8 test edi, edi PAGE:005302BA jl exit_and_deref PAGE:005302C0 mov eax, [ebp+ExceptionPortObject] PAGE:005302C3 mov [ebx+_EPROCESS.ExceptionPort], eax
PAGE:005302DE lea eax, [ebp+DirectoryTableBase] PAGE:005302E1 push eax ; DirectoryTableBase PAGE:005302E2 push ebx ; NewProcess PAGE:005302E3 push [ebp+WorkingSetMinimum] ; MinimumWorkingSetSize PAGE:005302E6 call _MmCreateProcessAddressSpace@12 ;
PAGE:005303CE push eax ; Enable PAGE:005303CF lea eax, [ebp+DirectoryTableBase] PAGE:005303D2 push eax ; DirectoryTableBase PAGE:005303D3 push [ebp+Affinity] ; Affinity PAGE:005303D6 push 8 ; BasePriority = NORMAL_BASE_PRIORITY PAGE:005303D8 push ebx ; Process PAGE:005303D9 call _KeInitializeProcess@20 ; 初始化进程EPROCESS结构
PAGE:005303DE push ebx ; Child PAGE:005303DF push esi ; Parent PAGE:005303E0 call _PspInitializeProcessSecurity@8 ; 继承父进程的安全属性
PAGE:0053040F PriorityClass__Idle: PAGE:0053040F mov [eax], cl PAGE:00530411 PAGE:00530411 PriorityClass__No_Normal: PAGE:00530411 ; CODE XREF: PspCreateProcess(x,x,x,x,x,x,x,x,x)+341 j PAGE:00530411 push ebx ; NewProcess PAGE:00530412 mov eax, [ebp+Flags] PAGE:00530415 and al, 4 ; PROCESS_CREATE_FLAGS_INHERIT_HANDLES PAGE:00530417 neg al PAGE:00530419 sbb eax, eax PAGE:0053041B and eax, edx PAGE:0053041D push eax ; ParentProcess PAGE:0053041E call _ObInitProcess@8 ; 初始化进程对象表
1. Boot Process,系统引导时调用,无父进程。
2. System Process,系统进程的初始化,无父进程,无文件区域对象。
3. User Process (Cloned Address Space),根据父进程克隆地址空间。
4. User Process (New Image Address Space),根据指定文件区域对象映射地址空间
此函数的功能:
1. 初始化新进程 EPROCESS对象有关变量
2. 对新进程的可执行映像文件在地址空间的映射,或者在拷贝父进程地址空间。
PAGE:0053043F lea eax, [ebx+_EPROCESS.SeAuditProcessCreationInfo] PAGE:00530445 push eax ; AuditName PAGE:00530446 lea eax, [ebp+Flags] PAGE:00530449 push eax ; CreateFlags PAGE:0053044A push [ebp+SectionObject] ; SectionToMap PAGE:0053044D push esi ; ProcessToClone PAGE:0053044E push ebx ; ProcessToInitialize PAGE:0053044F call _MmInitializeProcessAddressSpace@20 ;
PAGE:00530511 mov dword ptr [ebp+CidEntry.___u0], ebx PAGE:00530514 and dword ptr [ebp+CidEntry.___u1], 0 PAGE:00530518 lea eax, [ebp+CidEntry] PAGE:0053051B push eax ; HandleTableEntry PAGE:0053051C push _PspCidTable ; HandleTable PAGE:00530522 call _ExCreateHandle@8 ; 创建进程ID PAGE:00530527 mov [ebx+_EPROCESS.UniqueProcessId], eax
PAGE:00530649 xor eax, eax ; <- 初始化PEB结构体 PAGE:0053064B lea edi, [ebp+InitialPeb] PAGE:0053064E stosd ; - > PAGE:0053064F or [ebp+InitialPeb.Mutant], -1 PAGE:00530653 mov al, [ebp+InitialPeb.BitField] PAGE:00530656 xor al, [ebp+UseLargePages] PAGE:00530659 and al, 1 PAGE:0053065B xor [ebp+InitialPeb.BitField], al PAGE:0053065E cmp [ebp+SectionHandle], 0 PAGE:00530662 jz short loc_530687 PAGE:00530664 lea eax, [ebx+_EPROCESS.Peb] PAGE:0053066A push eax ; Base PAGE:0053066B lea eax, [ebp+InitialPeb] PAGE:0053066E push eax ; InitialPeb PAGE:0053066F push ebx ; TargetProcess PAGE:00530670 call _MmCreatePeb@12 ; 初始化PEB结构
PAGE:005306E7 lea eax, [ebx+_EPROCESS.ActiveProcessLinks] ; 添加EPROCESS到全局EPROCESS链表中 PAGE:005306ED mov ecx, dword_4A5EC4 PAGE:005306F3 mov dword ptr [eax], offset _PsActiveProcessHead PAGE:005306F9 mov [eax+4], ecx PAGE:005306FC mov [ecx], eax
PAGE:005307A7 lea eax, [ebp+LocalProcessHandle] PAGE:005307AA push eax ; Handle PAGE:005307AB push 0 ; NewObject PAGE:005307AD push 1 ; ObjectPointerBias PAGE:005307AF push [ebp+DesiredAccess] ; DesiredAccess PAGE:005307B2 push [ebp+AccessState] ; AccessState PAGE:005307B5 push ebx ; Object PAGE:005307B6 call _ObInsertObject@24 ; 在当前进程句柄表中插入对象
PAGE:005307D6 lea eax, [ebp+QuantumReset] PAGE:005307D9 push eax ; QuantumReset PAGE:005307DA push 0 ; PriorityMode PAGE:005307DC push ebx ; Process PAGE:005307DD call _PspComputeQuantumAndPriority@12 ;
到此,函数返回。
注: 因本人水平有限,加上时间仓促,难免存在错误与纰漏之处,恳请各位高手给予指正!