在windows下保存密码无非就是两个位置:注册表和文件。于是用windbg打开查询分析器(版本为SQL Server Management Studio 2005 Express),下几个条件断点:
1
2
3
|
bp kernel32!CreateFileW “.printf /”file:%mu//n/”,poi(@esp+4);g;”
bp advapi32!RegCreateKeyExW “.printf /”reg key:%mu//n/”,poi(@esp+8);g;”
bp advapi32!RegSetValueExW “.printf /”reg value:%mu//n/”,poi(@esp+8);g;”
|
1
|
Console.WriteLine(Encoding.Unicode.GetString(System.Security.Cryptography.ProtectedData.Unprotect(Convert.FromBase64String(“AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA/GdUMC8fOkSbZeHVvNAo5AAAAAAQAAAARABlAGYAYQB1AGwAdAAAABBmAAAAAQAAIAAAABH2ACkH8BeAkWtFpoTTAJkOVsrKIKhgee/heYeTpF7nAAAAAA6AAAAAAgAAIAAAABsgv9bezhjwgM4UJmBEhO3GVZ+1+dNrvNIIsogzsX/qEAAAAM1k6Re4z8UJWAVWT6excM1AAAAAX/lp4sh4tHXD3OZQcV6Rs35q6HQ21zEfpJpGkDyFDQT6fVieZxe1m5oY02sGKne1nvD24RQAtiS8fb467EWMsA==”),null,System.Security.Cryptography.DataProtectionScope.LocalMachine)));
|
|
执行后抛出一个异常:
1
|
System.Runtime.Serialization.SerializationException: 无法找到程序集“Microsoft.SqlServer.Express.ConnectionDlg, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91”
|
显然这个序列化对象是其私有程序集中自定义的结构,私有程序集大多时候都保存在主程序目录下,查看安装目录果然看到了这个程序集。鉴于可能需要加载很多私有程序集,于是注册以下回调,使得在程序集缺失的情况下自动加载依赖项:
再次进行反序列化,反序列化成功,得到了一个[Microsoft.SqlServer.Express.ConnectionDlg]Microsoft.SqlServer.Management.UI.ConnectionDlg.Personalization类型的实例。
用reflector打开此程序集,可以看到其内部实例字段为两个字典:typeTable和stringTable。
很明显,stringTable的键以@为分隔符保存了数据库名称和用户的信息,最后的ET、Password等则是一个字段名称标记。
以Password结尾的键所对应的值是一个[Microsoft.SqlServer.Express.ConnectionDlg]Microsoft.SqlServer.Management.UI.ConnectionDlg.StringList的实例,这个类型实现了IEnumerable接口,于是可以获取其枚举器并进行遍历:
最终得到了最开始获取的那段base64,解密后就是原始的密码,结合键名即可获取到完整的登录信息。
从SQL2008开始,其储存方式又有了区别,首先到%appdata%/Microsoft/Microsoft SQL Server目录下查找.net序列化的文件,发现SqlStudio.bin非常可疑:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
SqlStudio
└─SSMS
└─ConnectionOptions
├─ServerTypes-1
│ ├─Servers-1
│ │ │ Instance
│ │ │
│ │ ├─Connections-1
│ │ │ Password
│ │ │ UserName
│ │ │
│ │ └─Connections-2
│ │ Password
│ │ UserName
│ │
│ └─Servers-2
│ │ Instance
│ │
│ └─Connections-1
│ Password
│ UserName
│
└─ServerTypes-2
├─Servers-1
│ │ Instance
│ │
│ ├─Connections-1
│ │ Password
│ │ UserName
│ │
│ └─Connections-2
│ Password
│ UserName
│
└─Servers-2
│ Instance
│
└─Connections-1
Password
UserName
|
知道了保存方式,接下来只要遍历就能取到结果了。需要注意的是由于其列表和字典都是其自定义类,要用其实现的接口IDictionary和IEnumerable进行操作,其伪代码大致为:
更高版本的序列化文件结构与SSMS2008并无任何区别,但由于其依赖版本改为了.net 4.0,所以必须要用.net4.0编译才能成功反序列化。
附件中SSMSPwd-20.exe与SSMSPwd-40.exe为编译好的程序,分别用.net 2.0和.net 4.0编译,使用方法如下:
1
2
3
4
5
6
|
#显示所有保存了密码的登录信息
SSMSPwd.exe
#显示所有保存信息,无论是否保存了密码
SSMSPwd.exe -a
#解密指定的文件
SSMSPwd.exe -f c:/SqlStudio.bin -p “c:/Program Files/Microsoft SQL Server/110/Tools/Binn/ManagementStudio/“
|
SSMSPwd.cs为工具源码,编译命令行:
1
|
csc SSMSPwd.cs
|
注意版本高于2008的SSMS必须使用.net 4.0提供的csc进行编译;此工具在SSMS2005/SSMSES2005/SSMS2008/SSMS2008R2/SSMS2012/SSMS2014上测试成功。
已知错误信息:
1
|
Password: (dec err : 该项不适于在指定状态下使用。)
|
用户不匹配,需要切换到指定用户执行此程序(抓明文之后runas,或者其他黑科技)。
Copyright © hongdaChiaki. All Rights Reserved. 鸿大千秋 版权所有
联系方式:
地址: 深圳市南山区招商街道沿山社区沿山路43号创业壹号大楼A栋107室
邮箱:service@hongdaqianqiu.com
备案号:粤ICP备15078875号