演示从注册表中还原MSNMessenger口令 @ 1/1/2005

学习类
from: http://yscx.net/list.asp?id=885

/* MSNMessenger的口令是经过DPAPI加密后保存在注册表中的
* 这个程序演示解码过程
* tombkeeper[0x40]nsfocus[0x2e]com
* tombkeeper[0x40]xfocus[0x2e]net
* 2004.08.11
*/

#include <Windows.h>

#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 _CRYPTPROTECT_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 ret;
  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, HEY_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 ((hNtdll = LoadLibrary ("Crypt32.dll")) != NULL);
  FCHK ((CryptUnprotectData = (PCryptUnprotectData)  GetProcAddress (hNtdll, "CryptUnprotectData")) != NULL);

  DataIn.pbData = Data + 2; //口令密文从第二位开始
  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 them, 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 around.
    */
    if (state != 0)
      return (-1);
  }
  return (tarindex);
}
发布于 1/1/2005 16:58:36 | 评论:2
Nick @ 1/1/2005 22:05:10
楼主有没有亲自试一试这个东西的真实性?呵呵


p.s. Happy new year!
吴雨 @ 1/2/2005 19:14:11
没有测过,看了一下,我装的是MSN Messenger 7.0,在注册表里面找不到"Password.NET Messenger Service"。所以无法检验程序的正确性。

看帖要回帖...

categories
archives
links
statistics
  • 网志数:1183
  • 评论数:2015