自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

通過查找非權(quán)限進(jìn)程中的泄漏句柄來查找權(quán)限升級(jí)和UAC

安全 漏洞
你可能想知道為什么使用 switch 語句而不是簡單的 if。一些代碼已被刪除,因?yàn)檫@些是我們高級(jí)持久性 Tortellini 專門為尋找我們?cè)谖恼麻_頭提到的漏洞而編寫的工具的摘錄。

在某些情況下,具有高完整性或系統(tǒng)完整性的進(jìn)程會(huì)向權(quán)限進(jìn)程/線程/令牌請(qǐng)求句柄,然后生成低完整性進(jìn)程。如果這些句柄足夠強(qiáng)大,且類型正確,并且由子進(jìn)程繼承,我們可以從另一個(gè)進(jìn)程復(fù)制它們,然后濫用它們來升級(jí)權(quán)限或繞過UAC。在這篇文章中,我們將介紹如何尋找和濫用這種漏洞。

介紹

本質(zhì)上,這個(gè)想法是看看我們是否可以自動(dòng)找到擁有高完整性(也就是提升)或SYSTEM進(jìn)程的權(quán)限句柄的非權(quán)限進(jìn)程,然后檢查我們是否可以作為一個(gè)非權(quán)限用戶附加到這些進(jìn)程上,并復(fù)制這些句柄,以便以后濫用它們。我們的工具會(huì)受到哪些限制?

1.它必須作為中等完整性進(jìn)程運(yùn)行;

2. 進(jìn)程令牌中沒有 SeDebugPrivilege(中等完整性的進(jìn)程默認(rèn)沒有這個(gè)權(quán)限);

3. 沒有 UAC 繞過,因?yàn)樗脖仨氝m用于非管理用戶;

這個(gè)過程有點(diǎn)復(fù)雜,我們將經(jīng)歷的步驟或多或少如下:

1.枚舉所有進(jìn)程持有的所有句柄;

2.過濾掉我們不感興趣的句柄,現(xiàn)在我們只關(guān)注進(jìn)程、線程和令牌的句柄,因?yàn)樗鼈兏菀妆晃淦骰?

3.過濾掉引用低完整性進(jìn)程/線程/令牌的句柄;

4.過濾掉完整性大于中等的進(jìn)程持有的句柄,除非獲得SeDebugPrivilege,否則我們不能附加到它們上,這違背了本文的目的;

5.復(fù)制其余的句柄并將它們導(dǎo)入我們的進(jìn)程,并試圖濫用它們來升級(jí)權(quán)限或者至少繞過UAC;

當(dāng)然,我們不太可能在一臺(tái)全新的Windows設(shè)備上滿足這些條件,所以為了避免這個(gè)問題,我將使用一個(gè)我專門為此目的編寫的易受攻擊的應(yīng)用程序。

句柄處理

正如我在這個(gè)Twitter線程中簡要討論的那樣,Windows是一個(gè)基于對(duì)象的操作系統(tǒng),這意味著每個(gè)實(shí)體(進(jìn)程、線程、互斥鎖等)在內(nèi)核中都以數(shù)據(jù)結(jié)構(gòu)的形式有一個(gè)“對(duì)象”表示。例如,對(duì)于進(jìn)程,該數(shù)據(jù)結(jié)構(gòu)的類型是_EPROCESS。作為存在于內(nèi)核空間的數(shù)據(jù),普通的用戶模式代碼無法直接與這些數(shù)據(jù)結(jié)構(gòu)交互,因此操作系統(tǒng)公開了一個(gè)間接機(jī)制,該機(jī)制依賴于特殊的HANDLE類型變量以及用于服務(wù)的 SC_HANDLE 等派生類型。句柄只不過是內(nèi)核空間表中的索引,對(duì)每個(gè)進(jìn)程來說都是私有的。表中的每一項(xiàng)都包含了它所指向的對(duì)象的地址以及該句柄對(duì)該對(duì)象的訪問級(jí)別。這個(gè)表由每個(gè)進(jìn)程的_EPROCESS結(jié)構(gòu)的ObjectTable成員(它的類型是_HANDLE_TABLE*,因此它指向一個(gè)_HANDLE_TABLE)指向。

