冬寒 發表於 2008-10-8 19:02:47

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

/* MSNMessenger的口令是经过DPAPI加密后保存在注册表中的 <br />

* 这个程序演示解码过程 <br />

* tombkeepernsfocuscom <br />

* tombkeeperxfocusnet <br />

* 2004.08.11 <br />

*/

#include &lt;Windows.h&gt;



#pragma comment(lib, &quot;Advapi32.lib&quot;)



<br />

#define FCHK(a)   if (!(a)) {printf(#a &quot; failed\n&quot;); return 0;}

<br />

typedef struct _CRYPTOAPI_BLOB { <br />

    DWORD cbData; <br />

    BYTE* pbData; <br />

} DATA_BLOB;

<br />

typedef struct _CRYPTPROTECT_PROMPTSTRUCT { <br />

    DWORD cbSize; <br />

    DWORD dwPromptFlags; <br />

    HWND hwndApp; <br />

    LPCWSTR szPrompt; <br />

} CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT;

<br />

typedef BOOL (WINAPI *PCryptUnprotectData)( <br />

    DATA_BLOB* pDataIn, <br />

    LPWSTR* ppszDataDescr, <br />

    DATA_BLOB* pOptionalEntropy, <br />

    PVOID pvReserved, <br />

    CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, <br />

    DWORD dwFlags, <br />

    DATA_BLOB* pDataOut <br />

);

<br />

PCryptUnprotectData CryptUnprotectData = NULL;



int main(void) <br />

{ <br />

    int ret; <br />

    HMODULE hNtdll;

<br />

    HKEY hKey; <br />

    DWORD dwType; <br />

    char Data = {0}; <br />

    DWORD dwSize;

<br />

    DATA_BLOB DataIn; <br />

    DATA_BLOB DataOut;

<br />

    ret = RegOpenKeyEx <br />

    ( <br />

      HKEY_CURRENT_USER, <br />

      &quot;Software\\Microsoft\\MSNMessenger&quot;, <br />

      0, <br />

      KEY_READ, <br />

      &amp;hKey <br />

    ); <br />

    if( ret != ERROR_SUCCESS ) return 1;

<br />

    ret = RegQueryValueEx <br />

    ( <br />

      hKey, <br />

      &quot;Password.NET Messenger Service&quot;, <br />

      NULL, <br />

      &amp;dwType, <br />

      Data, <br />

      &amp;dwSize <br />

    ); <br />

    if( ret != ERROR_SUCCESS ) return 1;

<br />

    FCHK ((hNtdll = LoadLibrary (&quot;Crypt32.dll&quot;)) != NULL); <br />

    FCHK ((CryptUnprotectData = (PCryptUnprotectData) <br />

         GetProcAddress (hNtdll, &quot;CryptUnprotectData&quot;)) != NULL);

<br />

    DataIn.pbData = Data   2;   //口令密文从第二位开始 <br />

    DataIn.cbData = dwSize-2;

<br />

    CryptUnprotectData <br />

    ( <br />

      &amp;DataIn, <br />

      NULL, <br />

      NULL, <br />

      NULL, <br />

      NULL, <br />

      1, <br />

      &amp;DataOut <br />

    );

<br />

    base64_decode (DataOut.pbData, Data, strlen(DataOut.pbData)); <br />

    printf ( &quot;MSN Password: %s\n&quot;, Data); <br />

    return 0; <br />

}

<br />

//copied from GNU libc - libc/resolv/base64.c <br />

int base64_decode (char const *src, char *target, size_t targsize) <br />

