by using DPAPI,program MUST be run on USER CONTEXT.
(use impersonate to do it.)
Bulid
#for .net 2.0
%systemroot%\microsoft.net\framework\v2.0.50727\csc.exe SSMSPwd.cs
#for .net 4.0
%systemroot%\microsoft.net\framework\v4.0.30319\csc.exe /out:SSMSPwd40.exe SSMSPwd.cs
Usage
SSMSPwd [-f file] [-p path] [-all]
-f: decrypt from specified file
-p: path of SSMS installation
-a: dump all saved info(only dump password information default)
Remarks
SSMS save password to a binary file using BinaryFormatter,and the type was defined on private assembly in the installation directory.
This file saved in %appdata%\Microsoft\Microsoft SQL Server\(VERSION)\Tools\Shell
on SSMS2005 or SSMS2008, %appdata%\Microsoft\Microsoft SQL Server\(VERSION)\Tools\ShellSEM
on Express Version,%appdata%\Microsoft\SQL Server Management Studio
on others.its named mru.dat
on SSMS2005,SqlStudio.bin
on SSMS2008 to last release.
SSMS2005 saved a IDirectory
named stringTable
in file,the key like this:
[email protected]\SQLEXPRESS@1@sa@Password
[email protected]\SQLEXPRESS@1@sa@ET
Split by @
,we can get instance
,user
.
If the key ends with Password
,the value will be encrypted password using DPAPI and Base64Encode
.
Other versions,binary file saved a big tree like:
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
We can get IDirectory
and IEnumerable
on nodes,the pseudocode was:
foreach ServerType in SqlStudio['SSMS']['ConnectionOptions']['ServerTypes']
{
foreach Server in ServerType['Servers']
{
print Server.Instance
foreach Connection in Server['Connections']
{
print Connection.UserName,Connection.Password
}
}
}
The Password
use DPAPI and Base64Encode
too.Using ProtectedData::Uprotect to decrypt it.
DONOT forget,run program on USER CONTEXT.