為了更容易理解,讓我們看一個(gè)例子。要獲得進(jìn)程的句柄,我們可以使用OpenProcess Win32 API,定義如下:

它需要3個(gè)參數(shù):

dwDesiredAccess是一個(gè)DWORD,它指定了我們希望對(duì)我們?cè)噲D打開的進(jìn)程擁有的訪問級(jí)別;

bInheritHandle是一個(gè)布爾值,如果設(shè)置為TRUE,將使句柄可繼承,這意味著調(diào)用進(jìn)程在子進(jìn)程生成時(shí)將返回的句柄復(fù)制給子進(jìn)程(以防我們的程序調(diào)用CreateProcess之類的函數(shù));

dwProcessId是一個(gè)DWORD,用于指定我們想打開哪個(gè)進(jìn)程(通過提供它的PID);

在下一行中,我將嘗試打開系統(tǒng)進(jìn)程(它始終具有 PID 4)的句柄,向內(nèi)核指定我希望句柄擁有盡可能少的特權(quán),只需要查詢有關(guān)信息的子集進(jìn)程(PROCESS_QUERY_LIMITED_INFORMATION),并且我希望該程序的子進(jìn)程繼承返回的句柄(TRUE)。

OpenProcess返回的System進(jìn)程的句柄(如果它沒有因?yàn)槟撤N原因失敗)被放入hProcess變量中以供以后使用。

在后臺(tái),內(nèi)核執(zhí)行一些安全檢查,如果這些檢查通過,則獲取所提供的PID,解析相關(guān)_EPROCESS結(jié)構(gòu)的地址,并將其復(fù)制到句柄表中的一個(gè)新條目中。之后,它將訪問掩碼(即提供的訪問級(jí)別)復(fù)制到相同的條目中,并將條目值返回給調(diào)用代碼。

當(dāng)你調(diào)用其他函數(shù)(如OpenThread和OpenToken)時(shí),也會(huì)發(fā)生類似的事情。

查看句柄

正如我們前面介紹的,句柄本質(zhì)上是表的索引。每個(gè)條目都包含句柄所引用對(duì)象的地址以及句柄的訪問級(jí)別。我們可以使用 Process Explorer 或 Process Hacker 等工具查看這些信息:

從這個(gè) Process Explorer 屏幕截圖中,我們可以獲得一些信息:

紅框:句柄所指的對(duì)象類型;

藍(lán)色框:句柄值(表項(xiàng)的實(shí)際索引);

黃色框:句柄所指對(duì)象的地址;

綠色框:訪問掩碼及其解碼值(訪問掩碼是在 Windows.h 頭文件中定義的宏),這告訴我們?cè)趯?duì)象上授予句柄持有者哪些特權(quán);

有很多方法可以獲得這些信息,不一定需要使用在內(nèi)核模式下運(yùn)行的代碼。在這些方法中,最實(shí)用和最有用的是依賴原生 API NtQuerySystemInformation,當(dāng)調(diào)用它時(shí)傳遞 SystemHandleInformation (0x10) 值作為其第一個(gè)參數(shù),返回一個(gè)指向 SYSTEM_HANDLE 變量數(shù)組的指針,其中每個(gè)變量都引用一個(gè)由系統(tǒng)上的進(jìn)程打開的句柄。

讓我們來看看用c++實(shí)現(xiàn)它的一種可能的方法。

在這段代碼中,我們使用以下變量:

queryInfoStatus 將保存 NtQuerySystemInformation 的返回值;

tempHandleInfo 將保存有關(guān)系統(tǒng) NtQuerySystemInformation 為我們獲取的所有句柄的數(shù)據(jù);

