/*
Copyright (C) 2011-2012 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.DotNet;
using dnlib.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.SmartAssembly {
class AutomatedErrorReportingFinder : ExceptionLoggerRemover {
ModuleDefMD module;
bool enabled;
protected override bool HasExceptionLoggers {
get { return enabled; }
}
public AutomatedErrorReportingFinder(ModuleDefMD module) {
this.module = module;
}
protected override bool isExceptionLogger(IMethod method) {
return isExceptionLoggerMethod(method);
}
public void find() {
var entryPoint = module.EntryPoint;
if (entryPoint == null)
enabled = true;
else {
MethodDef exceptionMethod;
enabled = checkMethod(entryPoint, out exceptionMethod);
}
}
bool checkMethod(MethodDef method, out MethodDef exceptionMethod) {
exceptionMethod = null;
var body = method.Body;
if (body == null)
return false;
var instrs = body.Instructions;
if (instrs.Count < 1)
return false;
if (body.ExceptionHandlers.Count == 0)
return false;
var eh = body.ExceptionHandlers[body.ExceptionHandlers.Count - 1];
if (eh.HandlerType != ExceptionHandlerType.Catch)
return false;
if (eh.FilterStart != null)
return false;
if (eh.CatchType == null || eh.CatchType.FullName != "System.Exception")
return false;
if (eh.HandlerStart == null)
return false;
int handlerStart = instrs.IndexOf(eh.HandlerStart);
int handlerEnd = eh.HandlerEnd == null ? instrs.Count : instrs.IndexOf(eh.HandlerEnd);
exceptionMethod = DotNetUtils.getMethod(module, checkHandler(instrs, handlerStart, handlerEnd));
if (exceptionMethod == null || !exceptionMethod.IsStatic || exceptionMethod.Body == null)
return false;
return isExceptionLoggerMethod(exceptionMethod);
}
IMethod checkHandler(IList instrs, int start, int end) {
IMethod calledMethod = null;
for (int i = start; i < end; i++) {
var instr = instrs[i];
if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt) {
if (calledMethod != null)
return null;
var method = instr.Operand as IMethod;
if (method == null)
return null;
calledMethod = method;
}
}
return calledMethod;
}
static bool isExceptionLoggerMethod(IMethod method) {
if (method.Name == ".ctor" || method.Name == ".cctor")
return false;
var sig = method.MethodSig;
if (sig == null || sig.Params.Count < 1)
return false;
var rtype = sig.RetType.GetFullName();
var type0 = sig.Params[0].GetFullName();
var type1 = sig.Params.Count < 2 ? "" : sig.Params[1].GetFullName();
int index;
if (rtype == "System.Void") {
if (type0 == "System.Exception" && type1 == "System.Int32")
index = 2;
else if (type0 == "System.Object[]" && type1 == "System.Exception")
return true;
else if (sig.Params.Count == 2 && type0 == "System.Int32" && type1 == "System.Object[]")
return true;
else if (type0 == "System.Exception")
index = 1;
else
return false;
}
else if (rtype == "System.Exception") {
if (type0 == "System.Exception" && type1 == "System.Int32")
index = 2;
else if (type0 == "System.Int32" && type1 == "System.Exception")
index = 2;
else if (sig.Params.Count == 2 && type0 == "System.Int32" && type1 == "System.Object[]")
return true;
else if (type0 == "System.Exception")
index = 1;
else
return false;
}
else
return false;
if (index + 1 == sig.Params.Count && sig.Params[index].GetFullName() == "System.Object[]")
return true;
for (int i = index; i < sig.Params.Count; i++) {
if (sig.Params[i].GetElementType() != ElementType.Object)
return false;
}
return true;
}
}
}