日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CreateProcess

發(fā)布時(shí)間:2023/12/13 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CreateProcess 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Windows 進(jìn)程創(chuàng)建完整過程(除去細(xì)節(jié))

當(dāng)前流程是分析WinXP x86得到的,在最新版本W(wǎng)indows上不一定正確,但是可以做一個(gè)參考,

由于我這里符號(hào)并不全,所以導(dǎo)致我這里有些東西看到的可能是錯(cuò)誤的,誤導(dǎo)了我,然后我就做了個(gè)錯(cuò)誤的記錄,

有緣人如果看到的話,可以幫我指正一下,我會(huì)很高興。

工作挺忙的,三天的業(yè)余時(shí)間,哎,個(gè)人水平問題吧,還是沒有辦法詳細(xì)地分析出完整套路,算是個(gè)簡要分析吧。

?

差點(diǎn)忘記了,我這里分析的文件是 kernel32.dll 和 ntoskrnl.exe

?

?

1:入口  CreateProcessW

當(dāng)我們?cè)趹?yīng)用層調(diào)用CreateProcessW的時(shí)候,參數(shù)稍作整理,會(huì)直接調(diào)用到?CreateProcessInternalW

(CreateProcessA,會(huì)調(diào)用 CreateProcessInternalA,然后整理了參數(shù)也會(huì)調(diào)用到CreateProcessInternalW)

?

?

2:CreateProcessInternalW

首先,開場是大概是2000來行的匯編指令,判斷進(jìn)程創(chuàng)建參數(shù),以及文件安全屬性等等亂七八糟沒用的,

?

然后是?NtOpenFile?NtCreateSection 一系列的函數(shù),獲取文件句柄和section句柄

?

中間經(jīng)過一系列的文件類型判斷,有效性判斷,及屬性判斷,

?

調(diào)用?NtQuerySection 獲取段屬性,

?

判斷是否需要Debug方式啟動(dòng),并且做對(duì)應(yīng)的設(shè)置,

?

加載?advapi32.dll ,然后獲取?CreateProcessAsUserSecure 函數(shù)地址,但是并沒有使用它,

?

很可能是根據(jù)這個(gè)函數(shù)是否存在,來判斷當(dāng)前操作系統(tǒng)版本,后面直接調(diào)用?NtQuerySystemInformation 來獲取操作系統(tǒng)信息,參數(shù)很奇怪,0x47,可能就是特殊的情況,

(有空再看)

?

中間判斷了一個(gè)位,然后調(diào)用了DBG相關(guān)的函數(shù),(可能是判斷DBG相關(guān)吧)

?

最后就是一個(gè)Nt函數(shù),NtCreateProcessEx,進(jìn)入內(nèi)核了,(也可能是個(gè)Zw函數(shù))

?

?

3:NtCreateProcessEx

上一部分,調(diào)用ntdll 的ZwCreateProcessEx/NtCreateProcessEx 之后,

進(jìn)入內(nèi)核,走SSDT表,第48項(xiàng),進(jìn)入NtCreateProcessEx,

?

判斷當(dāng)前執(zhí)行模式,內(nèi)核模式的話,就往下走,否則,改了模式往下走

調(diào)用PspCreateProcessEx,

?

1)獲取父進(jìn)程信息,

并且繼承父進(jìn)程的執(zhí)行位置

?

2)給子進(jìn)程創(chuàng)建一個(gè)EPROCESS,然后初步設(shè)置它

?

3)初始化子進(jìn)程的線程列表

?

4)增加引用計(jì)數(shù),并且繼承父進(jìn)程的QuotaBlock,如果父進(jìn)程存在的話,否則用系統(tǒng)默認(rèn)的

?

5)繼承父進(jìn)程的DeviceMap,如果有父進(jìn)程,否則用系統(tǒng)默認(rèn)的

?

6)如果父進(jìn)程存在,那么再繼承父進(jìn)程的屬性

?

7)如果參數(shù)Section句柄存在,那么就獲取對(duì)象,并且保存,后面需要用,保存到進(jìn)程中

這個(gè)Section,實(shí)際上是上面應(yīng)用層CreateProcessInternalW函數(shù)創(chuàng)建的那個(gè)Section

?

8)如果Debug端口存在,那么就獲取它的對(duì)象,如果不存在,則從父進(jìn)程繼承

上面的第一個(gè)jnz跳轉(zhuǎn)到下面,下面的最后一個(gè)jmp回到上面的cmp處

?

9)初始化PrimaryToken

?

10)中間繼續(xù)初始化各種亂七八糟東西,包括

初始化進(jìn)程地址空間

如果當(dāng)前進(jìn)程EProcess不存在,就用另外一種方法,初始化進(jìn)程空間

PCB

優(yōu)先級(jí)組,因?yàn)楹竺嬷苯泳陀肊PROCESS了,所以我推斷這里可能同時(shí)也初始化了EPROCESS剩下的部分

