diff --git a/de4dot.code/DumpedMethodsRestorer.cs b/de4dot.code/DumpedMethodsRestorer.cs index b4852164..b7e8224c 100644 --- a/de4dot.code/DumpedMethodsRestorer.cs +++ b/de4dot.code/DumpedMethodsRestorer.cs @@ -61,13 +61,13 @@ namespace de4dot.code { return false; } - public bool GetMethodBody(uint rid, RVA rva, IList parameters, out MethodBody methodBody) { + public bool GetMethodBody(uint rid, RVA rva, IList parameters, GenericParamContext gpContext, out MethodBody methodBody) { var dm = GetDumpedMethod(rid); if (dm == null) { methodBody = null; return false; } - methodBody = MethodBodyReader.CreateCilBody(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok); + methodBody = MethodBodyReader.CreateCilBody(module, dm.code, dm.extraSections, parameters, dm.mhFlags, dm.mhMaxStack, dm.mhCodeSize, dm.mhLocalVarSigTok, gpContext); return true; } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverterBase.cs b/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverterBase.cs index b9726049..3ee297b9 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverterBase.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverterBase.cs @@ -232,13 +232,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { if (numLocals < 0) throw new ApplicationException("Invalid number of locals"); + var gpContext = GenericParamContext.Create(cilMethod); for (int i = 0; i < numLocals; i++) - locals.Add(new Local(ReadTypeRef(reader))); + locals.Add(new Local(ReadTypeRef(reader, gpContext))); return locals; } - TypeSig ReadTypeRef(BinaryReader reader) { + TypeSig ReadTypeRef(BinaryReader reader, GenericParamContext gpContext) { var etype = (ElementType)reader.ReadInt32(); switch (etype) { case ElementType.Void: return module.CorLibTypes.Void; @@ -263,12 +264,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { case ElementType.ValueType: case ElementType.Var: case ElementType.MVar: - return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig(); + return (module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef).ToTypeSig(); case ElementType.GenericInst: etype = (ElementType)reader.ReadInt32(); if (etype == ElementType.ValueType) - return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig(); + return (module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef).ToTypeSig(); // ElementType.Class return module.CorLibTypes.Object; @@ -299,6 +300,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { if (numExceptions < 0) throw new ApplicationException("Invalid number of exception handlers"); + var gpContext = GenericParamContext.Create(cilMethod); for (int i = 0; i < numExceptions; i++) { var eh = new ExceptionHandler((ExceptionHandlerType)reader.ReadInt32()); eh.TryStart = GetInstruction(reader.ReadInt32()); @@ -306,7 +308,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { eh.HandlerStart = GetInstruction(reader.ReadInt32()); eh.HandlerEnd = GetInstructionEnd(reader.ReadInt32()); if (eh.HandlerType == ExceptionHandlerType.Catch) - eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + eh.CatchType = module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; else if (eh.HandlerType == ExceptionHandlerType.Filter) eh.FilterStart = GetInstruction(reader.ReadInt32()); diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v1/CsvmToCilMethodConverter.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v1/CsvmToCilMethodConverter.cs index ac039506..c50eedde 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v1/CsvmToCilMethodConverter.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v1/CsvmToCilMethodConverter.cs @@ -34,12 +34,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { } protected override List ReadInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) { + var gpContext = GenericParamContext.Create(cilMethod); var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions)); var instrs = new List(); uint offset = 0; while (reader.BaseStream.Position < reader.BaseStream.Length) { int vmOpCode = reader.ReadUInt16(); - var instr = opCodeDetector.Handlers[vmOpCode].Read(reader, module); + var instr = opCodeDetector.Handlers[vmOpCode].Read(reader, module, gpContext); instr.Offset = offset; offset += (uint)GetInstructionSize(instr); SetCilToVmIndex(instr, instrs.Count); diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v1/OpCodeHandler.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v1/OpCodeHandler.cs index 81475049..4c8b5407 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v1/OpCodeHandler.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v1/OpCodeHandler.cs @@ -29,7 +29,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { public string Name { get; set; } public OpCodeHandlerSigInfo OpCodeHandlerSigInfo { get; set; } public Predicate Check { get; set; } - public Func Read { get; set; } + public Func Read { get; set; } public bool Detect(UnknownHandlerInfo info) { var sigInfo = OpCodeHandlerSigInfo; @@ -68,7 +68,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { } static partial class OpCodeHandlers { - static Instruction arithmetic_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction arithmetic_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { switch (reader.ReadByte()) { case 0: return OpCodes.Add.ToInstruction(); case 1: return OpCodes.Add_Ovf.ToInstruction(); @@ -91,22 +91,22 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Type System.Reflection.Module::ResolveType(System.Int32)"); } - static Instruction newarr_read(BinaryReader reader, IInstructionOperandResolver resolver) { - return new Instruction(OpCodes.Newarr, resolver.ResolveToken(reader.ReadUInt32())); + static Instruction newarr_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { + return new Instruction(OpCodes.Newarr, resolver.ResolveToken(reader.ReadUInt32(), gpContext)); } - static Instruction box_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction box_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { var instr = new Instruction(); switch (reader.ReadByte()) { case 0: instr.OpCode = OpCodes.Box; break; case 1: instr.OpCode = OpCodes.Unbox_Any; break; default: throw new ApplicationException("Invalid opcode"); } - instr.Operand = resolver.ResolveToken(reader.ReadUInt32()); + instr.Operand = resolver.ResolveToken(reader.ReadUInt32(), gpContext); return instr; } - static Instruction call_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction call_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { var instr = new Instruction(); switch (reader.ReadByte()) { case 0: instr.OpCode = OpCodes.Newobj; break; @@ -114,22 +114,22 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { case 2: instr.OpCode = OpCodes.Callvirt; break; default: throw new ApplicationException("Invalid opcode"); } - instr.Operand = resolver.ResolveToken(reader.ReadUInt32()); + instr.Operand = resolver.ResolveToken(reader.ReadUInt32(), gpContext); return instr; } - static Instruction cast_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction cast_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { var instr = new Instruction(); switch (reader.ReadByte()) { case 0: instr.OpCode = OpCodes.Castclass; break; case 1: instr.OpCode = OpCodes.Isinst; break; default: throw new ApplicationException("Invalid opcode"); } - instr.Operand = resolver.ResolveToken(reader.ReadUInt32()); + instr.Operand = resolver.ResolveToken(reader.ReadUInt32(), gpContext); return instr; } - static Instruction compare_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction compare_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { int type = reader.ReadByte(); Instruction instr = new Instruction(); switch (type) { @@ -202,7 +202,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { new InstructionInfo1 { Type = 11, Second = true, Third = true, OpCode = OpCodes.Conv_Ovf_U_Un }, new InstructionInfo1 { Type = 12, Second = true, Third = true, OpCode = OpCodes.Conv_R_Un }, }; - static Instruction convert_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction convert_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { byte type = reader.ReadByte(); bool second = reader.ReadBoolean(); bool third = reader.ReadBoolean(); @@ -221,7 +221,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return instr; } - static Instruction dup_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction dup_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { switch (reader.ReadByte()) { case 0: return OpCodes.Dup.ToInstruction(); case 1: return OpCodes.Pop.ToInstruction(); @@ -259,7 +259,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { new InstructionInfo2 { First = true, Second = true, Value = 28, OpCode = OpCodes.Ldelem_Ref }, new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem }, }; - static Instruction ldelem_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldelem_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { Instruction instr = null; bool first = reader.ReadBoolean(); bool second = reader.ReadBoolean(); @@ -273,7 +273,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { if (second) instr = new Instruction(info.OpCode); else - instr = new Instruction(info.OpCode, resolver.ResolveToken((uint)value)); + instr = new Instruction(info.OpCode, resolver.ResolveToken((uint)value, gpContext)); break; } if (instr == null) @@ -286,13 +286,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)"); } - static Instruction endfinally_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction endfinally_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return OpCodes.Endfinally.ToInstruction(); } - static Instruction ldfld_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldfld_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { byte b = reader.ReadByte(); - var field = resolver.ResolveToken(reader.ReadUInt32()) as IField; + var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField; switch (b) { case 0: return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsfld, OpCodes.Ldfld, field)); case 1: return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsflda, OpCodes.Ldflda, field)); @@ -301,11 +301,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { } } - static Instruction initobj_read(BinaryReader reader, IInstructionOperandResolver resolver) { - return new Instruction(OpCodes.Initobj, resolver.ResolveToken(reader.ReadUInt32())); + static Instruction initobj_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { + return new Instruction(OpCodes.Initobj, resolver.ResolveToken(reader.ReadUInt32(), gpContext)); } - static Instruction ldloc_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldloc_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { bool isLdarg = reader.ReadBoolean(); ushort index = reader.ReadUInt16(); @@ -322,7 +322,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return instr; } - static Instruction ldloca_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldloca_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { Instruction instr = new Instruction(); if (reader.ReadBoolean()) { instr.OpCode = OpCodes.Ldarga; @@ -336,19 +336,19 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return instr; } - static Instruction ldelema_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldelema_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return new Instruction(OpCodes.Ldelema, null); } - static Instruction ldlen_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldlen_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return OpCodes.Ldlen.ToInstruction(); } - static Instruction ldobj_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldobj_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return new Instruction(OpCodes.Ldobj, null); } - static Instruction ldstr_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldstr_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return OpCodes.Ldstr.ToInstruction(reader.ReadString()); } @@ -356,8 +356,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)"); } - static Instruction ldtoken_read(BinaryReader reader, IInstructionOperandResolver resolver) { - return new Instruction(OpCodes.Ldtoken, resolver.ResolveToken(reader.ReadUInt32())); + static Instruction ldtoken_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { + return new Instruction(OpCodes.Ldtoken, resolver.ResolveToken(reader.ReadUInt32(), gpContext)); } static bool leave_check(UnknownHandlerInfo info) { @@ -366,12 +366,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MemberInfo System.Reflection.Module::ResolveMember(System.Int32)"); } - static Instruction leave_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction leave_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { int displacement = reader.ReadInt32(); return new Instruction(OpCodes.Leave, new TargetDisplOperand(displacement)); } - static Instruction ldc_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldc_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { switch ((ElementType)reader.ReadByte()) { case ElementType.I4: return Instruction.CreateLdcI4(reader.ReadInt32()); case ElementType.I8: return OpCodes.Ldc_I8.ToInstruction(reader.ReadInt64()); @@ -382,24 +382,24 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { } } - static Instruction ldftn_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ldftn_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { byte code = reader.ReadByte(); uint token = reader.ReadUInt32(); switch (code) { case 0: - return new Instruction(OpCodes.Ldftn, resolver.ResolveToken(token)); + return new Instruction(OpCodes.Ldftn, resolver.ResolveToken(token, gpContext)); case 1: reader.ReadInt32(); // token of newobj .ctor - return new Instruction(OpCodes.Ldvirtftn, resolver.ResolveToken(token)); + return new Instruction(OpCodes.Ldvirtftn, resolver.ResolveToken(token, gpContext)); default: throw new ApplicationException("Invalid opcode"); } } - static Instruction logical_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction logical_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { switch (reader.ReadByte()) { case 0: return OpCodes.And.ToInstruction(); case 1: return OpCodes.Or.ToInstruction(); @@ -425,7 +425,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return false; } - static Instruction nop_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction nop_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return OpCodes.Nop.ToInstruction(); } @@ -433,7 +433,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodBase System.Reflection.Module::ResolveMethod(System.Int32)"); } - static Instruction ret_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction ret_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { reader.ReadInt32(); // token of current method return OpCodes.Ret.ToInstruction(); } @@ -442,11 +442,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return info.ExecuteMethod.Body.Variables.Count == 0; } - static Instruction rethrow_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction rethrow_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return OpCodes.Rethrow.ToInstruction(); } - static Instruction stloc_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction stloc_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { bool isStarg = reader.ReadBoolean(); ushort index = reader.ReadUInt16(); @@ -464,11 +464,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return instr; } - static Instruction stobj_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction stobj_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return new Instruction(OpCodes.Stobj, null); } - static Instruction switch_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction switch_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { int numTargets = reader.ReadInt32(); int[] targetDispls = new int[numTargets]; for (int i = 0; i < targetDispls.Length; i++) @@ -480,11 +480,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v1 { return !DotNetUtils.CallsMethod(info.ExecuteMethod, "System.Reflection.MethodInfo System.Type::GetMethod(System.String,System.Reflection.BindingFlags)"); } - static Instruction throw_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction throw_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { return OpCodes.Throw.ToInstruction(); } - static Instruction neg_read(BinaryReader reader, IInstructionOperandResolver resolver) { + static Instruction neg_read(BinaryReader reader, IInstructionOperandResolver resolver, GenericParamContext gpContext) { switch (reader.ReadByte()) { case 0: return OpCodes.Neg.ToInstruction(); case 1: return OpCodes.Not.ToInstruction(); diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs index 9c25af10..b63d8c3c 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/CsvmToCilMethodConverter.cs @@ -35,7 +35,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { protected override List ReadInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) { var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions)); var instrs = new List(); - var handlerInfoReader = new OpCodeHandlerInfoReader(module); + var gpContext = GenericParamContext.Create(cilMethod); + var handlerInfoReader = new OpCodeHandlerInfoReader(module, gpContext); int numVmInstrs = reader.ReadInt32(); var vmInstrs = new ushort[numVmInstrs]; diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfoReader.cs b/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfoReader.cs index dd92c2bc..f61c9691 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfoReader.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/v2/OpCodeHandlerInfoReader.cs @@ -27,9 +27,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { class OpCodeHandlerInfoReader { IInstructionOperandResolver resolver; Dictionary> readHandlers; + readonly GenericParamContext gpContext; - public OpCodeHandlerInfoReader(IInstructionOperandResolver resolver) { + public OpCodeHandlerInfoReader(IInstructionOperandResolver resolver, GenericParamContext gpContext) { this.resolver = resolver; + this.gpContext = gpContext; this.readHandlers = new Dictionary> { { HandlerTypeCode.Add, Handler_Add }, { HandlerTypeCode.Add_Ovf, Handler_Add_Ovf }, @@ -176,7 +178,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Box(BinaryReader reader) { - var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; return OpCodes.Box.ToInstruction(type); } @@ -193,17 +195,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Call(BinaryReader reader) { - var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod; + var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; return OpCodes.Call.ToInstruction(method); } Instruction Handler_Callvirt(BinaryReader reader) { - var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod; + var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; return OpCodes.Callvirt.ToInstruction(method); } Instruction Handler_Castclass(BinaryReader reader) { - var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; return OpCodes.Castclass.ToInstruction(type); } @@ -312,12 +314,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Initobj(BinaryReader reader) { - var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; return OpCodes.Initobj.ToInstruction(type); } Instruction Handler_Isinst(BinaryReader reader) { - var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; return OpCodes.Isinst.ToInstruction(type); } @@ -349,17 +351,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Ldfld_Ldsfld(BinaryReader reader) { - var field = resolver.ResolveToken(reader.ReadUInt32()) as IField; + var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField; return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsfld, OpCodes.Ldfld, field)); } Instruction Handler_Ldflda_Ldsflda(BinaryReader reader) { - var field = resolver.ResolveToken(reader.ReadUInt32()) as IField; + var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField; return new Instruction(null, new FieldInstructionOperand(OpCodes.Ldsflda, OpCodes.Ldflda, field)); } Instruction Handler_Ldftn(BinaryReader reader) { - var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod; + var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; return OpCodes.Ldftn.ToInstruction(method); } @@ -384,12 +386,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Ldtoken(BinaryReader reader) { - var member = resolver.ResolveToken(reader.ReadUInt32()) as ITokenOperand; + var member = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITokenOperand; return OpCodes.Ldtoken.ToInstruction(member); } Instruction Handler_Ldvirtftn(BinaryReader reader) { - var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod; + var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; reader.ReadUInt32(); return OpCodes.Ldvirtftn.ToInstruction(method); } @@ -415,12 +417,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Newarr(BinaryReader reader) { - var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; return OpCodes.Newarr.ToInstruction(type); } Instruction Handler_Newobj(BinaryReader reader) { - var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod; + var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; return OpCodes.Newobj.ToInstruction(method); } @@ -449,7 +451,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Ret(BinaryReader reader) { - var method = resolver.ResolveToken(reader.ReadUInt32()) as IMethod; + var method = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; return OpCodes.Ret.ToInstruction(); } @@ -478,7 +480,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Stfld_Stsfld(BinaryReader reader) { - var field = resolver.ResolveToken(reader.ReadUInt32()) as IField; + var field = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as IField; return new Instruction(null, new FieldInstructionOperand(OpCodes.Stsfld, OpCodes.Stfld, field)); } @@ -517,7 +519,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm.v2 { } Instruction Handler_Unbox_Any(BinaryReader reader) { - var type = resolver.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + var type = resolver.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; return OpCodes.Unbox_Any.ToInstruction(type); } diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/MethodBodyReader.cs b/de4dot.code/deobfuscators/CryptoObfuscator/MethodBodyReader.cs index 760ffcd3..4273dc8c 100644 --- a/de4dot.code/deobfuscators/CryptoObfuscator/MethodBodyReader.cs +++ b/de4dot.code/deobfuscators/CryptoObfuscator/MethodBodyReader.cs @@ -28,6 +28,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { class MethodBodyReader : MethodBodyReaderBase { ModuleDefMD module; ushort maxStackSize; + GenericParamContext gpContext; public MethodBodyReader(ModuleDefMD module, IBinaryReader reader) : base(reader) { @@ -35,6 +36,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { } public void Read(MethodDef method) { + this.gpContext = GenericParamContext.Create(method); this.parameters = method.Parameters; SetLocals(GetLocals(method)); @@ -58,15 +60,15 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { } protected override IField ReadInlineField(Instruction instr) { - return module.ResolveToken(reader.ReadUInt32()) as IField; + return module.ResolveToken(reader.ReadUInt32(), gpContext) as IField; } protected override IMethod ReadInlineMethod(Instruction instr) { - return module.ResolveToken(reader.ReadUInt32()) as IMethod; + return module.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; } protected override MethodSig ReadInlineSig(Instruction instr) { - var sas = module.ResolveStandAloneSig(MDToken.ToRID(reader.ReadUInt32())); + var sas = module.ResolveStandAloneSig(MDToken.ToRID(reader.ReadUInt32()), gpContext); return sas == null ? null : sas.MethodSig; } @@ -75,11 +77,11 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { } protected override ITokenOperand ReadInlineTok(Instruction instr) { - return module.ResolveToken(reader.ReadUInt32()) as ITokenOperand; + return module.ResolveToken(reader.ReadUInt32(), gpContext) as ITokenOperand; } protected override ITypeDefOrRef ReadInlineType(Instruction instr) { - return module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + return module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; } void ReadExceptionHandlers(int numExceptionHandlers) { @@ -101,7 +103,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator { switch (eh.HandlerType) { case ExceptionHandlerType.Catch: - eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; + eh.CatchType = module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; break; case ExceptionHandlerType.Filter: diff --git a/de4dot.code/deobfuscators/ILProtector/MethodReader.cs b/de4dot.code/deobfuscators/ILProtector/MethodReader.cs index 700cdaf5..a20345ee 100644 --- a/de4dot.code/deobfuscators/ILProtector/MethodReader.cs +++ b/de4dot.code/deobfuscators/ILProtector/MethodReader.cs @@ -32,6 +32,7 @@ namespace de4dot.code.deobfuscators.ILProtector { MethodFlags flags; TypeDef delegateType; bool hasDelegateTypeFlag; + GenericParamContext gpContext; [Flags] enum MethodFlags { @@ -76,7 +77,8 @@ namespace de4dot.code.deobfuscators.ILProtector { this.module = module; } - public void Read() { + public void Read(MethodDef method) { + gpContext = GenericParamContext.Create(method); flags = (MethodFlags)reader.ReadByte(); if (HasDelegateType) { delegateType = Resolve(ReadTypeToken()); @@ -108,7 +110,7 @@ namespace de4dot.code.deobfuscators.ILProtector { } T Resolve(int token) { - return (T)module.ResolveToken(token); + return (T)module.ResolveToken(token, gpContext); } int ReadTypeToken() { @@ -182,7 +184,7 @@ namespace de4dot.code.deobfuscators.ILProtector { var token = reader.ReadUInt32(); if (MDToken.ToTable(token) != Table.StandAloneSig) return null; - var sas = module.ResolveStandAloneSig(MDToken.ToRID(token)); + var sas = module.ResolveStandAloneSig(MDToken.ToRID(token), gpContext); return sas == null ? null : sas.MethodSig; } diff --git a/de4dot.code/deobfuscators/ILProtector/MethodsDecrypterBase.cs b/de4dot.code/deobfuscators/ILProtector/MethodsDecrypterBase.cs index 8b27224a..6bda873d 100644 --- a/de4dot.code/deobfuscators/ILProtector/MethodsDecrypterBase.cs +++ b/de4dot.code/deobfuscators/ILProtector/MethodsDecrypterBase.cs @@ -87,7 +87,7 @@ namespace de4dot.code.deobfuscators.ILProtector { methodInfos.Remove(methodId.Value); var methodReader = new MethodReader(module, methodInfo.data, parameters); methodReader.HasDelegateTypeFlag = MethodReaderHasDelegateTypeFlag; - methodReader.Read(); + methodReader.Read(method); RestoreMethod(method, methodReader); if (methodReader.DelegateType != null) diff --git a/de4dot.code/deobfuscators/ProxyCallFixerBase.cs b/de4dot.code/deobfuscators/ProxyCallFixerBase.cs index 2a14920d..238e91c8 100644 --- a/de4dot.code/deobfuscators/ProxyCallFixerBase.cs +++ b/de4dot.code/deobfuscators/ProxyCallFixerBase.cs @@ -155,14 +155,15 @@ namespace de4dot.code.deobfuscators { }); } - protected static bool FixProxyCalls(Dictionary> removeInfos) { + protected bool FixProxyCalls(MethodDef method, Dictionary> removeInfos) { + var gpContext = GenericParamContext.Create(method); foreach (var block in removeInfos.Keys) { var list = removeInfos[block]; var removeIndexes = new List(list.Count); foreach (var info in list) { if (info.IsCall) { var opcode = info.DelegateInfo.callOpcode; - var newInstr = Instruction.Create(opcode, info.DelegateInfo.methodRef); + var newInstr = Instruction.Create(opcode, ReResolve(info.DelegateInfo.methodRef, gpContext)); block.Replace(info.Index, 1, newInstr); } else @@ -174,6 +175,12 @@ namespace de4dot.code.deobfuscators { return removeInfos.Count > 0; } + + IMethod ReResolve(IMethod method, GenericParamContext gpContext) { + if (method.IsMethodSpec || method.IsMemberRef) + method = module.ResolveToken(method.MDToken.Raw, gpContext) as IMethod ?? method; + return method; + } } // Fixes proxy calls that call the delegate inline in the code, eg.: @@ -279,7 +286,7 @@ namespace de4dot.code.deobfuscators { } } - return FixProxyCalls(removeInfos); + return FixProxyCalls(blocks.Method, removeInfos); } protected virtual BlockInstr FindProxyCall(DelegateInfo di, Block block, int index) { @@ -481,7 +488,7 @@ namespace de4dot.code.deobfuscators { } } - return FixProxyCalls(removeInfos); + return FixProxyCalls(blocks.Method, removeInfos); } } diff --git a/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs b/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs index b4c9b6b3..560d5c7e 100644 --- a/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/SmartAssembly/Deobfuscator.cs @@ -239,7 +239,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly { var attrs2 = new Dictionary(); foreach (var cattr in cattrs) { - if (!DotNetUtils.IsMethod(cattr.Constructor as IMethod, "System.Void", "(System.Int32)")) + if (!DotNetUtils.IsMethod(cattr.Constructor, "System.Void", "(System.Int32)")) continue; var attrType = cattr.AttributeType as TypeDef; if (attrType == null) diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v4/MetadataTokenObfuscator.cs b/de4dot.code/deobfuscators/dotNET_Reactor/v4/MetadataTokenObfuscator.cs index 825580d2..9c3a8cd9 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v4/MetadataTokenObfuscator.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor/v4/MetadataTokenObfuscator.cs @@ -76,6 +76,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { if (type == null) return; + var gpContext = GenericParamContext.Create(blocks.Method); foreach (var block in blocks.MethodBlocks.GetAllBlocks()) { var instrs = block.Instructions; for (int i = 0; i < instrs.Count - 1; i++) { @@ -98,7 +99,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { uint token = (uint)(int)instrs[i].Operand; instrs[i] = new Instr(OpCodes.Nop.ToInstruction()); - instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token) as ITokenOperand)); + instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token, gpContext) as ITokenOperand)); } } } diff --git a/de4dot.code/renamer/asmmodules/MemberRefFinder.cs b/de4dot.code/renamer/asmmodules/MemberRefFinder.cs index 3aeff2a9..71425395 100644 --- a/de4dot.code/renamer/asmmodules/MemberRefFinder.cs +++ b/de4dot.code/renamer/asmmodules/MemberRefFinder.cs @@ -285,9 +285,44 @@ namespace de4dot.code.renamer.asmmodules { void Add(DeclSecurity decl) { if (decl == null) return; + Add(decl.SecurityAttributes); Add(decl.CustomAttributes); } + void Add(IEnumerable secAttrs) { + if (secAttrs == null) + return; + foreach (var secAttr in secAttrs) + Add(secAttr); + } + + void Add(SecurityAttribute secAttr) { + if (secAttr == null) + return; + Add(secAttr.AttributeType); + Add(secAttr.NamedArguments); + } + + void Add(ITypeDefOrRef tdr) { + var td = tdr as TypeDef; + if (td != null) { + Add(td); + return; + } + + var tr = tdr as TypeRef; + if (tr != null) { + Add(tr); + return; + } + + var ts = tdr as TypeSpec; + if (ts != null) { + Add(ts); + return; + } + } + void Add(IEnumerable eds) { if (eds == null) return; @@ -326,6 +361,7 @@ namespace de4dot.code.renamer.asmmodules { Add(fd.CustomAttributes); Add(fd.Signature); Add(fd.DeclaringType); + Add(fd.MarshalType); } void Add(IEnumerable gps) { @@ -489,6 +525,22 @@ namespace de4dot.code.renamer.asmmodules { return; Add(pd.DeclaringMethod); Add(pd.CustomAttributes); + Add(pd.MarshalType); + } + + void Add(MarshalType mt) { + if (mt == null) + return; + + switch (mt.NativeType) { + case NativeType.SafeArray: + Add(((SafeArrayMarshalType)mt).UserDefinedSubType); + break; + + case NativeType.CustomMarshaler: + Add(((CustomMarshalType)mt).CustomMarshaler); + break; + } } void Add(IEnumerable mos) {