diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 7c946ab2..be5b26b7 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -159,7 +159,8 @@ - + + diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs index 284d2dbe..74a3db9b 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs @@ -159,6 +159,8 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { AddTypesToBeRemoved(stringDecrypter.DynocodeTypes, "Dynocode type"); AddResourceToBeRemoved(stringDecrypter.Resource, "Encrypted strings"); } + stringDecrypter.CloseServer(); + AddTypeToBeRemoved(assemblyResolver.Type, "Assembly resolver type"); AddTypeToBeRemoved(assemblyResolver.OtherType, "Assembly resolver other type"); AddTypeToBeRemoved(resourceResolver.Type, "Resource resolver type"); @@ -214,6 +216,14 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { DotNetUtils.RestoreBody(cctor, allInstructions, allExceptionHandlers); } + protected override void Dispose(bool disposing) { + if (disposing) { + if (stringDecrypter != null) + stringDecrypter.Dispose(); + } + base.Dispose(disposing); + } + public override IEnumerable GetStringDecrypterMethods() { var list = new List(); if (stringDecrypter.Method != null) diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/DynamicDynocodeIterator.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/DynamicDynocodeIterator.cs new file mode 100644 index 00000000..1d60eed1 --- /dev/null +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/DynamicDynocodeIterator.cs @@ -0,0 +1,109 @@ +/* + Copyright (C) 2011-2013 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 AssemblyData; +using de4dot.code.AssemblyClient; +using dnlib.DotNet; + +namespace de4dot.code.deobfuscators.Eazfuscator_NET { + class DynamicDynocodeIterator : IDisposable, IEnumerable { + IAssemblyClient assemblyClient; + List dynocodeTypes = new List(); + + public List Types { + get { return dynocodeTypes; } + } + + class MyEnumerator : IEnumerator { + DynamicDynocodeIterator ddi; + + public MyEnumerator(DynamicDynocodeIterator ddi) { + this.ddi = ddi; + } + + public int Current { + get { + return (int)ddi.assemblyClient.GenericService.SendMessage(DynocodeService.MSG_CALL_GET_CURRENT, null); + } + } + + public void Dispose() { + } + + object System.Collections.IEnumerator.Current { + get { return Current; } + } + + public bool MoveNext() { + return (bool)ddi.assemblyClient.GenericService.SendMessage(DynocodeService.MSG_CALL_MOVE_NEXT, null); + } + + public void Reset() { + throw new NotImplementedException(); + } + } + + public void Dispose() { + if (assemblyClient != null) + assemblyClient.Dispose(); + assemblyClient = null; + } + + public void Initialize(ModuleDef module) { + if (assemblyClient != null) + return; + + var serverVersion = NewProcessAssemblyClientFactory.GetServerClrVersion(module); + assemblyClient = new NewProcessAssemblyClientFactory(serverVersion).Create(AssemblyServiceType.Generic); + assemblyClient.Connect(); + assemblyClient.WaitConnected(); + + assemblyClient.GenericService.LoadUserService(typeof(DynocodeService), null); + assemblyClient.GenericService.LoadAssembly(module.Location); + } + + public void CreateEnumerable(MethodDef ctor, object[] args) { + var type = ctor.DeclaringType; + while (type.DeclaringType != null) + type = type.DeclaringType; + dynocodeTypes.Add(type); + assemblyClient.GenericService.SendMessage(DynocodeService.MSG_CREATE_ENUMERABLE, + new object[] { ctor.MDToken.ToUInt32(), args }); + } + + public void WriteEnumerableField(uint fieldToken, object value) { + assemblyClient.GenericService.SendMessage(DynocodeService.MSG_WRITE_ENUMERABLE_FIELD, + new object[] { fieldToken, value }); + } + + public void CreateEnumerator() { + assemblyClient.GenericService.SendMessage(DynocodeService.MSG_CREATE_ENUMERATOR, null); + } + + public IEnumerator GetEnumerator() { + return new MyEnumerator(this); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { + return new MyEnumerator(this); + } + } +} diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/Dynocode.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/Dynocode.cs deleted file mode 100644 index fcd689ba..00000000 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/Dynocode.cs +++ /dev/null @@ -1,289 +0,0 @@ -/* - Copyright (C) 2011-2013 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.Collections.Generic; -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using de4dot.blocks; - -namespace de4dot.code.deobfuscators.Eazfuscator_NET { - interface IDynocodeGenerator { - IEnumerable GetValues(int input); - } - - // Something added in EF 3.5 which they call Dynocode. The string decrypter can now - // call some iterator classes that will return some integers that it will use to - // XOR some key. - class Dynocode { - ISimpleDeobfuscator simpleDeobfuscator; - Dictionary typeToDCGen = new Dictionary(); - - class DCGen1 : IDynocodeGenerator { - public int magic1; - public int magic2; - public int magic3; - public int magic4; - public int magic5; - public int magic6; - public int magic7; - - public IEnumerable GetValues(int input) { - yield return magic1; - yield return magic2; - yield return input ^ magic3; - yield return magic4; - yield return magic5; - yield return magic6; - yield return input ^ magic7; - } - } - - class DCGen2 : IDynocodeGenerator { - public int magic1; - - public IEnumerable GetValues(int input) { - int x = 0; - int y = 1; - while (true) { - yield return y; - if (--input == 0) - break; - int tmp = y; - y = (x + y + input) ^ magic1; - x = tmp; - } - } - } - - class DCGen3 : IDynocodeGenerator { - public int magic1; - public int magic2; - public DCGen2 dc2; - - public IEnumerable GetValues(int input) { - int i = 7; - foreach (var val in dc2.GetValues(input)) { - int x = val ^ input; - if ((x % 4) == 0) - x ^= magic1; - if ((x % 16) == 0) - x ^= magic2; - yield return x; - if (--i == 0) - break; - } - } - } - - public IEnumerable Types { - get { - foreach (var type in typeToDCGen.Keys) - yield return type.DeclaringType; - } - } - - public Dynocode(ISimpleDeobfuscator simpleDeobfuscator) { - this.simpleDeobfuscator = simpleDeobfuscator; - } - - public IDynocodeGenerator GetDynocodeGenerator(TypeDef type) { - if (type == null) - return null; - var dt = type.DeclaringType; - if (dt == null) - return null; - IDynocodeGenerator dcGen; - if (typeToDCGen.TryGetValue(type, out dcGen)) - return dcGen; - - if (dt.NestedTypes.Count == 1) - dcGen = GetDCGen1(type); - else if (dt.NestedTypes.Count == 2) - dcGen = GetDCGen3(type); - - typeToDCGen[type] = dcGen; - - return dcGen; - } - - DCGen1 GetDCGen1(TypeDef type) { - var method = GetMoveNext(type); - if (method == null) - return null; - simpleDeobfuscator.Deobfuscate(method); - var swLabels = GetSwitchLabels(method); - if (swLabels == null || swLabels.Count < 7) - return null; - - var dcGen = new DCGen1(); - if (!GetMagicDC1(method, swLabels[0], out dcGen.magic1)) - return null; - if (!GetMagicDC1(method, swLabels[1], out dcGen.magic2)) - return null; - if (!GetMagicXorDC1(method, swLabels[2], out dcGen.magic3)) - return null; - if (!GetMagicDC1(method, swLabels[3], out dcGen.magic4)) - return null; - if (!GetMagicDC1(method, swLabels[4], out dcGen.magic5)) - return null; - if (!GetMagicDC1(method, swLabels[5], out dcGen.magic6)) - return null; - if (!GetMagicXorDC1(method, swLabels[6], out dcGen.magic7)) - return null; - - return dcGen; - } - - static IList GetSwitchLabels(MethodDef method) { - foreach (var instr in method.Body.Instructions) { - if (instr.OpCode.Code != Code.Switch) - continue; - return instr.Operand as IList; - } - return null; - } - - static bool GetMagicDC1(MethodDef method, Instruction target, out int magic) { - magic = 0; - var instrs = method.Body.Instructions; - int index = instrs.IndexOf(target); - if (index < 0) - return false; - - for (int i = index; i < instrs.Count - 3; i++) { - var instr = instrs[i]; - if (instr.OpCode.FlowControl != FlowControl.Next) - return false; - if (instr.OpCode.Code != Code.Stfld) - continue; - if (instrs[i + 1].OpCode.Code != Code.Ldarg_0) - continue; - var ldci4 = instrs[i + 2]; - if (!ldci4.IsLdcI4()) - continue; - if (instrs[i + 3].OpCode.Code != Code.Stfld) - continue; - - magic = ldci4.GetLdcI4Value(); - return true; - } - - return false; - } - - static bool GetMagicXorDC1(MethodDef method, Instruction target, out int magic) { - magic = 0; - var instrs = method.Body.Instructions; - int index = instrs.IndexOf(target); - if (index < 0) - return false; - - for (int i = index; i < instrs.Count - 2; i++) { - var instr = instrs[i]; - if (instr.OpCode.FlowControl != FlowControl.Next) - return false; - if (!instr.IsLdcI4()) - continue; - if (instrs[i + 1].OpCode.Code != Code.Xor) - continue; - if (instrs[i + 2].OpCode.Code != Code.Stfld) - continue; - - magic = instr.GetLdcI4Value(); - return true; - } - - return false; - } - - DCGen3 GetDCGen3(TypeDef type) { - var method = GetMoveNext(type); - if (method == null) - return null; - simpleDeobfuscator.Deobfuscate(method); - - var dcGen = new DCGen3(); - int index = 0; - if (!GetMagicDC3(method, ref index, out dcGen.magic1)) - return null; - if (!GetMagicDC3(method, ref index, out dcGen.magic2)) - return null; - - var dt = type.DeclaringType; - dcGen.dc2 = GetDCGen2(dt.NestedTypes[0] == type ? dt.NestedTypes[1] : dt.NestedTypes[0]); - - return dcGen; - } - - static bool GetMagicDC3(MethodDef method, ref int index, out int magic) { - var instrs = method.Body.Instructions; - for (int i = index; i < instrs.Count - 2; i++) { - var ldci4 = instrs[i]; - if (!ldci4.IsLdcI4()) - continue; - if (instrs[i + 1].OpCode.Code != Code.Xor) - continue; - if (instrs[i + 2].OpCode.Code != Code.Stfld) - continue; - - index = i + 3; - magic = ldci4.GetLdcI4Value(); - return true; - } - - magic = 0; - return false; - } - - DCGen2 GetDCGen2(TypeDef type) { - var method = GetMoveNext(type); - if (method == null) - return null; - simpleDeobfuscator.Deobfuscate(method); - - var dcGen = new DCGen2(); - int index = 0; - if (!GetMagicDC3(method, ref index, out dcGen.magic1)) - return null; - - return dcGen; - } - - static MethodDef GetMoveNext(TypeDef type) { - foreach (var m in type.Methods) { - if (!m.IsVirtual) - continue; - foreach (var mo in m.Overrides) { - if (mo.MethodDeclaration.FullName == "System.Boolean System.Collections.IEnumerator::MoveNext()") - return m; - } - } - foreach (var m in type.Methods) { - if (!m.IsVirtual) - continue; - if (m.Name != "MoveNext") - continue; - if (!DotNetUtils.IsMethod(m, "System.Boolean", "()")) - continue; - return m; - } - return null; - } - } -} diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/DynocodeService.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/DynocodeService.cs new file mode 100644 index 00000000..4c98d3d5 --- /dev/null +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/DynocodeService.cs @@ -0,0 +1,100 @@ +/* + Copyright (C) 2011-2013 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 System.Reflection; +using AssemblyData; + +namespace de4dot.code.deobfuscators.Eazfuscator_NET { + class DynocodeService : IUserGenericService { + public const int MSG_CREATE_ENUMERABLE = 0; + public const int MSG_WRITE_ENUMERABLE_FIELD = 1; + public const int MSG_CREATE_ENUMERATOR = 2; + public const int MSG_CALL_GET_CURRENT = 3; + public const int MSG_CALL_MOVE_NEXT = 4; + + Module reflObfModule; + IEnumerable ienumerable = null; + IEnumerator ienumerator = null; + + [CreateUserGenericService] + public static IUserGenericService Create() { + return new DynocodeService(); + } + + public void AssemblyLoaded(Assembly assembly) { + this.reflObfModule = assembly.ManifestModule; + } + + public object HandleMessage(int msg, object[] args) { + switch (msg) { + case MSG_CREATE_ENUMERABLE: + CreateEnumerable((uint)args[0], args[1] as object[]); + return true; + + case MSG_WRITE_ENUMERABLE_FIELD: + WriteEnumerableField((uint)args[0], args[1] as object); + return true; + + case MSG_CREATE_ENUMERATOR: + CreateEnumerator(); + return true; + + case MSG_CALL_GET_CURRENT: + return CallGetCurrent(); + + case MSG_CALL_MOVE_NEXT: + return CallMoveNext(); + + default: + throw new ApplicationException(string.Format("Invalid msg: {0:X8}", msg)); + } + } + + void CreateEnumerable(uint ctorToken, object[] args) { + var ctor = reflObfModule.ResolveMethod((int)ctorToken) as ConstructorInfo; + if (ctor == null) + throw new ApplicationException(string.Format("Invalid ctor with token: {0:X8}", ctorToken)); + ienumerable = (IEnumerable)ctor.Invoke(args); + } + + void WriteEnumerableField(uint fieldToken, object value) { + var field = reflObfModule.ResolveField((int)fieldToken); + if (field == null) + throw new ApplicationException(string.Format("Invalid field: {0:X8}", fieldToken)); + field.SetValue(ienumerable, value); + } + + void CreateEnumerator() { + ienumerator = ienumerable.GetEnumerator(); + } + + int CallGetCurrent() { + return ienumerator.Current; + } + + bool CallMoveNext() { + return ienumerator.MoveNext(); + } + + public void Dispose() { + } + } +} diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/ResourceMethodsRestorer.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/ResourceMethodsRestorer.cs index ec9a2216..96db8fe4 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/ResourceMethodsRestorer.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/ResourceMethodsRestorer.cs @@ -50,9 +50,11 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { var getStream2 = GetTheOnlyMethod(type, "System.IO.Stream", "(System.Reflection.Assembly,System.Type,System.String)"); var getNames = GetTheOnlyMethod(type, "System.String[]", "(System.Reflection.Assembly)"); + var getRefAsms = GetTheOnlyMethod(type, "System.Reflection.AssemblyName[]", "(System.Reflection.Assembly)"); var bitmapCtor = GetTheOnlyMethod(type, "System.Drawing.Bitmap", "(System.Type,System.String)"); var iconCtor = GetTheOnlyMethod(type, "System.Drawing.Icon", "(System.Type,System.String)"); - if (getStream2 == null && getNames == null && bitmapCtor == null && iconCtor == null) + if (getStream2 == null && getNames == null && getRefAsms == null && + bitmapCtor == null && iconCtor == null) continue; var resource = FindGetManifestResourceStreamTypeResource(type, simpleDeobfuscator, deob); @@ -62,6 +64,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { getManifestResourceStreamType = type; CreateGetManifestResourceStream2(getStream2); CreateGetManifestResourceNames(getNames); + CreateGetReferencedAssemblies(getRefAsms); CreateBitmapCtor(bitmapCtor); CreateIconCtor(iconCtor); getManifestResourceStreamTypeResource = resource; diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs index dd40699d..26b0d1cc 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs @@ -27,7 +27,7 @@ using de4dot.blocks; using de4dot.blocks.cflow; namespace de4dot.code.deobfuscators.Eazfuscator_NET { - class StringDecrypter { + class StringDecrypter : IDisposable { ModuleDefMD module; TypeDef stringType; MethodDef stringMethod; @@ -47,7 +47,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { EfConstantsReader stringMethodConsts; bool isV32OrLater; int? validStringDecrypterValue; - Dynocode dynocode; + DynamicDynocodeIterator dynocode; class StreamHelperType { public TypeDef type; @@ -228,7 +228,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { } bool FindConstants(ISimpleDeobfuscator simpleDeobfuscator) { - dynocode = new Dynocode(simpleDeobfuscator); + dynocode = new DynamicDynocodeIterator(); simpleDeobfuscator.Deobfuscate(stringMethod); stringMethodConsts = new EfConstantsReader(stringMethod); @@ -671,7 +671,11 @@ done: ; if (index + 4 >= instrs.Count) return false; var ldloc = instrs[index + 3]; - if (!ldloc.IsLdloc() || instrs[index + 4].OpCode.Code != Code.Stfld) + var stfld = instrs[index + 4]; + if (!ldloc.IsLdloc() || stfld.OpCode.Code != Code.Stfld) + return false; + var enumerableField = stfld.Operand as FieldDef; + if (enumerableField == null) return false; var initValue = emu.GetLocal(ldloc.GetLocal(stringMethod.Body.Variables)) as Int32Value; @@ -692,19 +696,46 @@ done: ; if (initValue2 == null || !initValue2.AllBitsValid()) return false; - var dcGen = dynocode.GetDynocodeGenerator(ctor.DeclaringType); - if (dcGen == null) + int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32 System.Collections.Generic.IEnumerator`1::get_Current()"); + int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean System.Collections.IEnumerator::MoveNext()"); + if (loopStart < 0 || loopEnd < 0) return false; - int loopLocalValue = initValue2.value; - foreach (var val in dcGen.GetValues(initValue.value)) - loopLocalValue ^= val; + loopStart++; + loopEnd--; + + dynocode.Initialize(module); + var ctorArg = emu.Pop() as Int32Value; + if (ctorArg == null || !ctorArg.AllBitsValid()) + return false; + dynocode.CreateEnumerable(ctor, new object[] { ctorArg.value }); + dynocode.WriteEnumerableField(enumerableField.MDToken.ToUInt32(), initValue.value); + dynocode.CreateEnumerator(); + foreach (var val in dynocode) { + emu.Push(new Int32Value(val)); + for (int i = loopStart; i < loopEnd; i++) + emu.Emulate(instrs[i]); + } - emu.SetLocal(loopLocal, new Int32Value(loopLocalValue)); - emu.Emulate(instr); index = newIndex - 1; return true; } + static int GetIndexOfCall(IList instrs, int startIndex, int endIndex, string fullMethodName) { + if (startIndex < 0 || endIndex < 0) + return -1; + for (int i = startIndex; i < endIndex; i++) { + var instr = instrs[i]; + if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt) + continue; + var method = instr.Operand as IMethod; + if (method == null || method.FullName != fullMethodName) + continue; + + return i; + } + return -1; + } + Local GetDCLoopLocal(int start, int end) { var instrs = stringMethod.Body.Instructions; for (int i = start; i < end - 1; i++) { @@ -980,5 +1011,15 @@ done: ; return false; } + + public void Dispose() { + CloseServer(); + } + + public void CloseServer() { + if (dynocode != null) + dynocode.Dispose(); + dynocode = null; + } } } diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs index f88d7f10..e38a6f98 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs @@ -722,7 +722,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { decryptStringMethod.Body.ExceptionHandlers.Count >= 2 && new LocalTypes(decryptStringMethod).All(locals35) && CheckTypeFields2(fields35)) { - return "3.5 - 3.6"; + return "3.5 - 4.0"; } } diff --git a/de4dot.code/deobfuscators/MethodCallRestorerBase.cs b/de4dot.code/deobfuscators/MethodCallRestorerBase.cs index 220067af..189549df 100644 --- a/de4dot.code/deobfuscators/MethodCallRestorerBase.cs +++ b/de4dot.code/deobfuscators/MethodCallRestorerBase.cs @@ -71,6 +71,15 @@ namespace de4dot.code.deobfuscators { Add(oldMethod, newMethod, OpCodes.Callvirt); } + public void CreateGetReferencedAssemblies(MethodDef oldMethod) { + if (oldMethod == null) + return; + var assemblyType = builder.Type("System.Reflection", "Assembly", builder.CorLib); + var asmNameArray = builder.Array(builder.Type("System.Reflection", "AssemblyName", builder.CorLib)); + var newMethod = builder.InstanceMethod("GetReferencedAssemblies", assemblyType.TypeDefOrRef, asmNameArray); + Add(oldMethod, newMethod, OpCodes.Callvirt); + } + public void CreateBitmapCtor(MethodDef oldMethod) { if (oldMethod == null) return;