diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index 7f3850a6..6edc798f 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -60,6 +60,7 @@
+
diff --git a/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs b/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs
index 1db27687..6bd5ef62 100644
--- a/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs
+++ b/de4dot.code/deobfuscators/CliSecure/ProxyDelegateFinder.cs
@@ -20,22 +20,50 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
+using Mono.Cecil.Cil;
+using de4dot.blocks;
namespace de4dot.deobfuscators.CliSecure {
class ProxyDelegateFinder : ProxyDelegateFinderBase {
+ IList memberReferences;
+
public ProxyDelegateFinder(ModuleDefinition module)
: base(module) {
+ this.memberReferences = new List(module.GetMemberReferences());
}
- protected override void getCallInfo(FieldDefinition field, out int methodIndex, out bool isVirtual) {
+ protected override object checkCctor(TypeDefinition type, MethodDefinition cctor) {
+ var instrs = cctor.Body.Instructions;
+ if (instrs.Count != 3)
+ return null;
+ if (!DotNetUtils.isLdcI4(instrs[0].OpCode.Code))
+ return null;
+ if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDefinition))
+ return null;
+ if (instrs[2].OpCode != OpCodes.Ret)
+ return null;
+
+ int delegateToken = 0x02000001 + DotNetUtils.getLdcI4Value(instrs[0]);
+ if (type.MetadataToken.ToInt32() != delegateToken) {
+ Log.w("Delegate token is not current type");
+ return null;
+ }
+
+ return new object();
+ }
+
+ protected override void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode) {
var name = field.Name;
- isVirtual = false;
+ callOpcode = OpCodes.Call;
if (name.EndsWith("%", StringComparison.Ordinal)) {
- isVirtual = true;
+ callOpcode = OpCodes.Callvirt;
name = name.TrimEnd(new char[] { '%' });
}
byte[] value = Convert.FromBase64String(name);
- methodIndex = BitConverter.ToInt32(value, 0); // 0-based memberRef index
+ int methodIndex = BitConverter.ToInt32(value, 0); // 0-based memberRef index
+ if (methodIndex >= memberReferences.Count)
+ throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count));
+ calledMethod = memberReferences[methodIndex] as MethodReference;
}
}
}
diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs b/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
index a6c20309..eba497e9 100644
--- a/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
+++ b/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
@@ -60,6 +60,7 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
bool foundCryptoObfuscatorAttribute = false;
bool foundObfuscatedSymbols = false;
+ ProxyDelegateFinder proxyDelegateFinder;
ResourceDecrypter resourceDecrypter;
ResourceResolver resourceResolver;
AssemblyResolver assemblyResolver;
@@ -102,6 +103,8 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
val += 10;
if (tamperDetection.Detected)
val += 10;
+ if (proxyDelegateFinder.Detected)
+ val += 10;
return val;
}
@@ -117,6 +120,8 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
if (checkCryptoObfuscator())
foundObfuscatedSymbols = true;
+ proxyDelegateFinder = new ProxyDelegateFinder(module);
+ proxyDelegateFinder.findDelegateCreator(module);
stringDecrypter = new StringDecrypter(module);
stringDecrypter.find();
tamperDetection = new TamperDetection(module);
@@ -182,9 +187,21 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
addTypeToBeRemoved(antiDebugger.AntiDebuggerType, "Anti-debugger type");
addTypeToBeRemoved(stringDecrypter.StringDecrypterType, "String decrypter type");
+ proxyDelegateFinder.find();
+
dumpEmbeddedAssemblies();
}
+ public override void deobfuscateMethodEnd(Blocks blocks) {
+ proxyDelegateFinder.deobfuscate(blocks);
+ base.deobfuscateMethodEnd(blocks);
+ }
+
+ public override void deobfuscateEnd() {
+ removeProxyDelegates(proxyDelegateFinder);
+ base.deobfuscateEnd();
+ }
+
void decryptResources() {
var rsrc = resourceResolver.mergeResources();
if (rsrc == null)
diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/ProxyDelegateFinder.cs b/de4dot.code/deobfuscators/CryptoObfuscator/ProxyDelegateFinder.cs
new file mode 100644
index 00000000..1e0ee90d
--- /dev/null
+++ b/de4dot.code/deobfuscators/CryptoObfuscator/ProxyDelegateFinder.cs
@@ -0,0 +1,191 @@
+/*
+ Copyright (C) 2011 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 Mono.Cecil;
+using Mono.Cecil.Cil;
+using de4dot.blocks;
+
+namespace de4dot.deobfuscators.CryptoObfuscator {
+ class ProxyDelegateFinder : ProxyDelegateFinderBase {
+ Dictionary methodToType = new Dictionary();
+
+ public ProxyDelegateFinder(ModuleDefinition module)
+ : base(module) {
+ }
+
+ enum ProxyCreatorType {
+ None,
+ CallOrCallvirt,
+ CallCtor,
+ Newobj,
+ }
+
+ class Context {
+ public int typeToken;
+ public int methodToken;
+ public int declaringTypeToken;
+ public ProxyCreatorType proxyCreatorType;
+ public Context(int typeToken, int methodToken, int declaringTypeToken, ProxyCreatorType proxyCreatorType) {
+ this.typeToken = typeToken;
+ this.methodToken = methodToken;
+ this.declaringTypeToken = declaringTypeToken;
+ this.proxyCreatorType = proxyCreatorType;
+ }
+ }
+
+ protected override object checkCctor(TypeDefinition type, MethodDefinition cctor) {
+ var instructions = cctor.Body.Instructions;
+ for (int i = 0; i < instructions.Count; i++) {
+ var instrs = DotNetUtils.getInstructions(instructions, i, OpCodes.Ldc_I4, OpCodes.Ldc_I4, OpCodes.Ldc_I4, OpCodes.Call);
+ if (instrs == null)
+ continue;
+
+ int typeToken = (int)instrs[0].Operand;
+ int methodToken = (int)instrs[1].Operand;
+ int declaringTypeToken = (int)instrs[2].Operand;
+ var createMethod = instrs[3].Operand as MethodDefinition;
+
+ ProxyCreatorType proxyCreatorType;
+ if (!methodToType.TryGetValue(createMethod, out proxyCreatorType))
+ continue;
+
+ return new Context(typeToken, methodToken, declaringTypeToken, proxyCreatorType);
+ }
+
+ return null;
+ }
+
+ protected override void onFoundProxyDelegate(TypeDefinition type) {
+ foreach (var method in type.Methods) {
+ if (!method.IsStatic || !method.HasBody || method.Name == ".ctor")
+ continue;
+
+ var instructions = method.Body.Instructions;
+ for (int i = 0; i < instructions.Count; i++) {
+ var instr = instructions[i];
+ if (instr.OpCode.Code != Code.Ldsfld)
+ continue;
+
+ add(method, (FieldDefinition)instr.Operand);
+ break;
+ }
+ }
+ }
+
+ protected override void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode) {
+ var ctx = (Context)context;
+
+ switch (ctx.proxyCreatorType) {
+ case ProxyCreatorType.CallOrCallvirt:
+ callOpcode = field.IsFamilyOrAssembly ? OpCodes.Callvirt : OpCodes.Call;
+ break;
+ case ProxyCreatorType.CallCtor:
+ callOpcode = OpCodes.Call;
+ break;
+ case ProxyCreatorType.Newobj:
+ callOpcode = OpCodes.Newobj;
+ break;
+ default:
+ throw new ApplicationException(string.Format("Invalid proxy creator type: {0}", ctx.proxyCreatorType));
+ }
+
+ calledMethod = module.LookupToken(ctx.methodToken) as MethodReference;
+ }
+
+ public void findDelegateCreator(ModuleDefinition module) {
+ foreach (var type in module.Types) {
+ var createMethod = getProxyCreateMethod(type);
+ if (createMethod == null)
+ continue;
+
+ var proxyCreatorType = getProxyCreatorType(type, createMethod);
+ if (proxyCreatorType == ProxyCreatorType.None)
+ continue;
+ methodToType[createMethod] = proxyCreatorType;
+ setDelegateCreatorMethod(createMethod);
+ }
+ }
+
+ MethodDefinition getProxyCreateMethod(TypeDefinition type) {
+ if (type.Fields.Count != 1)
+ return null;
+ if (DotNetUtils.findFieldType(type, "System.ModuleHandle", true) == null)
+ return null;
+
+ MethodDefinition 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;
+ }
+ return null;
+ }
+ if (!createMethod.HasBody)
+ return null;
+ if (type.HasEvents || type.HasProperties)
+ return null;
+ if (!findLdci4(createMethod, 0xFFFFFF))
+ return null;
+
+ return createMethod;
+ }
+
+ bool findLdci4(MethodDefinition method, int value) {
+ foreach (var instr in method.Body.Instructions) {
+ if (instr.OpCode.Code == Code.Ldc_I4 && (int)instr.Operand == value)
+ return true;
+ }
+ return false;
+ }
+
+ ProxyCreatorType getProxyCreatorType(TypeDefinition type, MethodDefinition createMethod) {
+ int numCalls = 0, numCallvirts = 0, numNewobjs = 0;
+ foreach (var instr in createMethod.Body.Instructions) {
+ if (instr.OpCode.Code != Code.Ldsfld)
+ continue;
+ var field = instr.Operand as FieldReference;
+ if (field == null)
+ continue;
+ switch (field.FullName) {
+ case "System.Reflection.Emit.OpCode System.Reflection.Emit.OpCodes::Call":
+ numCalls++;
+ break;
+ case "System.Reflection.Emit.OpCode System.Reflection.Emit.OpCodes::Callvirt":
+ numCallvirts++;
+ break;
+ case "System.Reflection.Emit.OpCode System.Reflection.Emit.OpCodes::Newobj":
+ numNewobjs++;
+ break;
+ }
+ }
+
+ if (numCalls == 1 && numCallvirts == 1 && numNewobjs == 0)
+ return ProxyCreatorType.CallOrCallvirt;
+ if (numCalls == 1 && numCallvirts == 0 && numNewobjs == 0)
+ return ProxyCreatorType.CallCtor;
+ if (numCalls == 0 && numCallvirts == 0 && numNewobjs == 1)
+ return ProxyCreatorType.Newobj;
+ return ProxyCreatorType.None;
+ }
+ }
+}
diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs
index 4866d097..2d66d363 100644
--- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs
+++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs
@@ -470,7 +470,7 @@ namespace de4dot.deobfuscators {
protected void removeProxyDelegates(ProxyDelegateFinderBase proxyDelegateFinder) {
addTypesToBeRemoved(proxyDelegateFinder.DelegateTypes, "Proxy delegate type");
if (proxyDelegateFinder.RemovedDelegateCreatorCalls > 0)
- addTypeToBeRemoved(proxyDelegateFinder.DelegateCreatorMethod.DeclaringType, "Proxy delegate creator type");
+ addTypesToBeRemoved(proxyDelegateFinder.DelegateCreatorTypes, "Proxy delegate creator type");
}
protected TypeDefinition getModuleType() {
diff --git a/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs b/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs
index ec6be447..93e44be0 100644
--- a/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs
+++ b/de4dot.code/deobfuscators/ProxyDelegateFinderBase.cs
@@ -25,46 +25,60 @@ using de4dot.blocks;
namespace de4dot.deobfuscators {
abstract class ProxyDelegateFinderBase {
- ModuleDefinition module;
- IList memberReferences;
- MethodDefinition delegateCreatorMethod;
+ protected ModuleDefinition module;
+ List delegateCreatorMethods = new List();
Dictionary delegateTypesDict = new Dictionary();
Dictionary fieldToDelegateInfo = new Dictionary();
+ Dictionary proxyMethodToField = new Dictionary();
class DelegateInfo {
public MethodReference methodRef; // Method we should call
public FieldDefinition field; // Field holding the Delegate instance
- public bool isVirtual;
- public DelegateInfo(FieldDefinition field, MethodReference methodRef, bool isVirtual) {
+ public OpCode callOpcode;
+ public DelegateInfo(FieldDefinition field, MethodReference methodRef, OpCode callOpcode) {
this.field = field;
this.methodRef = methodRef;
- this.isVirtual = isVirtual;
+ this.callOpcode = callOpcode;
}
}
public int RemovedDelegateCreatorCalls { get; set; }
+
public IEnumerable DelegateTypes {
get { return delegateTypesDict.Keys; }
}
- public MethodDefinition DelegateCreatorMethod {
- get { return delegateCreatorMethod; }
+
+ public IEnumerable DelegateCreatorTypes {
+ get {
+ foreach (var method in delegateCreatorMethods)
+ yield return method.DeclaringType;
+ }
}
public bool Detected {
- get { return delegateCreatorMethod != null; }
+ get { return delegateCreatorMethods.Count != 0; }
}
public ProxyDelegateFinderBase(ModuleDefinition module) {
this.module = module;
- this.memberReferences = new List(module.GetMemberReferences());
}
public void setDelegateCreatorMethod(MethodDefinition delegateCreatorMethod) {
- this.delegateCreatorMethod = delegateCreatorMethod;
+ if (delegateCreatorMethod == null)
+ return;
+ delegateCreatorMethods.Add(delegateCreatorMethod);
+ }
+
+ protected bool isDelegateCreatorMethod(MethodDefinition method) {
+ foreach (var m in delegateCreatorMethods) {
+ if (m == method)
+ return true;
+ }
+ return false;
}
public void find() {
- if (delegateCreatorMethod == null)
+ if (delegateCreatorMethods.Count == 0)
return;
Log.v("Finding all proxy delegates");
@@ -77,47 +91,44 @@ namespace de4dot.deobfuscators {
if (!type.HasFields)
continue;
- var instrs = cctor.Body.Instructions;
- if (instrs.Count != 3)
+ object context = checkCctor(type, cctor);
+ if (context == null)
continue;
- if (!DotNetUtils.isLdcI4(instrs[0].OpCode.Code))
- continue;
- if (instrs[1].OpCode != OpCodes.Call || instrs[1].Operand != delegateCreatorMethod)
- continue;
- if (instrs[2].OpCode != OpCodes.Ret)
- continue;
-
- int delegateToken = 0x02000001 + DotNetUtils.getLdcI4Value(instrs[0]);
- if (type.MetadataToken.ToInt32() != delegateToken) {
- Log.w("Delegate token is not current type");
- continue;
- }
Log.v("Found proxy delegate: {0} ({1:X8})", type, type.MetadataToken.ToUInt32());
RemovedDelegateCreatorCalls++;
+ onFoundProxyDelegate(type);
+
Log.indent();
foreach (var field in type.Fields) {
if (!field.IsStatic || field.IsPublic)
continue;
- int methodIndex;
- bool isVirtual;
- getCallInfo(field, out methodIndex, out isVirtual);
- if (methodIndex >= memberReferences.Count)
- throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count));
+ MethodReference calledMethod;
+ OpCode callOpcode;
+ getCallInfo(context, field, out calledMethod, out callOpcode);
- var methodRef = memberReferences[methodIndex] as MethodReference;
- if (methodRef == null)
- throw new ApplicationException("methodRef is null");
- fieldToDelegateInfo[new FieldReferenceAndDeclaringTypeKey(field)] = new DelegateInfo(field, methodRef, isVirtual);
- Log.v("Field: {0}, Virtual: {1}, Method: {2}, RID: {3}", field.Name, isVirtual, methodRef, methodIndex + 1);
+ if (calledMethod == null)
+ throw new ApplicationException("calledMethod is null");
+ fieldToDelegateInfo[new FieldReferenceAndDeclaringTypeKey(field)] = new DelegateInfo(field, calledMethod, callOpcode);
+ Log.v("Field: {0}, Opcode: {1}, Method: {2} ({3:X8})", field.Name, callOpcode, calledMethod, calledMethod.MetadataToken.ToUInt32());
}
Log.deIndent();
delegateTypesDict[type] = true;
}
}
- protected abstract void getCallInfo(FieldDefinition field, out int methodIndex, out bool isVirtual);
+ protected virtual void onFoundProxyDelegate(TypeDefinition type) {
+ }
+
+ protected abstract object checkCctor(TypeDefinition type, MethodDefinition cctor);
+ protected abstract void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode);
+
+ protected void add(MethodDefinition proxyMethod, FieldDefinition proxyField) {
+ if (proxyMethod == null || proxyField == null)
+ return;
+ proxyMethodToField[proxyMethod] = proxyField;
+ }
MethodDefinition findMethod(TypeDefinition type, string name) {
if (!type.HasMethods)
@@ -158,23 +169,35 @@ namespace de4dot.deobfuscators {
foreach (var block in allBlocks) {
var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) {
- var ldsfld = instrs[i];
- if (ldsfld.OpCode != OpCodes.Ldsfld)
- continue;
- var di = getDelegateInfo(ldsfld.Operand as FieldReference);
- if (di == null)
- continue;
+ var instr = instrs[i];
+ if (instr.OpCode == OpCodes.Ldsfld) {
+ var di = getDelegateInfo(instr.Operand as FieldReference);
+ if (di == null)
+ continue;
- var visited = new Dictionary();
- var callInfo = findProxyCall(di, block, i, visited, 1);
- if (callInfo != null) {
- add(removeInfos, block, i, null);
- add(removeInfos, callInfo.Block, callInfo.Index, di);
+ var visited = new Dictionary();
+ var callInfo = findProxyCall(di, block, i, visited, 1);
+ if (callInfo != null) {
+ add(removeInfos, block, i, null);
+ add(removeInfos, callInfo.Block, callInfo.Index, di);
+ }
+ else {
+ Log.w("Could not fix proxy call. Method: {0} ({1:X8}), Proxy type: {2} ({3:X8})",
+ blocks.Method, blocks.Method.MetadataToken.ToInt32(),
+ di.field.DeclaringType, di.field.DeclaringType.MetadataToken.ToInt32());
+ }
}
- else {
- Log.w("Could not fix proxy call. Method: {0} ({1:X8}), Proxy type: {2} ({3:X8})",
- blocks.Method, blocks.Method.MetadataToken.ToInt32(),
- di.field.DeclaringType, di.field.DeclaringType.MetadataToken.ToInt32());
+ else if (instr.OpCode == OpCodes.Call) {
+ var method = instr.Operand as MethodDefinition;
+ if (method == null)
+ continue;
+ FieldDefinition field;
+ if (!proxyMethodToField.TryGetValue(method, out field))
+ continue;
+ var di = getDelegateInfo(field);
+ if (di == null)
+ continue;
+ add(removeInfos, block, i, di);
}
}
}
@@ -184,7 +207,7 @@ namespace de4dot.deobfuscators {
var removeIndexes = new List(list.Count);
foreach (var info in list) {
if (info.IsCall) {
- var opcode = info.DelegateInfo.isVirtual ? OpCodes.Callvirt : OpCodes.Call;
+ var opcode = info.DelegateInfo.callOpcode;
var newInstr = Instruction.Create(opcode, info.DelegateInfo.methodRef);
block.replace(info.Index, 1, newInstr);
}
diff --git a/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs b/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs
index 1c78eecd..f1749bb8 100644
--- a/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs
+++ b/de4dot.code/deobfuscators/SmartAssembly/ProxyDelegateFinder.cs
@@ -17,8 +17,10 @@
along with de4dot. If not, see .
*/
+using System;
using System.Collections.Generic;
using Mono.Cecil;
+using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.deobfuscators.SmartAssembly {
@@ -35,6 +37,8 @@ namespace de4dot.deobfuscators.SmartAssembly {
'\x9E', '\x9F',
};
+ IList memberReferences;
+
static ProxyDelegateFinder() {
for (int i = 0; i < specialChars.Length; i++)
specialCharsDict[specialChars[i]] = i;
@@ -42,17 +46,38 @@ namespace de4dot.deobfuscators.SmartAssembly {
public ProxyDelegateFinder(ModuleDefinition module)
: base(module) {
+ this.memberReferences = new List(module.GetMemberReferences());
}
- protected override void getCallInfo(FieldDefinition field, out int methodIndex, out bool isVirtual) {
- isVirtual = false;
+ protected override object checkCctor(TypeDefinition type, MethodDefinition cctor) {
+ var instrs = cctor.Body.Instructions;
+ if (instrs.Count != 3)
+ return null;
+ if (!DotNetUtils.isLdcI4(instrs[0].OpCode.Code))
+ return null;
+ if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDefinition))
+ return null;
+ if (instrs[2].OpCode != OpCodes.Ret)
+ return null;
+
+ int delegateToken = 0x02000001 + DotNetUtils.getLdcI4Value(instrs[0]);
+ if (type.MetadataToken.ToInt32() != delegateToken) {
+ Log.w("Delegate token is not current type");
+ return null;
+ }
+
+ return new object();
+ }
+
+ protected override void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode) {
+ callOpcode = OpCodes.Call;
string name = field.Name;
- methodIndex = 0;
+ int methodIndex = 0;
for (int i = name.Length - 1; i >= 0; i--) {
char c = name[i];
if (c == '~') {
- isVirtual = true;
+ callOpcode = OpCodes.Callvirt;
break;
}
@@ -60,6 +85,9 @@ namespace de4dot.deobfuscators.SmartAssembly {
if (specialCharsDict.TryGetValue(c, out val))
methodIndex = methodIndex * specialChars.Length + val;
}
+ if (methodIndex >= memberReferences.Count)
+ throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count));
+ calledMethod = memberReferences[methodIndex] as MethodReference;
}
public void findDelegateCreator(ModuleDefinition module) {