???題目中的Windows憑據(jù)(Credential)其實(shí)就是指用戶帳戶和口令。最近項(xiàng)目中存在一臺(tái)Windows(PC)機(jī)去管理服務(wù)器(Server),這之中就設(shè)計(jì)到服務(wù)器管理員權(quán)限的問(wèn)題。需要用戶對(duì)Windows上存儲(chǔ)的用戶名和密碼進(jìn)行管理。
???在Windows XP和Server 2003 中都已存在了“存儲(chǔ)的用戶名和密碼”。在XP中,通過(guò)控制面板中的用戶帳戶-〉選擇用戶-〉管理我的網(wǎng)絡(luò)密碼。而在Server 2003中,則在控制面板下直接有“存儲(chǔ)的用戶名和密碼”項(xiàng)。
???我們調(diào)用一些API,如WTSOpenServer,QueryServiceStatus,NetUserEnum等等涉及到RPC的,只要當(dāng)前用戶存儲(chǔ)有目標(biāo)遠(yuǎn)程機(jī)的權(quán)限合適的憑據(jù),則這些API就不會(huì)因產(chǎn)生ERROR_ACCESS_DENIED而執(zhí)行失敗。因?yàn)槲疫€不Windows的底層是如何進(jìn)行控制的,比如,是否調(diào)用了SSPI,所以,執(zhí)行這些API時(shí),我只能向用戶要管理員口令。但又不可能每次都讓用戶去輸入一遍用戶名和密碼,那么,也就需要保存密碼。
???既然保存了密碼,就必須考慮刪除密碼,那么密碼管理的問(wèn)題也就來(lái)了。說(shuō)到密碼管理,我在前些年看電視的時(shí)候,看到介紹一個(gè)叫什么“網(wǎng)絡(luò)螃蟹”的網(wǎng)站,他就是專門(mén)提供個(gè)人密碼管理的,當(dāng)時(shí)我就想,有人會(huì)去把自己的密碼交給別人打理嗎?這好像不大可能。何來(lái)也就沒(méi)聽(tīng)到什么網(wǎng)絡(luò)螃蟹橫行的消息。
???現(xiàn)在我的項(xiàng)目中,如果用戶有了一臺(tái)機(jī)器(PC)的密碼,那么,他就有了N臺(tái)服務(wù)器的管理員權(quán)限。這當(dāng)然是不被允許的了。怎么辦?
???找了一些API,是Authentication Functions系列的。于是,下面一個(gè)小實(shí)驗(yàn)代碼就是想來(lái)枚舉用戶憑據(jù)的。
#include?<windows.h>
#include?
<WinCred.h>
int?main(){

??DWORD?dwCount?
=?0;
??PCREDENTIAL?
*?pCredArray?=?NULL?;

??
if(?CredEnumerate(?NULL,?0,?&dwCount,?&pCredArray?)?){

????
for(?DWORD?dwIndex?=?0;?dwIndex?<?dwCount;?dwIndex++){
??????PCREDENTIAL?pCredential?
=?pCredArray[dwIndex];

??????cout?
<<?"*********************************\r\n";

??????cout
<<??"Flags:?"?<<?pCredential->Flags?<<?"\n"
??????????
<<??"Type:??"?<<??pCredential->Type?<<?"\n"
??????????
<<??"Name:??"?<<?pCredential->TargetName?<<?"\n"
??????????
<<??"Persist:?"<<?pCredential->Persist??<<??"\n"
??????????
<<??"User:??"?<<??pCredential->UserName?<<??"\n";

??????cout?
<<?"Data:??\r\n";

??????
char?szHexBuffer[256]?=?"";
??????
char?szAsciiBuffer[256]?=?"";
??????
char?szHex[16];
??????
char?szAscii[2];
??????DWORD?dwByte;

??????
for?(dwByte?=?0;?dwByte?<?pCredential->CredentialBlobSize;?dwByte++)
??????
{
????????BYTE?byte1?
=?pCredential->CredentialBlob[dwByte];
????????sprintf(szHex,?
"%2.2X?",?byte1);
????????szAscii[
1]?=?'\0';

????????
if?(byte1?>=?32?&&?byte1?<?128)
??????????szAscii[
0]?=?(UCHAR)byte1;
????????
else
??????????szAscii[
0]?=?'?';

????????strcat(szHexBuffer,?szHex);
????????strcat(szAsciiBuffer,?szAscii);

????????
if?(dwByte?==?pCredential->CredentialBlobSize?-?1?
??????????
||?dwByte?%?16?==?15)
????????
{
??????????printf(
"%-50s?%s\r\n",?szHexBuffer,?szAsciiBuffer);
??????????szHexBuffer[
0]?=?'\0';
??????????szAsciiBuffer[
0]?=?'\0';
????????}


??????}


??????cout?
<<?"*********************************\r\n";

????}


????CredFree(?pCredArray?);
??}

??
//system(?"rundll32?keymgr.dll,KRShowKeyMgr");
??return?0;
}

???好像憑據(jù)數(shù)據(jù)還沒(méi)能打出來(lái)。

???后來(lái),本著“編程的最高境界就是不編程”的精神,我想,如果直接把Windows的那個(gè)“存儲(chǔ)的用戶名和密碼”對(duì)話框調(diào)出來(lái)用用不也可以嗎。用ProcessExplorer,找到一個(gè)叫keymgr.dll的東西,嗯,估計(jì)對(duì)話框就在里面。
???在“運(yùn)行”中輸入“control keymgr.dll”或“rundll32 keymgr.dll,KRShowKeyMgr”,對(duì)話框就出來(lái)了。
???又省事了!