???題目中的Windows憑據(Credential)其實就是指用戶帳戶和口令。最近項目中存在一臺Windows(PC)機去管理服務器(Server),這之中就設計到服務器管理員權限的問題。需要用戶對Windows上存儲的用戶名和密碼進行管理。
???在Windows XP和Server 2003 中都已存在了“存儲的用戶名和密碼”。在XP中,通過控制面板中的用戶帳戶-〉選擇用戶-〉管理我的網絡密碼。而在Server 2003中,則在控制面板下直接有“存儲的用戶名和密碼”項。
???我們調用一些API,如WTSOpenServer,QueryServiceStatus,NetUserEnum等等涉及到RPC的,只要當前用戶存儲有目標遠程機的權限合適的憑據,則這些API就不會因產生ERROR_ACCESS_DENIED而執行失敗。因為我還不Windows的底層是如何進行控制的,比如,是否調用了SSPI,所以,執行這些API時,我只能向用戶要管理員口令。但又不可能每次都讓用戶去輸入一遍用戶名和密碼,那么,也就需要保存密碼。
???既然保存了密碼,就必須考慮刪除密碼,那么密碼管理的問題也就來了。說到密碼管理,我在前些年看電視的時候,看到介紹一個叫什么“網絡螃蟹”的網站,他就是專門提供個人密碼管理的,當時我就想,有人會去把自己的密碼交給別人打理嗎?這好像不大可能。何來也就沒聽到什么網絡螃蟹橫行的消息。
???現在我的項目中,如果用戶有了一臺機器(PC)的密碼,那么,他就有了N臺服務器的管理員權限。這當然是不被允許的了。怎么辦?
???找了一些API,是Authentication Functions系列的。于是,下面一個小實驗代碼就是想來枚舉用戶憑據的。
#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;
}

???好像憑據數據還沒能打出來。

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