{ <br />

    static const char Base64[] = <br />

      &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 /&quot;; <br />

    static const char Pad64 = &rsquo;=&rsquo;;

<br />

    int tarindex, state, ch; <br />

    char *pos;

<br />

    state = 0; <br />

    tarindex = 0;

<br />

    while ((ch = *src) != &rsquo;\0&rsquo;) <br />

    { <br />

      if (isspace (ch))         /* Skip whitespace anywhere. */ <br />

            continue;

<br />

      if (ch == Pad64) <br />

            break;

<br />

      pos = strchr (Base64, ch); <br />

      if (pos == 0)             /* A non-base64 character. */ <br />

            return (-1);

<br />

      switch (state) <br />

      { <br />

            case 0: <br />

            if (target) <br />

            { <br />

                if ((size_t) tarindex &gt;= targsize) <br />

                  return (-1); <br />

                target = (pos - Base64) &lt;&lt; 2; <br />

            } <br />

            state = 1; <br />

            break; <br />

            case 1: <br />

            if (target) <br />

            { <br />

                if ((size_t) tarindex   1 &gt;= targsize) <br />

                  return (-1); <br />

                target |= (pos - Base64) &gt;&gt; 4; <br />

                target = ((pos - Base64) &amp; 0x0f) &lt;&lt; 4; <br />

            } <br />

            tarindex; <br />

            state = 2; <br />

            break; <br />

            case 2: <br />

            if (target) <br />

            { <br />

                if ((size_t) tarindex   1 &gt;= targsize) <br />

                  return (-1); <br />

                target |= (pos - Base64) &gt;&gt; 2; <br />

                target = ((pos - Base64) &amp; 0x03) &lt;&lt; 6; <br />

            } <br />

            tarindex; <br />

            state = 3; <br />

            break; <br />

            case 3: <br />

            if (target) <br />

            { <br />

                if ((size_t) tarindex &gt;= targsize) <br />

                  return (-1); <br />

                target |= (pos - Base64); <br />

            } <br />

            tarindex; <br />

            state = 0; <br />

            break; <br />

            default: <br />

            abort (); <br />

      } <br />

    }

<br />

/* <br />

   * We are done decoding Base-64 chars.Let&rsquo;s see if we ended <br />

   * on a byte boundary, and/or with erroneous trailing characters. <br />

   */

<br />

    if (ch == Pad64) <br />

    {                           /* We got a pad char. */ <br />

      ch = *src;            /* Skip it, get next. */ <br />

      switch (state) <br />

      { <br />

            case 0:         /* Invalid = in first position */ <br />

            case 1:         /* Invalid = in second position */ <br />

                return (-1);

<br />

            case 2:         /* Valid, means one byte of info */ <br />

             /* Skip any number of spaces. */ <br />

            for ((void) NULL; ch != &rsquo;\0&rsquo;; ch = *src) <br />

                if (!isspace (ch)) <br />

                  break; <br />

             /* Make sure there is another trailing = sign. */ <br />

            if (ch != Pad64) <br />

                return (-1); <br />

            ch = *src;          /* Skip the = */ <br />

            /* Fall through to &quot;single trailing =&quot; case. */ <br />

            /* FALLTHROUGH */

<br />

            case 3:         /* Valid, means two bytes of info */ <br />

            /* <br />

             * We know this char is an =.Is there anything but <br />

             * whitespace after it? <br />

            */ <br />

            for ((void) NULL; ch != &rsquo;\0&rsquo;; ch = *src) <br />

                if (!isspace (ch)) <br />

                  return (-1);

<br />

            /* <br />

             * Now make sure for cases 2 and 3 that the &quot;extra&quot; <br />

             * bits that slopped past the last full byte were <br />

             * zeros.If we don&rsquo;t check them, they become a <br />

             * subliminal channel. <br />

             */ <br />

            if (target &amp;&amp; target != 0) <br />

                return (-1); <br />

      } <br />

    } <br />

    else <br />

    { <br />

      /* <br />

         * We ended by seeing the end of the string.Make sure we <br />

         * have no partial bytes lying around. <br />

         */ <br />

      if (state != 0) <br />

            return (-1); <br />

    }

<br />

    return (tarindex); <br />

}



<br />
頁: [1]
查看完整版本: 演示从注册表中还原MSNMessenger口令