// TODO: Make 'ByteGuardGetInteger' method take only one parameter. public static void EmbedConstants(ModuleDef targetModule, string decryptionKey, bool compressConstants = true) { List <byte> constantByteList = new List <byte>(); // Finds the injected 'ByteGuardProtection' class that contains all the decryption methods. TypeDef constantProtections = targetModule.Find("ByteGuard.Protections.Online.Runtime.ByteGuardConstantProtections", true); // Finds the 'DecodeAndDecrypt' method located in the 'ByteGuardProtection' class/type. MethodDef byteguardGetInteger = constantProtections.FindMethod("ByteGuardGetInteger"); // Iterates through all the types and methods that are editable. foreach (TypeDef t in targetModule.GetTypes().Where(type => !type.Namespace.Contains("ByteGuard.Protections.Online.Runtime"))) { foreach (MethodDef m in t.Methods.Where(mtd => mtd.HasBody)) { // Simplifies all macros so that all constants can be encrypted. m.Body.SimplifyMacros(m.Parameters); // Iterates through each instruction inside the method body. for (int i = 0; i < m.Body.Instructions.Count; i++) { // Stores the current instruction into a variable for us to work with. Instruction ins = m.Body.Instructions[i]; // If the current instruction is a constant. if (ins.IsLdcI4()) { // Randomly generates an integer that is within the size of a byte. int randomInteger = R.Next(0, 128); // Inserts a call to the method that will get the constant from resources. m.Body.Instructions.Insert(i + 1, Instruction.CreateLdcI4(Convert.ToInt32(ins.Operand) ^ randomInteger)); m.Body.Instructions.Insert(i + 2, Instruction.Create(OpCodes.Call, byteguardGetInteger)); ins.Operand = constantByteList.Count; // Adds the generated byte to the byte list. constantByteList.Add(Convert.ToByte(randomInteger)); // Skips the newly added instructions. i += 2; } } // Optimizes macros to increase performed and reduce file size. m.Body.OptimizeMacros(); } } // Converts the constant byte list into a byte array. byte[] constantListBytes = constantByteList.ToArray(); // Creates a name for the resource. string resourceName = Runtime.ByteGuardHelper.GetMd5(EmbeddedResourceName = R.Next(1, 1000000).ToString()); // Creates an encryption key to encrypt the embedded resource with. string resourceEncryptionKey = resourceName + Runtime.ByteGuardHelper.GetMd5(decryptionKey); // Encrypts the byte array. constantListBytes = ProtectionHelper.AesEncrypt(constantListBytes, resourceEncryptionKey); // Compresses the byte array if the user has decided to compress. //if (compressBool) //constantListBytes = ProtectionHelper.GzipCompressBytes(constantListBytes); //else //Protection.Miscellaneous.ProtectionHelper.SetByteGuardBool(ByteGuardProtection, "DecompressEmbeddedConstants", false); constantListBytes = ProtectionHelper.GzipCompressBytes(constantListBytes); // Adds the byte array as an embedded resource to the module. EmbeddedResource constantResource = new EmbeddedResource(resourceName, constantListBytes); targetModule.Resources.Add(constantResource); CallLoadIntegersMethod(targetModule, false); }
// TODO: Complete this. private static void EmbedOfflineStrings(ModuleDef targetModule) { // Finds the injected 'ByteGuardStringProtections' class that contains all the decryption methods. TypeDef stringProtections = targetModule.Find("ByteGuard.Protections.Online.Runtime.ByteGuardStringProtections", true); // Finds the 'DecodeAndDecrypt' method located in the 'ByteGuardProtection' class/type. MethodDef getStringOfflineMethod = stringProtections.FindMethod("GetStringOffline"); // Creates an integer variable that will hold the starting index of each string. int stringIndex = 0; // A list collection for the method strings to be added to. List <string> stringList = new List <string>(); // Iterates through all the types and methods that are editable. foreach (TypeDef t in targetModule.GetTypes().Where(type => type.Namespace.Contains("ByteGuard.Protections.Online.Runtime"))) { foreach (MethodDef m in t.Methods.Where(mtd => mtd.HasBody && mtd.Name != "LoadIntegers" && mtd.Name != "LoadStrings" && mtd.Name != "LoadStringsOffline" && mtd.Name != "GetMd5")) { // Iterates through each instruction inside the method body. for (int i = 0; i < m.Body.Instructions.Count; i++) { // Stores the current instruction into a new variable. Instruction ins = m.Body.Instructions[i]; // Checks that the current instruction is a string and is not null. if (ins.Operand is string) { // Stores the string into a string variable. string stringToEmbed = ins.Operand.ToString(); // Adds the string to be embedded into the StringList collection. stringList.Add(stringToEmbed); // Changes the opcode and operand of the current instruction to hold the strings starting index. ins.OpCode = OpCodes.Ldc_I4; ins.Operand = stringIndex; // Inserts two new instructions containing the string length and the call to the 'GetString' method. m.Body.Instructions.Insert(i + 1, Instruction.CreateLdcI4(stringToEmbed.Length)); m.Body.Instructions.Insert(i + 2, Instruction.Create(OpCodes.Call, getStringOfflineMethod)); // Increases the StringIndex variable by the size of the string. stringIndex += stringToEmbed.Length; // Increase the counter by 3 to skip over the newly added instructions. i += 2; } } } } // Converts the 'StringList' collection into a byte array. byte[] stringListBytes = stringList.SelectMany(s => Encoding.UTF8.GetBytes(s)).ToArray(); // ResourceName = MD5Hash of randomly genereted integer. (Generated at the start of obfuscation). string resourceName = Runtime.ByteGuardHelper.GetMd5(StringProtections.EmbeddedResourceNameOffline = R.Next(1, 1000000).ToString()); // TODO: Encrypt. // Creates the ResourceEncryptionKey that will be used to encrypt the embedded constants. //string resourceEncryptionKey = resourceName + Runtime.ByteGuardHelper.GetMd5(decryptionKey); // Encrypts the embedded string bytes using the generated encryption key. //stringListBytes = ProtectionHelper.AesEncrypt(stringListBytes, resourceEncryptionKey); // Compresses the bytes. stringListBytes = ProtectionHelper.GzipCompressBytes(stringListBytes); // Embeds the byte array as a resource to the target module. EmbeddedResource stringsResource = new EmbeddedResource(resourceName, stringListBytes);//EmbeddedResourceName, StringListBytes); targetModule.Resources.Add(stringsResource); CallLoadStringsMethod(targetModule, true); }