Support latset version of SA
This commit is contained in:
parent
aa565b26ee
commit
5cb5f41d4a
|
@ -553,13 +553,13 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeProxyDelegates(ProxyDelegateFinderBase proxyDelegateFinder) {
|
protected void removeProxyDelegates(ProxyDelegateFinderBase proxyDelegateFinder, bool removeCreators = true) {
|
||||||
if (proxyDelegateFinder.Errors != 0) {
|
if (proxyDelegateFinder.Errors != 0) {
|
||||||
Log.v("Not removing proxy delegates and creator type since errors were detected.");
|
Log.v("Not removing proxy delegates and creator type since errors were detected.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addTypesToBeRemoved(proxyDelegateFinder.DelegateTypes, "Proxy delegate type");
|
addTypesToBeRemoved(proxyDelegateFinder.DelegateTypes, "Proxy delegate type");
|
||||||
if (proxyDelegateFinder.RemovedDelegateCreatorCalls > 0)
|
if (removeCreators && proxyDelegateFinder.RemovedDelegateCreatorCalls > 0)
|
||||||
addTypesToBeRemoved(proxyDelegateFinder.DelegateCreatorTypes, "Proxy delegate creator type");
|
addTypesToBeRemoved(proxyDelegateFinder.DelegateCreatorTypes, "Proxy delegate creator type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
continue;
|
continue;
|
||||||
var catchBlock = tryBlock.TryHandlerBlocks[0];
|
var catchBlock = tryBlock.TryHandlerBlocks[0];
|
||||||
if (catchBlock.HandlerType != ExceptionHandlerType.Catch ||
|
if (catchBlock.HandlerType != ExceptionHandlerType.Catch ||
|
||||||
!MemberReferenceHelper.verifyType(catchBlock.CatchType, "mscorlib", "System.Exception")) {
|
catchBlock.CatchType.FullName != "System.Exception") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (catchBlock.BaseBlocks.Count != 1)
|
if (catchBlock.BaseBlocks.Count != 1)
|
||||||
|
@ -77,7 +77,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
var calledMethod = callInstr.Operand as MethodReference;
|
var calledMethod = callInstr.Operand as MethodReference;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
continue;
|
continue;
|
||||||
if (!exceptionLoggerMethods.ContainsKey(calledMethod))
|
if (!isExceptionLogger(calledMethod))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -86,8 +86,16 @@ namespace de4dot.code.deobfuscators {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual bool isExceptionLogger(MethodReference method) {
|
||||||
|
return exceptionLoggerMethods.ContainsKey(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool HasExceptionLoggers {
|
||||||
|
get { return exceptionLoggerMethods.Count != 0; }
|
||||||
|
}
|
||||||
|
|
||||||
public bool remove(Blocks blocks) {
|
public bool remove(Blocks blocks) {
|
||||||
if (exceptionLoggerMethods.Count == 0)
|
if (!HasExceptionLoggers)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TryBlock tryBlock;
|
TryBlock tryBlock;
|
||||||
|
|
|
@ -71,11 +71,11 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssemblyResolverInfo : ResolverInfoBase {
|
class AssemblyResolverInfo : ResolverInfoBase {
|
||||||
TypeDefinition simpleZipType;
|
MethodDefinition simpleZipTypeMethod;
|
||||||
List<EmbeddedAssemblyInfo> embeddedAssemblyInfos = new List<EmbeddedAssemblyInfo>();
|
List<EmbeddedAssemblyInfo> embeddedAssemblyInfos = new List<EmbeddedAssemblyInfo>();
|
||||||
|
|
||||||
public TypeDefinition SimpleZipType {
|
public MethodDefinition SimpleZipTypeMethod {
|
||||||
get { return simpleZipType; }
|
get { return simpleZipTypeMethod; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<EmbeddedAssemblyInfo> EmbeddedAssemblyInfos {
|
public IList<EmbeddedAssemblyInfo> EmbeddedAssemblyInfos {
|
||||||
|
@ -163,7 +163,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
var calledMethod = call.Operand as MethodReference;
|
var calledMethod = call.Operand as MethodReference;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
continue;
|
continue;
|
||||||
if (!SimpleZipInfo.isSimpleZipDecryptMethod_QuickCheck(module, calledMethod, out simpleZipType))
|
if (!SimpleZipInfo.isSimpleZipDecryptMethod_QuickCheck(module, calledMethod, out simpleZipTypeMethod))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -24,267 +24,127 @@ using Mono.Cecil.Cil;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.SmartAssembly {
|
namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
class AutomatedErrorReportingFinder {
|
class AutomatedErrorReportingFinder : ExceptionLoggerRemover {
|
||||||
ModuleDefinition module;
|
ModuleDefinition module;
|
||||||
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
|
bool enabled;
|
||||||
TypeDefinition automatedErrorReportingType;
|
|
||||||
int constantArgs;
|
|
||||||
AerVersion aerVersion;
|
|
||||||
|
|
||||||
enum AerVersion {
|
protected override bool HasExceptionLoggers {
|
||||||
V0,
|
get { return enabled; }
|
||||||
V1,
|
|
||||||
V2,
|
|
||||||
V3,
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExceptionLoggerRemover ExceptionLoggerRemover {
|
|
||||||
get { return exceptionLoggerRemover; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeDefinition Type {
|
|
||||||
get { return automatedErrorReportingType; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Detected {
|
|
||||||
get { return automatedErrorReportingType != null; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AutomatedErrorReportingFinder(ModuleDefinition module) {
|
public AutomatedErrorReportingFinder(ModuleDefinition module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool isExceptionLogger(MethodReference method) {
|
||||||
|
return isExceptionLoggerMethod(method);
|
||||||
|
}
|
||||||
|
|
||||||
public void find() {
|
public void find() {
|
||||||
foreach (var type in module.Types) {
|
var entryPoint = module.EntryPoint;
|
||||||
if (detectAutomatedErrorReportingType(type))
|
if (entryPoint == null)
|
||||||
break;
|
enabled = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool detectAutomatedErrorReportingType(TypeDefinition type) {
|
|
||||||
if (automatedErrorReportingType != null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const int MIN_HELPER_METHODS = 6;
|
|
||||||
|
|
||||||
constantArgs = 0;
|
|
||||||
var methods = new List<MethodDefinition>();
|
|
||||||
MethodDefinition mainMethod = null;
|
|
||||||
foreach (var method in type.Methods) {
|
|
||||||
if (isAutomatedErrorReportingMethodHelper(method))
|
|
||||||
methods.Add(method);
|
|
||||||
else if (isAutomatedErrorReportingMethod(method))
|
|
||||||
mainMethod = method;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
initializeConstantArgs(method);
|
|
||||||
}
|
|
||||||
if (mainMethod == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (isV0(type)) {
|
|
||||||
aerVersion = AerVersion.V0;
|
|
||||||
foreach (var method in type.Methods) {
|
|
||||||
if (method.IsStatic)
|
|
||||||
exceptionLoggerRemover.add(method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
if (methods.Count < MIN_HELPER_METHODS)
|
MethodDefinition exceptionMethod;
|
||||||
return false;
|
enabled = checkMethod(entryPoint, out exceptionMethod);
|
||||||
|
|
||||||
if (isV1(mainMethod))
|
|
||||||
aerVersion = AerVersion.V1;
|
|
||||||
else if (isV2(mainMethod))
|
|
||||||
aerVersion = AerVersion.V2;
|
|
||||||
else
|
|
||||||
aerVersion = AerVersion.V3;
|
|
||||||
|
|
||||||
methods.Sort((a, b) => Utils.compareInt32(a.Parameters.Count, b.Parameters.Count));
|
|
||||||
for (int i = 0; i < methods.Count; i++) {
|
|
||||||
var method = methods[i];
|
|
||||||
if (method.Parameters.Count != i + constantArgs)
|
|
||||||
return false;
|
|
||||||
var methodCalls = DotNetUtils.getMethodCallCounts(method);
|
|
||||||
if (methodCalls.count(mainMethod.FullName) != 1)
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exceptionLoggerRemover.add(mainMethod);
|
bool checkMethod(MethodDefinition method, out MethodDefinition exceptionMethod) {
|
||||||
foreach (var method in methods)
|
exceptionMethod = null;
|
||||||
exceptionLoggerRemover.add(method);
|
|
||||||
automatedErrorReportingType = type;
|
|
||||||
|
|
||||||
if (aerVersion == AerVersion.V1) {
|
var body = method.Body;
|
||||||
foreach (var method in type.Methods) {
|
if (body == null)
|
||||||
if (DotNetUtils.isMethod(method, "System.Exception", "(System.Int32,System.Object[])"))
|
return false;
|
||||||
exceptionLoggerRemover.add(method);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
initUnhandledExceptionFilterMethods();
|
MethodReference checkHandler(IList<Instruction> instrs, int start, int end) {
|
||||||
|
MethodReference calledMethod = null;
|
||||||
return true;
|
for (int i = start; i < end; i++) {
|
||||||
}
|
var instr = instrs[i];
|
||||||
|
if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt) {
|
||||||
void initializeConstantArgs(MethodDefinition method) {
|
if (calledMethod != null)
|
||||||
if (constantArgs > 0)
|
return null;
|
||||||
return;
|
var method = instr.Operand as MethodReference;
|
||||||
constantArgs = getConstantArgs(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getConstantArgs(MethodDefinition method) {
|
|
||||||
if (method.Parameters.Count >= 2) {
|
|
||||||
if (isV1(method) || isV2(method))
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string[] v0Fields = new string[] {
|
|
||||||
"System.Int32",
|
|
||||||
"System.Object[]",
|
|
||||||
};
|
|
||||||
static bool isV0(TypeDefinition type) {
|
|
||||||
if (!new FieldTypes(type).exactly(v0Fields))
|
|
||||||
return false;
|
|
||||||
if (type.Methods.Count != 3)
|
|
||||||
return false;
|
|
||||||
if (type.HasEvents || type.HasProperties)
|
|
||||||
return false;
|
|
||||||
MethodDefinition ctor = null, meth1 = null, meth2 = null;
|
|
||||||
foreach (var method in type.Methods) {
|
|
||||||
if (method.Name == ".ctor") {
|
|
||||||
ctor = method;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!method.IsStatic)
|
|
||||||
return false;
|
|
||||||
if (DotNetUtils.isMethod(method, "System.Exception", "(System.Int32,System.Object[])"))
|
|
||||||
meth1 = method;
|
|
||||||
else if (DotNetUtils.isMethod(method, "System.Exception", "(System.Int32,System.Exception,System.Object[])"))
|
|
||||||
meth2 = method;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctor != null && meth1 != null && meth2 != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isV1(MethodDefinition method) {
|
|
||||||
if (method.Parameters.Count < 2)
|
|
||||||
return false;
|
|
||||||
var p0 = method.Parameters[0].ParameterType.FullName;
|
|
||||||
var p1 = method.Parameters[1].ParameterType.FullName;
|
|
||||||
return p0 == "System.Int32" && p1 == "System.Exception";
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isV2(MethodDefinition method) {
|
|
||||||
if (method.Parameters.Count < 2)
|
|
||||||
return false;
|
|
||||||
var p0 = method.Parameters[0].ParameterType.FullName;
|
|
||||||
var p1 = method.Parameters[1].ParameterType.FullName;
|
|
||||||
return p0 == "System.Exception" && p1 == "System.Int32";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isAutomatedErrorReportingMethodHelper(MethodDefinition method) {
|
|
||||||
if (!method.HasBody || !method.IsStatic || method.Name == ".ctor")
|
|
||||||
return false;
|
|
||||||
if (DotNetUtils.hasReturnValue(method) && method.MethodReturnType.ReturnType.FullName != "System.Exception")
|
|
||||||
return false;
|
|
||||||
if (method.Parameters.Count == 0)
|
|
||||||
return false;
|
|
||||||
if (!isV1(method) && !isV2(method) && method.Parameters[0].ParameterType.FullName != "System.Exception")
|
|
||||||
return false;
|
|
||||||
for (int i = getConstantArgs(method); i < method.Parameters.Count; i++) {
|
|
||||||
if (method.Parameters[i].ParameterType.FullName != "System.Object")
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isAutomatedErrorReportingMethod(MethodDefinition method) {
|
|
||||||
if (!method.HasBody || !method.IsStatic || method.Name == ".ctor")
|
|
||||||
return false;
|
|
||||||
return
|
|
||||||
// 5.x-6.x
|
|
||||||
DotNetUtils.isMethod(method, "System.Void", "(System.Exception,System.Object[])") ||
|
|
||||||
// 5.x-6.x
|
|
||||||
DotNetUtils.isMethod(method, "System.Void", "(System.Exception,System.Int32,System.Object[])") ||
|
|
||||||
// 3.x-4.x
|
|
||||||
DotNetUtils.isMethod(method, "System.Exception", "(System.Exception,System.Object[])") ||
|
|
||||||
// 2.x-4.x
|
|
||||||
DotNetUtils.isMethod(method, "System.Exception", "(System.Exception,System.Int32,System.Object[])") ||
|
|
||||||
// 1.x
|
|
||||||
DotNetUtils.isMethod(method, "System.Exception", "(System.Int32,System.Exception,System.Object[])");
|
|
||||||
}
|
|
||||||
|
|
||||||
void initUnhandledExceptionFilterMethods() {
|
|
||||||
var main = module.EntryPoint;
|
|
||||||
if (main == null || !main.HasBody)
|
|
||||||
return;
|
|
||||||
if (!main.Body.HasExceptionHandlers)
|
|
||||||
return;
|
|
||||||
|
|
||||||
MethodDefinition mainExceptionHandlerMethod = null;
|
|
||||||
var instructions = main.Body.Instructions;
|
|
||||||
for (int i = 0; i < instructions.Count; i++) {
|
|
||||||
var call = instructions[i];
|
|
||||||
if (call.OpCode != OpCodes.Call)
|
|
||||||
continue;
|
|
||||||
var method = getMainExceptionHandlerMethod(call.Operand as MethodReference);
|
|
||||||
if (method == null)
|
if (method == null)
|
||||||
continue;
|
return null;
|
||||||
|
calledMethod = method;
|
||||||
mainExceptionHandlerMethod = method; // Use the last one we find
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mainExceptionHandlerMethod != null)
|
return calledMethod;
|
||||||
exceptionLoggerRemover.add(mainExceptionHandlerMethod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodDefinition getMainExceptionHandlerMethod(MethodReference methodReference) {
|
static bool isExceptionLoggerMethod(MethodReference method) {
|
||||||
var type = DotNetUtils.getType(module, methodReference.DeclaringType);
|
if (method.Name == ".ctor" || method.Name == ".cctor")
|
||||||
var method = DotNetUtils.getMethod(type, methodReference);
|
return false;
|
||||||
if (method == null || !method.IsStatic)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (DotNetUtils.hasReturnValue(method))
|
var parameters = method.Parameters;
|
||||||
return null;
|
if (parameters.Count < 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (aerVersion) {
|
var rtype = method.MethodReturnType.ReturnType.FullName;
|
||||||
case AerVersion.V0:
|
var type0 = parameters[0].ParameterType.FullName;
|
||||||
case AerVersion.V1:
|
var type1 = parameters.Count < 2 ? "" : parameters[1].ParameterType.FullName;
|
||||||
if (!DotNetUtils.isMethod(method, "System.Void", "(System.Int32,System.Object[])"))
|
int index;
|
||||||
return null;
|
if (rtype == "System.Void") {
|
||||||
break;
|
if (type0 == "System.Exception" && type1 == "System.Int32")
|
||||||
|
index = 2;
|
||||||
|
else if (type0 == "System.Object[]" && type1 == "System.Exception")
|
||||||
|
return true;
|
||||||
|
else if (parameters.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 (parameters.Count == 2 && type0 == "System.Int32" && type1 == "System.Object[]")
|
||||||
|
return true;
|
||||||
|
else if (type0 == "System.Exception")
|
||||||
|
index = 1;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
case AerVersion.V2:
|
if (index + 1 == parameters.Count && parameters[index].ParameterType.FullName == "System.Object[]")
|
||||||
if (method.Parameters.Count < 2)
|
return true;
|
||||||
return null;
|
|
||||||
if (method.Parameters[0].ParameterType.ToString() != "System.Exception")
|
|
||||||
return null;
|
|
||||||
if (method.Parameters[1].ParameterType.ToString() != "System.Int32")
|
|
||||||
return null;
|
|
||||||
if (method.Parameters[method.Parameters.Count - 1].ParameterType.ToString() != "System.Object[]")
|
|
||||||
return null;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AerVersion.V3:
|
for (int i = index; i < parameters.Count; i++) {
|
||||||
if (method.Parameters.Count < 1)
|
if (parameters[i].ParameterType.FullName != "System.Object")
|
||||||
return null;
|
return false;
|
||||||
if (method.Parameters[0].ParameterType.ToString() != "System.Exception")
|
|
||||||
return null;
|
|
||||||
if (method.Parameters[method.Parameters.Count - 1].ParameterType.ToString() != "System.Object[]")
|
|
||||||
return null;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new ApplicationException("Invalid AER version");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return method;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,8 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
class Deobfuscator : DeobfuscatorBase {
|
class Deobfuscator : DeobfuscatorBase {
|
||||||
Options options;
|
Options options;
|
||||||
bool foundVersion = false;
|
bool foundVersion = false;
|
||||||
|
Version approxVersion = new Version(0, 0, 0, 0);
|
||||||
|
bool canRemoveTypes;
|
||||||
string poweredByAttributeString = null;
|
string poweredByAttributeString = null;
|
||||||
string obfuscatorName = DeobfuscatorInfo.THE_NAME;
|
string obfuscatorName = DeobfuscatorInfo.THE_NAME;
|
||||||
bool foundSmartAssemblyAttribute = false;
|
bool foundSmartAssemblyAttribute = false;
|
||||||
|
@ -123,8 +125,6 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
|
|
||||||
public override void init(ModuleDefinition module) {
|
public override void init(ModuleDefinition module) {
|
||||||
base.init(module);
|
base.init(module);
|
||||||
automatedErrorReportingFinder = new AutomatedErrorReportingFinder(module);
|
|
||||||
tamperProtectionRemover = new TamperProtectionRemover(module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override int detectInternal() {
|
protected override int detectInternal() {
|
||||||
|
@ -133,12 +133,6 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
if (foundSmartAssemblyAttribute)
|
if (foundSmartAssemblyAttribute)
|
||||||
val += 100;
|
val += 100;
|
||||||
|
|
||||||
// Since we don't remove this type, we will detect it even when we've deobfuscated
|
|
||||||
// an assembly. Don't use this code for now. When the type is removed, this code
|
|
||||||
// should be re-enabled.
|
|
||||||
// if (automatedErrorReportingFinder.Detected)
|
|
||||||
// val += 10;
|
|
||||||
|
|
||||||
if (memoryManagerInfo.Detected)
|
if (memoryManagerInfo.Detected)
|
||||||
val += 10;
|
val += 10;
|
||||||
|
|
||||||
|
@ -146,10 +140,10 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void scanForObfuscator() {
|
protected override void scanForObfuscator() {
|
||||||
proxyDelegateFinder = new ProxyDelegateFinder(module, DeobfuscatedFile);
|
|
||||||
findSmartAssemblyAttributes();
|
findSmartAssemblyAttributes();
|
||||||
findAutomatedErrorReportingType();
|
|
||||||
memoryManagerInfo = new MemoryManagerInfo(module);
|
memoryManagerInfo = new MemoryManagerInfo(module);
|
||||||
|
memoryManagerInfo.find();
|
||||||
|
proxyDelegateFinder = new ProxyDelegateFinder(module, DeobfuscatedFile);
|
||||||
proxyDelegateFinder.findDelegateCreator(module);
|
proxyDelegateFinder.findDelegateCreator(module);
|
||||||
|
|
||||||
if (!foundVersion)
|
if (!foundVersion)
|
||||||
|
@ -173,43 +167,53 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
|
|
||||||
poweredByAttributeString = s;
|
poweredByAttributeString = s;
|
||||||
|
|
||||||
var val = System.Text.RegularExpressions.Regex.Match(s, @"^Powered by (SmartAssembly \d+\.\d+\.\d+\.\d+)$");
|
var val = System.Text.RegularExpressions.Regex.Match(s, @"^Powered by (SmartAssembly (\d+)\.(\d+)\.(\d+)\.(\d+))$");
|
||||||
if (val.Groups.Count < 2)
|
if (val.Groups.Count < 6)
|
||||||
return;
|
return;
|
||||||
ObfuscatorName = val.Groups[1].ToString();
|
ObfuscatorName = val.Groups[1].ToString();
|
||||||
|
approxVersion = new Version(int.Parse(val.Groups[2].ToString()),
|
||||||
|
int.Parse(val.Groups[3].ToString()),
|
||||||
|
int.Parse(val.Groups[4].ToString()),
|
||||||
|
int.Parse(val.Groups[5].ToString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void guessVersion() {
|
void guessVersion() {
|
||||||
if (poweredByAttributeString == "Powered by SmartAssembly") {
|
if (poweredByAttributeString == "Powered by SmartAssembly") {
|
||||||
ObfuscatorName = "SmartAssembly 5.0/5.1";
|
ObfuscatorName = "SmartAssembly 5.0/5.1";
|
||||||
|
approxVersion = new Version(5, 0, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poweredByAttributeString == "Powered by {smartassembly}") {
|
if (poweredByAttributeString == "Powered by {smartassembly}") {
|
||||||
// It's SA 1.x - 4.x
|
// It's SA 1.x - 4.x
|
||||||
|
|
||||||
if (hasEmptyClassesInEveryNamespace() || proxyDelegateFinder.Detected) {
|
if (proxyDelegateFinder.Detected || hasEmptyClassesInEveryNamespace()) {
|
||||||
ObfuscatorName = "SmartAssembly 4.x";
|
ObfuscatorName = "SmartAssembly 4.x";
|
||||||
|
approxVersion = new Version(4, 0, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ver = checkTypeIdAttribute();
|
int ver = checkTypeIdAttribute();
|
||||||
if (ver == 2) {
|
if (ver == 2) {
|
||||||
ObfuscatorName = "SmartAssembly 2.x";
|
ObfuscatorName = "SmartAssembly 2.x";
|
||||||
|
approxVersion = new Version(2, 0, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ver == 1) {
|
if (ver == 1) {
|
||||||
ObfuscatorName = "SmartAssembly 1.x-2.x";
|
ObfuscatorName = "SmartAssembly 1.x-2.x";
|
||||||
|
approxVersion = new Version(1, 0, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasModuleCctor()) {
|
if (hasModuleCctor()) {
|
||||||
ObfuscatorName = "SmartAssembly 3.x";
|
ObfuscatorName = "SmartAssembly 3.x";
|
||||||
|
approxVersion = new Version(3, 0, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObfuscatorName = "SmartAssembly 1.x-4.x";
|
ObfuscatorName = "SmartAssembly 1.x-4.x";
|
||||||
|
approxVersion = new Version(1, 0, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,16 +294,18 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void findAutomatedErrorReportingType() {
|
|
||||||
automatedErrorReportingFinder.find();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void deobfuscateBegin() {
|
public override void deobfuscateBegin() {
|
||||||
base.deobfuscateBegin();
|
base.deobfuscateBegin();
|
||||||
|
|
||||||
|
tamperProtectionRemover = new TamperProtectionRemover(module);
|
||||||
|
automatedErrorReportingFinder = new AutomatedErrorReportingFinder(module);
|
||||||
|
automatedErrorReportingFinder.find();
|
||||||
|
|
||||||
if (options.RemoveMemoryManager) {
|
if (options.RemoveMemoryManager) {
|
||||||
addModuleCctorInitCallToBeRemoved(memoryManagerInfo.CctorInitMethod);
|
addModuleCctorInitCallToBeRemoved(memoryManagerInfo.CctorInitMethod);
|
||||||
addCallToBeRemoved(module.EntryPoint, memoryManagerInfo.CctorInitMethod);
|
addCallToBeRemoved(module.EntryPoint, memoryManagerInfo.CctorInitMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
initDecrypters();
|
initDecrypters();
|
||||||
proxyDelegateFinder.find();
|
proxyDelegateFinder.find();
|
||||||
}
|
}
|
||||||
|
@ -307,7 +313,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
void initDecrypters() {
|
void initDecrypters() {
|
||||||
assemblyResolverInfo = new AssemblyResolverInfo(module, DeobfuscatedFile, this);
|
assemblyResolverInfo = new AssemblyResolverInfo(module, DeobfuscatedFile, this);
|
||||||
assemblyResolverInfo.findTypes();
|
assemblyResolverInfo.findTypes();
|
||||||
resourceDecrypterInfo = new ResourceDecrypterInfo(module, assemblyResolverInfo.SimpleZipType, DeobfuscatedFile);
|
resourceDecrypterInfo = new ResourceDecrypterInfo(module, assemblyResolverInfo.SimpleZipTypeMethod, DeobfuscatedFile);
|
||||||
resourceResolverInfo = new ResourceResolverInfo(module, DeobfuscatedFile, this, assemblyResolverInfo);
|
resourceResolverInfo = new ResourceResolverInfo(module, DeobfuscatedFile, this, assemblyResolverInfo);
|
||||||
resourceResolverInfo.findTypes();
|
resourceResolverInfo.findTypes();
|
||||||
resourceDecrypter = new ResourceDecrypter(resourceDecrypterInfo);
|
resourceDecrypter = new ResourceDecrypter(resourceDecrypterInfo);
|
||||||
|
@ -323,7 +329,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
addModuleCctorInitCallToBeRemoved(resourceResolverInfo.CallResolverMethod);
|
addModuleCctorInitCallToBeRemoved(resourceResolverInfo.CallResolverMethod);
|
||||||
addCallToBeRemoved(module.EntryPoint, resourceResolverInfo.CallResolverMethod);
|
addCallToBeRemoved(module.EntryPoint, resourceResolverInfo.CallResolverMethod);
|
||||||
|
|
||||||
resourceDecrypterInfo.setSimpleZipType(getGlobalSimpleZipType(), DeobfuscatedFile);
|
resourceDecrypterInfo.setSimpleZipType(getGlobalSimpleZipTypeMethod(), DeobfuscatedFile);
|
||||||
|
|
||||||
if (!decryptResources())
|
if (!decryptResources())
|
||||||
throw new ApplicationException("Could not decrypt resources");
|
throw new ApplicationException("Could not decrypt resources");
|
||||||
|
@ -350,12 +356,12 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDefinition getGlobalSimpleZipType() {
|
MethodDefinition getGlobalSimpleZipTypeMethod() {
|
||||||
if (assemblyResolverInfo.SimpleZipType != null)
|
if (assemblyResolverInfo.SimpleZipTypeMethod != null)
|
||||||
return assemblyResolverInfo.SimpleZipType;
|
return assemblyResolverInfo.SimpleZipTypeMethod;
|
||||||
foreach (var info in stringDecrypterInfos) {
|
foreach (var info in stringDecrypterInfos) {
|
||||||
if (info.SimpleZipType != null)
|
if (info.SimpleZipTypeMethod != null)
|
||||||
return info.SimpleZipType;
|
return info.SimpleZipTypeMethod;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -383,7 +389,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
if (initd.ContainsKey(info))
|
if (initd.ContainsKey(info))
|
||||||
continue;
|
continue;
|
||||||
if (info.init(this, DeobfuscatedFile)) {
|
if (info.init(this, DeobfuscatedFile)) {
|
||||||
resourceDecrypterInfo.setSimpleZipType(info.SimpleZipType, DeobfuscatedFile);
|
resourceDecrypterInfo.setSimpleZipType(info.SimpleZipTypeMethod, DeobfuscatedFile);
|
||||||
initdInfo = info;
|
initdInfo = info;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -436,7 +442,8 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void deobfuscateEnd() {
|
public override void deobfuscateEnd() {
|
||||||
removeProxyDelegates(proxyDelegateFinder);
|
canRemoveTypes = findBigType() == null;
|
||||||
|
removeProxyDelegates(proxyDelegateFinder, canRemoveTypes);
|
||||||
removeMemoryManagerStuff();
|
removeMemoryManagerStuff();
|
||||||
removeTamperProtectionStuff();
|
removeTamperProtectionStuff();
|
||||||
removeStringDecryptionStuff();
|
removeStringDecryptionStuff();
|
||||||
|
@ -445,7 +452,37 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
base.deobfuscateEnd();
|
base.deobfuscateEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeDefinition findBigType() {
|
||||||
|
if (approxVersion <= new Version(6, 5, 3, 53))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
TypeDefinition bigType = null;
|
||||||
|
foreach (var type in module.Types) {
|
||||||
|
if (isBigType(type)) {
|
||||||
|
if (bigType == null || type.Methods.Count > bigType.Methods.Count)
|
||||||
|
bigType = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bigType;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isBigType(TypeDefinition type) {
|
||||||
|
if (type.Methods.Count < 50)
|
||||||
|
return false;
|
||||||
|
if (type.HasProperties || type.HasEvents)
|
||||||
|
return false;
|
||||||
|
if (type.Fields.Count > 3)
|
||||||
|
return false;
|
||||||
|
foreach (var method in type.Methods) {
|
||||||
|
if (!method.IsStatic)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void removeResolverInfoTypes(ResolverInfoBase info, string typeName) {
|
void removeResolverInfoTypes(ResolverInfoBase info, string typeName) {
|
||||||
|
if (!canRemoveTypes)
|
||||||
|
return;
|
||||||
addTypeToBeRemoved(info.CallResolverType, string.Format("{0} resolver type #1", typeName));
|
addTypeToBeRemoved(info.CallResolverType, string.Format("{0} resolver type #1", typeName));
|
||||||
addTypeToBeRemoved(info.Type, string.Format("{0} resolver type #2", typeName));
|
addTypeToBeRemoved(info.Type, string.Format("{0} resolver type #2", typeName));
|
||||||
}
|
}
|
||||||
|
@ -453,7 +490,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
void removeAutomatedErrorReportingCode(Blocks blocks) {
|
void removeAutomatedErrorReportingCode(Blocks blocks) {
|
||||||
if (!options.RemoveAutomatedErrorReporting)
|
if (!options.RemoveAutomatedErrorReporting)
|
||||||
return;
|
return;
|
||||||
if (automatedErrorReportingFinder.ExceptionLoggerRemover.remove(blocks))
|
if (automatedErrorReportingFinder.remove(blocks))
|
||||||
Log.v("Removed Automated Error Reporting code");
|
Log.v("Removed Automated Error Reporting code");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +502,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeMemoryManagerStuff() {
|
void removeMemoryManagerStuff() {
|
||||||
if (!options.RemoveMemoryManager)
|
if (!canRemoveTypes || !options.RemoveMemoryManager)
|
||||||
return;
|
return;
|
||||||
addTypeToBeRemoved(memoryManagerInfo.Type, "Memory manager type");
|
addTypeToBeRemoved(memoryManagerInfo.Type, "Memory manager type");
|
||||||
}
|
}
|
||||||
|
@ -489,11 +526,13 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
addResourceToBeRemoved(info.StringsResource, "Encrypted strings");
|
addResourceToBeRemoved(info.StringsResource, "Encrypted strings");
|
||||||
addFieldsToBeRemoved(info.getAllStringDelegateFields(), "String decrypter delegate field");
|
addFieldsToBeRemoved(info.getAllStringDelegateFields(), "String decrypter delegate field");
|
||||||
|
|
||||||
|
if (canRemoveTypes) {
|
||||||
addTypeToBeRemoved(info.StringsEncodingClass, "String decrypter type");
|
addTypeToBeRemoved(info.StringsEncodingClass, "String decrypter type");
|
||||||
addTypeToBeRemoved(info.StringsType, "Creates the string decrypter delegates");
|
addTypeToBeRemoved(info.StringsType, "Creates the string decrypter delegates");
|
||||||
addTypeToBeRemoved(info.GetStringDelegate, "String decrypter delegate type");
|
addTypeToBeRemoved(info.GetStringDelegate, "String decrypter delegate type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void removeStringsInitCode(Blocks blocks) {
|
void removeStringsInitCode(Blocks blocks) {
|
||||||
if (!canRemoveStringDecrypterStuff())
|
if (!canRemoveStringDecrypterStuff())
|
||||||
|
|
|
@ -40,10 +40,9 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
|
|
||||||
public MemoryManagerInfo(ModuleDefinition module) {
|
public MemoryManagerInfo(ModuleDefinition module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
find();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool find() {
|
public bool find() {
|
||||||
if (checkCalledMethods(DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor")))
|
if (checkCalledMethods(DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor")))
|
||||||
return true;
|
return true;
|
||||||
if (checkCalledMethods(module.EntryPoint))
|
if (checkCalledMethods(module.EntryPoint))
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
if (mostCalls == null)
|
if (mostCalls == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setDelegateCreatorMethod(DotNetUtils.getMethod(DotNetUtils.getType(module, mostCalls.DeclaringType), mostCalls));
|
setDelegateCreatorMethod(DotNetUtils.getMethod(module, mostCalls));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
ISimpleDeobfuscator simpleDeobfuscator;
|
ISimpleDeobfuscator simpleDeobfuscator;
|
||||||
IDeobfuscator deob;
|
IDeobfuscator deob;
|
||||||
TypeDefinition resolverType;
|
TypeDefinition resolverType;
|
||||||
TypeDefinition callResolverType;
|
|
||||||
MethodDefinition callResolverMethod;
|
MethodDefinition callResolverMethod;
|
||||||
|
|
||||||
public TypeDefinition Type {
|
public TypeDefinition Type {
|
||||||
|
@ -36,7 +35,13 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDefinition CallResolverType {
|
public TypeDefinition CallResolverType {
|
||||||
get { return callResolverType; }
|
get {
|
||||||
|
if (callResolverMethod == null)
|
||||||
|
return null;
|
||||||
|
if (!hasOnlyThisMethod(callResolverMethod.DeclaringType, callResolverMethod))
|
||||||
|
return null;
|
||||||
|
return callResolverMethod.DeclaringType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodDefinition CallResolverMethod {
|
public MethodDefinition CallResolverMethod {
|
||||||
|
@ -70,26 +75,17 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
continue;
|
continue;
|
||||||
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
|
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||||
continue;
|
continue;
|
||||||
if (checkAttachAppType(tuple.Item1, method))
|
if (checkAttachAppMethod(method))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkAttachAppType(TypeDefinition type, MethodDefinition attachAppMethod) {
|
bool checkAttachAppMethod(MethodDefinition attachAppMethod) {
|
||||||
callResolverType = null;
|
callResolverMethod = null;
|
||||||
if (!attachAppMethod.HasBody)
|
if (!attachAppMethod.HasBody)
|
||||||
return false;
|
return false;
|
||||||
if (type.Fields.Count > 0 || type.Properties.Count > 0 || type.Events.Count > 0)
|
|
||||||
return false;
|
|
||||||
foreach (var m in type.Methods) {
|
|
||||||
if (m.Name == ".cctor" || m.Name == ".ctor")
|
|
||||||
continue;
|
|
||||||
if (m == attachAppMethod)
|
|
||||||
continue;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var tuple in DotNetUtils.getCalledMethods(module, attachAppMethod)) {
|
foreach (var tuple in DotNetUtils.getCalledMethods(module, attachAppMethod)) {
|
||||||
var method = tuple.Item2;
|
var method = tuple.Item2;
|
||||||
|
@ -97,26 +93,25 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
continue;
|
continue;
|
||||||
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
|
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||||
continue;
|
continue;
|
||||||
if (!checkResolverType(tuple.Item1, method))
|
if (!checkResolverInitMethod(method))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
callResolverMethod = attachAppMethod;
|
callResolverMethod = attachAppMethod;
|
||||||
callResolverType = type;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasLdftn(attachAppMethod)) {
|
if (hasLdftn(attachAppMethod)) {
|
||||||
simpleDeobfuscator.deobfuscate(attachAppMethod);
|
simpleDeobfuscator.deobfuscate(attachAppMethod);
|
||||||
foreach (var resolverHandler in getResolverHandlers(type, attachAppMethod)) {
|
foreach (var resolverHandler in getResolverHandlers(attachAppMethod)) {
|
||||||
if (!resolverHandler.HasBody)
|
if (!resolverHandler.HasBody)
|
||||||
continue;
|
continue;
|
||||||
if (!checkResolverType2(resolverHandler.DeclaringType))
|
var resolverTypeTmp = getResolverType(resolverHandler);
|
||||||
|
if (resolverTypeTmp == null)
|
||||||
continue;
|
continue;
|
||||||
deobfuscate(resolverHandler);
|
deobfuscate(resolverHandler);
|
||||||
if (checkHandlerMethod(resolverHandler)) {
|
if (checkHandlerMethod(resolverHandler)) {
|
||||||
callResolverMethod = attachAppMethod;
|
callResolverMethod = attachAppMethod;
|
||||||
callResolverType = type;
|
resolverType = resolverTypeTmp;
|
||||||
resolverType = resolverHandler.DeclaringType;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,27 +130,21 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkResolverType2(TypeDefinition type) {
|
bool checkResolverInitMethod(MethodDefinition initMethod) {
|
||||||
if (type.Properties.Count > 1 || type.Events.Count > 0)
|
|
||||||
return false;
|
|
||||||
if (!checkResolverType(type))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkResolverType(TypeDefinition type, MethodDefinition initMethod) {
|
|
||||||
resolverType = null;
|
resolverType = null;
|
||||||
if (!initMethod.HasBody)
|
if (!initMethod.HasBody)
|
||||||
return false;
|
return false;
|
||||||
if (!checkResolverType2(type))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
deobfuscate(initMethod);
|
deobfuscate(initMethod);
|
||||||
foreach (var handlerDef in getResolverHandlers(type, initMethod)) {
|
foreach (var handlerDef in getResolverHandlers(initMethod)) {
|
||||||
deobfuscate(handlerDef);
|
deobfuscate(handlerDef);
|
||||||
|
|
||||||
|
var resolverTypeTmp = getResolverType(handlerDef);
|
||||||
|
if (resolverTypeTmp == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (checkHandlerMethod(handlerDef)) {
|
if (checkHandlerMethod(handlerDef)) {
|
||||||
resolverType = type;
|
resolverType = resolverTypeTmp;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,10 +157,31 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
simpleDeobfuscator.decryptStrings(method, deob);
|
simpleDeobfuscator.decryptStrings(method, deob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeDefinition getResolverType(MethodDefinition resolveHandler) {
|
||||||
|
if (resolveHandler.Body == null)
|
||||||
|
return null;
|
||||||
|
foreach (var instr in resolveHandler.Body.Instructions) {
|
||||||
|
if (instr.OpCode.Code != Code.Ldsfld && instr.OpCode.Code != Code.Stsfld)
|
||||||
|
continue;
|
||||||
|
var field = DotNetUtils.getField(module, instr.Operand as FieldReference);
|
||||||
|
if (field == null)
|
||||||
|
continue;
|
||||||
|
if (!checkResolverType(field.DeclaringType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return field.DeclaringType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkResolverType(resolveHandler.DeclaringType))
|
||||||
|
return resolveHandler.DeclaringType;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract bool checkResolverType(TypeDefinition type);
|
protected abstract bool checkResolverType(TypeDefinition type);
|
||||||
protected abstract bool checkHandlerMethod(MethodDefinition handler);
|
protected abstract bool checkHandlerMethod(MethodDefinition handler);
|
||||||
|
|
||||||
static IEnumerable<MethodDefinition> getResolverHandlers(TypeDefinition type, MethodDefinition method) {
|
IEnumerable<MethodDefinition> getResolverHandlers(MethodDefinition method) {
|
||||||
int numHandlers = 0;
|
int numHandlers = 0;
|
||||||
var instructions = method.Body.Instructions;
|
var instructions = method.Body.Instructions;
|
||||||
for (int i = 0; i < instructions.Count; i++) {
|
for (int i = 0; i < instructions.Count; i++) {
|
||||||
|
@ -184,7 +194,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var ldftn = instrs[2];
|
var ldftn = instrs[2];
|
||||||
var handlerDef = DotNetUtils.getMethod(type, ldftn.Operand as MethodReference);
|
var handlerDef = DotNetUtils.getMethod(module, ldftn.Operand as MethodReference);
|
||||||
if (handlerDef == null)
|
if (handlerDef == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -204,5 +214,18 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
if (numHandlers == 0)
|
if (numHandlers == 0)
|
||||||
yield return method;
|
yield return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hasOnlyThisMethod(TypeDefinition type, MethodDefinition method) {
|
||||||
|
if (type == null || method == null)
|
||||||
|
return false;
|
||||||
|
foreach (var m in type.Methods) {
|
||||||
|
if (m.Name == ".cctor" || m.Name == ".ctor")
|
||||||
|
continue;
|
||||||
|
if (m == method)
|
||||||
|
continue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.SmartAssembly {
|
namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
class ResourceDecrypterInfo {
|
class ResourceDecrypterInfo {
|
||||||
ModuleDefinition module;
|
ModuleDefinition module;
|
||||||
TypeDefinition simpleZipType;
|
MethodDefinition simpleZipTypeDecryptMethod;
|
||||||
|
|
||||||
public byte[] DES_Key { get; private set; }
|
public byte[] DES_Key { get; private set; }
|
||||||
public byte[] DES_IV { get; private set; }
|
public byte[] DES_IV { get; private set; }
|
||||||
|
@ -33,31 +33,29 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
public byte[] AES_IV { get; private set; }
|
public byte[] AES_IV { get; private set; }
|
||||||
|
|
||||||
public bool CanDecrypt {
|
public bool CanDecrypt {
|
||||||
get { return simpleZipType != null; }
|
get { return simpleZipTypeDecryptMethod != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceDecrypterInfo(ModuleDefinition module) {
|
public ResourceDecrypterInfo(ModuleDefinition module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceDecrypterInfo(ModuleDefinition module, TypeDefinition simpleZipType, ISimpleDeobfuscator simpleDeobfuscator)
|
public ResourceDecrypterInfo(ModuleDefinition module, MethodDefinition simpleZipTypeDecryptMethod, ISimpleDeobfuscator simpleDeobfuscator)
|
||||||
: this(module) {
|
: this(module) {
|
||||||
setSimpleZipType(simpleZipType, simpleDeobfuscator);
|
setSimpleZipType(simpleZipTypeDecryptMethod, simpleDeobfuscator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSimpleZipType(TypeDefinition type, ISimpleDeobfuscator simpleDeobfuscator) {
|
public void setSimpleZipType(MethodDefinition method, ISimpleDeobfuscator simpleDeobfuscator) {
|
||||||
if (simpleZipType != null || type == null)
|
if (simpleZipTypeDecryptMethod != null || method == null)
|
||||||
return;
|
return;
|
||||||
simpleZipType = type;
|
simpleZipTypeDecryptMethod = method;
|
||||||
init(simpleDeobfuscator);
|
init(simpleDeobfuscator, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(ISimpleDeobfuscator simpleDeobfuscator) {
|
void init(ISimpleDeobfuscator simpleDeobfuscator, MethodDefinition method) {
|
||||||
var desList = new List<byte[]>(2);
|
var desList = new List<byte[]>(2);
|
||||||
var aesList = new List<byte[]>(2);
|
var aesList = new List<byte[]>(2);
|
||||||
|
|
||||||
if (simpleZipType != null) {
|
|
||||||
foreach (var method in DotNetUtils.findMethods(simpleZipType.Methods, "System.Byte[]", new string[] { "System.Byte[]" }, true)) {
|
|
||||||
var instructions = method.Body.Instructions;
|
var instructions = method.Body.Instructions;
|
||||||
simpleDeobfuscator.deobfuscate(method);
|
simpleDeobfuscator.deobfuscate(method);
|
||||||
for (int i = 0; i <= instructions.Count - 2; i++) {
|
for (int i = 0; i <= instructions.Count - 2; i++) {
|
||||||
|
@ -82,8 +80,6 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
else if (field.InitialValue.Length == 16)
|
else if (field.InitialValue.Length == 16)
|
||||||
aesList.Add(field.InitialValue);
|
aesList.Add(field.InitialValue);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desList.Count >= 2) {
|
if (desList.Count >= 2) {
|
||||||
DES_Key = desList[desList.Count - 2];
|
DES_Key = desList[desList.Count - 2];
|
||||||
|
|
|
@ -23,18 +23,17 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.SmartAssembly {
|
namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
class SimpleZipInfo {
|
class SimpleZipInfo {
|
||||||
|
|
||||||
public static bool isSimpleZipDecryptMethod_QuickCheck(ModuleDefinition module, MethodReference method, out TypeDefinition simpleZipType) {
|
public static bool isSimpleZipDecryptMethod_QuickCheck(ModuleDefinition module, MethodReference method, out MethodDefinition simpleZipTypeMethod) {
|
||||||
simpleZipType = null;
|
simpleZipTypeMethod = null;
|
||||||
|
|
||||||
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[])"))
|
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[])"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var type = DotNetUtils.getType(module, method.DeclaringType);
|
var methodDef = DotNetUtils.getMethod(DotNetUtils.getType(module, method.DeclaringType), method);
|
||||||
var methodDef = DotNetUtils.getMethod(type, method);
|
|
||||||
if (methodDef == null)
|
if (methodDef == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
simpleZipType = type;
|
simpleZipTypeMethod = methodDef;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
TypeDefinition stringsEncodingClass;
|
TypeDefinition stringsEncodingClass;
|
||||||
EmbeddedResource stringsResource;
|
EmbeddedResource stringsResource;
|
||||||
int stringOffset;
|
int stringOffset;
|
||||||
TypeDefinition simpleZipType;
|
MethodDefinition simpleZipTypeMethod;
|
||||||
MethodDefinition stringDecrypterMethod;
|
MethodDefinition stringDecrypterMethod;
|
||||||
StringDecrypterVersion decrypterVersion;
|
StringDecrypterVersion decrypterVersion;
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
get { return resourceDecrypter == null || resourceDecrypter.CanDecrypt; }
|
get { return resourceDecrypter == null || resourceDecrypter.CanDecrypt; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeDefinition SimpleZipType {
|
public MethodDefinition SimpleZipTypeMethod {
|
||||||
get { return simpleZipType; }
|
get { return simpleZipTypeMethod; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmbeddedResource StringsResource {
|
public EmbeddedResource StringsResource {
|
||||||
|
@ -71,7 +71,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool StringsEncrypted {
|
public bool StringsEncrypted {
|
||||||
get { return simpleZipType != null; }
|
get { return simpleZipTypeMethod != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodDefinition StringDecrypterMethod {
|
public MethodDefinition StringDecrypterMethod {
|
||||||
|
@ -148,9 +148,9 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
decrypterVersion = StringDecrypterVersion.V4;
|
decrypterVersion = StringDecrypterVersion.V4;
|
||||||
}
|
}
|
||||||
|
|
||||||
simpleZipType = findSimpleZipType(cctor) ?? findSimpleZipType(stringDecrypterMethod);
|
simpleZipTypeMethod = findSimpleZipTypeMethod(cctor) ?? findSimpleZipTypeMethod(stringDecrypterMethod);
|
||||||
if (simpleZipType != null)
|
if (simpleZipTypeMethod != null)
|
||||||
resourceDecrypter = new ResourceDecrypter(new ResourceDecrypterInfo(module, simpleZipType, simpleDeobfuscator));
|
resourceDecrypter = new ResourceDecrypter(new ResourceDecrypterInfo(module, simpleZipTypeMethod, simpleDeobfuscator));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -292,9 +292,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find SmartAssembly.Zip.SimpleZip, which is the class that decrypts and inflates
|
MethodDefinition findSimpleZipTypeMethod(MethodDefinition method) {
|
||||||
// data in the resources.
|
|
||||||
TypeDefinition findSimpleZipType(MethodDefinition method) {
|
|
||||||
if (method == null || method.Body == null)
|
if (method == null || method.Body == null)
|
||||||
return null;
|
return null;
|
||||||
var instructions = method.Body.Instructions;
|
var instructions = method.Body.Instructions;
|
||||||
|
@ -302,7 +300,9 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
var call = instructions[i];
|
var call = instructions[i];
|
||||||
if (call.OpCode.Code != Code.Call)
|
if (call.OpCode.Code != Code.Call)
|
||||||
continue;
|
continue;
|
||||||
var calledMethod = call.Operand as MethodReference;
|
var calledMethod = call.Operand as MethodDefinition;
|
||||||
|
if (calledMethod == null)
|
||||||
|
continue;
|
||||||
if (!DotNetUtils.isMethod(calledMethod, "System.Byte[]", "(System.Byte[])"))
|
if (!DotNetUtils.isMethod(calledMethod, "System.Byte[]", "(System.Byte[])"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -315,11 +315,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
if (!MemberReferenceHelper.compareTypes(stringsEncodingClass, field.DeclaringType))
|
if (!MemberReferenceHelper.compareTypes(stringsEncodingClass, field.DeclaringType))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var type = DotNetUtils.getType(module, calledMethod.DeclaringType);
|
return calledMethod;
|
||||||
if (type == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user