NT平台ADSL拨号连接密码恢复原理
生活随笔
收集整理的這篇文章主要介紹了
NT平台ADSL拨号连接密码恢复原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
NT平臺撥號連接密碼恢復原理
創建時間:2004-11-08 更新時間:2004-11-12
文章屬性:原創
文章提交:eyas?(eyas_at_xfocus.org)
NT平臺撥號連接密碼恢復原理
Author : eyas
Email??: eyas at xfocus.org
Date?? : 2004-11-08
????前段時間ADSL密碼忘記了,但幸好還保存在撥號連接里面,于是到網上找了些星號密碼
顯示工具,可惜不起作用。后來找到一種名為dialupass的工具,這家伙不負重望把密碼給
我還原出來了。(用的dialupass v2.42,我的系統是windows xp)
????看起來dialupass非普通的星號密碼顯示工具,那它的原理是什么呢?上GOOGLE查了
一翻,沒找到相關資料(可能是我用的關鍵字有問題)。 一生氣便操起家伙(windbg)
準備把它大卸八塊。郁悶的是,用windbg加載后,密碼就還原不出來了,顯示是星號。換替
補ollydbg上場,情況依舊。莫非這小工具有Anti-Debug功能?當時只是一絲懷疑,因為實
在不相信這樣的小工具作者會花心思來保護。
????后來在用s-ice跟蹤的過程中,發現有這么一個調用:
????GetProcAddress(xx, "IsDebugPresent")。
????
????暈倒,原來真的有Anti-Debug功能,好在比較簡單。統計了一下,總共有5處進行了
Anti-Debug檢查。
????
????情況查明了,便換回windbg來調試,在windbg里面下這么一個斷點便可繞過Anti-Debug
檢測:
????bp KERNEL32!IsDebuggerPresent "g poi(esp);r eax=0;g"
????花了些時間跟蹤了一下,把dialupass恢復密碼的流程都搞清楚了。這小程序貓膩還
挺多的,總結如下:
????1. 關鍵函數不直接調用,而是用LoadLibraryA和GetProcAddress來獲取函數地址
后再CALL。
????2. 函數名是經過編碼的,反匯編后看字符串是看不到的。
????3. 關鍵地方一概用花指令來迷惑你和反匯編軟件。
????
????其實原理很簡單,就是用rasapi32.dll里面的一些函數來獲取撥號連接的一些信息,
再用 ADVAPI32!LsaRetrievePrivateData 函數來獲取密碼。
????根據dialupasss的原理,寫了個類似的工具,源代碼參見后面的x_dialupass.c。
????后來用"LsaRetrievePrivateData"和"RasDialParams"做關鍵字,重新在GOOGLE搜索了
一遍,找到一些類似的代碼。
????參考資源[1]和[2]的是俄羅斯人公布的演示代碼,沒有對LsaRetrievePrivateData返回
的數據進行拆分用戶名和密碼。參考資源[3]是日本人公布的完整的應用程序的代碼,可惜
在對LsaRetrievePrivateData返回的數據進行拆分處理時存在BUG,導致有些情況下用戶名
和密碼取的不正確。
????
????后來發現lsadump2 DUMP出來的數據里面包含了"LsaRetrievePrivateData"返回的數
據。lsadump2的原理大致如下:
????1)插入一線程到lsass.exe進程
????2)打開LSA Policy database
????3)從注冊表"HKLM\SECURITY\Policy\Secrets"中枚舉子鍵
????4)LsarOpenSecret
????5)LsarQuerySecret
????進一步跟蹤后發現,其實ADVAPI32!LsaRetrievePrivateData是通過NdrClientCall2
發送RPC調用到lsass.exe進程,lsass.exe里面再調用LsarOpenSecret、LsarQuerySecret
來完成獲取撥號連接信息過程的。(注:LsarOpenSecret里面有權限判斷,非ADMIN組用
戶是沒有權限來調用ADVAPI32!LsaRetrievePrivateData的)
?? 跟蹤了一下LsarQuerySecret,發現它返回的數據其實是從注冊表中讀取。保存撥號
連接信息的注冊表鍵值為:
????HKLM\SECURITY\Policy\Secrets\RasDialParams!SID#0\CurrVal
????SID對應的是用戶的string SID。(“HKLM\SECURITY”這個鍵只有SYSTEM有權限讀
寫,連admin都沒有權限)
????LsarQuerySecret從注冊表中讀取出來數據后,接著調用LsapCrDecryptValue函數來
解密,對于同一臺機器來說,解密時用的KEY始終都是固定的,這個KEY在lsasrv.dll里面
變量名為"_LsapDbSecretCipherKey"。在windows 2003里面,變量名不一樣,對應的有兩
個,分別為"LsapDbSecretCipherKeyWrite"和"LsapDbSecretCipherKeyRead",但這兩個
變量里面的數據是一樣的。
????LsapCrDecryptValue用的似乎是標準DES算法,解密時主要流程如下:
????lsasrv!LsapCrDecryptValue
????????|_ advapi32!SystemFunction005
????????????|_ advapi32!DecryptDataLength
????????????????|_ advapi32!SystemFunction002
????????????????????|_ advapi32!DES_ECB_LM
????????????????????????|_ advapi32!des
????解密后,在"<<"標示處還有一個判斷:
????.text:785462F0???????????????? call????_LsapCrDecryptValue@12
????.text:785462F5???????????????? test????eax, eax
????.text:785462F7???????????????? mov???? [ebp+var_8], eax
????.text:785462FA???????????????? jl??????loc_785838E1
????.text:78546300?
????.text:78546300 loc_78546300:??????????????????????????
????.text:78546300???????????????? cmp???? byte ptr [esi+45h], 0?? <<<<<<<<<<<<
????.text:78546304???????????????? jz??????short loc_7854632E
????......
????.text:7854632E loc_7854632E:
????.text:7854632E???????????????? lea???? eax, [ebp+var_10]
????.text:78546331???????????????? push????eax
????.text:78546332???????????????? push????[ebp+arg_8]
????.text:78546335???????????????? push????[ebp+var_C]
????.text:78546338???????????????? call????_LsapCrEncryptValue@12
????假如[esi+45h]為0的話(esi是LsarOpenSecret函數返回的HANDLE),它會把解密后的
數據再進行一次加密,不管是2000還是2003,這時用的KEY始終都是固定為
“SystemLibraryDTC”。
????lsadump2里面調用LsarOpenSecret得到的HANDLE,偏移0x45處值為1,所以
LsarQuerySecret函數返回的就是解密后的數據了。
????而在調用ADVAPI32!LsaRetrievePrivateData時,LsarOpenSecret返回的HANDLE偏移
0x45處值為0x0,所以LsarQuerySecret返回的是解密后又加密的數據,所以在
ADVAPI32!LsaRetrievePrivateData里面還有一個對應的解密過程。相應的,
LsapCrEncryptValue加密的主要流程如下:
????lsasrv!LsapCrEncryptValue
????????|_ advapi32!SystemFunction004
????????????|_ advapi32!EncryptDataLength
????????????????|_ advapi32!SystemFunction001
????????????????????|_ advapi32!DES_ECB_LM
????????????????????????|_ advapi32!des
????開始我以為在同一版本的windows里面,_LsapDbSecretCipherKey是固定的,后來
發現我錯了。那么這個_LsapDbSecretCipherKey是如何產生的?流程如下:
????(1)調用ntdll!NtConnectPort打開 L"\Security\WxApiPort"
????(2)調用ntdll!NtRequestWaitReplyPort得到一些數據
????????ebp-40處為NtRequestWaitReplyPort返回的LPCMESSAGE
????????kd> dd ebp-40
????????0006fcb8??00400028 00000002 000000dc 000000d8
????????0006fcc8??00000024 00000000 00000000 00000000
????????0006fcd8??00000001 00000010 00000010 fd317e3e
????????0006fce8??7e24e86d d12503d3 5f7d01a8 7665f528
????????kd> db ebp-14
????????0006fce4??3e 7e 31 fd 6d e8 24 7e-d3 03 25 d1 a8 01 7d 5f
????(3)將上述"ebp-14"處的0x10字節數據COPY到lsasrv.dll里面的"_LsapDbSysKey"變量。
"_LsapDbSysKey"在不同的機器上面(即使版本相同)都是不一樣的。它是怎么產生的?有
幸拜讀了flashsky的大作后(參考資源[4]),才明白這就是傳說中的"SYSKEY"。用flashsky
的代碼驗證一下:
????????c:\>getsyskey
????????3e 7e 31 fd 6d e8 24 7e d3 03 25 d1 a8 01 7d 5f
????跟蹤系統啟動過程,可知道"\Security\WxApiPort"是由winlogon.exe進程創建的,然
后lsass進程通過這個LPC PORT從winlogon進程獲取SYSKEY,隨后winlogon進程會關閉這
個LPC PORT。所以在系統啟動完成之后,用"Process Explorer"等工具是看不到這個
LPC PORT存在的,而且在winlogon和LSASS進程空間都搜索不到上述SYSKEY。
????(4)從注冊表"HKLM\SECURITY\Policy\PolSecretEncryptionKey"中讀取出來一段數據,
調用函數_LsapDbDecryptKeyWithSyskey,把它用"_LsapDbSysKey"來解密,
"_LsapDbSecretCipherKey"就在解密完后的數據里面。("LsapDbDecryptKeyWithSyskey"函
數做的其實就是MD5和RC4運算)
????????
????了解原理后,我們就可以直接從注冊表里面來獲取撥號連接中的密碼等數據了。但
有幾個問題需要解決:
????(1)原料。
????Q:"HKLM\SECURITY"鍵只有SYSTEM有權限讀寫?
????A:我們可以把代碼插入到SYSTEM進程里面去運行,或者把這個鍵修改為ADMIN有
權限讀,或者提升本進程權限。
????(2)催化劑:)
????Q: 如何獲取"_LsapDbSysKey"?解密用的函數_LsapDbDecryptKeyWithSyskey為非導出函
數,怎么辦?
????A1: 用flashsky的代碼來獲取SYSKEY,利用公開的MD5和RC4庫函數來解密。
????A2: 直接從lsass.exe進程里面搜索"_LsapDbSecretCipherKey",它的結構如下,
????typedef struct _LSA_BLOB {
????????????DWORD cbData;
????????????DWORD cbMaxData;
????????????BYTE* pbData;
????} LSA_BLOB;
????pbData指向存儲KEY的地址,KEY長度固定為0x10字節,即cbData和cbMaxData都是固定
為0x10。所以從lsass進程的空間里面搜索"\x10\x00\x00\x00\x10\x00\x00\x00"即可找到
正確的KEY。結果可能會有多個,可以把所有搜索到的KEY都試一下,總有一個正確的。
????(3)工具
????Q: 解密函數LsapCrDecryptValue為非導出函數,怎么辦?
????A: 或許可以根據特征碼來搜索,但總覺得不太可靠。幸好,LsapCrDecryptValue
調用的advapi32!SystemFunction005是導出函數:)。或者直接利用公開的DES庫函數,
自己來運算。
????x_dialupass2.cpp中的代碼演示了直接從注冊表中讀取數據并解密之的過程,沒有
太多實際意義,just for fun!
-=-=-=-=-=-=-=-=-=-=??x_dialupass.c??-=-=-=-=-=-=-=-=-=-=
/*
演示還原NT平臺上撥號連接的密碼
可運行于windows 2000/xp/2003
原理基于分析dialupass v2.42
eyas at xfocus.org
http://www.xfocus.net
2004-10-01
FileName: x_dialupass.c
*/
#define WINVER 0x500
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <ras.h>
#include <raserror.h>
#include <Ntsecapi.h>
#include <Userenv.h>
#include <Sddl.h>
#pragma comment(lib,"Rasapi32.lib")
#pragma comment(lib,"advapi32.lib")
#pragma comment(lib,"UserEnv.lib")
unsigned char????????????private_data[0x500];
int????????????????????????data_len;
unsigned char * get_real_pass(unsigned char *user, DWORD dwDialParamsUID)
{
????int????i, j;
????unsigned char *p, szDialParamsUID[52], *pass=NULL;
????_snprintf(szDialParamsUID, sizeof(szDialParamsUID),?
????????"%d", dwDialParamsUID);
????p = private_data;
????for(i=0;i<data_len;i++)
????{
????????if(strcmp(&p[i], szDialParamsUID) == 0 )
????????{
????????????for(j=i;j<data_len;j++)
????????????{
????????????????if(strcmp(&p[j], user) == 0 )
????????????????{
????????????????????pass = p + j + strlen(user) + 1;
????????????????????break;
????????????????}
????????????}
????????????break;
????????}
????}
????return pass;
}
void main()
{
????LPRASENTRYNAME lpRasEntryName;
????LPRASDIALPARAMS lpRasDialParams;
????DWORD????????????cb, nRet, i, cEntries;
????BOOL????????????b;
????char????????????szPhoneBook1[512], szPhoneBook2[512],?
????????????????????szUserName[128], szDomainName[128];
????DWORD????????????dwSize, dwDialParamsUID, dwTmp;
????PSID????????????pSid = NULL;
????SID_NAME_USE????peUse;
????LSA_OBJECT_ATTRIBUTES????lsa_object_attr;
????LSA_HANDLE????????????????lsa_handle;
????PLSA_UNICODE_STRING????????plsa_private_data;
????LSA_UNICODE_STRING????????lsa_keyname;
????NTSTATUS????????????????status;
????int????????????????????????ret;
????unsigned char????????????*pass;
????WCHAR????????????????????*sid;
????printf("dialup password recover tool for win 2k/xp/2003\n"
????????????"code by eyas at xfocus.org\n"
????????????"http://www.xfocus.net\n"
????????????"2004-10-01\n\n");
????//get current user's string sid
????dwSize = sizeof(szUserName);
????GetUserName(szUserName, &dwSize);
????dwSize = 0;
????dwTmp = sizeof(szDomainName);
????LookupAccountName(NULL, szUserName, pSid, &dwSize, szDomainName,?
????????????????????&dwTmp, &peUse);
????if(!dwSize)
????{
????????printf("[-] LookupAccountName failed.\n");
????????return;
????}
????pSid = (PSID)malloc(dwSize);
????LookupAccountName(NULL, szUserName, pSid, &dwSize, szDomainName,
???????????????????? &dwTmp, &peUse);
????ConvertSidToStringSidW(pSid, &sid);
????memset(&lsa_object_attr, 0, sizeof(lsa_object_attr));
????lsa_object_attr.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
????LsaOpenPolicy(0, &lsa_object_attr, 0x800, &lsa_handle);
????plsa_private_data = (PLSA_UNICODE_STRING)malloc(sizeof(LSA_UNICODE_STRING));
????plsa_private_data->Length = 0x500;
????plsa_private_data->MaximumLength = 0x500;
????plsa_private_data->Buffer = (PWSTR)malloc(0x500);
????lsa_keyname.MaximumLength = 0x200;
????lsa_keyname.Buffer = (PWSTR)malloc(0x200);
????wcscpy(lsa_keyname.Buffer,L"RasDialParams!");
????wcscat(lsa_keyname.Buffer, sid);
????wcscat(lsa_keyname.Buffer, L"#0");
????lsa_keyname.Length = wcslen(lsa_keyname.Buffer) * 2;
????//get current user's dialup info
????status = LsaRetrievePrivateData(lsa_handle,?
????????&lsa_keyname,
????????&plsa_private_data);
????LsaClose(lsa_handle);
????if(status != 0)
????{
????????printf("[-] LsaRetrievePrivateData failed: %d\n",
???????????????????? LsaNtStatusToWinError(status));
????????return;
????}
????ret = WideCharToMultiByte(0, 0, plsa_private_data->Buffer,
???????????????????????????? plsa_private_data->Length,?
????????private_data, sizeof(private_data), 0, 0);
????if(ret == 0)
????{
????????printf("[-] WideCharToMultiByte failed:%d\n", GetLastError());
????????return;
????}
????data_len = ret;
????//get phone book name
????GetEnvironmentVariable("ALLUSERSPROFILE", szPhoneBook1,
???????????????????????????? sizeof(szPhoneBook1)-200);
????GetEnvironmentVariable("USERPROFILE", szPhoneBook2,
???????????????????????????? sizeof(szPhoneBook2)-200);
????strcat(szPhoneBook1,?
????????"\\Application Data\\Microsoft\\Network"
????????"\\Connections\\pbk\\rasphone.pbk");
????strcat(szPhoneBook2,?
????????"\\Application Data\\Microsoft\\Network"
????????"\\Connections\\pbk\\rasphone.pbk");
????lpRasEntryName = (LPRASENTRYNAME)GlobalAlloc(GPTR, sizeof(RASENTRYNAME));
????lpRasEntryName->dwSize = sizeof(RASENTRYNAME);
????cb = sizeof(RASENTRYNAME);
????if ((nRet = RasEnumEntries(NULL, NULL, lpRasEntryName, &cb, &cEntries))?
????????== ERROR_BUFFER_TOO_SMALL)
????{
????????lpRasEntryName = (LPRASENTRYNAME)GlobalAlloc(GPTR, cb);
????????lpRasEntryName->dwSize = sizeof(RASENTRYNAME);
????}
????// Calling RasEnumEntries to enumerate the phone-book entries????
????nRet = RasEnumEntries(NULL, NULL, lpRasEntryName, &cb, &cEntries);
????if (nRet != ERROR_SUCCESS)
????{
????????printf("[-] RasEnumEntries failed: Error %d\n", nRet);
????????return;
????}
????for(i=0;i < cEntries;i++)
????{
????????lpRasDialParams = malloc(sizeof(RASDIALPARAMS));
????????strcpy(lpRasDialParams->szEntryName, lpRasEntryName->szEntryName);
????????lpRasDialParams->dwSize = sizeof(RASDIALPARAMS);
????????RasGetEntryDialParams(0, lpRasDialParams, &b);
????????dwDialParamsUID = GetPrivateProfileInt(lpRasEntryName->szEntryName,?
????????????"DialParamsUID", 0, szPhoneBook1);
????????if(dwDialParamsUID == 0)
????????{
????????????dwDialParamsUID = GetPrivateProfileInt(lpRasEntryName->szEntryName,?
????????????????????????????????"DialParamsUID", 0, szPhoneBook2);
????????????if(dwDialParamsUID == 0)
????????????{
????????????????printf("[-] Can't get DialParamsUID from PhoneBook.\n");
????????????????return;
????????????}
????????}
????????pass = get_real_pass(lpRasDialParams->szUserName, dwDialParamsUID);
????????printf(
????????????"-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"
????????????"EntryName : %s\n"
????????????"UserName??: %s\n"
????????????"PassWord??: %s\n\n",
????????????lpRasEntryName->szEntryName,
????????????lpRasDialParams->szUserName,?
????????????pass);
????????free(lpRasDialParams);
????????lpRasEntryName++;
????}
}
-=-=-=-=-=-=-=-=-=-= code end -=-=-=-=-=-=-=-=-=-=
-=-=-=-=-=-=-=-=-=-= x_dialupass2.cpp -=-=-=-=-=-=-=-=-=-=
/*
演示還原NT平臺撥號連接密碼
原理:直接從注冊表中讀取加密后的數據,解密之。
可運行于windows 2000/xp/2003平臺,必須有權限讀取注冊表 "HKLM\SECURITY"。
eyas at xfocus.org
http://www.xfocus.net
2004-10-01
*/
#include <Windows.h>
#include <stdio.h>
#include <Psapi.h>
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "psapi.lib")
//抄襲tombkeeper的代碼:)
#define FCHK(a)???? if (!(a)) {printf(#a " failed %d\n", GetLastError()); return?
0;}
typedef struct _LSA_BLOB {
????DWORD cbData;
????DWORD cbMaxData;
????BYTE* pbData;
} LSA_BLOB;
typedef int (WINAPI *PSystemFunction005)(
????LSA_BLOB* pDataIn,
????LSA_BLOB* pDataKey,
????LSA_BLOB* pDataOut
);
PSystemFunction005????SystemFunction005;
DWORD????????????????dwFlag=0;
//來自lsadump2中的dumplsa.c
int myisprint (int ch)
{
????return ((ch >= ' ') && (ch <= '~'));
}
//來自lsadump2中的dumplsa.c
void
dump_bytes (unsigned char *p, size_t sz)
{
????char szDumpBuff[256];
????if(sz==0)
????????return;
????while (sz > 16) {
????????_snprintf (szDumpBuff, sizeof (szDumpBuff),
?????????????????? " %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X?
%02X %02X %02X %02X??%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
?????????????????? p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
?????????????????? p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15],
?????????????????? myisprint(p[0]) ? p[0] : '.',
?????????????????? myisprint(p[1]) ? p[1] : '.',
?????????????????? myisprint(p[2]) ? p[2] : '.',
?????????????????? myisprint(p[3]) ? p[3] : '.',
?????????????????? myisprint(p[4]) ? p[4] : '.',
?????????????????? myisprint(p[5]) ? p[5] : '.',
?????????????????? myisprint(p[6]) ? p[6] : '.',
?????????????????? myisprint(p[7]) ? p[7] : '.',
?????????????????? myisprint(p[8]) ? p[8] : '.',
?????????????????? myisprint(p[9]) ? p[9] : '.',
?????????????????? myisprint(p[10]) ? p[10] : '.',
?????????????????? myisprint(p[11]) ? p[11] : '.',
?????????????????? myisprint(p[12]) ? p[12] : '.',
?????????????????? myisprint(p[13]) ? p[13] : '.',
?????????????????? myisprint(p[14]) ? p[14] : '.',
?????????????????? myisprint(p[15]) ? p[15] : '.');
????????printf ("%s", szDumpBuff);
????????p+=16;
????????sz -= 16;
????}
????if (sz) {
????????char buf[17];
????????int i = 0;
????????int j = 16 - sz;
????????memset (buf, 0, sizeof (buf));
????????szDumpBuff[0] = 0;
????????while (sz--) {
????????????_snprintf (szDumpBuff+strlen (szDumpBuff),
?????????????????????? sizeof (szDumpBuff) - strlen (szDumpBuff),
?????????????????????? " %02X", *p);
????????????if (myisprint (*p))
????????????????buf[i++] = *p;
????????????else
????????????????buf[i++] = '.';
????????????p++;
????????}
????????_snprintf (szDumpBuff+strlen (szDumpBuff),
?????????????????? sizeof (szDumpBuff)-strlen (szDumpBuff),
?????????????????? "%*s%s\n", j*3 + 2, "", buf);
????????printf ("%s", szDumpBuff);
????}
}
DWORD search_LsapDbSecretCipherKey(BYTE **ppKey, DWORD pid)
{
????HANDLE????hLsass, hLsasrv;
????DWORD????dwRead, i, dwAddr;
????BYTE????*pImage = NULL;
????MODULEINFO????mod;
????BOOL????bRet = FALSE;
????DWORD????dwCount = 0, dwMaxCount=100;
????FCHK ( (hLsasrv = LoadLibrary("lsasrv.dll")) );
????FCHK ( GetModuleInformation(GetCurrentProcess(), (HMODULE)hLsasrv,?
????????&mod, sizeof(mod)) );
????FCHK ( hLsass = OpenProcess(PROCESS_VM_READ, FALSE, pid) );
????pImage = (BYTE*)malloc(mod.SizeOfImage);
????ReadProcessMemory(hLsass, (BYTE*)hLsasrv,?
????????????????????????????pImage, mod.SizeOfImage-0x10, &dwRead);
????*ppKey = (BYTE*)malloc(dwMaxCount*0x10);
????
????__try
????{
????????for(i=0;i<mod.SizeOfImage;i++)
????????{
????????????if( memcmp(&pImage[i], "\x10\x00\x00\x00\x10\x00\x00\x00", 8) == 0)
????????????{
????????????????dwAddr = *(DWORD *)(&pImage[i+8]);
????????????????if( ReadProcessMemory(hLsass, (LPCVOID)dwAddr,?
????????????????????????????&(*ppKey[dwCount*0x10]), 0x10, &dwRead) )
????????????????{
????????????????????????dwCount++;
????????????????}
????????????}
????????}//end of for
????}
????__except(EXCEPTION_EXECUTE_HANDLER)
????{
????????return dwCount;
????}
????return dwCount;
}
int main(int argc, char **argv)
{
????int ret,i,j;
????HMODULE hAdvApi32;
????HKEY hKeySecrets;
????HKEY hKey;
????DWORD dwType;
????char Data[0x500] = {0};
????BYTE????*pKey;
????DWORD dwSize;
????LSA_BLOB LSADataIn;
????LSA_BLOB LSADataOut;
????LSA_BLOB LSADataKey;
????char szSecret[500];
????char szSubKey[0x500];
????DWORD dwErr, dwCount=0;
????if(argc!=2)
????{
????????printf("Usage: %s <pid of lsass.exe>\n", argv[0]);
????????return 0;
????}
????FCHK ((hAdvApi32 = LoadLibrary("advapi32.dll")));
????FCHK ((SystemFunction005 = (PSystemFunction005)
?????????? GetProcAddress (hAdvApi32, "SystemFunction005")) != NULL);
????
????FCHK ((RegOpenKeyEx (HKEY_LOCAL_MACHINE,
??????????????????????"SECURITY\\Policy\\Secrets",
??????????????????????0, KEY_READ, &hKeySecrets) == ERROR_SUCCESS))
????FCHK ( ( dwCount = search_LsapDbSecretCipherKey(&pKey, atoi(argv[1])) ) != 0?
);
????printf("Search \"LsapDbSecretCipherKey\" return: %d\n", dwCount);
????for(j=0;j<dwCount;j++)
????{
????????printf("LsapDbSecretCipherKey [%d]\n", j);
????????dump_bytes(&pKey[j*0x10], 0x10);
????????LSADataKey.cbData = LSADataKey.cbMaxData = 0x10;
????????LSADataKey.pbData = &pKey[j*0x10];
????????//search our target
????????for (i=0; TRUE; i++)
????????{
????????????dwErr = RegEnumKeyA (hKeySecrets, i, szSecret, sizeof (szSecret));
????????????if (dwErr != ERROR_SUCCESS)
????????????????//
????????????????// No More Secrets
????????????????//
????????????????break;
????????????printf("\n%s\n", szSecret);
????????????//open it
????????????_snprintf(szSubKey, sizeof(szSubKey),?
????????????????"SECURITY\\Policy\\Secrets\\%s\\CurrVal", szSecret);
????????????if (ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
????????????????????????????????????szSubKey,
????????????????????????????????????0,
????????????????????????????????????KEY_READ,
????????????????????????????????????&hKey
????????????????????????????????????) != ERROR_SUCCESS )
????????????????continue;
????????????dwSize = sizeof(Data);
????????????FCHK ((ret = RegQueryValueEx(hKey,
????????????????????????????????"",
????????????????????????????????NULL,
????????????????????????????????&dwType,
????????????????????????????????(LPBYTE)Data,
????????????????????????????????&dwSize) == ERROR_SUCCESS ))
????????????LSADataIn.pbData = (BYTE *)Data + 0xC;??//密文從第0xC位開始
????????????LSADataIn.cbData = dwSize-0xC;
????????????LSADataIn.cbMaxData = LSADataIn.cbData;
????????????//dump_bytes(LSADataIn.pbData, LSADataIn.cbData);
????????????LSADataOut.cbData = 0;
????????????LSADataOut.cbMaxData = 0;
????????????LSADataOut.pbData = NULL;
????????????SystemFunction005(&LSADataIn, &LSADataKey, &LSADataOut);
????????????if (LSADataOut.cbData == 0)
????????????{
????????????????printf("null\n");
????????????????continue;
????????????}
????????????FCHK ((LSADataOut.pbData = (BYTE*)malloc(LSADataOut.cbData) ) !=?
NULL);
????????????LSADataOut.cbMaxData = LSADataOut.cbData;
????????????SystemFunction005(&LSADataIn, &LSADataKey, &LSADataOut);
????????????dump_bytes(LSADataOut.pbData, LSADataOut.cbData);
????????????free(LSADataOut.pbData);
????????}//end of for
????????printf("Press any key to use next \"LsapDbSecretCipherKey\", or Ctrl+C?
to exit.\n");
????????getchar();
????}
????if(pKey)
????????free(pKey);
????return 0;
}
-=-=-=-=-=-=-=-=-=-= code end -=-=-=-=-=-=-=-=-=-=??
參考資源:
[1]?http://www.lwteam.ru/modules/news/article.php?storyid=167
????2003-06-24 by Cmeptb
[2]?http://www.wasm.ru/forum/index.php?action=vthread&forum=12&topic=4873
????2004-01-10 by ??
[3]?http://homepage2.nifty.com/spw/software/rtrick/
????2004-01-05 by ???
[4] SAM的散列存儲加密解密算法以及SYSKEY的計算
????http://www.xfocus.net/articles/200306/550.html
????2003-06-04 by flashsky at xfocus.org
轉載于:https://www.cnblogs.com/xtfnpgy/p/9285382.html
總結
以上是生活随笔為你收集整理的NT平台ADSL拨号连接密码恢复原理的全部內容,希望文章能夠幫你解決所遇到的問題。