/// <summary> /// Wait until all threads are done. Pretty much hardcoded. /// </summary> private void WaitMakeSure() { int occ = 0; long prevState = 0; while (true) { if (occ < 3 && _inWork == 0) { occ++; } else if (occ >= 3) { break; } else { occ = 0; } Thread.Sleep(100); if (Math.Abs(prevState - _inWork) > 25) { Message(XConsole.Info("Waiting far all threads to finish! In work: " + _inWork)); } prevState = _inWork; } }
public void BeginProcessing() { #if DEBUG Stopwatch debugStopwatch = new Stopwatch(); debugStopwatch.Start(); try { #endif if (Processed) { throw new NameMapperProcessingException("Already processed! This class is a one-time use."); } // -- BEGIN PROCESSING // -- Trying to find exactly same methods using entry as a start point. var cleanEntry = FindEntryPoint(CleanModule); var obfEntry = FindEntryPoint(ObfModule); Message(XConsole.Info("Recursing using entry as a start point.")); StartRecurseThread(cleanEntry, obfEntry); WaitMakeSure(); // -- // -- 1. Getting unique methods from both obf and clean types as two separate lists (NameProcessed, but not IsFullyProcessed) // -- 2. Comparing unique obf methods to unique clean methods, recursing same methods // -- 3. IsFullyProcessed = true Message(XConsole.Info("Recursing unique methods.")); int prevCount = -1; var procMan = _namableProcessor.Processed; while (true) { foreach (var item in procMan.Types) { if (item.IsFullyProcessed) { continue; } var cleanMethods = item.Clean.ScopeType.ResolveTypeDef()?.Methods.Where(x => !x.IsNameObfuscated()).ToList(); var obfMethods = item.Obfuscated.ScopeType.ResolveTypeDef()?.Methods.Where(x => !x.IsEazInternalName()).ToList(); if (cleanMethods is null || obfMethods is null) { continue; } List <MethodDef> cleanUniqueMethods = cleanMethods.GetUniqueMethods(); List <MethodDef> obfUniqueMethods = obfMethods.GetUniqueMethods(); foreach (var cleanMethod in cleanUniqueMethods) { var obfMethod = obfUniqueMethods.FirstOrDefault(x => AreOpcodesEqual(cleanMethod?.Body?.Instructions, x.Body?.Instructions) == -1); if (obfMethod != null) { StartRecurseThread(cleanMethod, obfMethod); } } item.IsFullyProcessed = true; } WaitMakeSure(); int count = procMan.Types.Count; if (count == prevCount) { break; } Message(XConsole.Info($"{count - prevCount} new types! Processing...")); prevCount = count; } // -- if (DeobfuscateNames) { // -- Filling up interfaces foreach (var type in procMan.Types) { var obfTypeDef = type.Obfuscated.ScopeType.ResolveTypeDef(); if (obfTypeDef.HasInterfaces) { var interfaceMethods = obfTypeDef.Interfaces.Where(x => x.Interface.IsFromModule(this)).SelectMany(x => x.Interface.ResolveTypeDef().Methods).Where(x => x.IsNameObfuscated()).ToList(); foreach (var method in obfTypeDef.Methods) { if (NamePairs.TryGetValue(method.Name, out string obfName)) { var interfaceMethod = interfaceMethods.FirstOrDefault(x => x.Name == obfName); if (interfaceMethod != null) { interfaceMethod.Name = method.Name; } } } } } // -- // -- Renaming all names left var obfCleanDict = NamePairs.Swap(); var res = new MemberFinder().FindAll(ObfModule); foreach (var meth in res.MethodDefs.Select(x => x.Key).Where(x => x.IsNameObfuscated())) { if (obfCleanDict.TryGetValue(meth.Name, out string value)) { meth.Name = value; } } foreach (var type in res.TypeDefs.Select(x => x.Key).Where(x => x.IsNameObfuscated())) { if (obfCleanDict.TryGetValue(type.Name, out string value)) { type.Name = value; } } foreach (var field in res.FieldDefs.Select(x => x.Key).Where(x => x.IsNameObfuscated())) { if (obfCleanDict.TryGetValue(field.Name, out string value)) { field.Name = value; } } foreach (var genParam in res.GenericParams.Select(x => x.Key).Where(x => x.IsNameObfuscated())) { if (obfCleanDict.TryGetValue(genParam.Name, out string value)) { genParam.Name = value; } } // -- } WaitMakeSure(); if (_overallErroredMethods > 0) { Message(XConsole.Warn($"Not all methods are processed! {_overallErroredMethods} left behind.")); } Message(XConsole.Info($"Overall known classes: {procMan.Types.Count}; Fully processed classes: {procMan.Types.Count(x => x.IsFullyProcessed)}")); var processedTypesCount = procMan.Types.Count; var allTypesCount = ObfModule.CountTypes(x => !x.IsNameObfuscated()); var processedPercentage = (float)processedTypesCount / allTypesCount; if (processedPercentage < MINIMAL_SUCCESS_PERCENTAGE) { throw new NameMapperProcessingException($"Processed types percentage: {processedTypesCount}/{allTypesCount} => {processedPercentage * 100}% < {MINIMAL_SUCCESS_PERCENTAGE * 100}% (min), counting as unsuccessful."); } Processed = true; #if DEBUG } catch (Exception ex) { Message(XConsole.Error(ex.ToString())); Console.ReadKey(); // because debug } finally { debugStopwatch.Stop(); Message(XConsole.Info($"Mapped everything in: {debugStopwatch.ElapsedMilliseconds}ms")); } #endif // -- END }