调用CreateProcessW
调用CreateProcessInternalW
参数检查
获取进程文件路径
调用 BasepMapFile 映射文件(内部调用NtCreateSection)
判断是否是一个DLL文件
判断子系统类型(只能是GUI和CUI中的一种)
是GUI时,则去掉CREATE_NEW_CONSOLE标志,增加DETACHED_PROCESS
如果dwCreationFlags参数中包含DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS,则调用DbgUiConnectToDbg创建调试对象(debugPort)
调用NtCreateProcess开始创建进程
调用NtCreateProcessEx
调用PspCreateProcess
关联相关句柄的内核对象(SectionHandle,DebugPort,ExceptionPort)
创建进程空间( MmCreateProcessAddressSpace )
初始化进程内核对象(KeInitializeProcess)
复制父进程的Token(PspInitializeProcessSecurity)
初始化进程句柄表(ObInitProcess)
把进程模块映射进内存(MmInitializeProcessAddressSpace-->MmMapViewOfSection)
映射系统模块(PspMapSystemDll-->MmMapViewOfSection)
把该内核对象加入到进程线程对象表(PspCidTable)中,并得到进程ID
创建PEB(MmCreatePeb)
获取进程句柄(ObInsertObject)
权限检查(SeAccessCheck)
执行(监控进程创建)回调函数(PspRunCreateProcessNotifyRoutines)
设置进程优先级
设置进程参数(BasePushProcessParameters)
关闭由BasepMapFile函数创建的section句柄
复制标准输入、输出、错误设备句柄
调用BasepNotifyCsrOfCreation
创建第一个线程BasepCreateFirstThread
创建线程栈(BaseCreateStack)
初始化线程环境块(BaseInitializeContext)
设置寄存器
eax = 入口点
ebx = 参数
esp = 栈底指针
eip = BaseProcessStartThunk
创建线程内核对象(NtCreateThread)
调用PspCreateThread
创建线程对象(ObCreateObject)
得到线程ID(ExCreateHandle)
初始化相关链表
创建TEB(MmCreateTeb)
设置线程的起始地址
初始化线程对象(KeInitThread)
第三个参数传入的是:PspUserThreadStartup
调用KiInitializeContextThread
CtxSwitchFrame->RetAddr = KiThreadStartup;
启动第一个线程NtResumeThread
线程是怎么启动的?
KiThreadStartup
调用 PspUserThreadStartup
插入APC回调 LdrInitializeThunk函数
1. 线程启动时会先执行APC回调
LdrInitializeThunk内部实现
调用LdrpInit
如果是进程中第一个线程
调用LdrpInitializeProcess
初始化NLS
创建堆(RtlCreateHeap)
初始化Loader Data
把进程模块和NTDLL模块信息写入Loader Data中
遍历主模块输入表并加载相关模块(LdrpWalkImportDescriptor)
修正主模块重定位(LdrRelocateImageWithBias)
初始化TLS(LdrpInitializeTls) 计算TLS占用的空间大小
如果有调试器,通知调试器
调用模块入口点LdrpRunInitializeRoutines(包括TLS CALLBACK)(DLL_PROCESS_ATTACH)
非第一个线程
调用LdrpInitializeThread
循环调用各个模块的TLS callback
入口点
(DLL_THREAD_ATTACH)
调用CreateProcessInternalW
参数检查
获取进程文件路径
调用 BasepMapFile 映射文件(内部调用NtCreateSection)
判断是否是一个DLL文件
判断子系统类型(只能是GUI和CUI中的一种)
是GUI时,则去掉CREATE_NEW_CONSOLE标志,增加DETACHED_PROCESS
如果dwCreationFlags参数中包含DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS,则调用DbgUiConnectToDbg创建调试对象(debugPort)
调用NtCreateProcess开始创建进程
调用NtCreateProcessEx
调用PspCreateProcess
关联相关句柄的内核对象(SectionHandle,DebugPort,ExceptionPort)
创建进程空间( MmCreateProcessAddressSpace )
初始化进程内核对象(KeInitializeProcess)
复制父进程的Token(PspInitializeProcessSecurity)
初始化进程句柄表(ObInitProcess)
把进程模块映射进内存(MmInitializeProcessAddressSpace-->MmMapViewOfSection)
映射系统模块(PspMapSystemDll-->MmMapViewOfSection)
把该内核对象加入到进程线程对象表(PspCidTable)中,并得到进程ID
创建PEB(MmCreatePeb)
获取进程句柄(ObInsertObject)
权限检查(SeAccessCheck)
执行(监控进程创建)回调函数(PspRunCreateProcessNotifyRoutines)
设置进程优先级
设置进程参数(BasePushProcessParameters)
关闭由BasepMapFile函数创建的section句柄
复制标准输入、输出、错误设备句柄
调用BasepNotifyCsrOfCreation
创建第一个线程BasepCreateFirstThread
创建线程栈(BaseCreateStack)
初始化线程环境块(BaseInitializeContext)
设置寄存器
eax = 入口点
ebx = 参数
esp = 栈底指针
eip = BaseProcessStartThunk
创建线程内核对象(NtCreateThread)
调用PspCreateThread
创建线程对象(ObCreateObject)
得到线程ID(ExCreateHandle)
初始化相关链表
创建TEB(MmCreateTeb)
设置线程的起始地址
初始化线程对象(KeInitThread)
第三个参数传入的是:PspUserThreadStartup
调用KiInitializeContextThread
CtxSwitchFrame->RetAddr = KiThreadStartup;
启动第一个线程NtResumeThread
线程是怎么启动的?
KiThreadStartup
调用 PspUserThreadStartup
插入APC回调 LdrInitializeThunk函数
1. 线程启动时会先执行APC回调
LdrInitializeThunk内部实现
调用LdrpInit
如果是进程中第一个线程
调用LdrpInitializeProcess
初始化NLS
创建堆(RtlCreateHeap)
初始化Loader Data
把进程模块和NTDLL模块信息写入Loader Data中
遍历主模块输入表并加载相关模块(LdrpWalkImportDescriptor)
修正主模块重定位(LdrRelocateImageWithBias)
初始化TLS(LdrpInitializeTls) 计算TLS占用的空间大小
如果有调试器,通知调试器
调用模块入口点LdrpRunInitializeRoutines(包括TLS CALLBACK)(DLL_PROCESS_ATTACH)
非第一个线程
调用LdrpInitializeThread
循环调用各个模块的TLS callback
入口点
(DLL_THREAD_ATTACH)
测试Alart(NtTestAlert)
2. APC执行完后执行PspUserThreadStartup函数
PspUserThreadStartup函数调用线程入口地址,开始执行线程