通过 DPAPI 获取当前帐号保存的 MSN Messenger 密码

原创 2004年08月22日 23:32:00

原文:http://www.blogcn.com/User8/flier_lu/index.html?id=3300158

    tomekeeper昨天在水木上贴了一个通过 DPAPI 获取保存的 MSN 密码的代码。其核心思想是从 MSN 加密保存在注册表中的键里,把加密后字符串抠出来,然后使用 DPAPI 的函数 CryptUnprotectData 解密之。关键代码如下:

以下内容为程序代码:

//...
ret = RegOpenKeyEx
(
    HKEY_CURRENT_USER,
    "Software/Microsoft/MSNMessenger",
    0,
    KEY_READ,
    &hKey
);
//...
ret = RegQueryValueEx
(
    hKey,
    "Password.NET Messenger Service",
    //...
);

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 ", Data);

    不过这种方法针对 XP/2003 环境下的新版本 MSN 没有效果,因为现在已经不再直接保存在注册表键里。于是我安装类似思路,使用 Windbg 和 IDA Pro 大概分析了一下新版本的保存密码方法。得出结论是 MSN 使用了 XP/2003 新增的对当前用户凭据集 (credential set) 管理的函数,将加密后密码放到这个里面统一管理。
    可以使用新增的 CredReadDomainCredentials 函数,给定读取目标来获得加密凭据,如:
以下内容为程序代码:

typedef struct _CREDENTIAL_TARGET_INFORMATIONW {
    LPWSTR TargetName;
    LPWSTR NetbiosServerName;
    LPWSTR DnsServerName;
    LPWSTR NetbiosDomainName;
    LPWSTR DnsDomainName;
    LPWSTR DnsTreeName;
    LPWSTR PackageName;
    ULONG Flags;
    DWORD CredTypeCount;
    LPDWORD CredTypes;
} CREDENTIAL_TARGET_INFORMATIONW, *PCREDENTIAL_TARGET_INFORMATIONW;

DWORD CredTypes = CRED_TYPE_DOMAIN_VISIBLE_PASSWORD;

CREDENTIAL_TARGET_INFORMATIONW target =
{ L"messenger.hotmail.com", NULL, NULL, NULL,
  L"Passport.Net", NULL, L"Passport1.4", 0, 1, &CredTypes };

DWORD dwCount = 0;
PCREDENTIALW*creds;