?

11)如果 section存在,那么attach到子進(jìn)程,

在很深的位置先循環(huán)調(diào)用了N次?MiMapViewOfPhysicalSection 函數(shù)來映射物理內(nèi)存地址,然后

初始化section,根據(jù)section展開文件到子進(jìn)程

這里有else,但是一般來說,不會(huì)走到else里面,因?yàn)槿绻怯行E,那么section肯定存在,這是應(yīng)用層已經(jīng)找到的,然后轉(zhuǎn)化成的內(nèi)核對(duì)象,

然后向自己內(nèi)部再影射一個(gè)子進(jìn)程模塊的內(nèi)存,映射了之后,就釋放掉,只是判斷是否成功,如果成功,什么都不干,不成功就返回到label_48

(走到else里面也是同樣的操作,只不過目標(biāo)section不存在,那么就只能映射自己的)

?

///中間有一塊這段代碼,個(gè)人能力問題,無法看出這里是做什么的,因?yàn)榻Y(jié)構(gòu)體識(shí)別可能是有一定的問題

///?

?

12)初始化PEB

PEB

實(shí)際上這里有點(diǎn)問題,v74在前面的時(shí)候,是必須 hSection 存在的時(shí)候,才會(huì) ==1,也就是說必須hSection存在,才會(huì)進(jìn)入外層if

但是外層if進(jìn)入了之后,反過來說,就是hSection肯定存在,肯定不會(huì)走else,但是為什么它這么寫

?

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

然后判斷APC對(duì)列里面有沒有APC,如果有的話,觸發(fā)一個(gè)軟中斷,去運(yùn)行它

?

14)做一個(gè) AccessState ,然后使用它把子進(jìn)程EPROCESS放到進(jìn)程句柄表中,返回一個(gè)句柄

然后AccessState就沒用了,釋放掉

最后設(shè)置一下進(jìn)程優(yōu)先級(jí)組

?

15)接近尾聲,這里獲取當(dāng)前進(jìn)程允許的訪問權(quán)限位

?

16)收尾

設(shè)置進(jìn)程創(chuàng)建時(shí)間,然后返回進(jìn)程句柄,減掉自己的引用計(jì)數(shù),防止泄露

?

?

4:CreateProcessInternalW,回到應(yīng)用層了

沿著第二部分的NtCreateProcessEx繼續(xù)來看,這里已經(jīng)回到應(yīng)用層了,

繼續(xù)往下,并且這里拿到了一個(gè) 新進(jìn)程的句柄,也就是第一個(gè)參數(shù)

?

一大片代碼,設(shè)置進(jìn)程優(yōu)先級(jí)和處理模式相關(guān)

NtSetInformationProcess

NtAllocateVirtualMemory

申請(qǐng)了一塊內(nèi)存,然后好像也沒用過,

創(chuàng)建命令行參數(shù),

初始化stdin stdout stderr

BasePushProcessParameters

就是直接dup出來,然后給對(duì)面進(jìn)程用

給目標(biāo)進(jìn)程創(chuàng)建一個(gè)棧

給線程構(gòu)建上下文

然后,主線程就可以跑了

(上下文構(gòu)建中,其實(shí)有個(gè)小細(xì)節(jié))

其實(shí)在?BaseInitializeContext 函數(shù)中,根據(jù)第五個(gè)參數(shù),會(huì)判斷走哪個(gè)啟動(dòng)函數(shù)

如上,進(jìn)程啟動(dòng),最后一個(gè)參數(shù),寫死為0,則會(huì)走最下面的?BaseProcessStartThunk 函數(shù)

而?BaseProcessStartThunk 內(nèi)部還調(diào)用了。。。

再往里看,就是這樣

通過對(duì)比另外兩個(gè)函數(shù),可以推斷,這里應(yīng)該就是走主線程 _tmainCRTStartup / wWinMainCRTStartup 位置的了

?

?

5:NtCreateThread 開始主線程部分

應(yīng)用層陷入內(nèi)核,走SSDT,到了驅(qū)動(dòng)里面的NtCreateThread,

進(jìn)來還是模式校驗(yàn),

然后走

?

1)獲取進(jìn)程對(duì)象

?

2)創(chuàng)建ETHREAD

?

3)在進(jìn)程句柄表中創(chuàng)建線程的handle

?

4)創(chuàng)建TEB

初始化TEB

?

5)中間使用了超級(jí)大篇幅來初始化這個(gè)ETHREAD

初始化了之后,這一塊,就是準(zhǔn)備開跑了,

進(jìn)程的活動(dòng)線程數(shù)++,然后插入列表,然后啟動(dòng)線程,

?

6)直到這里,這里是進(jìn)程創(chuàng)建回調(diào),注意哦,這里是在父進(jìn)程里面調(diào)用的

?

