演示从注册表中还原MSNMessenger口令
/* MSNMessenger的口令是经过DPAPI加密后保存在注册表中的 <br />* 这个程序演示解码过程 <br />
* tombkeepernsfocuscom <br />
* tombkeeperxfocusnet <br />
* 2004.08.11 <br />
*/
#include <Windows.h>
#pragma comment(lib, "Advapi32.lib")
<br />
#define FCHK(a) if (!(a)) {printf(#a " failed\n"); return 0;}
<br />
typedef struct _CRYPTOAPI_BLOB { <br />
DWORD cbData; <br />
BYTE* pbData; <br />
} DATA_BLOB;
<br />
typedef struct _CRYPTPROTECT_PROMPTSTRUCT { <br />
DWORD cbSize; <br />
DWORD dwPromptFlags; <br />
HWND hwndApp; <br />
LPCWSTR szPrompt; <br />
} CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT;
<br />
typedef BOOL (WINAPI *PCryptUnprotectData)( <br />
DATA_BLOB* pDataIn, <br />
LPWSTR* ppszDataDescr, <br />
DATA_BLOB* pOptionalEntropy, <br />
PVOID pvReserved, <br />
CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, <br />
DWORD dwFlags, <br />
DATA_BLOB* pDataOut <br />
);
<br />
PCryptUnprotectData CryptUnprotectData = NULL;
int main(void) <br />
{ <br />
int ret; <br />
HMODULE hNtdll;
<br />
HKEY hKey; <br />
DWORD dwType; <br />
char Data = {0}; <br />
DWORD dwSize;
<br />
DATA_BLOB DataIn; <br />
DATA_BLOB DataOut;
<br />
ret = RegOpenKeyEx <br />
( <br />
HKEY_CURRENT_USER, <br />
"Software\\Microsoft\\MSNMessenger", <br />
0, <br />
KEY_READ, <br />
&hKey <br />
); <br />
if( ret != ERROR_SUCCESS ) return 1;
<br />
ret = RegQueryValueEx <br />
( <br />
hKey, <br />
"Password.NET Messenger Service", <br />
NULL, <br />
&dwType, <br />
Data, <br />
&dwSize <br />
); <br />
if( ret != ERROR_SUCCESS ) return 1;
<br />
FCHK ((hNtdll = LoadLibrary ("Crypt32.dll")) != NULL); <br />
FCHK ((CryptUnprotectData = (PCryptUnprotectData) <br />
GetProcAddress (hNtdll, "CryptUnprotectData")) != NULL);
<br />
DataIn.pbData = Data 2; //口令密文从第二位开始 <br />
DataIn.cbData = dwSize-2;
<br />
CryptUnprotectData <br />
( <br />
&DataIn, <br />
NULL, <br />
NULL, <br />
NULL, <br />
NULL, <br />
1, <br />
&DataOut <br />
);
<br />
base64_decode (DataOut.pbData, Data, strlen(DataOut.pbData)); <br />
printf ( "MSN Password: %s\n", Data); <br />
return 0; <br />
}
<br />
//copied from GNU libc - libc/resolv/base64.c <br />
int base64_decode (char const *src, char *target, size_t targsize) <br />
{ <br />
static const char Base64[] = <br />
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 /"; <br />
static const char Pad64 = ’=’;
<br />
int tarindex, state, ch; <br />
char *pos;
<br />
state = 0; <br />
tarindex = 0;
<br />
while ((ch = *src) != ’\0’) <br />
{ <br />
if (isspace (ch)) /* Skip whitespace anywhere. */ <br />
continue;
<br />
if (ch == Pad64) <br />
break;
<br />
pos = strchr (Base64, ch); <br />
if (pos == 0) /* A non-base64 character. */ <br />
return (-1);
<br />
switch (state) <br />
{ <br />
case 0: <br />
if (target) <br />
{ <br />
if ((size_t) tarindex >= targsize) <br />
return (-1); <br />
target = (pos - Base64) << 2; <br />
} <br />
state = 1; <br />
break; <br />
case 1: <br />
if (target) <br />
{ <br />
if ((size_t) tarindex 1 >= targsize) <br />
return (-1); <br />
target |= (pos - Base64) >> 4; <br />
target = ((pos - Base64) & 0x0f) << 4; <br />
} <br />
tarindex; <br />
state = 2; <br />
break; <br />
case 2: <br />
if (target) <br />
{ <br />
if ((size_t) tarindex 1 >= targsize) <br />
return (-1); <br />
target |= (pos - Base64) >> 2; <br />
target = ((pos - Base64) & 0x03) << 6; <br />
} <br />
tarindex; <br />
state = 3; <br />
break; <br />
case 3: <br />
if (target) <br />
{ <br />
if ((size_t) tarindex >= targsize) <br />
return (-1); <br />
target |= (pos - Base64); <br />
} <br />
tarindex; <br />
state = 0; <br />
break; <br />
default: <br />
abort (); <br />
} <br />
}
<br />
/* <br />
* We are done decoding Base-64 chars.Let’s see if we ended <br />
* on a byte boundary, and/or with erroneous trailing characters. <br />
*/
<br />
if (ch == Pad64) <br />
{ /* We got a pad char. */ <br />
ch = *src; /* Skip it, get next. */ <br />
switch (state) <br />
{ <br />
case 0: /* Invalid = in first position */ <br />
case 1: /* Invalid = in second position */ <br />
return (-1);
<br />
case 2: /* Valid, means one byte of info */ <br />
/* Skip any number of spaces. */ <br />
for ((void) NULL; ch != ’\0’; ch = *src) <br />
if (!isspace (ch)) <br />
break; <br />
/* Make sure there is another trailing = sign. */ <br />
if (ch != Pad64) <br />
return (-1); <br />
ch = *src; /* Skip the = */ <br />
/* Fall through to "single trailing =" case. */ <br />
/* FALLTHROUGH */
<br />
case 3: /* Valid, means two bytes of info */ <br />
/* <br />
* We know this char is an =.Is there anything but <br />
* whitespace after it? <br />
*/ <br />
for ((void) NULL; ch != ’\0’; ch = *src) <br />
if (!isspace (ch)) <br />
return (-1);
<br />
/* <br />
* Now make sure for cases 2 and 3 that the "extra" <br />
* bits that slopped past the last full byte were <br />
* zeros.If we don’t check them, they become a <br />
* subliminal channel. <br />
*/ <br />
if (target && target != 0) <br />
return (-1); <br />
} <br />
} <br />
else <br />
{ <br />
/* <br />
* We ended by seeing the end of the string.Make sure we <br />
* have no partial bytes lying around. <br />
*/ <br />
if (state != 0) <br />
return (-1); <br />
}
<br />
return (tarindex); <br />
}
<br />
頁:
[1]