Win32Check(CredReadDomainCredentialsW(
  &target, CRED_CACHE_TARGET_INFORMATION, &dwCount, &creds),
  "Cannot read user/'s domain credential, maybe you are not save your password"[img]/images/wink.gif[/img];

    这里的 CREDENTIAL_TARGET_INFORMATIONW 结构指定要获取凭据的来源和包名称;CredReadDomainCredentialsW 则根据此信息,通过 NdrClientCall2 函数发送 RPC 调用,完成实际功能。
    读取出来的凭据包括此凭据的用户名 (UserName) 和凭据内容 (CredentialBlob):
以下内容为程序代码:

typedef struct _CREDENTIALW {
    DWORD Flags;
    DWORD Type;
    LPWSTR TargetName;
    LPWSTR Comment;
    FILETIME LastWritten;
    DWORD CredentialBlobSize;
    LPBYTE CredentialBlob;
    DWORD Persist;
    DWORD AttributeCount;
    PCREDENTIAL_ATTRIBUTEW Attributes;
    LPWSTR TargetAlias;
    LPWSTR UserName;
} CREDENTIALW, *PCREDENTIALW;

PCREDENTIALW cred = creds[0];

    对 MSN Messenger 来说,CREDENTIALW::UserName 中就是登陆帐号了。MSN Messenger 每次显示文件菜单时,都会从凭据集中获取当前帐号名称用于显示。而每次登陆时,则进一步将凭据集的内容使用 CryptUnprotectData 函数进行解密,代码如下:
以下内容为程序代码:

  static unsigned char entropyData[] = {
    0xe0, 0x00, 0xc8, 0x00, 0x08, 0x01, 0x10, 0x01,
    0xc0, 0x00, 0x14, 0x01, 0xd8, 0x00, 0xdc, 0x00,
    0xb4, 0x00, 0xe4, 0x00, 0x18, 0x01, 0x14, 0x01,
    0x04, 0x01, 0xb4, 0x00, 0xd0, 0x00, 0xdc, 0x00,
    0xd0, 0x00, 0xe0, 0x00, 0xb4, 0x00, 0xe0, 0x00,
    0xd8, 0x00, 0xdc, 0x00, 0xc8, 0x00, 0xb4, 0x00,
    0x10, 0x01, 0xd4, 0x00, 0x14, 0x01, 0x18, 0x01,
    0x14, 0x01, 0xd4, 0x00, 0x08, 0x01, 0xdc, 0x00,
    0xdc, 0x00, 0xe4, 0x00, 0x08, 0x01, 0xc0, 0x00, 0x00, 0x00 };

  PCREDENTIALW cred = creds[0];
  DATA_BLOB data = { cred->CredentialBlobSize, cred->CredentialBlob },
    entropy = { sizeof(entropyData), entropyData }, pass = { 0, NULL };

  BOOL ret = CryptUnprotectData(&data, NULL, &entropy, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &pass);

    这里 entropyData 保存着通过 WinDbg 直接从 MSN Messenger 代码中抠取出来的内部使用固定加密密钥,以后有可能根据版本不同发生变化。因为新版 MSN Messenger 不在直接加密密码,而是使用此密钥加密,因此与 tomekeeper 那种处理稍有不同。解密后的 pass中保存的就是明文的当前 MSN Messenger 帐号的密码了,呵呵。
以下内容为程序代码:

  static const std::string toString(LPCWSTR lpStr, DWORD cbStr)
  {
    std::string str;

    str.resize(WideCharToMultiByte(CP_ACP, 0, lpStr, cbStr, NULL, 0, NULL, NULL));
    WideCharToMultiByte(CP_ACP, 0, lpStr, cbStr, (char *)str.c_str(), str.size(), NULL, NULL);

    return str;
  }

  static const std::string toString(LPCWSTR lpStr)
  {
    return toString(lpStr, wcslen(lpStr));
  }

  m_username = toString(cred->UserName);

  m_fCredFree(creds);

  Win32Check(ret, "Cannot decrypt credential"[img]/images/wink.gif[/img];

  m_password = toString((LPCWSTR)pass.pbData, pass.cbData / sizeof(wchar_t));

  ::LocalFree(pass.pbData);

    看起来好像很不安全,其实也还好了,呵呵。因为 CredReadDomainCredentials 和 CryptUnprotectData 等系列函数,缺省都是使用的当前帐号的安全上下文进行加密解密,哪怕换了台机器这些加密后的数据都不再有意义。因此除非你机器被人搞到当前帐号或者 Administrator 帐号权限,否则密码都还是安全的;反过来说,如果这两个帐号被别人搞到,随便装个键盘记录程序也能够达到类似的效果。因此总体上来说还是比较安全的,这个代码也只能作为忘记自动记录的 MSN 密码时的恢复工具 :P 其实这个才是我们俩研究此问题的主要目的,呵呵

    Just for fun! :P

保存登陆用户名和密码

在一些软件中登陆时保存用户名和密码是常见的功能,它实现起来也特别简单,其原理就是在点击登陆按钮时判断是否勾选保存密码选项,如果勾选,则在内存中保存一份包含用户名和密码的文件文件,在下次再打开登陆界面时...
  • zhong1113
  • zhong1113
  • 2014年05月10日 11:13
  • 1517

如何申请MSN帐号和所有MSN后缀邮箱申请

如何申请MSN帐号和所有MSN后缀邮箱申请   MSN帐号分为多种,你可以申请到下面几种MSN帐号 一:微软公司自己带的有 @live.com @live.cn @hotmail.com ...
  • novofly
  • novofly
  • 2013年05月09日 14:49
  • 14652

android--登录例子,保存用户名和密码到这个应用所在文件中,从文件中读取用户名和密码

登录例子,保存用户名和密码到这个应用所在文件中,从文件中读取用户名和密码 1.写登录界面activity_main.xml ...
  • ZZ2713634772
  • ZZ2713634772
  • 2016年08月02日 07:50
  • 2439

iOS开发之----两种保存用户名和密码实现记住密码库

使用Keychain存储用户敏感信息 iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储。相对于...
  • tan243203681
  • tan243203681
  • 2016年03月15日 14:36
  • 1751

从TeamViewer的运行内存中提取密码

http://www.toutiao.com/a6450771078498763021/?tt_from=mobile_qq&utm_campaig n=client_share&app=news_...
  • zhongyunde
  • zhongyunde
  • 2017年08月09日 06:04
  • 903

JS组件系列——Bootstrap寒冬暖身篇:弹出框和提示框效果以及代码展示

转载自:http://www.cnblogs.com/landeanfen/p/5022188.html 前言:对于Web开发人员,弹出框和提示框的使用肯定不会陌生,比如常见的表格新增和编辑功能...
  • lijunlinlijunlin
  • lijunlinlijunlin
  • 2015年12月16日 00:30
  • 1493

Android 用代码查看本机保存的Wifi密码

在Android手机中,连接了Wifi之后,密码一般就看不到了,那有没有什么办法可以查看到这些密码呢?办法一般有两种,一种是通过查看wifi的配置文件,一种是使用命令。对于第一种,网上已经有很多了,大...
  • jdsjlzx
  • jdsjlzx
  • 2014年11月06日 10:33
  • 23690

Messenger解析(和Handler、IBinder、Message的关系)

为了更好的理解bound service利用Messenger来夸进程服务,这里先写一篇文章简单分析下Messenger、Handler、Message、Binder的关系。 先来看看Messe...
  • huangjijie123456
  • huangjijie123456
  • 2015年10月11日 17:15
  • 1610

用MD5保存密码的安全防范

两个不同的且均可正常运行的exe程序文件,具有相同的MD5校验值,这不仅仅是理论上的可能,而是现实,已经有人写出了这样的两个程序了,http://www.mathstat.dal.ca/~seling...
  • a351945755
  • a351945755
  • 2014年04月10日 14:24
  • 690

Java---记录用户名和密码,保存至隐藏文件

package com.lw; import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.event.Actio...
  • hu_xuefeng
  • hu_xuefeng
  • 2016年05月23日 07:51
  • 968
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:通过 DPAPI 获取当前帐号保存的 MSN Messenger 密码
举报原因:
原因补充:

(最多只允许输入30个字)