宽带连接用户名称和密码恢复原理.docx
《宽带连接用户名称和密码恢复原理.docx》由会员分享,可在线阅读,更多相关《宽带连接用户名称和密码恢复原理.docx(16页珍藏版)》请在冰豆网上搜索。
宽带连接用户名称和密码恢复原理
宽带连接用户名称和密码恢复原理
ADSL密码忘记了,但幸好还保存在拨号连接里面,到网上找了些星号密码显示工具,可惜不起作用。
后来找到一"获得宽带用户名称和密码"(xp)。
该工具并非非普通的星号密码显示工具,那它的原理是什么呢?
其实原理很简单,就是用rasapi32.dll里面的一些函数来获取拨号连接的一些信息(),再用ADVAPI32!
LsaRetrievePrivateData函数来获取密码,后来研究"LsaRetrievePrivateData"返回的数据。
其原理大致如下:
1)插入一线程到lsass.exe进程
2)打开LSAPolicydatabase
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对应的是用户的stringSID。
(“HKLM\SECURITY”这个键只有SYSTEM有权限读写,连admin都没有权限)LsarQuerySecret从注册表中读取出来数据后,接着调用LsapCrDecryptValue函数来解密,对于同一台机器来说,解密时用的KEY始终都是固定的,这个KEY在lsasrv.dll里面变量名为"_LsapDbSecretCipherKey"。
在windows2003里面,变量名不一样,对应的有两个,分别为"LsapDbSecretCipherKeyWrite"和"LsapDbSecretCipherKeyRead",但这两个变量里面的数据是一样的。
LsapCrDecryptValue用的似乎是标准DES算法,解密时主要流程如下:
lsasrv!
LsapCrDecryptValue
|_advapi32!
SystemFunction005
|_advapi32!
DecryptDataLength
|_advapi32!
SystemFunction002
|_advapi32!
DES_ECB_LM
|_advapi32!
des
解密后,在"<<"标示处还有一个判断:
.text:
785462F0call_LsapCrDecryptValue@12
.text:
785462F5testeax,eax
.text:
785462F7mov[ebp+var_8],eax
.text:
785462FAjlloc_785838E1
.text:
78546300
.text:
78546300loc_78546300:
.text:
78546300cmpbyteptr[esi+45h],0<<<<<<<<<<<<
.text:
78546304jzshortloc_7854632E
......
.text:
7854632Eloc_7854632E:
.text:
7854632Eleaeax,[ebp+var_10]
.text:
78546331pusheax
.text:
78546332push[ebp+arg_8]
.text:
78546335push[ebp+var_C]
.text:
78546338call_LsapCrEncryptValue@12
假如[esi+45h]为0的话(esi是LsarOpenSecret函数返回的HANDLE),它会把解密后的数据再进行一次加密,不管是Win2000还是Win2003,这时用的KEY始终都是固定为“SystemLibraryDTC”。
调用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
那么这个_LsapDbSecretCipherKey是如何产生的?
流程如下:
(1)调用ntdll!
NtConnectPort打开L"\Security\WxApiPort"
(2)调用ntdll!
NtRequestWaitReplyPort得到一些数据ebp-40处为NtRequestWaitReplyPort返回的LPCMESSAGE
kd>ddebp-40
0006fcb80040002800000002000000dc000000d8
0006fcc800000024000000000000000000000000
0006fcd8000000010000001000000010fd317e3e
0006fce87e24e86dd12503d35f7d01a87665f528
kd>dbebp-14
0006fce43e7e31fd6de8247e-d30325d1a8017d5f
(3)将上述"ebp-14"处的0x10字节数据COPY到lsasrv.dll里面的"_LsapDbSysKey"变量。
"_LsapDbSysKey"在不同的机器上面(即使版本相同)都是不一样的。
跟踪系统启动过程,可知道"\Security\WxApiPort"是由winlogon.exe进程创建的,然后lsass进程通过这个LPCPORT从winlogon进程获取SYSKEY,随后winlogon进程会关闭这个LPCPORT。
所以在系统启动完成之后,用"ProcessExplorer"等工具是看不到这个LPCPORT存在的,而且在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",它的结构如下,
typedefstruct_LSA_BLOB{
DWORDcbData;
DWORDcbMaxData;
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-=-=-=-=-=-=-=-=-=-=
/*
演示还原NT平台拨号连接密码
原理:
直接从注册表中读取加密后的数据,解密之。
可运行于windows2000/xp/2003平台,必须有权限读取注册表"HKLM\SECURITY"。
eyasatxfocus.org
2004-10-01
*/
#include
#include
#include
#pragmacomment(lib,"Advapi32.lib")
#pragmacomment(lib,"psapi.lib")
//抄袭tombkeeper的代码:
)
#defineFCHK(a)if(!
(a)){printf(#a"failed%d\n",GetLastError());return
0;}
typedefstruct_LSA_BLOB{
DWORDcbData;
DWORDcbMaxData;
BYTE*pbData;
}LSA_BLOB;
typedefint(WINAPI*PSystemFunction005)(
LSA_BLOB*pDataIn,
LSA_BLOB*pDataKey,
LSA_BLOB*pDataOut
);
PSystemFunction005SystemFunction005;
DWORDdwFlag=0;
//来自lsadump2中的dumplsa.c
intmyisprint(intch)
{
return((ch>='')&&(ch<='~'));
}
//来自lsadump2中的dumplsa.c
void
dump_bytes(unsignedchar*p,size_tsz)
{
charszDumpBuff[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){
charbuf[17];
inti=0;
intj=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);
}
}
DWORDsearch_LsapDbSecretCipherKey(BYTE**ppKey,DWORDpid)
{
HANDLEhLsass,hLsasrv;
DWORDdwRead,i,dwAddr;
BYTE*pImage=NULL;
MODULEINFOmod;
BOOLbRet=FALSE;
DWORDdwCount=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++;
}
}
}//endoffor
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
returndwCount;
}
returndwCount;
}
intmain(intargc,char**argv)
{
intret,i,j;
HMODULEhAdvApi32;
HKEYhKeySecrets;
HKEYhKey;
DWORDdwType;
charData[0x500]={0};
BYTE*pKey;
DWORDdwSize;
LSA_BLOBLSADataIn;
LSA_BLOBLSADataOut;
LSA_BLOBLSADataKey;
charszSecret[500];
charszSubKey[0x500];
DWORDdwErr,dwCount=0;
if(argc!
=2)
{
printf("Usage:
%s\n",argv[0]);
return0;
}
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];
//searchourtarget
for(i=0;TRUE;i++)
{
dwErr=RegEnumKeyA(hKeySecrets,i,szSecret,sizeof(szSecret));
if(dwErr!
=ERROR_SUCCESS)
//
//NoMoreSecrets
//
break;
printf("\n%s\n",szSecret);
//openit
_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);
}//endoffor
printf("Pressanykeytousenext\"LsapDbSecretCipherKey\",orCtrl+C
toexit.\n");
getchar();
}
if(pKey)
free(pKey);
r