handleInfoSize 是對(duì)所說數(shù)據(jù)量的“猜測(cè)”。不要擔(dān)心,因?yàn)槊看?NtQuerySystemInformation 將返回 STATUS_INFO_LENGTH_MISMATCH 時(shí)這個(gè)變量都會(huì)加倍,這是一個(gè)告訴我們分配的空間不夠的值;

handleInfo 是指向內(nèi)存位置的指針 NtQuerySystemInformation 將填充我們需要的數(shù)據(jù);

不要對(duì)這里的 while 循環(huán)感到困惑,正如我們所說,我們只是反復(fù)調(diào)用函數(shù),直到分配的內(nèi)存空間足夠大,可以容納所有的數(shù)據(jù)。在使用Windows本機(jī)API時(shí),這種類型的操作非常普遍。

NtQuerySystemInformation 獲取的數(shù)據(jù)可以通過簡單的迭代來解析,如下所示:

從代碼中可以看出,變量句柄是 SYSTEM_HANDLE 類型的結(jié)構(gòu)(自動(dòng)從代碼中刪除)有許多成員提供有關(guān)它所引用的句柄的有用信息。最有趣的成員是:

ProcessId:持有句柄的進(jìn)程;

Handle:持有句柄本身的進(jìn)程內(nèi)部的句柄值;

Object:句柄指向的對(duì)象在內(nèi)核空間中的地址;

ObjectTypeNumber:一個(gè)未記錄的 BYTE 變量,用于標(biāo)識(shí)句柄所指對(duì)象的類型。為了解釋它,需要進(jìn)行一些逆向工程和挖掘,只要說進(jìn)程由值 0x07 標(biāo)識(shí),線程由 0x08 標(biāo)識(shí),令牌由 0x05 標(biāo)識(shí)就足夠了;

GrantedAccess 句柄授予的對(duì)內(nèi)核對(duì)象的訪問級(jí)別,對(duì)于進(jìn)程,你可以找到諸如 PROCESS_ALL_ACCESS、PROCESS_CREATE_PROCESS 等值。

讓我們運(yùn)行上述代碼并查看其輸出結(jié)果:

我們可以從對(duì)象類型的 0x7 值推斷出,在這段摘錄中,我們看到 PID 為 4 的進(jìn)程(即任何 Windows 機(jī)器上的系統(tǒng)進(jìn)程)當(dāng)前已打開 3 個(gè)句柄。所有這些句柄都引用進(jìn)程類型的內(nèi)核對(duì)象,每個(gè)都有自己的內(nèi)核空間地址,但只有第一個(gè)是特權(quán)句柄,正如你可以從其值推斷出的那樣, 0x1fffff,這是 PROCESS_ALL_ACCESS 翻譯的內(nèi)容。不幸的是,在我的研究中,我發(fā)現(xiàn)沒有直接的方法可以直接提取 SYSTEM_HANDLE 結(jié)構(gòu)的 ObjectAddress 成員所指向的進(jìn)程的 PID。稍后我們將看到一個(gè)巧妙的技巧來規(guī)避這個(gè)問題,但現(xiàn)在讓我們使用 Process Explorer 檢查它正在使用哪個(gè)進(jìn)程。

正如你所看到的,值為0x828的句柄的類型是process,它引用進(jìn)程services.exe。對(duì)象地址和被授予的訪問也都簽出了,如果你查看圖像的右側(cè),你將看到解碼的訪問掩碼顯示PROCESS_ALL_ACCESS,正如預(yù)期的那樣。

這是非常有趣的,因?yàn)樗举|(zhì)上允許我們查看任何進(jìn)程的句柄表,而不管它的安全上下文和PP(L)級(jí)別。

從目標(biāo)進(jìn)程的對(duì)象地址獲取目標(biāo)進(jìn)程的PID

