Add proxy delegate fixer

This commit is contained in:
de4dot 2011-10-23 13:43:32 +02:00
parent 32bb14fa5a
commit f776148574
7 changed files with 350 additions and 62 deletions

View File

@ -60,6 +60,7 @@
<Compile Include="deobfuscators\CryptoObfuscator\AntiDebugger.cs" /> <Compile Include="deobfuscators\CryptoObfuscator\AntiDebugger.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" /> <Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\Deobfuscator.cs" /> <Compile Include="deobfuscators\CryptoObfuscator\Deobfuscator.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ProxyDelegateFinder.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ResourceDecrypter.cs" /> <Compile Include="deobfuscators\CryptoObfuscator\ResourceDecrypter.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\ResourceResolver.cs" /> <Compile Include="deobfuscators\CryptoObfuscator\ResourceResolver.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\StringDecrypter.cs" /> <Compile Include="deobfuscators\CryptoObfuscator\StringDecrypter.cs" />

View File

@ -20,22 +20,50 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.deobfuscators.CliSecure { namespace de4dot.deobfuscators.CliSecure {
class ProxyDelegateFinder : ProxyDelegateFinderBase { class ProxyDelegateFinder : ProxyDelegateFinderBase {
IList<MemberReference> memberReferences;
public ProxyDelegateFinder(ModuleDefinition module) public ProxyDelegateFinder(ModuleDefinition module)
: base(module) { : base(module) {
this.memberReferences = new List<MemberReference>(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; var name = field.Name;
isVirtual = false; callOpcode = OpCodes.Call;
if (name.EndsWith("%", StringComparison.Ordinal)) { if (name.EndsWith("%", StringComparison.Ordinal)) {
isVirtual = true; callOpcode = OpCodes.Callvirt;
name = name.TrimEnd(new char[] { '%' }); name = name.TrimEnd(new char[] { '%' });
} }
byte[] value = Convert.FromBase64String(name); 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;
} }
} }
} }

View File

@ -60,6 +60,7 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
bool foundCryptoObfuscatorAttribute = false; bool foundCryptoObfuscatorAttribute = false;
bool foundObfuscatedSymbols = false; bool foundObfuscatedSymbols = false;
ProxyDelegateFinder proxyDelegateFinder;
ResourceDecrypter resourceDecrypter; ResourceDecrypter resourceDecrypter;
ResourceResolver resourceResolver; ResourceResolver resourceResolver;
AssemblyResolver assemblyResolver; AssemblyResolver assemblyResolver;
@ -102,6 +103,8 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
val += 10; val += 10;
if (tamperDetection.Detected) if (tamperDetection.Detected)
val += 10; val += 10;
if (proxyDelegateFinder.Detected)
val += 10;
return val; return val;
} }
@ -117,6 +120,8 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
if (checkCryptoObfuscator()) if (checkCryptoObfuscator())
foundObfuscatedSymbols = true; foundObfuscatedSymbols = true;
proxyDelegateFinder = new ProxyDelegateFinder(module);
proxyDelegateFinder.findDelegateCreator(module);
stringDecrypter = new StringDecrypter(module); stringDecrypter = new StringDecrypter(module);
stringDecrypter.find(); stringDecrypter.find();
tamperDetection = new TamperDetection(module); tamperDetection = new TamperDetection(module);
@ -182,9 +187,21 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
addTypeToBeRemoved(antiDebugger.AntiDebuggerType, "Anti-debugger type"); addTypeToBeRemoved(antiDebugger.AntiDebuggerType, "Anti-debugger type");
addTypeToBeRemoved(stringDecrypter.StringDecrypterType, "String decrypter type"); addTypeToBeRemoved(stringDecrypter.StringDecrypterType, "String decrypter type");
proxyDelegateFinder.find();
dumpEmbeddedAssemblies(); dumpEmbeddedAssemblies();
} }
public override void deobfuscateMethodEnd(Blocks blocks) {
proxyDelegateFinder.deobfuscate(blocks);
base.deobfuscateMethodEnd(blocks);
}
public override void deobfuscateEnd() {
removeProxyDelegates(proxyDelegateFinder);
base.deobfuscateEnd();
}
void decryptResources() { void decryptResources() {
var rsrc = resourceResolver.mergeResources(); var rsrc = resourceResolver.mergeResources();
if (rsrc == null) if (rsrc == null)

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.deobfuscators.CryptoObfuscator {
class ProxyDelegateFinder : ProxyDelegateFinderBase {
Dictionary<MethodDefinition, ProxyCreatorType> methodToType = new Dictionary<MethodDefinition, ProxyCreatorType>();
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;
}
}
}

View File

@ -470,7 +470,7 @@ namespace de4dot.deobfuscators {
protected void removeProxyDelegates(ProxyDelegateFinderBase proxyDelegateFinder) { protected void removeProxyDelegates(ProxyDelegateFinderBase proxyDelegateFinder) {
addTypesToBeRemoved(proxyDelegateFinder.DelegateTypes, "Proxy delegate type"); addTypesToBeRemoved(proxyDelegateFinder.DelegateTypes, "Proxy delegate type");
if (proxyDelegateFinder.RemovedDelegateCreatorCalls > 0) if (proxyDelegateFinder.RemovedDelegateCreatorCalls > 0)
addTypeToBeRemoved(proxyDelegateFinder.DelegateCreatorMethod.DeclaringType, "Proxy delegate creator type"); addTypesToBeRemoved(proxyDelegateFinder.DelegateCreatorTypes, "Proxy delegate creator type");
} }
protected TypeDefinition getModuleType() { protected TypeDefinition getModuleType() {

View File

@ -25,46 +25,60 @@ using de4dot.blocks;
namespace de4dot.deobfuscators { namespace de4dot.deobfuscators {
abstract class ProxyDelegateFinderBase { abstract class ProxyDelegateFinderBase {
ModuleDefinition module; protected ModuleDefinition module;
IList<MemberReference> memberReferences; List<MethodDefinition> delegateCreatorMethods = new List<MethodDefinition>();
MethodDefinition delegateCreatorMethod;
Dictionary<TypeDefinition, bool> delegateTypesDict = new Dictionary<TypeDefinition, bool>(); Dictionary<TypeDefinition, bool> delegateTypesDict = new Dictionary<TypeDefinition, bool>();
Dictionary<FieldReferenceAndDeclaringTypeKey, DelegateInfo> fieldToDelegateInfo = new Dictionary<FieldReferenceAndDeclaringTypeKey, DelegateInfo>(); Dictionary<FieldReferenceAndDeclaringTypeKey, DelegateInfo> fieldToDelegateInfo = new Dictionary<FieldReferenceAndDeclaringTypeKey, DelegateInfo>();
Dictionary<MethodDefinition, FieldDefinition> proxyMethodToField = new Dictionary<MethodDefinition, FieldDefinition>();
class DelegateInfo { class DelegateInfo {
public MethodReference methodRef; // Method we should call public MethodReference methodRef; // Method we should call
public FieldDefinition field; // Field holding the Delegate instance public FieldDefinition field; // Field holding the Delegate instance
public bool isVirtual; public OpCode callOpcode;
public DelegateInfo(FieldDefinition field, MethodReference methodRef, bool isVirtual) { public DelegateInfo(FieldDefinition field, MethodReference methodRef, OpCode callOpcode) {
this.field = field; this.field = field;
this.methodRef = methodRef; this.methodRef = methodRef;
this.isVirtual = isVirtual; this.callOpcode = callOpcode;
} }
} }
public int RemovedDelegateCreatorCalls { get; set; } public int RemovedDelegateCreatorCalls { get; set; }
public IEnumerable<TypeDefinition> DelegateTypes { public IEnumerable<TypeDefinition> DelegateTypes {
get { return delegateTypesDict.Keys; } get { return delegateTypesDict.Keys; }
} }
public MethodDefinition DelegateCreatorMethod {
get { return delegateCreatorMethod; } public IEnumerable<TypeDefinition> DelegateCreatorTypes {
get {
foreach (var method in delegateCreatorMethods)
yield return method.DeclaringType;
}
} }
public bool Detected { public bool Detected {
get { return delegateCreatorMethod != null; } get { return delegateCreatorMethods.Count != 0; }
} }
public ProxyDelegateFinderBase(ModuleDefinition module) { public ProxyDelegateFinderBase(ModuleDefinition module) {
this.module = module; this.module = module;
this.memberReferences = new List<MemberReference>(module.GetMemberReferences());
} }
public void setDelegateCreatorMethod(MethodDefinition delegateCreatorMethod) { 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() { public void find() {
if (delegateCreatorMethod == null) if (delegateCreatorMethods.Count == 0)
return; return;
Log.v("Finding all proxy delegates"); Log.v("Finding all proxy delegates");
@ -77,47 +91,44 @@ namespace de4dot.deobfuscators {
if (!type.HasFields) if (!type.HasFields)
continue; continue;
var instrs = cctor.Body.Instructions; object context = checkCctor(type, cctor);
if (instrs.Count != 3) if (context == null)
continue; 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()); Log.v("Found proxy delegate: {0} ({1:X8})", type, type.MetadataToken.ToUInt32());
RemovedDelegateCreatorCalls++; RemovedDelegateCreatorCalls++;
onFoundProxyDelegate(type);
Log.indent(); Log.indent();
foreach (var field in type.Fields) { foreach (var field in type.Fields) {
if (!field.IsStatic || field.IsPublic) if (!field.IsStatic || field.IsPublic)
continue; continue;
int methodIndex; MethodReference calledMethod;
bool isVirtual; OpCode callOpcode;
getCallInfo(field, out methodIndex, out isVirtual); getCallInfo(context, field, out calledMethod, out callOpcode);
if (methodIndex >= memberReferences.Count)
throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count));
var methodRef = memberReferences[methodIndex] as MethodReference; if (calledMethod == null)
if (methodRef == null) throw new ApplicationException("calledMethod is null");
throw new ApplicationException("methodRef is null"); fieldToDelegateInfo[new FieldReferenceAndDeclaringTypeKey(field)] = new DelegateInfo(field, calledMethod, callOpcode);
fieldToDelegateInfo[new FieldReferenceAndDeclaringTypeKey(field)] = new DelegateInfo(field, methodRef, isVirtual); Log.v("Field: {0}, Opcode: {1}, Method: {2} ({3:X8})", field.Name, callOpcode, calledMethod, calledMethod.MetadataToken.ToUInt32());
Log.v("Field: {0}, Virtual: {1}, Method: {2}, RID: {3}", field.Name, isVirtual, methodRef, methodIndex + 1);
} }
Log.deIndent(); Log.deIndent();
delegateTypesDict[type] = true; 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) { MethodDefinition findMethod(TypeDefinition type, string name) {
if (!type.HasMethods) if (!type.HasMethods)
@ -158,10 +169,9 @@ namespace de4dot.deobfuscators {
foreach (var block in allBlocks) { foreach (var block in allBlocks) {
var instrs = block.Instructions; var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
var ldsfld = instrs[i]; var instr = instrs[i];
if (ldsfld.OpCode != OpCodes.Ldsfld) if (instr.OpCode == OpCodes.Ldsfld) {
continue; var di = getDelegateInfo(instr.Operand as FieldReference);
var di = getDelegateInfo(ldsfld.Operand as FieldReference);
if (di == null) if (di == null)
continue; continue;
@ -177,6 +187,19 @@ namespace de4dot.deobfuscators {
di.field.DeclaringType, di.field.DeclaringType.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);
}
}
} }
foreach (var block in removeInfos.Keys) { foreach (var block in removeInfos.Keys) {
@ -184,7 +207,7 @@ namespace de4dot.deobfuscators {
var removeIndexes = new List<int>(list.Count); var removeIndexes = new List<int>(list.Count);
foreach (var info in list) { foreach (var info in list) {
if (info.IsCall) { 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); var newInstr = Instruction.Create(opcode, info.DelegateInfo.methodRef);
block.replace(info.Index, 1, newInstr); block.replace(info.Index, 1, newInstr);
} }

View File

@ -17,8 +17,10 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>. along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks; using de4dot.blocks;
namespace de4dot.deobfuscators.SmartAssembly { namespace de4dot.deobfuscators.SmartAssembly {
@ -35,6 +37,8 @@ namespace de4dot.deobfuscators.SmartAssembly {
'\x9E', '\x9F', '\x9E', '\x9F',
}; };
IList<MemberReference> memberReferences;
static ProxyDelegateFinder() { static ProxyDelegateFinder() {
for (int i = 0; i < specialChars.Length; i++) for (int i = 0; i < specialChars.Length; i++)
specialCharsDict[specialChars[i]] = i; specialCharsDict[specialChars[i]] = i;
@ -42,17 +46,38 @@ namespace de4dot.deobfuscators.SmartAssembly {
public ProxyDelegateFinder(ModuleDefinition module) public ProxyDelegateFinder(ModuleDefinition module)
: base(module) { : base(module) {
this.memberReferences = new List<MemberReference>(module.GetMemberReferences());
} }
protected override void getCallInfo(FieldDefinition field, out int methodIndex, out bool isVirtual) { protected override object checkCctor(TypeDefinition type, MethodDefinition cctor) {
isVirtual = false; 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; string name = field.Name;
methodIndex = 0; int methodIndex = 0;
for (int i = name.Length - 1; i >= 0; i--) { for (int i = name.Length - 1; i >= 0; i--) {
char c = name[i]; char c = name[i];
if (c == '~') { if (c == '~') {
isVirtual = true; callOpcode = OpCodes.Callvirt;
break; break;
} }
@ -60,6 +85,9 @@ namespace de4dot.deobfuscators.SmartAssembly {
if (specialCharsDict.TryGetValue(c, out val)) if (specialCharsDict.TryGetValue(c, out val))
methodIndex = methodIndex * specialChars.Length + 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) { public void findDelegateCreator(ModuleDefinition module) {