???題目中的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)了。
???又省事了!