<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    迷霧退散:揭秘創建進程時ebx為什么指向peb的答案

    VSole2021-10-14 16:31:33

    一、背景

    這篇文章的起因,是筆者之前在做樣本分析的時候,經常會遇到需要調試傀儡進程的情況,而其中有一種情景是將啟動的白進程PE文件整個掏空并用黑進程進行替換。

    為了確保被替換后的進程能順利執行不崩潰,需要獲取原進程各種上下文,并修改被替換后的新進程上下文,其中在原進程被掛起還沒開始執行的時候,需要將eax指向新oep,而ebx指向新peb,而為什么這樣設置的原因卻很少有人提及。為此,在經過查閱了一定的資料與簡單的分析后,我們可以找到答案。

    二、具體分析

    先拋出結論,這里的eax與ebx屬于線程上下文信息,在一個PE文件開始被運行的過程中,主線程上下文初始化過程是在進程已經創建完成,而主線程還沒創建的階段發生的,下面是具體更詳細的分析:

    首先我們需要對進程的創建有一個大概的認識,在ring3下創建進程API無非是CreateProcessA/W,但是無論調用哪一個,最終都會將相關參數轉化為Unicode字符串,并最終調用CreateProcessInternalW,因此以下將主要分析CreateProcessInternalW,而在xp和win7下,它具體實現又有一些不一樣的地方。

    2.1 XP下執行流程

    在xp下,它大概分為四個部分,分別是ring3下創建進程,ring0下創建進程,ring3下創建線程,ring0下創建線程,以NtCreateProcessEx為分界線,NtCreateProcessEx之前為ring3下創建進程主要流程。

    2.1.1Ring3下創建進程

    1. 判斷處理dwCreationFlag各種標志位,包括是否包含不合法標記組合,判斷優先級。

    2. 判斷lpEnvironment是否為空,

    不為空則調用RtlAnsiStringToUnicodeString將其轉為UniCode字符串。

    3. 判斷lpApplicationName、lpCommandLine是否為空。

    如果lpApplicationName不為空直接調用RtlDosPathNameToNtPathName_U函數。

    將DOS路徑(C:\\WINDOWS\\XXX)轉換為NT路徑(\\Device\\HarddiskVolume1\\WINDOWS\\XXX),

    為空則會解析lpCommandLine,主要按照’”’引號,’ ’空格,’\t’制表符作為分隔符進行解析并獲取相應的PE文件,然后將DOS路徑轉換為NT路徑。

    4. 調用NtOpenFile得到文件句柄,調用了NtCreateSectiond函數得到內存區對象句柄。

    5. 調用BasepIsProcessAllowed函數, 該函數用來判斷應用程序名是否在授權文件列表中。

    6. 之后會經過一大段的函數進行各種校驗,再得到內存區對象句柄后調用NtQuerySection函數,

    返回后得到節的基本信息(節基地址,大小,屬性),并判斷創建標志中是否包含DEBUG_PROCESS或者DEBUG_ONLY_THIS_PROCESS,

    如果不包含該標志,則判斷PEB->ReadImageFileExecOptions域是否為0,

    如果包含DEBUG_PROCESS或者DEBUG_ONLY_THIS_PROCESS,或者不包含該標志但ReadImageFileExecOptions域不為0,

    調用LdrQueryImageFileExecutionOptions函數查詢該信息。

    7. 檢查鏡像文件的部分信息的有效性,并調用函數BasepIsImageVersionOk判斷鏡像文件版本是否合法。

    8. 加載advapi32.dll并獲得CreateProcessAsUserSecure函數的地址。

    9. 調用BaseFormatObjectAttributes將安全屬性結構格式為NT對象屬性結構(得到了對象屬性),接著調用了_DbgUiConnectToDbg在實現通過調用NtCreateDebugObject函數來創建調試對象,

    調用DbgUiGetThreadDebugObject來獲得調試對象(作為參數傳遞到0環)。

    10. 最后調用NtCreateProcessEx函數。

    2.1.2Ring0下創建進程

    NtCreateProcessEx內為ring0下創建進程主要流程。

    判斷父進程是否存在,不存在則退出,否則,調用PspCreateProcess。

    在PspCreateProcess中,保存當前線程運行的前一個模式。通過KTHREAD->PreviousMode可以得到前一個模式。判斷創建標志是否包含除DEBUG_PROCESSDEBUG_ONLY_THIS_PROCESS,CREATE_SUSPENDED之外其它標志, 如果包含其他的標志,則報錯退出。


    3. 通過參數ParentProcess調用ObReferenceObjectByHandle函數得到父進程對象的指針。

    4. 判斷參數 JobMemberLevel是否為0, 如果不為0,接著判斷父進程的EPROCESS->Job是否為0,如果JobMemberLevel不為為0且EPROCESS->Job為0,則返回無效參數錯誤后退出該函數;否則的話,將父進程對象中的屬性保存到局部變量中。

    5. 調用ObCreateObject函數創建新進程對象并將對象內容初始化為0,然后從父進程繼承配額信息(PspInheritQuot)和設備位圖信息(ObInheritDeviceMap),將父進程對象中的部分域給新進程。

    6. 判斷參數SectionHandle是否為0,若不為0,調用ObReferenceObjectByHandle函數得到區對象指針,然后將區對象指針賦值給新進程EPROCESS的相應域。

    7. 接著就判斷參數DebugPort是否為0,若不為0,調用ObReferenceObjectByHandle函數通過調試對象句柄得到調試對象指針,否則調用DbgkCopyProcessDebugPort函數從父進程拷貝DebugPort給新進程。

    8. 判斷參數ExceptionPort是否為0,若不為0,調用ObReferenceObjectByHandle函數通過異常端口對象句柄得到異常端口對象指針。

    9. 接著調用PspInitializeProcessSecurity函數來設置新進程的安全屬性, 主要是設置新進程的安全令牌對象。該函數會調用SeSubProcessToken函數來設置新進程對象的令牌對象。

    10. 接著調用MmCreateProcessAddressSpace為新進程創建地址空間,并構建頁目錄表、頁表及物理頁的關系。

    11. 調用KeInitializeProcess函數初始化新進程對象中內核對象、優先級、親和性、頁目錄表物理地址幀號。

    12. 調用ObInitProcess函數來初始化新進程對象的表。

    13. 調用MmInitializeProcessAddressSpace函數初始化進程地址空間,該函數的實現中調用了KiAttachProcess函數來實現進程的切換(將當前線程掛靠到新進程中),以及初始化EPROCESS中的部分域和PFN、工作集列表等。

    14. 調用PspMapSystemDll函數映射新進程對象的系統DLL(即NTDLL,映射第一個DLL),該函數會調用MmMapViewOfSection映射節區,而MmMapViewOfSection會調用MiMapViewOfImageSection函數將DLL作為鏡像映射。

    15. 接著調用MmGetSessionId函數獲得指定進程的會話ID,然后調用SeSetSessionIdToken函數設置令牌的會話ID,

    之后再調用ExCreateHandle函數在PspCidTable中添加一項(PID)。

    16. 調用MmCreatePeb為新進程創建PEB,該函數首先通過調用KeAttachProcess函數將當前線程切換到新進程對象,然后通過MmMapViewOfSection函數將NLS節區映射到新進程的地址空間中,隨后調用MiCreatePebOrTeb創建PEB/TEB。

    在MiCreatePebOrTeb函數中首先會通過ExAllocatePoolWithTag來申請0x34大小的空間,接著通過MiFindEmptyAddressRangeDownTree函數在VAD樹中查找一塊未被使用的地址空間范圍,并返回該范圍的起始地址,最后通過MiInsertVad函數將申請的地址空間插入到VAD樹中。

    在創建PEB結構后,初始化PEB中部分域的值(鏡像基地址,操作系統編譯號等域),最后調用KeDetachProcess函數使線程回到原來的線程中。截止此步驟,PEB創建完成。

    同時觀察也可以發現,這里也解析了包括Nt頭、擴展頭、擴展頭魔術字效驗等關鍵PE結構信息,聯想到之前分析流程也處理了一部分PE結構,可以猜測早期的PE文件結構逆向可能也是通過逆向進程創建過程,即逆向CreateProcess API來實現的。

    17. 最后將新進程對象EPROCESS.ActiveProcessLinks更新為全局的活動進程鏈表(PsActiveProcessHead), 判斷父進程是否為系統進程,調用SeCreateAccessStateEx設置訪問狀態,

    調用ObInsertObject函數將進程對象加入到進程對象的句柄表中,并通過KeQuerySystemTime(獲取當前系統時間)結束PspCreateProcess的調用,完成ring0下進程的創建。

    接下來我們回到CreateProcessInternalW,以NtCreateThread為分界線,NtCreateProcessEx之后到NtCreateThread之前為ring3下創建線程流程,而NtCreateThread內則是ring0下創建線程流程,經過分析發現,我們所需要尋找的線程上下文設置其實就在ring3下創建線程流程內。

    函數調用初始化
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    概述在windows系統上,涉及到內核對象的功能函數,都需要從應用層權限轉換到內核層權限,然后再執行想要的內核函數,最終將函數結果返回給應用層。本文就是用OpenProcess函數來觀察函數從應用層到內核層的整體調用流程。OpenProcess函數,根據指定的進程ID,返回進程句柄。NTSTATUS Status; //保存函數執行狀態。OBJECT_ATTRIBUTES Obja; //待打開對象的對象屬性。HANDLE Handle; //存儲打開的句柄。CLIENT_ID ClientId; //進程、線程ID. dwDesiredAccess, //預打開進程并獲取對應的權限。ObjectNamePresent = ARGUMENT_PRESENT ; //判斷對象名稱是否為空
    關于堆棧ShellCode操作:基礎理論002-利用fs寄存器尋找當前程序dll的入口:從動態運行的程序中定位所需dll003-尋找大兵LoadLibraryA:從定位到的dll中尋找所需函數地址004-被截斷的shellCode:加解密,解決shellCode的零字截斷問題
    uds診斷協議-逆向題 WP
    2022-08-14 16:17:02
    介紹這是一道uds診斷協議的逆向題。比賽的時候時間太短沒做出來,又花時間研究了一下拿出來分享。UdsRoutineControlService這個函數從getflag這看起來就像目標函數,要求的條件很多。
    EXP編寫學習之繞過GS
    2023-02-20 09:58:16
    棧中的守護天使 :GSGS原理向棧內壓入一個隨機的DWORD值,這個隨機數被稱為canary ,IDA稱為 Security Cookie。Security Cookie 放入 ebp前,并且data節中存放一個 Security Cookie的副本。棧中發生溢出時,Security Cookie首先被淹沒,之后才是ebp和返回地址。函數返回之前,會添加一個Security Cookie驗證操作,稱為Security Check。檢測到溢出時,系統將進入異常處理流程,函數不會正常返回,ret也不會被執行。函數使用無保護的關鍵字標記。緩沖區不是8字節類型 且 大小不大于4個字節。可以為函數強制啟用GS。
    一般情況下,SSRF針對的都是一些外網無法訪問的內網,所以需要SSRF使目標后端去訪問內網,進而達到我們攻擊內網的目的。
    shellcode編寫探究
    2022-06-09 15:34:57
    前言shellcode是不依賴環境,放到任何地方都可以執行的機器碼。shellcode的應用場景很多,本文不研究shellcode的具體應用,而只是研究編寫一個shellcode需要掌握哪些知識。要使用字符串,需要使用字符數組。所以我們需要用到 LoadLibrary 和 GetProcAddress 這兩個函數,來動態獲取系統API的函數指針。
    在所有函數調用發生時,向棧幀內壓入一個額外的隨機 DWORD,隨機數標注為“SecurityCookie”。在函數返回之前,系統將執行一個額外的安全驗證操作,被稱做 Security check。
    獨立 LSA 進程存儲的數據使用基于虛擬化的安全性進行保護,操作系統的其余部分無法訪問。LSA 使用遠程過程調用來與隔離的 LSA 進程進行通信。使用可用于自定義安全包的 LSA 支持函數,開發人員可以實現高級安全功能,例如令牌創建、 補充憑據支持和直通身份驗證。這樣便可以繞過 Credential Guard 的保護機制。這兩種執行模式分別稱為 LSA 模式和用戶模式。結構數組的形式傳遞給 LSA。SpAcceptCredentials將為經過身份驗證的安全主體存儲的憑據傳遞給安全包。
    當線程從等待狀態蘇醒后,會自動檢測自己得APC隊列中是否存在APC過程。所以只需要將目標進程的線程的APC隊列里面添加APC過程,當然為了提高命中率可以向進程的所有線程中添加APC過程。然后促使線程從休眠中恢復就可以實現APC注入。往線程APC隊列添加APC,系統會產生一個軟中斷。第二個參數表示插入APC的線程句柄,要求線程句柄必須包含THREAD_SET_CONTEXT訪問權限。第三個參數表示傳遞給執行函數的參數。如果直接傳入shellcode不設置第三個函數,可以直接執行shellcode。
    01高門檻,勿入在Cisco平臺上有一個很有用的Traceback log功能,實時記錄當前Code運行到特
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类