導(dǎo)語:在本文中,我將描述我編寫的一個(gè)工具,能使用API鉤子從Microsoft RDP客戶端提取明文憑據(jù),而且如果是在已經(jīng)受感染用戶的權(quán)限下操作(比如網(wǎng)絡(luò)釣魚導(dǎo)致),并且該用戶已打開RDP會(huì)話,則可以提取明文憑據(jù)而無需提權(quán)。
介紹
遠(yuǎn)程桌面(RDP)是用于管理Windows Server的最廣泛使用的工具之一,除了被管理員使用外,也容易成為攻擊者的利用目標(biāo)。登錄到RDP會(huì)話的憑據(jù)通常用于是具有管理權(quán)限的,這也使得它們成為紅隊(duì)行動(dòng)的一個(gè)理想目標(biāo)。站在傳統(tǒng)的角度看,許多人傾向于使用LSASS進(jìn)行憑據(jù)盜竊,但是lsass.exe通常受到EDR和防病毒產(chǎn)品的監(jiān)視,而且對(duì)LSASS的操作通常需要權(quán)限訪問,于是我們自然就會(huì)考慮,有沒有一種更容易的替代方案?
在本文中,我將描述我編寫的一個(gè)工具,能使用API鉤子從Microsoft RDP客戶端提取明文憑據(jù),而且如果是在已經(jīng)受感染用戶的權(quán)限下操作(比如網(wǎng)絡(luò)釣魚導(dǎo)致),并且該用戶已打開RDP會(huì)話,則可以提取明文憑據(jù)而無需提權(quán)。
API鉤子
簡(jiǎn)單來說,API鉤子是通過將程序重定向到另一個(gè)函數(shù)來攔截程序中函數(shù)調(diào)用的過程。這是通過重新編寫目標(biāo)函數(shù)的內(nèi)存代碼來實(shí)現(xiàn)的。有幾種API掛鉤方法,技術(shù)都比較復(fù)雜,細(xì)述的話需要單獨(dú)的篇章。
而就本文而言,我們將使用到的是Microsoft Detours庫(kù),該庫(kù)是開源的,并且支持32位和64位進(jìn)程。其他框架(如Frida)也能提供類似的功能,但是Detours是非常輕量級(jí)的。為了演示這個(gè)庫(kù)有多么強(qiáng)大,我們將使用它為MessageBox函數(shù)創(chuàng)建一個(gè)鉤子。
鉤住函數(shù)之前,我們需要做兩件事,一個(gè)是包含原始函數(shù)地址和被鉤住函數(shù)地址的目標(biāo)指針,為了使鉤子正常工作,目標(biāo)函數(shù)和被鉤住的函數(shù)都應(yīng)具有相同數(shù)量的參數(shù)、參數(shù)類型和調(diào)用約定。
在下面的示例中,我們鉤住了MessageBox調(diào)用并修改了傳遞給原始函數(shù)的參數(shù)。
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include <detours.h>
static int(WINAPI * TrueMessageBox)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) = MessageBox;
int WINAPI _MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) {
return TrueMessageBox(NULL, L"Hooked", L"Hooked", 0);
}
int main()
{
// Hook MessageBox
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueMessageBox, _MessageBox); // Two Arguments DetourTransactionCommit();
MessageBox(NULL, L"We can't be hooked", L"Hello", 0); // Detach Hooked Function
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueMessageBox, _MessageBox); DetourTransactionCommit();
}
運(yùn)行程序,第二個(gè)消息框應(yīng)為Unhooked,但由于我們將其鉤住并修改了參數(shù),所以消息框如下圖所示:
尋找要鉤住的函數(shù)
在進(jìn)行任何掛鉤之前,我們需要確定感興趣的函數(shù)。這些函數(shù)最好將我們感興趣的數(shù)據(jù)作為參數(shù);在本例中,是服務(wù)器主機(jī)名/IP、用戶名和密碼。對(duì)于這種情況,API監(jiān)視器是一個(gè)非常強(qiáng)大的工具,它允許你附加到一個(gè)進(jìn)程,記錄所有API調(diào)用并瀏覽結(jié)果。
為此,我們將API監(jiān)視器附加到mstsc.exe并啟動(dòng)一個(gè)示例連接:
現(xiàn)在,我們可以在所有API調(diào)用中搜索作為用戶名提供的字符串。在本例中,幾個(gè)API調(diào)用都包含此字符串,但是最值得注意的一個(gè)是CredIsMarshaledCredentialW。
通過MSDN,我們可以看到它只使用一個(gè)指向C Unicode字符串的long指針類型的參數(shù)。
為了確保通過掛鉤此函數(shù)獲得正確的數(shù)據(jù),我們將Windbg附加到mstsc.exe,并在CredIsMarshaledCredentialW處設(shè)置一個(gè)斷點(diǎn)。嘗試登錄時(shí),我們可以看到傳遞給該函數(shù)的第一個(gè)參數(shù)是Unicode字符串的地址。
按照相同的方法搜索密碼字符串,然后可以看到對(duì)CryptProtectMemory的調(diào)用,并帶有指向密碼字符串的指針。
根據(jù)API監(jiān)視器,CryptProtectMemory位于Crypt32.dll中,由于該函數(shù)是在最新版本的Win10上由dpapi.dll導(dǎo)出的,因此位置不正確。為了確保我們?cè)诖薃PI調(diào)用上也具有正確的數(shù)據(jù),我們將Windbg附加到進(jìn)程,并為CryptProtectMemory函數(shù)設(shè)置一個(gè)斷點(diǎn)。
通過檢查內(nèi)存,我們可以假定傳遞的參數(shù)是指向結(jié)構(gòu)的指針。由于我們所需要的信息只是結(jié)構(gòu)的開始,因此不必完全解析它。與前面的示例相反,該函數(shù)有多個(gè)調(diào)用,其中不包含我們所需要的信息。我們可以觀察到前4個(gè)字節(jié)中包含了密碼字符串的大小,從內(nèi)存中讀取大小,并比較它是否大于0x2,如果條件為true,則意味著結(jié)構(gòu)中包含密碼并可提取。
SspiPrepareForCredRead遵循相同的過程,該過程接收IP地址作為第二個(gè)參數(shù)。
RdpThief演示
現(xiàn)在,我們清楚地了解了需要掛鉤哪些函數(shù)以提取信息,這些信息可以作為實(shí)現(xiàn)類似于RdpThief的功能的基礎(chǔ)。
RdpThief本身是一個(gè)獨(dú)立的DLL,當(dāng)注入mstsc.exe進(jìn)程時(shí),它將執(zhí)行API鉤子,提取明文憑據(jù)并將其保存到文件中。它附帶一個(gè)攻擊者腳本,負(fù)責(zé)管理狀態(tài)、監(jiān)視新進(jìn)程并將shellcode注入mstsc.exe。DLL已使用sRDI項(xiàng)目轉(zhuǎn)換為shellcode。啟用后,RdpThief將每5秒獲取一次進(jìn)程列表,搜索mstsc.exe后注入其中。
當(dāng)將攻擊者腳本加載到Cobalt Strike上時(shí),將提供三個(gè)新命令:
rdpthief_enable:?jiǎn)⒂脤?duì)新的mstsc.exe進(jìn)程的心跳檢查并將其注入。
rdpthief_disable:禁用新mstsc.exe的心跳檢查,但不會(huì)卸載已加載的DLL。
rdpthief_dump:打印提取的憑據(jù)(如果有的話)。
可以在此視頻中找到RdpThief的簡(jiǎn)單演示。文章來源:http://www.zghlxwxcb.cn/news/detail-433553.html
RdpThief工具源代碼在此。文章來源地址http://www.zghlxwxcb.cn/news/detail-433553.html
到了這里,關(guān)于從遠(yuǎn)程桌面客戶端提取明文憑證的工具RdpThief的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!