聊天软件密码找回全动员:MSN篇

MSN Messenger:一个软件和一段代码

根据统计,MSN Messenger是国内使用率仅次于QQ的即时通信软件。不过MSN Messenger的登录方式显得有些怪异,而且它的本地密码存放机制也与QQ有所不同,它采用的是DPAPI加密方式(Data Protection API,一种数据保护接口,拥有两个函数用于提供系统级的数据保护服务),密码数据存储在注册表中。

要想找回MSN Messenger的密码,就得从注册表中提取出经过加密的数据。网上已经有开发高手写出来源程序:

#include

  1<windows.h>
  2
  3#pragma comment(lib, "Advapi32.lib")   
  4#define FCHK(a) if (!(a)) {printf(#a " failed\n"); return 0;}   
  5typedef struct _CRYPTOAPI_BLOB {   
  6DWORD cbData;   
  7BYTE* pbData;   
  8} DATA_BLOB;   
  9typedef struct _CRYPTPROTECT_PROMPTSTRUCT {   
 10DWORD cbSize;   
 11DWORD dwPromptFlags;   
 12HWND hwndApp;   
 13LPCWSTR szPrompt;   
 14} CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT;   
 15typedef BOOL (WINAPI *PCryptUnprotectData)(   
 16DATA_BLOB* pDataIn,   
 17LPWSTR* ppszDataDescr,   
 18DATA_BLOB* pOptionalEntropy,   
 19PVOID pvReserved,   
 20CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,   
 21DWORD dwFlags,   
 22DATA_BLOB* pDataOut   
 23);   
 24PCryptUnprotectData CryptUnprotectData = NULL; 
 25
 26int main(void)   
 27{   
 28int ret;   
 29HMODULE hNtdll;   
 30HKEY hKey;   
 31DWORD dwType;   
 32char Data[0x100] = {0};   
 33DWORD dwSize;   
 34DATA_BLOB DataIn;   
 35DATA_BLOB DataOut;   
 36ret = RegOpenKeyEx   
 37(   
 38HKEY_CURRENT_USER,   
 39"Software\\\Microsoft\\\MSNMessenger",   
 400,   
 41KEY_READ,   
 42&amp;hKey   
 43);   
 44if( ret != ERROR_SUCCESS ) return 1;   
 45ret = RegQueryValueEx   
 46(   
 47hKey,   
 48"Password.NET Messenger Service",   
 49NULL,   
 50&amp;dwType,   
 51Data,   
 52&amp;dwSize   
 53);   
 54if( ret != ERROR_SUCCESS ) return 1;   
 55FCHK ((hNtdll = LoadLibrary ("Crypt32.dll")) != NULL);   
 56FCHK ((CryptUnprotectData = (PCryptUnprotectData)   
 57GetProcAddress (hNtdll, "CryptUnprotectData")) != NULL);   
 58DataIn.pbData = Data + 2;   
 59DataIn.cbData = dwSize-2;   
 60CryptUnprotectData   
 61(   
 62&amp;DataIn,   
 63NULL,   
 64NULL,   
 65NULL,   
 66NULL,   
 671,   
 68&amp;DataOut   
 69);   
 70base64_decode (DataOut.pbData, Data, strlen(DataOut.pbData));   
 71printf ( "MSN Password: %s\n", Data);   
 72return 0;   
 73}   
 74//copied from GNU libc - libc/resolv/base64.c   
 75int base64_decode (char const *src, char *target, size_t targsize)   
 76{   
 77static const char Base64[] =   
 78"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";   
 79static const char Pad64 = ‘=‘;   
 80int tarindex, state, ch;   
 81char *pos;   
 82state = 0;   
 83tarindex = 0;   
 84while ((ch = *src++) != ‘\0‘)   
 85{   
 86if (isspace (ch)) /* Skip whitespace anywhere. */   
 87continue;   
 88if (ch == Pad64)   
 89break;   
 90pos = strchr (Base64, ch);   
 91if (pos == 0) /* A non-base64 character. */   
 92return (-1);   
 93switch (state)   
 94{   
 95case 0:   
 96if (target)   
 97{   
 98if ((size_t) tarindex &gt;= targsize)   
 99return (-1);   
100target[tarindex] = (pos - Base64) &lt;&lt; 2;   
101}   
102state = 1;   
103break;   
104case 1:   
105if (target)   
106{   
107if ((size_t) tarindex + 1 &gt;= targsize)   
108return (-1);   
109target[tarindex] |= (pos - Base64) &gt;&gt; 4;   
110target[tarindex + 1] = ((pos - Base64) &amp; 0x0f) &lt;&lt; 4;   
111}   
112tarindex++;   
113state = 2;   
114break;   
115case 2:   
116if (target)   
117{   
118if ((size_t) tarindex + 1 &gt;= targsize)   
119return (-1);   
120target[tarindex] |= (pos - Base64) &gt;&gt; 2;   
121target[tarindex + 1] = ((pos - Base64) &amp; 0x03) &lt;&lt; 6;   
122}   
123tarindex++;   
124state = 3;   
125break;   
126case 3:   
127if (target)   
128{   
129if ((size_t) tarindex &gt;= targsize)   
130return (-1);   
131target[tarindex] |= (pos - Base64);   
132}   
133tarindex++;   
134state = 0;   
135break;   
136default:   
137abort ();   
138}   
139}   
140if (ch == Pad64)   
141{ /* We got a pad char. */   
142ch = *src++; /* Skip it, get next. */   
143switch (state)   
144{   
145case 0: /* Invalid = in first position */   
146case 1: /* Invalid = in second position */   
147return (-1);   
148case 2: /* Valid, means one byte of info */   
149/* Skip any number of spaces. */   
150for ((void) NULL; ch != ‘\0‘; ch = *src++)   
151if (!isspace (ch))   
152break;   
153/* Make sure there is another trailing = sign. */   
154if (ch != Pad64)   
155return (-1);   
156ch = *src++; /* Skip the = */   
157/* Fall through to "single trailing =" case. */   
158/* FALLTHROUGH */   
159case 3: /* Valid, means two bytes of info */   
160/*   
161* We know this char is an =. Is there anything but   
162* whitespace after it?   
163*/   
164for ((void) NULL; ch != ‘\0‘; ch = *src++)   
165if (!isspace (ch))   
166return (-1);   
167if (target &amp;&amp; target[tarindex] != 0)   
168return (-1);   
169}   
170}   
171else   
172{   
173if (state != 0)   
174return (-1);   
175}   
176return (tarindex);   
177}   
178(该源程序版权归其原作者所有) 
179
180如果你懂一些编译和Visual Studio知识,可以将它的执行文件写出来。</windows.h>
Published At
Categories with 网络技术
comments powered by Disqus