如上所述,我沒有找到一種方法來取回給定進(jìn)程的 SYSTEM_HANDLE 進(jìn)程的 PID,但我確實(shí)找到了一個(gè)有趣的解決方法。讓我們先來看看一些假設(shè):

1.SYSTEM_HANDLE結(jié)構(gòu)包含Object成員,該成員保存內(nèi)核對(duì)象地址,該地址在內(nèi)核空間中;

2.在Windows上,所有進(jìn)程都有自己的地址空間,但是地址空間的內(nèi)核空間部分(64位進(jìn)程的最大128TB)對(duì)所有進(jìn)程是相同的。內(nèi)核空間中的地址在所有進(jìn)程中保存相同的數(shù)據(jù);

3.提到進(jìn)程的句柄時(shí),SYSTEM_HANDLE的Object成員指向進(jìn)程本身的_EPROCESS結(jié)構(gòu);

4.每個(gè)進(jìn)程只有一個(gè) _EPROCESS 結(jié)構(gòu);

5.我們可以通過調(diào)用 OpenProcess 并將 PROCESS_QUERY_LIMITED_INFORMATION 指定為所需的訪問值來獲取任何進(jìn)程的句柄,而不管其安全上下文如何;

從這些假設(shè)中,我們可以推斷出以下信息:

1.如果句柄在同一個(gè)對(duì)象上打開,則兩個(gè)不同 SYSTEM_HANDLE 結(jié)構(gòu)的 Object 成員將相同,而與持有該句柄的進(jìn)程無關(guān),例如,由兩個(gè)不同進(jìn)程在同一文件上打開的兩個(gè)句柄將具有相同的 Object 值:

1.1由兩個(gè)不同進(jìn)程打開的同一進(jìn)程的兩個(gè)句柄將具有匹配的 Object 值;

1.2線程、令牌等也是如此;

2.當(dāng)調(diào)用 NtQuerySystemInformation 時(shí),我們可以枚舉我們自己的進(jìn)程持有的句柄;

如果我們通過 OpenProcess 獲得一個(gè)進(jìn)程的句柄,我們就知道該進(jìn)程的 PID,并且通過 NtQuerySystemInformation,它的 _EPROCESS 的內(nèi)核空間地址

你能看到我們要去哪里嗎?如果我們?cè)O(shè)法打開一個(gè)對(duì)所有進(jìn)程具有訪問 PROCESS_QUERY_LIMITED_INFORMATION 的句柄,然后通過 NtQuerySystemInformation 檢索所有系統(tǒng)句柄,我們就可以過濾掉所有不屬于我們進(jìn)程的句柄,并從那些屬于我們進(jìn)程的句柄中提取對(duì)象值并在它與生成的 PID 之間進(jìn)行匹配。當(dāng)然,線程也可以這樣做,只使用 OpenThread 和 THREAD_QUERY_INFORMATION_LIMITED。

為了有效地打開系統(tǒng)上的所有進(jìn)程和線程,我們可以依賴 TlHelp32.h 庫的例程,它會(huì)允許我們拍攝系統(tǒng)上所有進(jìn)程和線程的快照,并遍歷該快照以獲取拍攝快照時(shí)運(yùn)行的進(jìn)程和線程的 PID 和 TID(線程 ID)。

下面的代碼塊顯示了我們?nèi)绾潍@取所述快照并遍歷它以獲取所有進(jìn)程的 PID。

首先定義一個(gè)std::map,這是c++中的一個(gè)類似字典的類,它允許我們跟蹤指向PID的句柄,我們將其稱為 mHandleId。

完成后,我們使用 CreateToolhelp32Snapshot 獲取有關(guān)進(jìn)程的系統(tǒng)狀態(tài)快照,并指定我們只需要進(jìn)程(通過 TH32CS_SNAPPROCESS 參數(shù))。這個(gè)快照被分配給快照變量,它的類型是 wil::unique_handle,它是 WIL 庫的一個(gè) C++ 類,它使我們擺脫了在使用句柄后必須正確清理句柄的負(fù)擔(dān)。完成后,我們定義并初始化一個(gè)名為 processEntry 的 PROCESSENTRY32W 變量,一旦我們開始遍歷快照,它將保存我們正在檢查的進(jìn)程的信息。

