Copyright Notice: 9CBS is this BLOG managed service provider. If this paper involves copyright issues, 9CBS does not assume relevant responsibilities, please contact the copyright owner directly with the article Author.
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 end * on a byte boundary, and / or with erroneous trailing character.
* /
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);
}