7)判斷作業(yè)是否在工作,所在進(jìn)程是否在作業(yè)中,如果在的話,特殊處理,讓他去完成,并且清理APC

?

8)壓軸戲,線程創(chuàng)建回調(diào)

?

9)兩個(gè)回調(diào)結(jié)束之后,似乎就沒什么好做得了,把線程對(duì)象插入句柄表

這里的插入和前面的創(chuàng)建不是一個(gè)東西,那個(gè)ExCreateHandle 是創(chuàng)建全局句柄表,

這里是插入進(jìn)程句柄表

?

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

寫時(shí)間戳,寫訪問權(quán)限,解對(duì)象引用,

再清理一次APC,

然后把線程句柄返回,

?

11)補(bǔ)充一下吧

正常結(jié)束時(shí),這里實(shí)際上是有個(gè)收尾的小工作的,

這里面KeReadyThread 是關(guān)鍵操作,它把 ETHREAD 放到了進(jìn)程 KPROCESS 的?ReadyListHead 里面,

這樣應(yīng)該就可以swapcontext了,

其實(shí)它內(nèi)部還有眾多關(guān)鍵函數(shù),如?KiSetSwapEvent ,看名字和內(nèi)部實(shí)現(xiàn),似乎就是搶搶占時(shí)間片去了。

?

我所關(guān)心的整個(gè)部分,實(shí)際上就是,

進(jìn)程、線程創(chuàng)建回調(diào)的觸發(fā)時(shí)機(jī),實(shí)際上觸發(fā)的進(jìn)程上下文都在父進(jìn)程中,觸發(fā)時(shí)機(jī)都在PspCreateThread中,

因?yàn)閷?shí)際工作中,我們能用到的部分,也就這里了

?

?

6:回到應(yīng)用層

這里直接判斷返回值,有問題的話,直接錯(cuò)誤返回,

沒有問題的情況下,那么繼續(xù)往下做判斷

?

1)通知Csrss

由于我這里符號(hào)不全,我想下面的ExitStatus 應(yīng)該是 Csrss返回的吧。

一旦有問題,立刻退出

?

2)指派進(jìn)程到一個(gè)作業(yè)中

?

3)后面直到最后,通篇都是整理內(nèi)存,釋放空間了,

基本上就沒有干別的活,

最后才是函數(shù)返回。

?

這樣,整體流程結(jié)束。

?

?

補(bǔ)充一下,鏡像加載回調(diào)的位置吧,

這個(gè),實(shí)際上,鏡像加載回調(diào)被調(diào)用的時(shí)候,已經(jīng)和鏡像沒什么關(guān)系了,

而且鏡像早早已經(jīng)被鋪到內(nèi)存中了

在InitThread之前,是初始化TEB部分,這里初始化了TEB之后,設(shè)置了一個(gè)回調(diào)函數(shù)

創(chuàng)建應(yīng)用層線程PspUserThreadStartup

進(jìn)入這個(gè)函數(shù)里面,可以看到

有這樣一個(gè)判斷,由于我實(shí)在沒有找到那個(gè)6代表什么,可能是2|4,但是我沒找到,所以無法知道它是什么,

進(jìn)入函數(shù)之后,里面會(huì)進(jìn)行一次鏡像加載回調(diào)狀態(tài)的判斷,如果非隱藏狀態(tài),那么再經(jīng)過一個(gè)函數(shù),

就會(huì)到這里,聯(lián)系外面的函數(shù),可以清晰地看出,這里就是鏡像加載回調(diào)的調(diào)用位置,

總地來說,由于鏡像加載回調(diào)有可能是異步調(diào)用的,所以無法確切地知道它的位置,

但是它的位置實(shí)際上是在前兩個(gè)回調(diào)之后的(其實(shí)已知,這些都是廢話)

?

?

?

重點(diǎn):

在CreateProcess 函數(shù)中,會(huì)開辟子進(jìn)程的進(jìn)程空間,

然后同時(shí)會(huì)map子進(jìn)程的主模塊到進(jìn)程空間中,這時(shí)不會(huì)調(diào)用鏡像加載回調(diào)和進(jìn)程創(chuàng)建回調(diào),

到了CreateThread 里面,整理了線程各種信息之后,

會(huì)先調(diào)用進(jìn)程創(chuàng)建回調(diào),

然后調(diào)用線程創(chuàng)建回調(diào),

這時(shí),當(dāng)前進(jìn)程上下文還是在父進(jìn)程中,

最后,當(dāng)線程跑起來之后,

第一個(gè)回調(diào)會(huì)被觸發(fā),就是主模塊的鏡像加載回調(diào),

這時(shí)剩下的就是其他模塊的鏡像加載回調(diào)了,

后面就不是很重要了,前面這個(gè)流程應(yīng)該是最重要的。

轉(zhuǎn)載于:https://www.cnblogs.com/suanguade/p/5844296.html

總結(jié)

以上是生活随笔為你收集整理的CreateProcess的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。