浙江麻将机生产厂家
危險漫步博客
有時候,正是那些意想不到之人,成就了無人能成之事。
文章1443 瀏覽13842309

Windows7注冊表之SAM文件取證分析

Windows注冊表包含大量的鍵值,而且這些鍵值可能被用戶修改過,犯罪嫌疑犯也可能借用它隱藏一些隱私,如用戶密碼。故,一些注冊表鍵值在許多取證分析中都要被調查,它們并無必要對應一個給定領域,但是它們和大量計算機調查相關。這些鍵值包括基本的系統信息(誰使用了該系統,安裝了什么應用程序)和關鍵系統領域的更詳細信息(安裝了哪些硬件,裝載了哪些驅動器)等,如運行過的程序、訪問過的網站、編輯過的文檔等。這些信息可以為取證分析提供一定的幫助,而且容易獲取,因為都是明文顯示即通過注冊表API函數RegOpenKeyEx、RegEnumKeyEx、RegQueryValueEx即可獲取。讀者若對這些關鍵值路徑感興趣,可參考《InitialCaseAnalysisusingWindowsRegistryinComputerForensics》。

本文重點論述注冊表中隱藏的關鍵信息即用戶ID和密碼。

若系統事先設有密碼,則用戶輸入密碼進行系統之前,windows會對此明文密碼采用MD4算法進行散列,然后將散列值與系統中保存的HASH值進行比對。這些MD4散列值即存放在安全賬戶管理器SAM文件內。盡管SAM文件在最高權限下都無法訪問,但所有的信息都存放在注冊表內,故完全可以在SYSTEM權限下,通過調用注冊表API函數獲取到這些信息。本文是在參考VincentRoch在codeproject上發表的文章“RetrievetheWindows7PasswordHashontheFly”、DustinHurlbut的文章“ForensicDeterminationofaUser’sLogon的基礎上并結合自己的理解分析完成的,探討windows下SAM文件用戶密碼的破解分析。

1.SAM結構分析

SAM結構中包含兩內hash分別為:LanManhash和NThash,然而從Vista版本開始,因為LMhash的安全性略低于后者,故已經基本上不再使用了。在注冊表中用戶信息都存放在HKLM\SAM\SAM\Domains\Account\users\userRID下,其下的子鍵即每個賬號的SID相對標志符。每個賬戶下包含兩個子項,F和V。V值包含了用戶名、以及散列后的用戶密碼值等。

它實際上可以看作一個微型文件系統,包含多個指針即指向一個可變長度的結構體。每個指針結構為一個12字節值,例如第2個12字節結構體,前4字節即用戶數據起始相對偏移值(需要加上偏移量0xCC),中間4字節表示用戶名的長度,后4字節保留未用。如圖1所示,0xBC+0xCC=188,即偏移188處即為用戶名。

圖1.SAM文件中Adminitrator用戶的SID結構

而且,圖1中的12字節結構體中的第二個4字節包含特殊含義,即0xBC000000—ADMINISTRATIVEUSER0xD4000000USER—ONLYPRIVILEGELEVEL即受限制的用戶權限0xB0000000—GUESTACCOUNT

“F”鍵值中保存的是一些登錄記錄,如上次登錄時間、錯誤登錄次數等。從上面的分析,可知用戶密碼保存在SAM文件中,雖然系統默認下config文件受保護,但用戶信息全部存在在注冊表內,故這里我們可以在SCM(服務控制管理器)內注冊一個系統服務實現SAM文件取證。

2.創建新服務實現SAM文件取證

當一個服務控制程序請求開啟一個新的服務時,SCM開啟服務的同時,向控制調度器發送一個開始請求。控制調度器為服務創建一個新的線程來運行ServiceMain函數。代碼如下:


intAPIENTRYWinMain(HINSTANCEhProg,HINSTANCEhPrevInstance,LPSTRlpCmdLine,
intnCmdShow){
/*SERVICE_TABLE_ENTRY結構類型的數組,設置調用進程所提供的GetSAM服務的入口函數及字符串名*/
SERVICE_TABLE_ENTRYDispatchTable[]=
{
{GetSAM,(LPSERVICE_MAIN_FUNCTION)GetSAMServiceMain},
{NULL,NULL}
};
//連接程序主線程到服務控制管理程序
StartServiceCtrlDispatcher(DispatchTable);
}
DWORDWINAPIHandlerFunction(DWORDdwControl,DWORDdwEventType,LPVOID
lpEventData,LPVOIDlpContext){
SERVICE_STATUSServiceStatus;
if(dwControl==SERVICE_CONTROL_SHUTDOWN||
dwControl==SERVICE_CONTROL_STOP){
ServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hServiceStatus,ServiceStatus);
}
return(0);
}
voidGetSAMServiceMain(DWORDdwArgc,LPTSTR*lpszArgv){
SERVICE_STATUSServiceStatus;
//注冊一個處理控制請求的HandlerFunction函數
hServiceStatus=RegisterServiceCtrlHandlerEx(GetSAM,
(LPHANDLER_FUNCTION_EX)HandlerFunction,NULL);
ZeroMemory(ServiceStatus,sizeof(SERVICE_STATUS));
ServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState=SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN|
SERVICE_ACCEPT_STOP;
//調用SetServiceStatus函數來報告當前狀態為RUNNING態
SetServiceStatus(hServiceStatus,ServiceStatus);
//后臺服務程序開始分析SAM文件
RegistryEnumerateSAM();
}


