public CfgManipulator(IModule module, PeReader.DefaultHost host, Log.Log logger, MethodCfg methodCfg) { this.host = host; this.logger = logger; this.module = module; this.methodCfg = methodCfg; }
public CodeGenerator(IModule module, PeReader.DefaultHost host, Log.Log logger, Random prng, MethodCfg methodCfg, bool debugging = false, CfgManipulator manipulator = null) { this.host = host; this.logger = logger; this.module = module; this.prng = prng; this.methodCfg = methodCfg; this.debugging = debugging; this.manipulator = manipulator; callableMethods = retrieveCallableMethods(); }
public CodeMutator(IModule module, PeReader.DefaultHost host, Log.Log logger, Random prng, MethodCfg methodCfg, CfgManipulator manipulator, bool debugging = false) { this.host = host; this.logger = logger; this.module = module; this.prng = prng; this.methodCfg = methodCfg; this.debugging = debugging; this.manipulator = manipulator; returnBlock = new BasicBlock(); var exitBranch = new ExitBranchTarget(); returnBlock.exitBranch = exitBranch; returnBlock.operations.Add(createNewOperation(OperationCode.Ret)); methodCfg.basicBlocks.Add(returnBlock); }
// adds a nop instruction after every instruction in the given method cfg public void addNopsToCfg(MethodCfg methodCfg) { foreach (BasicBlock tempBB in methodCfg.basicBlocks) { List <IOperation> newOperations = new List <IOperation>(); for (int idx = 0; idx < tempBB.operations.Count(); idx++) { IOperation currentOperation = tempBB.operations.ElementAt(idx); // copy current operation to new operations list newOperations.Add(currentOperation); if (idx == tempBB.operations.Count() - 1) { break; } // ignore all prefixes (because nop after prefix will crash the program) if (currentOperation.OperationCode == OperationCode.No_ || currentOperation.OperationCode == OperationCode.Constrained_ || currentOperation.OperationCode == OperationCode.Readonly_ || currentOperation.OperationCode == OperationCode.Tail_ || currentOperation.OperationCode == OperationCode.Unaligned_ || currentOperation.OperationCode == OperationCode.Volatile_) { continue; } InternalOperation newNopOperation = new InternalOperation(); newNopOperation.OperationCode = OperationCode.Nop; // add nop operation after current one newOperations.Add(newNopOperation); } // replace old operations with new ones tempBB.operations = newOperations; } }
static void Main(string[] args) { String inputFile; String targetFile; String targetNamespace; String targetClass; String targetMethod; int depth; int dimension; int numberValidPaths; int duplicateBasicBlockWeight; int duplicateBasicBlockCorrectionValue; int stateChangeWeight; int stateChangeCorrectionValue; int insertOpaquePredicateWeight; int seed; // Add debugging code into the obfuscated method (dump obfuscation graphs and so on) bool graphTransformerDebug = false; // Should the obfuscated code contain information to trace the control flow? bool basicBlockTrace = false; // When debugging is active, should the whole obfuscation graph be dumped or only the vpaths in it? bool graphOnlyDumpVPaths = true; // The number of random interfaces that are added to the program int numberRandomInterfaces = 100; if (args.Length != 14) { System.Console.WriteLine("Needed parameters: <inputBinary> <outputBinary> <namespace> <class> <method> <depth> <dimension> <numberValidPaths> <duplicateBasicBlockWeight> <duplicateBasicBlockCorrectionValue> <stateChangeWeight> <stateChangeCorrectionValue> <insertOpaquePredicateWeight> <seed>"); return; } else { inputFile = args[0]; targetFile = args[1]; targetNamespace = args[2]; targetClass = args[3]; targetMethod = args[4]; depth = Convert.ToInt32(args[5]); dimension = Convert.ToInt32(args[6]); numberValidPaths = Convert.ToInt32(args[7]); duplicateBasicBlockWeight = Convert.ToInt32(args[8]); duplicateBasicBlockCorrectionValue = Convert.ToInt32(args[9]); stateChangeWeight = Convert.ToInt32(args[10]); stateChangeCorrectionValue = Convert.ToInt32(args[11]); insertOpaquePredicateWeight = Convert.ToInt32(args[12]); seed = Convert.ToInt32(args[13]); } String logDir = Path.GetDirectoryName(targetFile); Log.Log logger = new Log.Log(logDir, "probfuscation_logfile.txt"); System.Console.WriteLine("Obfuscating: " + inputFile); logger.writeLine("Obfuscating: " + inputFile); System.Console.WriteLine("Output file: " + targetFile); logger.writeLine("Output file: " + targetFile); System.Console.WriteLine("Target namespace: " + targetNamespace); logger.writeLine("Target namespace: " + targetNamespace); System.Console.WriteLine("Target class: " + targetClass); logger.writeLine("Target class: " + targetClass); System.Console.WriteLine("Target method: " + targetMethod); logger.writeLine("Target method: " + targetMethod); System.Console.WriteLine("Depth: " + depth); logger.writeLine("Depth: " + depth); System.Console.WriteLine("Dimension: " + dimension); logger.writeLine("Dimension: " + dimension); System.Console.WriteLine("Number of vpaths: " + numberValidPaths); logger.writeLine("Number of vpaths: " + numberValidPaths); System.Console.WriteLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); logger.writeLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); System.Console.WriteLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); logger.writeLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); System.Console.WriteLine("State change weight: " + stateChangeWeight); logger.writeLine("State change weight: " + stateChangeWeight); System.Console.WriteLine("State change correction value: " + stateChangeCorrectionValue); logger.writeLine("State change correction value: " + stateChangeCorrectionValue); System.Console.WriteLine("Opaque predicate weight: " + insertOpaquePredicateWeight); logger.writeLine("Opaque predicate weight: " + insertOpaquePredicateWeight); System.Console.WriteLine("Seed: " + seed); logger.writeLine("Seed: " + seed); // Seed PRNG for interfaces PRNGRandomInterfaces = new Random(seed); using (var host = new PeReader.DefaultHost()) { IModule /*?*/ module = host.LoadUnitFrom(inputFile) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(inputFile + " is not a PE file containing a CLR module or assembly."); return; } module = new MetadataDeepCopier(host).Copy(module); if (module as Assembly == null) { logger.writeLine("File does not have CIL assembly"); return; } // create analyzer object object CfgBuilder analyze = new Cfg.CfgBuilder(module, host, logger); PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { logger.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null; if (pdbReader != null) { localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader); } // search the namespace the interface should be added to IUnitNamespace foundNamespace = null; foreach (var tempMember in module.UnitNamespaceRoot.Members) { if ((tempMember as IUnitNamespace) == null) { continue; } IUnitNamespace tempNamespace = (tempMember as IUnitNamespace); if (tempNamespace.ToString() == targetNamespace) { foundNamespace = tempNamespace; break; } } if (foundNamespace == null) { throw new ArgumentException("Not able to find target namespace."); } // add created interface (and implemented methods) to all classes bool classFound = false; foreach (var tempClass in module.GetAllTypes()) { if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { continue; } NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); if (foundClass.ContainingUnitNamespace.ToString() == "") { continue; } if (foundClass.ToString() != targetNamespace + "." + targetClass) { continue; } classFound = true; Random prng = new Random(); GraphTransformer graphTransformer = new GraphTransformer(module, host, logger, prng, foundNamespace, foundClass, depth, dimension, graphTransformerDebug); graphTransformer.duplicateBasicBlockWeight = duplicateBasicBlockWeight; graphTransformer.duplicateBasicBlockCorrectionValue = duplicateBasicBlockCorrectionValue; graphTransformer.stateChangeWeight = stateChangeWeight; graphTransformer.stateChangeCorrectionValue = stateChangeCorrectionValue; graphTransformer.insertOpaquePredicateWeight = insertOpaquePredicateWeight; graphTransformer.trace = basicBlockTrace; graphTransformer.graphOnlyDumpVPaths = graphOnlyDumpVPaths; graphTransformer.debuggingDumpLocation = logDir; // Add 100 random interfaces to the namespace Helper testHelper = new Helper(module, host, logger); List <NamespaceTypeDefinition> randomInterfaces = new List <NamespaceTypeDefinition>(); for (int i = 0; i < numberRandomInterfaces; i++) { String randName = randomString(20); NamespaceTypeDefinition temp = testHelper.createNewInterface(randName, foundNamespace); randomInterfaces.Add(temp); } InterfaceTransformer interfaceTransformer = new InterfaceTransformer(module, host, logger); foreach (var classToAdd in module.GetAllTypes()) { if ((classToAdd as NamespaceTypeDefinition) == null || classToAdd.IsAbstract || classToAdd.IsInterface || classToAdd.IsEnum || classToAdd.IsDelegate || classToAdd.IsGeneric || classToAdd.IsStruct) { continue; } if (((NamespaceTypeDefinition)classToAdd).ContainingUnitNamespace.ToString() == "") { continue; } /* * // Use this code if you want to add standard interfaces to the target class * interfaceTransformer.addStdInterfacesGivenByFile(@"e:\code\dotnet_standard_interfaces.txt"); * * // add std interfaces to class * if (foundClass != (classToAdd as NamespaceTypeDefinition)) { * foreach (ITypeDefinition temp in interfaceTransformer.getInterfacesList()) { * interfaceTransformer.addInterface((classToAdd as NamespaceTypeDefinition), temp); * } * } */ // Add random interfaces to the classes List <NamespaceTypeDefinition> alreadyAdded = new List <NamespaceTypeDefinition>(); int max = PRNGRandomInterfaces.Next(numberRandomInterfaces); NamespaceTypeDefinition interfaceClass = (classToAdd as NamespaceTypeDefinition); logger.writeLine("Adding " + max + " random interfaces to class \"" + interfaceClass.ToString() + "\""); for (int i = 0; i < max; i++) { NamespaceTypeDefinition randInterface = randomInterfaces.ElementAt(PRNGRandomInterfaces.Next(randomInterfaces.Count)); if (alreadyAdded.Contains(randInterface)) { continue; } alreadyAdded.Add(randInterface); logger.writeLine("Adding interface: \"" + randInterface.ToString() + "\""); // add nodes interface to class if (interfaceClass.Interfaces != null) { interfaceClass.Interfaces.Add(randInterface); } else { interfaceClass.Interfaces = new List <ITypeReference>(); interfaceClass.Interfaces.Add(randInterface); } } logger.writeLine(""); // Add special interface for the obfuscation scheme to the class // (makes sure that all needed attributes and methods are implemented) graphTransformer.addNodeInterfaceToTargetClass((classToAdd as NamespaceTypeDefinition)); } // Prepare obfuscation graph graphTransformer.generateGraph(numberValidPaths); graphTransformer.createGraphMethods(); // Search method to obfuscate MethodDefinition methodToObfu = null; foreach (MethodDefinition tempMethod in foundClass.Methods) { if (tempMethod.Name.ToString() == targetMethod) { methodToObfu = tempMethod; break; } } if (methodToObfu == null) { throw new ArgumentException("Not able to find target method."); } // Obfuscate target method MethodCfg cfg = analyze.buildCfgForMethod(methodToObfu); logger.dumpMethodCfg(cfg, "before"); graphTransformer.addObfuscationToMethod(cfg); analyze.createMethodFromCfg(cfg); logger.dumpMethodCfg(cfg, "after"); break; } if (!classFound) { throw new ArgumentException("Not able to find target class."); } /* * This code can be used if not only one specific method should be obfuscated, * but the whole class. * List<ClassCfg> classCfgList = new List<ClassCfg>(); * foreach (var tempClass in module.GetAllTypes()) { * if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { || continue; || } || || // create basic blocks || NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); || || logger.writeLine("Create CFG for class \"" + foundClass.Name.ToString() + "\""); || ClassCfg temp = analyze.buildCfgForClass(foundClass); || classCfgList.Add(temp); || logger.writeLine("\n---------------------------------\n"); ||} || ||// transform each function ||NopTransformer transformator = new NopTransformer(module, host, logger); ||foreach (ClassCfg tempClassCfg in classCfgList) { || foreach (MethodCfg tempMethodCfg in tempClassCfg.methodCfgs) { || logger.writeLine("Transform method CFG of \"" + tempMethodCfg.method.ToString() + "\""); || transformator.addNopsToCfg(tempMethodCfg); || logger.writeLine("\n---------------------------------\n"); || } ||} || ||foreach (ClassCfg tempClassCfg in classCfgList) { || logger.writeLine("Create class from CFG for \"" + tempClassCfg.classObj.Name.ToString() + "\""); || analyze.createClassFromCfg(tempClassCfg); || logger.writeLine("\n---------------------------------\n"); ||} */ using (var peStream = File.Create(targetFile)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(targetFile, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } }