游乐游手机版
首页/网络安全/文章详情

Windows系统演示从注册表中还原MSN Messenger口令的方法

时间:2026-07-24 06:30
在早期版本的MSN Messenger中,用户登录密码会通过Windows DPAPI(数据保护API)进行加密,并存储在注册表中。以下提供的C语言代码示例,展示了如何利用Windows CryptUnprotectData函数解密该加密凭据,从而恢复出原始明文密码。这段代码编写于2004年,其中的

在早期版本的MSN Messenger中,用户登录密码会通过Windows DPAPI(数据保护API)进行加密,并存储在注册表中。以下提供的C语言代码示例,展示了如何利用Windows CryptUnprotectData函数解密该加密凭据,从而恢复出原始明文密码。这段代码编写于2004年,其中的base64_decode函数源自GNU C标准库,至今仍是研究本地凭据存储机制与安全实践的经典参考。

#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
         * ha ve no partial bytes lying around.
         */
        if (state != 0)
            return (-1);
    }
    return (tarindex);
}
来源:https://www.jb51.net/hack/5068.html
上一篇织梦Dedecms内容管理系统漏洞详解 下一篇黑客窃取密码的原理与防范措施
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
零基础Python网络安全学习指南,包住宿实战培训
网络安全 · 2026-07-25

零基础Python网络安全学习指南,包住宿实战培训

先抛出几个核心判断:网络安全人才缺口确实已经超过70万。这个数字不算夸张,各大招聘网站上安全岗位的薪资涨幅和需求增长都是实实在在的。但实话实说,行业真正缺的是能上手干活的人,不是只懂几个理论概念的新手。因此,一套扎实且成体系的训练方案,对于零基础转行或进阶提升就显得格外关键。 从零基础到能够独立应对

网络安全定义与核心概念详解
网络安全 · 2026-07-25

网络安全定义与核心概念详解

谈到网络安全,不同组织与标准体系对其定义虽有差异,但核心目标高度统一:保护信息与系统不受威胁侵害。以下梳理几种主流定义—— 什么是网络安全? 国际标准化组织(ISO)在ISO-74982文献中将安全定义为:最大程度地降低数据和资源遭受攻击的可能性。该定义虽简短,却精准点出安全的本质——即风险控制。

IIS 7.0网站漏洞利用与修复方法指南
网络安全 · 2026-07-25

IIS 7.0网站漏洞利用与修复方法指南

先来聊聊当前网络安全领域比较流行的一种实战技巧——以PHP环境为例,详细讲解图片马合并与解析漏洞利用的具体操作步骤。整个过程并不复杂,但细节往往决定成败,大家跟着流程逐步操作即可。 合并一张PHP一句话图片马 首先,我们需要将一句话木马脚本与一张正常图片合并,生成一个看似无害的图片文件。合并方式主要

织梦管理系统后台查找功能教程
网络安全 · 2026-07-25

织梦管理系统后台查找功能教程

通过SQL注入漏洞获取织梦CMS(DedeCMS)管理员密码后,满怀期待地准备进入后台,却发现怎么也找不到登录入口——这种情况其实相当常见。别着急,这里有一个实用的技巧值得尝试。 直接在网站地址后面添加以下路径: include dialog select_media php?f=form1 mur

微软IE浏览器BrowseDialog类(ccrpbds6.dll)拒绝服务安全漏洞深度分析
网络安全 · 2026-07-25

微软IE浏览器BrowseDialog类(ccrpbds6.dll)拒绝服务安全漏洞深度分析

BrowseDialog Class (ccrpbds6 dll) 导致 Internet Explorer 拒绝服务漏洞分析 该漏洞的PoC(概念验证代码)实现极为直接——触发浏览器崩溃的条件简单得令人意外。测试环境采用Windows XP Professional SP2(已安装全部补丁)并运行