墨香年少 32 发布于 2021年2月25日 #include <string> #include <fstream> #include <iostream> #include <cstdlib> #include <vector> using namespace std; typedef unsigned char uchar; #define PW_MAGIC 0xA3 #define PW_MAXLEN 50 #define PW_FLAG 0xFF string decrypt(string pwd, string key); #ifdef WIN #include <windows.h> #define REG_MAXLEN_KEY 255 #define REG_MAXLEN_VAL 16383 const string session_path = TEXT("SOFTWARE\\Martin Prikryl\\WinSCP 2\\Sessions"); // mostly from MSDN bool reg_get_list (string key, vector<string>& keylist, vector<string>& vallist) { HKEY hKey; TCHAR achKey[REG_MAXLEN_KEY]; // buffer for subkey name DWORD cbName; // size of name string TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name DWORD cchClassName = MAX_PATH; // size of class string DWORD cSubKeys=0; // number of subkeys DWORD cbMaxSubKey; // longest subkey size DWORD cchMaxClass; // longest class string DWORD cValues; // number of values for key DWORD cchMaxValue; // longest value name DWORD cbMaxValueData; // longest value data DWORD cbSecurityDescriptor; // size of security descriptor FILETIME ftLastWriteTime; // last write time DWORD i, retCode; TCHAR achValue[REG_MAXLEN_VAL]; DWORD cchValue = REG_MAXLEN_VAL; retCode = RegOpenKeyExA(HKEY_CURRENT_USER, key.c_str(), 0, KEY_READ, &hKey); if(retCode != ERROR_SUCCESS) { cout << "bark\n"; return false; } // Get the class name and the value count. retCode = RegQueryInfoKey( hKey, // key handle achClass, // buffer for class name &cchClassName, // size of class string NULL, // reserved &cSubKeys, // number of subkeys &cbMaxSubKey, // longest subkey size &cchMaxClass, // longest class string &cValues, // number of values for this key &cchMaxValue, // longest value name &cbMaxValueData, // longest value data &cbSecurityDescriptor, // security descriptor &ftLastWriteTime); // last write time if (cSubKeys) { // printf( "\nNumber of subkeys: %lu\n", cSubKeys); for (i=0; i<cSubKeys; i++) { cbName = REG_MAXLEN_KEY; retCode = RegEnumKeyEx(hKey, i, achKey, &cbName, NULL, NULL, NULL, &ftLastWriteTime); if (retCode == ERROR_SUCCESS) { // printf("(%lu) %s\n", i+1, achKey); keylist.push_back(achKey); } } } if (cValues) { // printf( "\nNumber of values: %lu\n", cValues); for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) { cchValue = REG_MAXLEN_VAL; achValue[0] = '\0'; retCode = RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL); if(retCode == ERROR_SUCCESS) { // printf("(%lu) %s\n", i+1, achValue); vallist.push_back(achValue); } } } RegCloseKey(hKey); return true; } bool reg_get_key (string location, string name, string& val) { HKEY key; TCHAR value[1024]; DWORD bufLen = 1024*sizeof(TCHAR); long ret; ret = RegOpenKeyExA(HKEY_CURRENT_USER, location.c_str(), 0, KEY_QUERY_VALUE, &key); if(ret != ERROR_SUCCESS) { return false; } ret = RegQueryValueExA(key, name.c_str(), 0, 0, (LPBYTE) value, &bufLen); RegCloseKey(key); if ( (ret != ERROR_SUCCESS) || (bufLen > 1024*sizeof(TCHAR)) ){ return false; } string stringValue = string(value, (size_t)bufLen - 1); size_t i = stringValue.length(); while( i > 0 && stringValue[i-1] == '\0' ){ --i; } val = stringValue; return true; } void decrypt_registry_session (string session) { const string kuser = TEXT("UserName"), khost = TEXT("HostName"), kpw = TEXT("Password"), ktunuser = TEXT("TunnelUserName"), ktunhost = TEXT("TunnelHostName"), ktunpw = TEXT("TunnelPassword"); bool r = true; string user, host, pw; string path = session_path + TEXT("\\") + session; // normal session r = r && reg_get_key(path, kuser, user); r = r && reg_get_key(path, khost, host); r = r && reg_get_key(path, kpw, pw); if(r) cout << user << "@" << host << "\t" << decrypt(pw, user+host) << "\n"; // tunnel session r = r && reg_get_key(path, ktunuser, user); r = r && reg_get_key(path, ktunhost, host); r = r && reg_get_key(path, ktunpw, pw); if(r) cout << user << "@" << host << "\t" << decrypt(pw, user+host) << "\n"; } void read_registry () { vector<string> keylist, vallist; bool r; r = reg_get_list(session_path, keylist, vallist); for(int i = 0; i < keylist.size(); i++) decrypt_registry_session(keylist[i]); } #endif int dec_next_char(string &s) { if(s.length() <= 0) return 0; const string base = "0123456789ABCDEF"; int a = base.find(s[0]); int b = base.find(s[1]); uchar r = (uchar) ~((a << 4) + (b << 0) ^ PW_MAGIC); s.erase(0, 2); return r; } string decrypt(string pwd, string key) { string clearpwd; uchar length, flag; flag = dec_next_char(pwd); if(flag == PW_FLAG) { dec_next_char(pwd); length = dec_next_char(pwd); } else length = flag; pwd.erase(0, (dec_next_char(pwd))*2); for(int i = 0; i < length; i++) clearpwd += (char)dec_next_char(pwd); if(flag == PW_FLAG) { if(clearpwd.substr(0, key.length()) != key) clearpwd = ""; else clearpwd.erase(0, key.length()); } return clearpwd; } string clean (string s) { int len = s.length(); if(len && s[len-1] == '\r') s.erase(len-1, 1); return s; } void parse_wscp_conf (char* path) { string l; string host, user, pwd; string tunnel_host, tunnel_user, tunnel_pwd; ifstream f(path); if(!f.is_open()) { cerr << "Cannot open " << path << "\n"; exit(1); } cerr << "reading " << path << "\n"; while(f.good()) { getline(f, l); if(l.substr(0, 9) == "UserName=") { user = clean(l.substr(9)); } else if(l.substr(0, 15) == "TunnelUserName=") { tunnel_user = clean(l.substr(15)); } else if(l.substr(0, 9) == "HostName=") { host = clean(l.substr(9)); } else if(l.substr(0, 15) == "TunnelHostName=") { tunnel_host = clean(l.substr(15)); } else if(l.substr(0, 9) == "Password=" || l.substr(0,15) == "TunnelPassword=") { int password_start = l.find_first_of('=') + 1; bool is_tunnel = password_start == 9; pwd = clean(l.substr(password_start)); if(is_tunnel && !user.empty() && !host.empty() && !pwd.empty()) { cout << user << "@" << host << "\t" << decrypt(pwd, user+host) << "\n"; } else if(!is_tunnel && !tunnel_user.empty() && !tunnel_host.empty()) { cout << tunnel_user << "@" << tunnel_host << "\t" << decrypt(pwd, tunnel_user+tunnel_host) << "\n"; } user = host = pwd = ""; } } f.close(); } int main (int argc, char** argv) { string user, host, pwd; switch(argc-1) { #ifdef WIN case 0: read_registry(); break; #endif case 1: if(string("-h") == argv[1] || string("/?") == argv[1]) goto help; parse_wscp_conf(argv[1]); break; case 3: user = argv[1]; host = argv[2]; pwd = argv[3]; cout << user << "@" << host << "\t" << decrypt(pwd, user+host); break; help: default: cerr << "Restore stored password from WinSCP.\n" << "Usage:\n\t" << argv[0] << " [user host cryptedpwd | path/to/winscp.ini | -h | /? ]\n" << "On Windows, no options means look up in the registry.\n" << "\nExamples:\n" << "\t" << argv[0] << " foo example.com A35C4E4502235B7335F65E12961302012888799B78BAF39F5A632CA6073A333339243D312C3039723F33313F3D3739B012F6\n" << "\t" << argv[0] << " /tmp/winscp.ini\n"; break; } return 0; } 目之所及,皆是回忆,心之所想,皆是过往 分享这篇帖子 链接帖子 分享到其他站点
墨香年少 32 发布于 2023年2月8日 使用vs编译上面的代码,然后在winscp里把配置文件存储在本地磁盘,然后把上面代码生成的exe在cmd里执行 详细视频教程 看这里: https://www.bilibili.com/video/BV1kp4y1H7hL/?vd_source=938ce6137c677f788657172b007ac802 目之所及,皆是回忆,心之所想,皆是过往 分享这篇帖子 链接帖子 分享到其他站点