通過調(diào)用 Process32FirstW 并用快照中第一個(gè)進(jìn)程的數(shù)據(jù)填充 processEntry。對(duì)于每個(gè)進(jìn)程,我們嘗試在其 PID 上使用 PROCESS_QUERY_LIMITED_INFORMATION 調(diào)用 OpenProcess,如果成功,我們將句柄 - PID 對(duì)存儲(chǔ)在 mHandleId 映射中。

在每個(gè) while 循環(huán)中,我們執(zhí)行 Process32NextW 并用新進(jìn)程填充 processEntry 變量,直到它返回 false 并且我們退出循環(huán)?,F(xiàn)在,我們的句柄和它們指向的進(jìn)程的 PID 之間有一個(gè) 1 對(duì) 1 的映射?,F(xiàn)在進(jìn)入第二階段!

現(xiàn)在是獲取所有系統(tǒng)句柄并過濾掉不屬于我們進(jìn)程的句柄的時(shí)候了,我們已經(jīng)了解了如何檢索所有句柄,現(xiàn)在只需檢查每個(gè) SYSTEM_HANDLE 并將其 ProcessId 成員與我們的進(jìn)程的 PID 進(jìn)行比較,可通過恰當(dāng)命名的 GetCurrentProcessId 函數(shù)獲得。然后,我們以與處理句柄-PID 對(duì)類似的方式存儲(chǔ)屬于我們進(jìn)程的那些 SYSTEM_HANDLE 的 Object 和 Handle 成員的值,使用我們稱為 mAddressHandle 的映射。

你可能想知道為什么使用 switch 語句而不是簡單的 if。一些代碼已被刪除,因?yàn)檫@些是我們高級(jí)持久性 Tortellini 專門為尋找我們?cè)谖恼麻_頭提到的漏洞而編寫的工具的摘錄。

現(xiàn)在我們已經(jīng)填充了兩個(gè)映射,當(dāng)我們只知道它的 _EPROCESS 地址時(shí),獲取一個(gè)進(jìn)程的 PID 是一件輕而易舉的事。

我們首先將對(duì)象的地址保存在地址變量中,然后使用 find 方法在 mAddressHandle 映射中查找該地址,該方法將返回< uint64_t,HANDLE >。這對(duì)包含地址和它對(duì)應(yīng)的句柄。我們通過保存對(duì)成員的值來獲取句柄second并將其保存在foundHandle變量中。之后,只需要做我們剛才所做的事情,但是使用mHandleId映射和handlePid變量將保存進(jìn)程的 PID,其地址是我們開始的那個(gè)進(jìn)程。

現(xiàn)在我們有了一種可靠的方法來匹配地址和 PID,我們需要專門尋找那些完整性小于高進(jìn)程持有有趣的句柄的情況,這些句柄與完整性等于或大于高的進(jìn)程保持一致。但是從安全的角度來看,是什么讓句柄“有趣”呢?我們將關(guān)注的句柄是具有以下訪問掩碼的句柄:

PROCESS_ALL_ACCESS

PROCESS_CREATE_PROCESS

PROCESS_CREATE_THREAD

PROCESS_DUP_HANDLE

PROCESS_VM_WRITE

如果你在非特權(quán)進(jìn)程中找到具有至少一個(gè)此訪問掩碼的特權(quán)進(jìn)程的句柄,那非常幸運(yùn)。讓我們看看我們?nèi)绾巫龅竭@一點(diǎn)。