通過自建的后臺服務,我們具備了分析SAM文件的權限。但密碼存放在用戶對應的SID的V鍵下卻是以一種密文形式存放。Windows2000版本之后,V鍵值內容似乎可結合用戶ID下的某個鍵值作為key輸入到DES算法中解密。事情變得卻是比較詭秘,微軟通過HKLM\SYSTEM\CurrentControlSet\Control\Lsa\{JD,Skew1,GBG,Data}四個鍵值的CLASS值,結合一個置換表換位得來。獲取syskey后,仍然存在兩大障礙需要解決。首先我們需要計算syskey的散列值,即使用syskey和F鍵的前0x10字節,與特殊的字符串

[email protected]#$%^*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@%,0123456789012345678901234567890123456789做MD5運算,再與F鍵的后0x20字節做RC4運算得到一個解密密鑰dkey即解密SAM中加密數據到散列態。當需要解密SAM中加密數據到散列時,需要將此dkey與當前用戶的SID、散列類型名NTPASSWORD做MD5運算獲取針對此用戶密碼散列的會話密鑰skey。利用skey作為RC4算法的解密密鑰對散列進行處理,然后將用戶SID擴展為14字節做DES切分,生成DESECB,再對RC4處理后的散列進行分開2次DES解密即可得到密碼散列。整個處理流程十分詭異。最后將用戶SID值作為salt,可確保不同用戶的相同散列在SAM中存放不一樣。

3.核心代碼分析

在獲取到每個HKLM\SAM\SAM\Domains\Account\users\UserID之后,我們需要對每個用戶的SAM進行分析。首先讀取SAM文件中的V鍵值對應的內容,其包含了Unicode形式表示的用戶名、字符串長度以及NThash的加密版本。


EnumerateRegValues(hSAM,V,VBlock,VBlockLen);//獲取NThash的密文長度
dwNTHashLen=VBlock[0xAC]+0x100*VBlock[0xAD]-4;//獲取用戶名長度
dwUserNameLen=VBlock[0x10]+0x100*VBlock[0x1a];
for(i=0;idwNTHashLen;i++){//獲取NThash密文
nthash[i]=VBlock[VBlock[0xa8]+VBlock[0xa9]*0x100+4+0xcc+i];
}
for(i=0;idwUserNameLen/2;i++){//獲取用戶名
UserNameA[i]=VBlock[VBlock[0xc]+VBlock[0xd]*0x100+0xcc+2*i];
}


前面我們也講到了如何獲取Syskey值,它由四個不同的鍵碼值信息組成,每個信息均存放在鍵值的class屬性內。


#defineREGISTRY_LSAJDSYSTEM\\CurrentControlSet\\Control\\Lsa\\JD
#defineREGISTRY_LSASKEWSYSTEM\\CurrentControlSet\\Control\\Lsa\\Skew1
#defineREGISTRY_LSAGBGSYSTEM\\CurrentControlSet\\Control\\Lsa\\GBG
#defineREGISTRY_LSADATASYSTEM\\CurrentControlSet\\Control\\Lsa\\Data//獲取這些鍵值對應的class屬性內容
dwError=RegQueryInfoKey(hKey,Class,dwcClass,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
for(i=0;i4;i++){
temp[0]=Class[2*i];
temp[1]=Class[2*i+1];//將ASCII轉換為16進制數
RegistryKeyValue[i]=strtol(temp,stop,16);
}
for(i=0;i4;i++){
/*依次從JD,Skew1,GBG,Data開始,分別獲取bootkey[0-3],bootkey[4-7],
bootkey[8-11],bootkey[12-15]值*/
bootkey[i]=RegistryKeyValue[i];
}
//對bootkey進行P置換得到syskey
for(i=0;i16;i++)syskey[i]=bootkey[p[i]];


至此,我們已經獲取到了syskey值。下面就是繁瑣的解密過程了,代碼就不在給出了。

按著前面分析的解密流程,即可實現。

4.小結

Windows注冊表容納了所有應用程序和計算機系統的全部配置信息、系統和應用程序的初始化信息、應用程序和文檔文件的關聯關系、硬件設備的說明、狀態和屬性以及各種狀態信息和數據。對于計算機取證分析員而言,注冊表的分析是至關重要一環。

浙江麻将机生产厂家 快乐十分同步开奖 ag电子游艺哪里有 秒速时时彩平台推荐 郑州如何赚钱 快乐10分开奖查询 上海时时乐官网 下载中心真人斗地主 彩票大奖组 广西快三开奖结果360 广东36选7走势图带坐标