繁体中文
设为首页
加入收藏
当前位置:技术首页 >> 安全 >> 系统和数据 >> NT平台拨号连接密码恢复原理

NT平台拨号连接密码恢复原理

2006-12-12 22:16:19  作者:雪焰  来源:xfocus  浏览次数:149  文字大小:【】【】【
简介:前段时间ADSL密码忘记了,但幸好还保存在拨号连接里面,于是到网上找了些星号密码显示工具,可惜不起作用。后来找到一种名为dialupass的工具,这家伙不负重望把密码给我还原出来了。(用的dialupass v2.42,我的系统是windows xp)
关键字:恢复 原理 平台 连接
前段时间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

#include

#include

#include

#include

#include

#include

#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
{

if(strcmp(&p[i], szDialParamsUID) == 0 )

{

for(j=i;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

#include

#include

#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
{

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 \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
{

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

责任编辑:雪焰

本文引用地址: http://tech.itzero.com/2006/1212/5179.html 请粘贴到你的QQ/MSN上推荐给你的好友

相关文章
交换机、路由口令恢复的步骤
Cisco路由器的口令恢复技巧
Cisco系列路由器密码恢复研究与实践
华为MSR路由器密码恢复功略
恢复Cisco路由器设置到起始配置
路由器原理综述
Windows Vista 的计算机从睡眠状态中恢复后,通过 USB 连接的 Portable Media Center 设备不再工作
备份和恢复Windows IIS服务器设置
IIS的连接参数、常见问题、错误代码
路由无法工作时,怎样恢复出厂默认值?
路由器口令恢复
 

最新文章

更多

· 苹果新系统遭破解 普通P...
· 设计差异引发 Web Servi...
· 关闭Windows XP自动播放...
· 大量开源安全应用程序确...
· 虚拟技术暗藏隐患 威胁...
· 通过建立安全模型保障We...
· 数据库安全应用 使用MyS...
· 无需攻击lsass进程即可解...
· 合理设计安全问题加强出...
· 从数据库管理下手 多手...

热点文章

更多

其它推荐