Windows内核--CreateProcess到内核NtCreateProcess(2.3)

CreateProcessA vs CreateProcessW

        A和W后缀代表ANSI和UNICODE版本。早期,Windows为了兼容之前ANSI版本,为了推广UNICODE版本,所以做出了两套API.

        注意,并不是所有Windows API都有*A和*W两套,只有API参数包含"字符串"才可能有两个版本。

        CreateProcess只是一个宏,在UNICODE版本是*W, ANSI是*A.

                

CreateProcessA vs CreateProcessAsUser

        后者多了参数hToken, 可指定在此token对应的安全上下文,默认创建的进程是不可交互的,且不可接受输入。

        UAC就会使用CreateProcessAsUser做权限管控。

CreateProcess到NtCreateProcess经过哪些DLL?

        kernel32.dll --> KernelBase.dll(自Vista之后新增) --> ntdll.dll

Callstack (环境: Win10)

        WinDbg attach到cmd.exe,  cmd.exe里创建应用程序触发创建进程的断点。

        

XP系统是会Kernel32 CreateProcess(A/W)进入到ntdll NtCreateProcess.

Win 10变成kernel32放存根, KERNELBASE具体实现参数检查、环境创建并调入ntdll并进入系统调用,改用NtCreateUserProcess, 弃用了NtCreateProcess.

NtCreateUserProcess

        和裸调系统调用类似,syscall或者int 2Eh完成进入内核SSDT.

0:000> u ntdll!NtCreateUserProcess
ntdll!NtCreateUserProcess:
00007ffd`30b6e650 4c8bd1          mov     r10,rcx
00007ffd`30b6e653 b8c8000000      mov     eax,0C8h
00007ffd`30b6e658 f604250803fe7f01 test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffd`30b6e660 7503            jne     ntdll!NtCreateUserProcess+0x15 (00007ffd`30b6e665)
00007ffd`30b6e662 0f05            syscall
00007ffd`30b6e664 c3              ret
00007ffd`30b6e665 cd2e            int     2Eh
00007ffd`30b6e667 c3              ret

它与NtCreateProcess差在系统服务号eax不同,其他都类似。

0:000> u ntdll!NtCreateProcess
ntdll!NtCreateProcess:
00007ffd`30b6e470 4c8bd1          mov     r10,rcx
00007ffd`30b6e473 b8b9000000      mov     eax,0B9h
00007ffd`30b6e478 f604250803fe7f01 test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffd`30b6e480 7503            jne     ntdll!NtCreateProcess+0x15 (00007ffd`30b6e485)
00007ffd`30b6e482 0f05            syscall
00007ffd`30b6e484 c3              ret
00007ffd`30b6e485 cd2e            int     2Eh
00007ffd`30b6e487 c3              ret

注意看:

    test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1

    根据SharedUserData + 0x308和1比较,如果是0,用int, 否则用syscall.

  SharedUserData (_KUSER_SHARED_DATA)

        Windows NT+开始, 从2000到Win10都有此结构。目的为了让内核把频繁访问的信息,比如时间等,用全局一致的共享结构给用户空间,减少频繁系统调用带来的性能消耗。

:000> dt _KUSER_SHARED_DATA 00000000`7ffe0308
ntdll!_KUSER_SHARED_DATA
   +0x000 TickCountLowDeprecated : 0
   +0x004 TickCountMultiplier : 0
   +0x008 InterruptTime    : _KSYSTEM_TIME
   +0x014 SystemTime       : _KSYSTEM_TIME
   ......
   ......
   +0x308 SystemCall       : 0           // 此处是0
   +0x30c Reserved2        : 0
   +0x310 SystemCallPad    : [2] 0

  WRK _KUSER_SHARED_DATA结构体

  

代码调用CreateProcess, 为什么能跑进kernel32 CreateProcessWStub?

        首先CreateProcess根据UNICODE定义与否,选择是否调用CreateProcessW.

        编译器直接插入了stub, 将调入转入到kernel32.

        

回到CreateProcessInternalW

        ReactOS: dll/win32/kernel32/client/proc.c File Reference + IDA win10 DLL

        a. 验证参数合法

                

                参数creationFlags同时有DETEACHED_PROCESS和NEW_CONSOLE是非法的。

                进程优先级Idle/Nromal等状态从此参数获取,这里只列举部分参数,源代码里面有很多检查。

        b. 搜索可执行文件,并加载

                

                 

                  注意,DosPath to NtPath转换类似于:

                        C:\\WINDOWS\\exefile --> \\Device\\HarddiskVolume1\\WINDOWS\\exefile

                        内核不认识C盘字符:"C:\\", 它是方便用户查阅的符号链接。

        c. 调用NtOpenFile打开可执行文件并创建section

                

                

                创建进程映射空间,为加载做准备(参考: NtCreateSection function).

        d. 确认Subsystem是GUI或CUI, 且MajorVersion和MinVersion符合预期

                 

                

                 这是为什么VS设置错了subsystem(version)程序不能启动的原因。

        e. 调用ntdll创建进程

                

                Win10: NtCreateUserProcess

        f. 创建主线程

                 

                 

                 

               注意,如果参数带CREATE_SUSPENED, 线程默认是不会执行的。 

               内核创建完进程和线程后,如何执行到真正的用户层线程代码?

                     参考:Windows内核--代码只有main函数, 进程怎么创建的? (2.1)     

  为什么用户层会有这么多参数检查和流程处理,不移到内核处理?

        让内核处理过多的参数检查,和流程处理并不是很好的做法,反而加重了内核的负担。可以在用户层发现错误就返回,比进入内核检查到错误再返回更高效。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值