/* Copyright (C) 2011-2015 de4dot@gmail.com This file is part of de4dot. de4dot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. de4dot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with de4dot. If not, see . */ using System; using System.Collections.Generic; using dnlib.DotNet; using de4dot.blocks; namespace de4dot.code.deobfuscators.MaxtoCode { class MainType { ModuleDefMD module; TypeDef mcType; bool isOld; ModuleRef runtimeModule1, runtimeModule2; public bool IsOld { get { return isOld; } } public TypeDef Type { get { return mcType; } } public IEnumerable InitMethods { get { var list = new List(); if (mcType == null) return list; foreach (var method in mcType.Methods) { if (method.IsStatic && DotNetUtils.IsMethod(method, "System.Void", "()")) list.Add(method); } return list; } } public IEnumerable RuntimeModuleRefs { get { if (runtimeModule1 != null) yield return runtimeModule1; if (runtimeModule2 != null) yield return runtimeModule2; } } public bool Detected { get { return mcType != null; } } public MainType(ModuleDefMD module) { this.module = module; } public MainType(ModuleDefMD module, MainType oldOne) { this.module = module; this.mcType = Lookup(oldOne.mcType, "Could not find main type"); } T Lookup(T def, string errorMessage) where T : class, ICodedToken { return DeobUtils.Lookup(module, def, errorMessage); } public void Find() { foreach (var cctor in DeobUtils.GetInitCctors(module, 3)) { if (CheckCctor(cctor)) break; } } bool CheckCctor(MethodDef cctor) { foreach (var method in DotNetUtils.GetCalledMethods(module, cctor)) { if (method.Name != "Startup") continue; if (!DotNetUtils.IsMethod(method, "System.Void", "()")) continue; bool isOldTmp; if (!CheckType(method.DeclaringType, out runtimeModule1, out runtimeModule2, out isOldTmp)) continue; mcType = method.DeclaringType; isOld = isOldTmp; return true; } return false; } static bool CheckType(TypeDef type, out ModuleRef module1, out ModuleRef module2, out bool isOld) { module1 = module2 = null; isOld = false; if (type.FindMethod("Startup") == null) return false; var pinvokes = GetPinvokes(type); var pinvokeList = GetPinvokeList(pinvokes, "CheckRuntime"); if (pinvokeList == null) return false; if (GetPinvokeList(pinvokes, "MainDLL") == null) return false; // Newer versions (3.4+ ???) also have GetModuleBase() isOld = GetPinvokeList(pinvokes, "GetModuleBase") == null; module1 = pinvokeList[0].ImplMap.Module; module2 = pinvokeList[1].ImplMap.Module; return true; } static Dictionary> GetPinvokes(TypeDef type) { var pinvokes = new Dictionary>(StringComparer.Ordinal); foreach (var method in type.Methods) { var info = method.ImplMap; if (info == null || UTF8String.IsNullOrEmpty(info.Name)) continue; List list; if (!pinvokes.TryGetValue(info.Name.String, out list)) pinvokes[info.Name.String] = list = new List(); list.Add(method); } return pinvokes; } static List GetPinvokeList(Dictionary> pinvokes, string methodName) { List list; if (!pinvokes.TryGetValue(methodName, out list)) return null; if (list.Count != 2) return null; return list; } } }