在這段代碼中,我們首先定義一個(gè)名為 vSysHandle 的 std::vector,它將保存有趣的 SYSTEM_HANDLE。之后,我們開始對(duì) NtQuerySystemInformation 返回的數(shù)據(jù)進(jìn)行常規(guī)迭代,只是這次我們跳過了當(dāng)前進(jìn)程持有的句柄。然后,我們通過我編寫的名為 GetTargetIntegrityLevel 的幫助函數(shù)檢查持有我們當(dāng)前正在分析的句柄的進(jìn)程的完整性級(jí)別。這個(gè)函數(shù)基本上返回一個(gè) DWORD,告訴我們與它作為參數(shù)接收的 PID 相關(guān)聯(lián)的令牌的完整性級(jí)別,并且改編自許多在線可用的 PoC 和 MSDN 函數(shù)。

一旦我們檢索到進(jìn)程的完整性級(jí)別,我們要確保它小于高完整性,因?yàn)槲覀兏信d趣的是持有感興趣的句柄的中完整性或低完整性進(jìn)程,我們還要確保我們正在處理的SYSTEM_HANDLE類型是進(jìn)程(0x7)。檢查后,我們轉(zhuǎn)到檢查句柄授予的訪問權(quán)限。如果句柄不是PROCESS_ALL_ACCESS或不包含任何指定的標(biāo)志,則跳過它。否則,我們更進(jìn)一步,檢索句柄所指進(jìn)程的 PID,并獲取其完整性級(jí)別。如果它是高完整性或更高的(例如SYSTEM),我們將SYSTEM_HANDLE保存在我們的vsyhandle中供以后使用。

首先,我們打開持有權(quán)限句柄的進(jìn)程,然后復(fù)制該句柄。

這是相當(dāng)簡單的,首先,你使用PROCESS_DUP_HANDLE訪問權(quán)限打開進(jìn)程,這是復(fù)制句柄所需的最小權(quán)限,然后在該進(jìn)程上調(diào)用DuplicateHandle,告訴函數(shù)你希望復(fù)制保存在syhandle中的句柄,并將其保存到clonedHandle變量中的當(dāng)前進(jìn)程中。

通過這種方式,我們的進(jìn)程現(xiàn)在處于權(quán)限句柄的控制之下,我們可以使用它來生成一個(gè)新進(jìn)程,把它的父進(jìn)程偽裝成該句柄所指向的權(quán)限進(jìn)程,從而使新進(jìn)程繼承它的安全上下文,并獲得命令shell等。

讓我們看看它的實(shí)際應(yīng)用:

本文翻譯自:https://aptw.tf/2022/02/10/leaked-handle-hunting.html

責(zé)任編輯:武曉燕 來源: 嘶吼網(wǎng)
相關(guān)推薦

2018-01-29 14:57:16

Linux文件權(quán)限find命令

2020-11-04 09:46:40

Volodya漏洞惡意軟件

2023-01-30 14:27:14

Linux進(jìn)程

2022-03-22 07:51:45

JS父節(jié)點(diǎn)

2017-12-21 18:41:46

Java內(nèi)存泄漏代碼

2020-11-09 09:33:19

Volodya漏洞惡意軟件

2021-05-09 20:22:41

順序查找二叉查找數(shù)據(jù)結(jié)構(gòu)

2017-01-17 15:29:59

2009-11-22 12:20:05

2009-02-05 10:39:23

BUGWindows7微軟

2012-12-13 13:46:08

2019-10-16 16:31:59

權(quán)限Android程序

2011-03-03 15:13:05

ProFTPD權(quán)限

2023-02-13 11:26:03

符號(hào)鏈接Linux

2009-10-21 13:39:08

UACWindows 7微軟

2010-09-16 16:06:37

2013-12-18 16:43:16

順序多核

2022-04-06 06:35:58

進(jìn)程命令CPU

2022-04-28 07:59:11

Polkitpkexec漏洞

2010-11-29 14:14:29

Sybase用戶權(quán)限
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)