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

来源:互联网 发布:卡玛d1c知乎 编辑:程序博客网 时间:2024/03/28 18:17

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


作者:tombkeeper (t0mbkeeper_at_hotmail.com)

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

#include


#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);
}
发表于 2004年08月27日 9:45 AM

从注册表中还原MSNMessenger口令 2004-08-27 12:07 PM rockrabbit

程序在VC++6里面编译无法通过啊。

 to rockrabbit: 2004-08-28 12:01 PM 周星星
错误是有几个,但都是语法小错误,自己改一下就行了。
我测试了一下,结果是正确的。
原创粉丝点击