/* Copyright (C) 2011-2015 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 dnlib.IO; using dnlib.DotNet; using dnlib.DotNet.Emit; using de4dot.blocks; namespace de4dot.code.deobfuscators.CryptoObfuscator { class MethodBodyReader : MethodBodyReaderBase { ModuleDefMD module; ushort maxStackSize; GenericParamContext gpContext; public MethodBodyReader(ModuleDefMD module, IBinaryReader reader) : base(reader) { this.module = module; } public void Read(MethodDef method) { this.gpContext = GenericParamContext.Create(method); this.parameters = method.Parameters; SetLocals(GetLocals(method)); maxStackSize = (ushort)reader.ReadInt32(); ReadInstructionsNumBytes(reader.ReadUInt32()); ReadExceptionHandlers(); } void ReadExceptionHandlers() { int totalSize = reader.ReadInt32(); if (totalSize == 0) return; reader.ReadInt32(); ReadExceptionHandlers((totalSize - 4) / 24); } static IList GetLocals(MethodDef method) { if (method.Body == null) return new List(); return method.Body.Variables; } protected override IField ReadInlineField(Instruction instr) { return module.ResolveToken(reader.ReadUInt32(), gpContext) as IField; } protected override IMethod ReadInlineMethod(Instruction instr) { return module.ResolveToken(reader.ReadUInt32(), gpContext) as IMethod; } protected override MethodSig ReadInlineSig(Instruction instr) { var sas = module.ResolveStandAloneSig(MDToken.ToRID(reader.ReadUInt32()), gpContext); return sas == null ? null : sas.MethodSig; } protected override string ReadInlineString(Instruction instr) { return module.ReadUserString(reader.ReadUInt32()); } protected override ITokenOperand ReadInlineTok(Instruction instr) { return module.ResolveToken(reader.ReadUInt32(), gpContext) as ITokenOperand; } protected override ITypeDefOrRef ReadInlineType(Instruction instr) { return module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; } void ReadExceptionHandlers(int numExceptionHandlers) { exceptionHandlers = new ExceptionHandler[numExceptionHandlers]; for (int i = 0; i < exceptionHandlers.Count; i++) exceptionHandlers[i] = ReadExceptionHandler(); } ExceptionHandler ReadExceptionHandler() { var eh = new ExceptionHandler((ExceptionHandlerType)reader.ReadUInt32()); uint tryOffset = reader.ReadUInt32(); eh.TryStart = GetInstructionThrow(tryOffset); eh.TryEnd = GetInstruction(tryOffset + reader.ReadUInt32()); uint handlerOffset = reader.ReadUInt32(); eh.HandlerStart = GetInstructionThrow(handlerOffset); eh.HandlerEnd = GetInstruction(handlerOffset + reader.ReadUInt32()); switch (eh.HandlerType) { case ExceptionHandlerType.Catch: eh.CatchType = module.ResolveToken(reader.ReadUInt32(), gpContext) as ITypeDefOrRef; break; case ExceptionHandlerType.Filter: eh.FilterStart = GetInstructionThrow(reader.ReadUInt32()); break; case ExceptionHandlerType.Finally: case ExceptionHandlerType.Fault: default: reader.ReadUInt32(); break; } return eh; } public override void RestoreMethod(MethodDef method) { base.RestoreMethod(method); method.Body.MaxStack = maxStackSize; } } }