public void InitializeEmbeddedFiles() { foreach (var info in assemblyInfos) { info.Resource = DotNetUtils.GetResource(module, info.ResourceName) as EmbeddedResource; if (info.Resource == null) { throw new ApplicationException(string.Format("Could not find resource {0}", Utils.ToCsharpString(info.ResourceName))); } info.Data = info.Resource.GetResourceData(); if (info.IsEncrypted) { Decrypt(info.Data); } if (info.IsCompressed) { info.Data = Decompress(info.Data); } InitializeNameAndExtension(info); } }
MethodDef GetDecryptMethod() { foreach (var method in resolverType.Methods) { if (!method.IsStatic || method.Body == null) { continue; } if (!DotNetUtils.IsMethod(method, "System.Byte[]", "(System.Byte[])")) { continue; } if (!DeobUtils.HasInteger(method, 32) || !DeobUtils.HasInteger(method, 121)) { continue; } return(method); } return(null); }
bool findTypeAndResources() { var bundleDataTmp = DotNetUtils.getResource(module, ".bundle.dat") as EmbeddedResource; var bundleXmlFileTmp = DotNetUtils.getResource(module, ".bundle.manifest") as EmbeddedResource; if (bundleDataTmp == null || bundleXmlFileTmp == null) { return(false); } var bundleTypeTmp = findBundleType(); if (bundleTypeTmp == null) { return(false); } bundleData = bundleDataTmp; bundleXmlFile = bundleXmlFileTmp; bundleType = bundleTypeTmp; findOtherTypes(); return(true); }
MethodDef GetProxyCreateMethod(TypeDef type) { if (DotNetUtils.FindFieldType(type, "System.ModuleHandle", true) == null) { return(null); } if (type.Fields.Count < 1 || type.Fields.Count > 20) { return(null); } MethodDef createMethod = null; foreach (var m in type.Methods) { if (m.Name == ".ctor" || m.Name == ".cctor") { continue; } if (createMethod == null && DotNetUtils.IsMethod(m, "System.Void", "(System.Int32,System.Int32,System.Int32)")) { createMethod = m; continue; } continue; } if (createMethod == null || !createMethod.HasBody) { return(null); } if (!DeobUtils.HasInteger(createMethod, 0xFFFFFF)) { return(null); } return(createMethod); }
void deleteEmptyCctors() { var emptyCctorsToRemove = new List <MethodDefinition>(); foreach (var type in module.GetTypes()) { var cctor = DotNetUtils.getMethod(type, ".cctor"); if (cctor != null && DotNetUtils.isEmpty(cctor)) { emptyCctorsToRemove.Add(cctor); } } if (emptyCctorsToRemove.Count == 0) { return; } Log.v("Removing empty .cctor methods"); Log.indent(); foreach (var cctor in emptyCctorsToRemove) { var type = cctor.DeclaringType; if (type == null) { continue; } if (type.Methods.Remove(cctor)) { Log.v("{0:X8}, type: {1} ({2:X8})", cctor.MetadataToken.ToUInt32(), Utils.removeNewlines(type), type.MetadataToken.ToUInt32()); } } Log.deIndent(); }
public void Find(ISimpleDeobfuscator simpleDeobfuscator) { var additionalTypes = new string[] { "System.String", }; foreach (var type in module.Types) { if (type.BaseType == null || type.BaseType.FullName != "System.Object") { continue; } if (!CheckFields(type.Fields)) { continue; } foreach (var method in type.Methods) { if (!method.IsStatic || !method.HasBody) { continue; } if (!DotNetUtils.IsMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)") && !DotNetUtils.IsMethod(method, "System.Reflection.Assembly", "(System.Object,System.Object)")) { continue; } if (!encryptedResource.CouldBeResourceDecrypter(method, additionalTypes, false)) { continue; } encryptedResource.Method = method; return; } } }
bool Find(MethodDef method) { if (method == null || method.Body == null) { return(false); } foreach (var instr in method.Body.Instructions) { if (instr.OpCode.Code != Code.Call) { continue; } var calledMethod = instr.Operand as MethodDef; try { // If the body is encrypted, this could throw if (calledMethod == null || calledMethod.Body == null) { continue; } } catch { continue; } if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()")) { continue; } if (!CheckType(calledMethod.DeclaringType, calledMethod)) { continue; } initMethod = calledMethod; return(true); } return(false); }
bool CheckMethod(MethodDef method) { if (method == null || method.Body == null) { return(false); } foreach (var instr in method.Body.Instructions) { if (instr.OpCode.Code != Code.Call) { continue; } var calledMethod = instr.Operand as MethodDef; if (calledMethod == null || !calledMethod.IsStatic) { continue; } if (!DotNetUtils.IsMethod(calledMethod, "System.Void", "()")) { continue; } var type = calledMethod.DeclaringType; if (type == null) { continue; } if (CheckMethod_normal(type, calledMethod) || CheckMethod_safe(type, calledMethod)) { initMethod = calledMethod; return(true); } } return(false); }
MethodDefinition findInitMethod(ISimpleDeobfuscator simpleDeobfuscator) { var ctor = DotNetUtils.getMethod(Type, ".ctor"); foreach (var method in Type.Methods) { if (!method.IsStatic || method.Body == null) continue; if (!DotNetUtils.isMethod(method, "System.Void", "()")) continue; if (method.Body.Variables.Count > 1) continue; simpleDeobfuscator.deobfuscate(method); bool stsfldUsed = false, newobjUsed = false; foreach (var instr in method.Body.Instructions) { if (instr.OpCode.Code == Code.Stsfld) { var field = instr.Operand as FieldReference; if (field == null || field.FieldType.FullName != "System.Boolean") continue; if (!MemberReferenceHelper.compareTypes(Type, field.DeclaringType)) continue; stsfldUsed = true; } else if (instr.OpCode.Code == Code.Newobj) { var calledCtor = instr.Operand as MethodReference; if (calledCtor == null) continue; if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledCtor, ctor)) continue; newobjUsed = true; } } if (!stsfldUsed || !newobjUsed) continue; return method; } return null; }
FieldReference findOffsetField(MethodDefinition method) { var instructions = method.Body.Instructions; for (int i = 0; i <= instructions.Count - 2; i++) { var ldsfld = instructions[i]; if (ldsfld.OpCode.Code != Code.Ldsfld) { continue; } var field = ldsfld.Operand as FieldReference; if (field == null || field.FieldType.FullName != "System.String") { continue; } if (!MemberReferenceHelper.compareTypes(stringsEncodingClass, field.DeclaringType)) { continue; } var call = instructions[i + 1]; if (call.OpCode.Code != Code.Call) { continue; } var calledMethod = call.Operand as MethodReference; if (!DotNetUtils.isMethod(calledMethod, "System.Int32", "(System.String)")) { continue; } return(field); } return(null); }
static MethodDefinition checkMethods_v36(TypeDefinition type) { if (type.Methods.Count != 2) { return(null); } MethodDefinition decrypterMethod = null; MethodDefinition cctor = null; foreach (var method in type.Methods) { if (method.Name == ".cctor") { cctor = method; continue; } if (decrypterMethod != null) { return(null); } if (!DotNetUtils.isMethod(method, "System.String", "(System.Int32,System.Int32,System.Int32)")) { return(null); } decrypterMethod = method; } if (cctor == null) { return(null); } if (decrypterMethod == null || !decrypterMethod.IsStatic) { return(null); } return(decrypterMethod); }
IField FindOffsetField(MethodDef method) { var instructions = method.Body.Instructions; for (int i = 0; i <= instructions.Count - 2; i++) { var ldsfld = instructions[i]; if (ldsfld.OpCode.Code != Code.Ldsfld) { continue; } var field = ldsfld.Operand as IField; if (field == null || field.FieldSig.GetFieldType().GetElementType() != ElementType.String) { continue; } if (!new SigComparer().Equals(stringsEncodingClass, field.DeclaringType)) { continue; } var call = instructions[i + 1]; if (call.OpCode.Code != Code.Call) { continue; } var calledMethod = call.Operand as IMethod; if (!DotNetUtils.IsMethod(calledMethod, "System.Int32", "(System.String)")) { continue; } return(field); } return(null); }
bool find(MethodDef method) { if (method == null || method.Body == null || !method.IsStatic) { return(false); } var instrs = method.Body.Instructions; for (int i = 0; i < instrs.Count; i++) { var call = instrs[i]; if (call.OpCode.Code != Code.Call) { continue; } var initMethodTmp = call.Operand as MethodDef; if (initMethodTmp == null || initMethodTmp.Body == null || !initMethodTmp.IsStatic) { continue; } if (!DotNetUtils.isMethod(initMethodTmp, "System.Void", "()")) { continue; } if (!checkType(initMethodTmp.DeclaringType)) { continue; } decrypterType = initMethodTmp.DeclaringType; initMethod = initMethodTmp; return(true); } return(false); }
void deleteEmptyCctors() { var emptyCctorsToRemove = new List <MethodDef>(); foreach (var type in module.GetTypes()) { var cctor = type.FindStaticConstructor(); if (cctor != null && DotNetUtils.isEmpty(cctor)) { emptyCctorsToRemove.Add(cctor); } } if (emptyCctorsToRemove.Count == 0) { return; } Logger.v("Removing empty .cctor methods"); Logger.Instance.indent(); foreach (var cctor in emptyCctorsToRemove) { var type = cctor.DeclaringType; if (type == null) { continue; } if (type.Methods.Remove(cctor)) { Logger.v("{0:X8}, type: {1} ({2:X8})", cctor.MDToken.ToUInt32(), Utils.removeNewlines(type), type.MDToken.ToUInt32()); } } Logger.Instance.deIndent(); }
MethodDef GetDecryptMethod() { foreach (var type in module.Types) { if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed)) { continue; } if (!CheckMethods(type.Methods)) { continue; } foreach (var method in type.Methods) { if (!DotNetUtils.IsMethod(method, "System.Object", "(System.UInt32,System.UInt32)")) { continue; } return(method); } } return(null); }
static void GetReadAndExecMethods(TypeDef handler, out MethodDef readMethod, out MethodDef execMethod) { readMethod = execMethod = null; foreach (var method in handler.Methods) { if (!method.IsVirtual) { continue; } if (DotNetUtils.IsMethod(method, "System.Void", "(System.IO.BinaryReader)")) { if (readMethod != null) { throw new ApplicationException("Found another read method"); } readMethod = method; } else if (!DotNetUtils.HasReturnValue(method) && method.MethodSig.GetParamCount() == 1) { if (execMethod != null) { throw new ApplicationException("Found another execute method"); } execMethod = method; } } if (readMethod == null) { throw new ApplicationException("Could not find read method"); } if (execMethod == null) { throw new ApplicationException("Could not find execute method"); } }
// The obfuscator could be buggy and call a proxy delegate without pushing the // instance field. SA has done it, so let's fix it. void FixBrokenCalls(MethodDef obfuscatedMethod, IList <Block> allBlocks) { foreach (var block in allBlocks) { var instrs = block.Instructions; for (int i = 0; i < instrs.Count; i++) { var call = instrs[i]; if (call.OpCode != OpCodes.Call && call.OpCode != OpCodes.Callvirt) { continue; } var methodRef = call.Operand as IMethod; if (methodRef == null || methodRef.Name != "Invoke") { continue; } MethodDef method = DotNetUtils.GetMethod2(module, methodRef); if (method == null || method.DeclaringType == null) { continue; } if (!delegateTypesDict.ContainsKey(method.DeclaringType)) { continue; } // Oooops!!! The obfuscator is buggy. Well, let's hope it is, or it's my code. ;) Logger.w("Holy obfuscator bugs, Batman! Found a proxy delegate call with no instance push in {0:X8}. Replacing it with a throw...", obfuscatedMethod.MDToken.ToInt32()); block.Insert(i, OpCodes.Ldnull.ToInstruction()); block.Replace(i + 1, 1, OpCodes.Throw.ToInstruction()); i++; } } }
EmbeddedResource FindGetManifestResourceStreamTypeResource(TypeDef type, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) { foreach (var method in type.Methods) { if (!method.IsPrivate || !method.IsStatic || method.Body == null) { continue; } if (!DotNetUtils.IsMethod(method, "System.String", "(System.Reflection.Assembly,System.Type,System.String)")) { continue; } simpleDeobfuscator.Deobfuscate(method); simpleDeobfuscator.DecryptStrings(method, deob); foreach (var s in DotNetUtils.GetCodeStrings(method)) { if (DotNetUtils.GetResource(module, s) is EmbeddedResource resource) { return(resource); } } } return(null); }
public static bool findNewarr(MethodDefinition method, ref int i, out int size) { var instructions = method.Body.Instructions; for (; i < instructions.Count; i++) { var instr = instructions[i]; if (instr.OpCode.Code != Code.Newarr || i < 1) { continue; } var ldci4 = instructions[i - 1]; if (!DotNetUtils.isLdcI4(ldci4)) { continue; } size = DotNetUtils.getLdcI4Value(ldci4); return(true); } size = -1; return(false); }
/// <summary> /// Check if a called method's body contains the given pattern, and that the called /// method is given a Boolean of a specific value as the third argument. /// </summary> /// <param name="val">Boolean value to expect</param> /// <param name="codePattern">Pattern to search for in called method</param> /// <remarks> /// Looks like: [static] ??? method(Value, Value, Boolean) /// </remarks> /// <returns>true if match, false if not</returns> public Boolean MatchesIndirectWithBoolean(Boolean val, IList <Code> codePattern) { this.CheckDelegateMethod(); var called = DotNetUtils.GetCalledMethods(this.Parent.Module, this.DelegateMethod); var targetMethod = called.FirstOrDefault((m) => { return(m.Parameters.Count == 4 && m.Parameters[3].Type.FullName.Equals("System.Boolean")); }); if (targetMethod == null) { return(false); } // Expected value of ldc.i4 operand, loading the bool value Int32 expected = val ? 1 : 0; var instrs = this.DelegateMethod.Body.Instructions; for (Int32 i = 0; i < instrs.Count; i++) { var instr = this.DelegateMethod.Body.Instructions[i]; if (instr.OpCode.Code == Code.Call && instr.Operand is MethodDef && ((MethodDef)instr.Operand) == targetMethod && i != 0 && instrs[i - 1].IsLdcI4() && Helpers.GetLdcOperand(instrs[i - 1]) == expected) { // If we get here, we have the right method return(Helpers.FindOpCodePatterns(targetMethod.Body.Instructions, codePattern).Count > 0); } } return(false); }
bool CheckType(TypeDef type, MethodDef initMethod, ISimpleDeobfuscator simpleDeobfuscator) { if (DotNetUtils.FindFieldType(type, "System.Collections.Hashtable", true) == null) { return(false); } simpleDeobfuscator.Deobfuscate(initMethod); if (!CheckInitMethod(initMethod)) { return(false); } if ((asmSeparator = FindAssemblySeparator(initMethod)) == null) { return(false); } List <AssemblyInfo> newAssemblyInfos = null; foreach (var s in DotNetUtils.GetCodeStrings(initMethod)) { newAssemblyInfos = InitializeEmbeddedAssemblies(s); if (newAssemblyInfos != null) { break; } } if (newAssemblyInfos == null) { return(false); } resolverType = type; resolverMethod = initMethod; assemblyInfos = newAssemblyInfos; return(true); }
public StreamHelperType(TypeDef type) { this.type = type; foreach (var method in type.Methods) { if (method.IsStatic || method.Body == null || method.IsPrivate || method.GenericParameters.Count > 0) { continue; } if (DotNetUtils.IsMethod(method, "System.Int16", "()")) { readInt16Method = method; } else if (DotNetUtils.IsMethod(method, "System.Int32", "()")) { readInt32Method = method; } else if (DotNetUtils.IsMethod(method, "System.Byte[]", "(System.Int32)")) { readBytesMethod = method; } } }
/* 0x00000375 06 IL_007D: ldloc.0 * 0x00000376 6F1500000A IL_007E: callvirt * 0x0000037B 19 IL_0083: ldc.i4.3 * 0x0000037C 6F1600000A IL_0084: callvirt */ private bool ReplaceFieldNameChar(ref IList <Instruction> instructions, string fieldName, Local fieldLocal) { for (var i = 0; i < instructions.Count; i++) { var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Callvirt, OpCodes.Ldc_I4, OpCodes.Callvirt); if (instrs == null) { continue; } if ((Local)instrs[0].Operand != fieldLocal) { continue; } if (!instrs[1].Operand.ToString().Contains("get_Name")) { continue; } if (!instrs[3].Operand.ToString().Contains("get_Chars")) { continue; } var charIndex = (int)instrs[2].Operand; int @char = fieldName[charIndex]; instructions[i].OpCode = OpCodes.Ldc_I4; instructions[i].Operand = @char; instructions[i + 1].OpCode = OpCodes.Nop; instructions[i + 2].OpCode = OpCodes.Nop; instructions[i + 3].OpCode = OpCodes.Nop; return(true); } return(false); }
static int findMagic3(MethodDefinition method) { var instrs = method.Body.Instructions; for (int i = 0; i < instrs.Count - 2; i++) { var ldarg = instrs[i]; if (!DotNetUtils.isLdarg(ldarg) || DotNetUtils.getArgIndex(ldarg) != 2) { continue; } var ldci4 = instrs[i + 1]; if (!DotNetUtils.isLdcI4(ldci4)) { continue; } if (instrs[i + 2].OpCode.Code != Code.Xor) { continue; } return(DotNetUtils.getLdcI4Value(ldci4)); } throw new ApplicationException("Could not find magic3"); }
void InitializeVersion(TypeDef attr) { var s = DotNetUtils.GetCustomArgAsString(GetAssemblyAttribute(attr), 0); if (s == null) { return; } poweredByAttributeString = s; var val = System.Text.RegularExpressions.Regex.Match(s, @"^Powered by (SmartAssembly (\d+)\.(\d+)\.(\d+)\.(\d+))$"); if (val.Groups.Count < 6) { return; } ObfuscatorName = val.Groups[1].ToString(); approxVersion = new Version(int.Parse(val.Groups[2].ToString()), int.Parse(val.Groups[3].ToString()), int.Parse(val.Groups[4].ToString()), int.Parse(val.Groups[5].ToString())); return; }
void FindDecrypterInfos() { foreach (var type in module.Types) { if (type.Attributes != (TypeAttributes.Abstract | TypeAttributes.Sealed)) { continue; } if (!CheckMethods(type.Methods)) { continue; } foreach (var method in type.Methods) { if (!DotNetUtils.IsMethod(method, "System.Object", "(System.UInt32,System.UInt32)")) { continue; } var info = new DecrypterInfoV17(version, method); Add(info); } } }
void deobfuscate(MethodDefinition method, string msg, Action <Blocks> handler) { if (savedMethodBodies != null) { savedMethodBodies.save(method); } Log.v("{0}: {1} ({2:X8})", msg, Utils.removeNewlines(method), method.MetadataToken.ToUInt32()); Log.indent(); if (hasNonEmptyBody(method)) { var blocks = new Blocks(method); handler(blocks); IList <Instruction> allInstructions; IList <ExceptionHandler> allExceptionHandlers; blocks.getCode(out allInstructions, out allExceptionHandlers); DotNetUtils.restoreBody(method, allInstructions, allExceptionHandlers); } Log.deIndent(); }
static VariableDefinition getFlagsLocal(MethodDefinition method, int index) { var instrs = method.Body.Instructions; if (index + 5 >= instrs.Count) { return(null); } if (instrs[index++].OpCode.Code != Code.And) { return(null); } if (instrs[index++].OpCode.Code != Code.Ldc_I4_0) { return(null); } if (instrs[index++].OpCode.Code != Code.Ceq) { return(null); } if (instrs[index++].OpCode.Code != Code.Ldc_I4_0) { return(null); } if (instrs[index++].OpCode.Code != Code.Ceq) { return(null); } var stloc = instrs[index++]; if (!DotNetUtils.isStloc(stloc)) { return(null); } return(DotNetUtils.getLocalVar(method.Body.Variables, stloc)); }
public IEnumerable <FieldDef> cleanUp() { var removedFields = new List <FieldDef>(); var moduleCctor = DotNetUtils.getModuleTypeCctor(module); if (moduleCctor == null) { return(removedFields); } var moduleCctorBlocks = new Blocks(moduleCctor); var keep = findFieldsToKeep(); foreach (var fieldInfo in fieldToInfo.getValues()) { if (keep.ContainsKey(fieldInfo)) { continue; } if (removeInitCode(moduleCctorBlocks, fieldInfo)) { removedFields.Add(fieldInfo.field); removedFields.Add(fieldInfo.arrayInitField); } fieldInfo.arrayInitField.InitialValue = new byte[1]; fieldInfo.arrayInitField.FieldSig.Type = module.CorLibTypes.Byte; fieldInfo.arrayInitField.RVA = 0; } IList <Instruction> allInstructions; IList <ExceptionHandler> allExceptionHandlers; moduleCctorBlocks.getCode(out allInstructions, out allExceptionHandlers); DotNetUtils.restoreBody(moduleCctorBlocks.Method, allInstructions, allExceptionHandlers); return(removedFields); }
bool Find(MethodDef methodToCheck) { if (methodToCheck == null) { return(false); } foreach (var method in DotNetUtils.GetCalledMethods(module, methodToCheck)) { bool result = false; switch (frameworkType) { case FrameworkType.Desktop: result = FindDesktop(method); break; case FrameworkType.Silverlight: result = FindSilverlight(method); break; case FrameworkType.CompactFramework: result = FindCompactFramework(method); break; } if (!result) { continue; } tamperType = method.DeclaringType; tamperMethod = method; return(true); } return(false); }