void Check(MethodDef method) { if (method.Body == null) { return; } if (possiblyUnusedMethods.ContainsKey(method)) { return; } if (removedMethods.Exists(method)) { return; } foreach (var instr in method.Body.Instructions) { switch (instr.OpCode.Code) { case Code.Call: case Code.Calli: case Code.Callvirt: case Code.Newobj: case Code.Ldtoken: case Code.Ldftn: case Code.Ldvirtftn: break; default: continue; } var calledMethod = DotNetUtils.GetMethod2(module, instr.Operand as IMethod); if (calledMethod == null) { continue; } if (possiblyUnusedMethods.ContainsKey(calledMethod)) { notUnusedStack.Push(calledMethod); } } }
protected override void GetCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) { uint rid = 0; foreach (var c in field.Name.String) { rid = (rid << 4) + (uint)HexToInt((char)((byte)c + 0x2F)); } rid &= 0x00FFFFFF; calledMethod = module.ResolveMemberRef(rid); var calledMethodDef = DotNetUtils.GetMethod2(module, calledMethod); if (calledMethodDef != null) { proxyMethodsType = calledMethodDef.DeclaringType; proxyTargetMethods.Add(calledMethodDef, true); calledMethod = calledMethodDef; } callOpcode = OpCodes.Call; }
// 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++; } } }