Esempio n. 1
0
        /// <summary>
        /// Processes the instructions replacing all strings being loaded with an encrypted version.
        /// </summary>
        /// <param name="assemblyDef">The assembly definition.</param>
        /// <param name="body">The body.</param>
        /// <param name="decryptMethod">The decrypt method.</param>
        private void ProcessInstructions(AssemblyDefinition assemblyDef, MethodBody body, MethodReference decryptMethod)
        {
            var instructions = body.Instructions;
            var il = body.GetILProcessor();

            List<Instruction> instructionsToExpand = new List<Instruction>();
            List<int> offsets = new List<int>();
            foreach (Instruction instruction in instructions)
            {
                //Find the call statement
                switch (instruction.OpCode.Name)
                {
                    case "ldstr":
                        //We've found a string load message - we need to replace this instruction
                        if (instruction.Operand is string) //Only do the direct strings for now
                            instructionsToExpand.Add(instruction);
                        break;
                }
            }
            //Fix each ldstr instruction found
            foreach (Instruction instruction in instructionsToExpand)
            {
                //What we do is replace the ldstr "bla" with:
                //ldstr bytearray encrypted_array
                //ldc.i4 random_integer
                //call string class Decrypt(string, int32)

                //First get the original value
                string originalValue = instruction.Operand.ToString();
                offsets.Add(instruction.Offset);

                //Secondly generate a random integer as a salt
                int salt = random.Next(5000, 10000);

                //Now we need to work out what the encrypted value is and set the operand
                OutputHelper.WriteLine("Encrypting string \"{0}\"", originalValue);
                string byteArray = EncryptString(originalValue, salt);
                Instruction loadString = il.Create(OpCodes.Ldstr, byteArray);
                il.Replace(instruction, loadString);

                //Now load the salt
                Instruction loadSalt = il.Create(OpCodes.Ldc_I4, salt);
                il.InsertAfter(loadString, loadSalt);

                //Process the decryption
                Instruction call = il.Create(OpCodes.Call, decryptMethod);
                il.InsertAfter(loadSalt, call);
            }

            //Unfortunately one thing Mono.Cecil doesn't do is adjust instruction offsets for branch statements
            //and exception handling start points. We need to fix these manually
            if (offsets.Count == 0)
                return;

            //Do the adjustments
            il.AdjustOffsets(body, offsets, 6 + assemblyDef.GetAddressSize());
        }