Merge branch 'master' into newcode

This commit is contained in:
de4dot 2012-01-18 06:15:31 +01:00
commit ed31063b1b
24 changed files with 316 additions and 396 deletions

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -441,6 +441,8 @@ namespace de4dot.blocks {
}
public static FieldDefinition getField(ModuleDefinition module, FieldReference field) {
if (field == null)
return null;
if (field is FieldDefinition)
return (FieldDefinition)field;
return getField(getType(module, field.DeclaringType), field);

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

2
cecil

@ -1 +1 @@
Subproject commit 188d7947ad6c9a260099f7b58e2595a13e9a5f07
Subproject commit 2bc3f2014c697f697e8bb09e5ca004e5e252fe06

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -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) {
Log.v("Not removing proxy delegates and creator type since errors were detected.");
return;
}
addTypesToBeRemoved(proxyDelegateFinder.DelegateTypes, "Proxy delegate type");
if (proxyDelegateFinder.RemovedDelegateCreatorCalls > 0)
if (removeCreators && proxyDelegateFinder.RemovedDelegateCreatorCalls > 0)
addTypesToBeRemoved(proxyDelegateFinder.DelegateCreatorTypes, "Proxy delegate creator type");
}

View File

@ -43,7 +43,7 @@ namespace de4dot.code.deobfuscators {
continue;
var catchBlock = tryBlock.TryHandlerBlocks[0];
if (catchBlock.HandlerType != ExceptionHandlerType.Catch ||
!MemberReferenceHelper.verifyType(catchBlock.CatchType, "mscorlib", "System.Exception")) {
catchBlock.CatchType.FullName != "System.Exception") {
continue;
}
if (catchBlock.BaseBlocks.Count != 1)
@ -77,7 +77,7 @@ namespace de4dot.code.deobfuscators {
var calledMethod = callInstr.Operand as MethodReference;
if (calledMethod == null)
continue;
if (!exceptionLoggerMethods.ContainsKey(calledMethod))
if (!isExceptionLogger(calledMethod))
continue;
return true;
@ -86,8 +86,16 @@ namespace de4dot.code.deobfuscators {
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) {
if (exceptionLoggerMethods.Count == 0)
if (!HasExceptionLoggers)
return false;
TryBlock tryBlock;

View File

@ -71,11 +71,11 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
}
class AssemblyResolverInfo : ResolverInfoBase {
TypeDefinition simpleZipType;
MethodDefinition simpleZipTypeMethod;
List<EmbeddedAssemblyInfo> embeddedAssemblyInfos = new List<EmbeddedAssemblyInfo>();
public TypeDefinition SimpleZipType {
get { return simpleZipType; }
public MethodDefinition SimpleZipTypeMethod {
get { return simpleZipTypeMethod; }
}
public IList<EmbeddedAssemblyInfo> EmbeddedAssemblyInfos {
@ -163,7 +163,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
var calledMethod = call.Operand as MethodReference;
if (calledMethod == null)
continue;
if (!SimpleZipInfo.isSimpleZipDecryptMethod_QuickCheck(module, calledMethod, out simpleZipType))
if (!SimpleZipInfo.isSimpleZipDecryptMethod_QuickCheck(module, calledMethod, out simpleZipTypeMethod))
continue;
return;

View File

@ -24,267 +24,127 @@ using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.SmartAssembly {
class AutomatedErrorReportingFinder {
class AutomatedErrorReportingFinder : ExceptionLoggerRemover {
ModuleDefinition module;
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
TypeDefinition automatedErrorReportingType;
int constantArgs;
AerVersion aerVersion;
bool enabled;
enum AerVersion {
V0,
V1,
V2,
V3,
}
public ExceptionLoggerRemover ExceptionLoggerRemover {
get { return exceptionLoggerRemover; }
}
public TypeDefinition Type {
get { return automatedErrorReportingType; }
}
public bool Detected {
get { return automatedErrorReportingType != null; }
protected override bool HasExceptionLoggers {
get { return enabled; }
}
public AutomatedErrorReportingFinder(ModuleDefinition module) {
this.module = module;
}
protected override bool isExceptionLogger(MethodReference method) {
return isExceptionLoggerMethod(method);
}
public void find() {
foreach (var type in module.Types) {
if (detectAutomatedErrorReportingType(type))
break;
}
}
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);
}
}
var entryPoint = module.EntryPoint;
if (entryPoint == null)
enabled = true;
else {
if (methods.Count < MIN_HELPER_METHODS)
return false;
MethodDefinition exceptionMethod;
enabled = checkMethod(entryPoint, out exceptionMethod);
}
}
if (isV1(mainMethod))
aerVersion = AerVersion.V1;
else if (isV2(mainMethod))
aerVersion = AerVersion.V2;
else
aerVersion = AerVersion.V3;
bool checkMethod(MethodDefinition method, out MethodDefinition exceptionMethod) {
exceptionMethod = null;
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;
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);
}
MethodReference checkHandler(IList<Instruction> instrs, int start, int end) {
MethodReference 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 MethodReference;
if (method == null)
return null;
calledMethod = method;
}
}
exceptionLoggerRemover.add(mainMethod);
foreach (var method in methods)
exceptionLoggerRemover.add(method);
automatedErrorReportingType = type;
if (aerVersion == AerVersion.V1) {
foreach (var method in type.Methods) {
if (DotNetUtils.isMethod(method, "System.Exception", "(System.Int32,System.Object[])"))
exceptionLoggerRemover.add(method);
}
}
initUnhandledExceptionFilterMethods();
return true;
return calledMethod;
}
void initializeConstantArgs(MethodDefinition method) {
if (constantArgs > 0)
return;
constantArgs = getConstantArgs(method);
}
static bool isExceptionLoggerMethod(MethodReference method) {
if (method.Name == ".ctor" || method.Name == ".cctor")
return false;
static int getConstantArgs(MethodDefinition method) {
if (method.Parameters.Count >= 2) {
if (isV1(method) || isV2(method))
return 2;
}
return 1;
}
var parameters = method.Parameters;
if (parameters.Count < 1)
return false;
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;
var rtype = method.MethodReturnType.ReturnType.FullName;
var type0 = parameters[0].ParameterType.FullName;
var type1 = parameters.Count < 2 ? "" : parameters[1].ParameterType.FullName;
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 (parameters.Count == 2 && type0 == "System.Int32" && type1 == "System.Object[]")
return true;
else if (type0 == "System.Exception")
index = 1;
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")
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;
}
return true;
}
bool isAutomatedErrorReportingMethod(MethodDefinition method) {
if (!method.HasBody || !method.IsStatic || method.Name == ".ctor")
else
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;
if (index + 1 == parameters.Count && parameters[index].ParameterType.FullName == "System.Object[]")
return true;
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)
continue;
mainExceptionHandlerMethod = method; // Use the last one we find
for (int i = index; i < parameters.Count; i++) {
if (parameters[i].ParameterType.FullName != "System.Object")
return false;
}
if (mainExceptionHandlerMethod != null)
exceptionLoggerRemover.add(mainExceptionHandlerMethod);
}
MethodDefinition getMainExceptionHandlerMethod(MethodReference methodReference) {
var type = DotNetUtils.getType(module, methodReference.DeclaringType);
var method = DotNetUtils.getMethod(type, methodReference);
if (method == null || !method.IsStatic)
return null;
if (DotNetUtils.hasReturnValue(method))
return null;
switch (aerVersion) {
case AerVersion.V0:
case AerVersion.V1:
if (!DotNetUtils.isMethod(method, "System.Void", "(System.Int32,System.Object[])"))
return null;
break;
case AerVersion.V2:
if (method.Parameters.Count < 2)
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:
if (method.Parameters.Count < 1)
return null;
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;
}
}
}

View File

@ -72,6 +72,8 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
class Deobfuscator : DeobfuscatorBase {
Options options;
bool foundVersion = false;
Version approxVersion = new Version(0, 0, 0, 0);
bool canRemoveTypes;
string poweredByAttributeString = null;
string obfuscatorName = DeobfuscatorInfo.THE_NAME;
bool foundSmartAssemblyAttribute = false;
@ -123,8 +125,6 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
public override void init(ModuleDefinition module) {
base.init(module);
automatedErrorReportingFinder = new AutomatedErrorReportingFinder(module);
tamperProtectionRemover = new TamperProtectionRemover(module);
}
protected override int detectInternal() {
@ -133,12 +133,6 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
if (foundSmartAssemblyAttribute)
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)
val += 10;
@ -146,10 +140,10 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
}
protected override void scanForObfuscator() {
proxyDelegateFinder = new ProxyDelegateFinder(module, DeobfuscatedFile);
findSmartAssemblyAttributes();
findAutomatedErrorReportingType();
memoryManagerInfo = new MemoryManagerInfo(module);
memoryManagerInfo.find();
proxyDelegateFinder = new ProxyDelegateFinder(module, DeobfuscatedFile);
proxyDelegateFinder.findDelegateCreator(module);
if (!foundVersion)
@ -173,43 +167,53 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
poweredByAttributeString = s;
var val = System.Text.RegularExpressions.Regex.Match(s, @"^Powered by (SmartAssembly \d+\.\d+\.\d+\.\d+)$");
if (val.Groups.Count < 2)
var val = System.Text.RegularExpressions.Regex.Match(s, @"^Powered by (SmartAssembly (\d+)\.(\d+)\.(\d+)\.(\d+))$");
if (val.Groups.Count < 6)
return;
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;
}
void guessVersion() {
if (poweredByAttributeString == "Powered by SmartAssembly") {
ObfuscatorName = "SmartAssembly 5.0/5.1";
approxVersion = new Version(5, 0, 0, 0);
return;
}
if (poweredByAttributeString == "Powered by {smartassembly}") {
// It's SA 1.x - 4.x
if (hasEmptyClassesInEveryNamespace() || proxyDelegateFinder.Detected) {
if (proxyDelegateFinder.Detected || hasEmptyClassesInEveryNamespace()) {
ObfuscatorName = "SmartAssembly 4.x";
approxVersion = new Version(4, 0, 0, 0);
return;
}
int ver = checkTypeIdAttribute();
if (ver == 2) {
ObfuscatorName = "SmartAssembly 2.x";
approxVersion = new Version(2, 0, 0, 0);
return;
}
if (ver == 1) {
ObfuscatorName = "SmartAssembly 1.x-2.x";
approxVersion = new Version(1, 0, 0, 0);
return;
}
if (hasModuleCctor()) {
ObfuscatorName = "SmartAssembly 3.x";
approxVersion = new Version(3, 0, 0, 0);
return;
}
ObfuscatorName = "SmartAssembly 1.x-4.x";
approxVersion = new Version(1, 0, 0, 0);
return;
}
}
@ -290,16 +294,18 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
return true;
}
void findAutomatedErrorReportingType() {
automatedErrorReportingFinder.find();
}
public override void deobfuscateBegin() {
base.deobfuscateBegin();
tamperProtectionRemover = new TamperProtectionRemover(module);
automatedErrorReportingFinder = new AutomatedErrorReportingFinder(module);
automatedErrorReportingFinder.find();
if (options.RemoveMemoryManager) {
addModuleCctorInitCallToBeRemoved(memoryManagerInfo.CctorInitMethod);
addCallToBeRemoved(module.EntryPoint, memoryManagerInfo.CctorInitMethod);
}
initDecrypters();
proxyDelegateFinder.find();
}
@ -307,7 +313,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
void initDecrypters() {
assemblyResolverInfo = new AssemblyResolverInfo(module, DeobfuscatedFile, this);
assemblyResolverInfo.findTypes();
resourceDecrypterInfo = new ResourceDecrypterInfo(module, assemblyResolverInfo.SimpleZipType, DeobfuscatedFile);
resourceDecrypterInfo = new ResourceDecrypterInfo(module, assemblyResolverInfo.SimpleZipTypeMethod, DeobfuscatedFile);
resourceResolverInfo = new ResourceResolverInfo(module, DeobfuscatedFile, this, assemblyResolverInfo);
resourceResolverInfo.findTypes();
resourceDecrypter = new ResourceDecrypter(resourceDecrypterInfo);
@ -323,7 +329,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
addModuleCctorInitCallToBeRemoved(resourceResolverInfo.CallResolverMethod);
addCallToBeRemoved(module.EntryPoint, resourceResolverInfo.CallResolverMethod);
resourceDecrypterInfo.setSimpleZipType(getGlobalSimpleZipType(), DeobfuscatedFile);
resourceDecrypterInfo.setSimpleZipType(getGlobalSimpleZipTypeMethod(), DeobfuscatedFile);
if (!decryptResources())
throw new ApplicationException("Could not decrypt resources");
@ -350,12 +356,12 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
return true;
}
TypeDefinition getGlobalSimpleZipType() {
if (assemblyResolverInfo.SimpleZipType != null)
return assemblyResolverInfo.SimpleZipType;
MethodDefinition getGlobalSimpleZipTypeMethod() {
if (assemblyResolverInfo.SimpleZipTypeMethod != null)
return assemblyResolverInfo.SimpleZipTypeMethod;
foreach (var info in stringDecrypterInfos) {
if (info.SimpleZipType != null)
return info.SimpleZipType;
if (info.SimpleZipTypeMethod != null)
return info.SimpleZipTypeMethod;
}
return null;
}
@ -383,7 +389,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
if (initd.ContainsKey(info))
continue;
if (info.init(this, DeobfuscatedFile)) {
resourceDecrypterInfo.setSimpleZipType(info.SimpleZipType, DeobfuscatedFile);
resourceDecrypterInfo.setSimpleZipType(info.SimpleZipTypeMethod, DeobfuscatedFile);
initdInfo = info;
break;
}
@ -436,7 +442,8 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
}
public override void deobfuscateEnd() {
removeProxyDelegates(proxyDelegateFinder);
canRemoveTypes = findBigType() == null;
removeProxyDelegates(proxyDelegateFinder, canRemoveTypes);
removeMemoryManagerStuff();
removeTamperProtectionStuff();
removeStringDecryptionStuff();
@ -445,7 +452,37 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
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) {
if (!canRemoveTypes)
return;
addTypeToBeRemoved(info.CallResolverType, string.Format("{0} resolver type #1", typeName));
addTypeToBeRemoved(info.Type, string.Format("{0} resolver type #2", typeName));
}
@ -453,7 +490,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
void removeAutomatedErrorReportingCode(Blocks blocks) {
if (!options.RemoveAutomatedErrorReporting)
return;
if (automatedErrorReportingFinder.ExceptionLoggerRemover.remove(blocks))
if (automatedErrorReportingFinder.remove(blocks))
Log.v("Removed Automated Error Reporting code");
}
@ -465,7 +502,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
}
void removeMemoryManagerStuff() {
if (!options.RemoveMemoryManager)
if (!canRemoveTypes || !options.RemoveMemoryManager)
return;
addTypeToBeRemoved(memoryManagerInfo.Type, "Memory manager type");
}
@ -489,9 +526,11 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
addResourceToBeRemoved(info.StringsResource, "Encrypted strings");
addFieldsToBeRemoved(info.getAllStringDelegateFields(), "String decrypter delegate field");
addTypeToBeRemoved(info.StringsEncodingClass, "String decrypter type");
addTypeToBeRemoved(info.StringsType, "Creates the string decrypter delegates");
addTypeToBeRemoved(info.GetStringDelegate, "String decrypter delegate type");
if (canRemoveTypes) {
addTypeToBeRemoved(info.StringsEncodingClass, "String decrypter type");
addTypeToBeRemoved(info.StringsType, "Creates the string decrypter delegates");
addTypeToBeRemoved(info.GetStringDelegate, "String decrypter delegate type");
}
}
}

View File

@ -40,10 +40,9 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
public MemoryManagerInfo(ModuleDefinition module) {
this.module = module;
find();
}
bool find() {
public bool find() {
if (checkCalledMethods(DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor")))
return true;
if (checkCalledMethods(module.EntryPoint))

View File

@ -112,7 +112,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
if (mostCalls == null)
return;
setDelegateCreatorMethod(DotNetUtils.getMethod(DotNetUtils.getType(module, mostCalls.DeclaringType), mostCalls));
setDelegateCreatorMethod(DotNetUtils.getMethod(module, mostCalls));
}
}
}

View File

@ -28,7 +28,6 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
ISimpleDeobfuscator simpleDeobfuscator;
IDeobfuscator deob;
TypeDefinition resolverType;
TypeDefinition callResolverType;
MethodDefinition callResolverMethod;
public TypeDefinition Type {
@ -36,7 +35,13 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
}
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 {
@ -70,26 +75,17 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
continue;
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
continue;
if (checkAttachAppType(tuple.Item1, method))
if (checkAttachAppMethod(method))
return true;
}
return false;
}
bool checkAttachAppType(TypeDefinition type, MethodDefinition attachAppMethod) {
callResolverType = null;
bool checkAttachAppMethod(MethodDefinition attachAppMethod) {
callResolverMethod = null;
if (!attachAppMethod.HasBody)
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)) {
var method = tuple.Item2;
@ -97,26 +93,25 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
continue;
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
continue;
if (!checkResolverType(tuple.Item1, method))
if (!checkResolverInitMethod(method))
continue;
callResolverMethod = attachAppMethod;
callResolverType = type;
return true;
}
if (hasLdftn(attachAppMethod)) {
simpleDeobfuscator.deobfuscate(attachAppMethod);
foreach (var resolverHandler in getResolverHandlers(type, attachAppMethod)) {
foreach (var resolverHandler in getResolverHandlers(attachAppMethod)) {
if (!resolverHandler.HasBody)
continue;
if (!checkResolverType2(resolverHandler.DeclaringType))
var resolverTypeTmp = getResolverType(resolverHandler);
if (resolverTypeTmp == null)
continue;
deobfuscate(resolverHandler);
if (checkHandlerMethod(resolverHandler)) {
callResolverMethod = attachAppMethod;
callResolverType = type;
resolverType = resolverHandler.DeclaringType;
resolverType = resolverTypeTmp;
return true;
}
}
@ -135,27 +130,21 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
return false;
}
bool checkResolverType2(TypeDefinition type) {
if (type.Properties.Count > 1 || type.Events.Count > 0)
return false;
if (!checkResolverType(type))
return false;
return true;
}
bool checkResolverType(TypeDefinition type, MethodDefinition initMethod) {
bool checkResolverInitMethod(MethodDefinition initMethod) {
resolverType = null;
if (!initMethod.HasBody)
return false;
if (!checkResolverType2(type))
return false;
deobfuscate(initMethod);
foreach (var handlerDef in getResolverHandlers(type, initMethod)) {
foreach (var handlerDef in getResolverHandlers(initMethod)) {
deobfuscate(handlerDef);
var resolverTypeTmp = getResolverType(handlerDef);
if (resolverTypeTmp == null)
continue;
if (checkHandlerMethod(handlerDef)) {
resolverType = type;
resolverType = resolverTypeTmp;
return true;
}
}
@ -168,10 +157,31 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
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 checkHandlerMethod(MethodDefinition handler);
static IEnumerable<MethodDefinition> getResolverHandlers(TypeDefinition type, MethodDefinition method) {
IEnumerable<MethodDefinition> getResolverHandlers(MethodDefinition method) {
int numHandlers = 0;
var instructions = method.Body.Instructions;
for (int i = 0; i < instructions.Count; i++) {
@ -184,7 +194,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
continue;
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)
continue;
@ -204,5 +214,18 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
if (numHandlers == 0)
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;
}
}
}

View File

@ -25,7 +25,7 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.SmartAssembly {
class ResourceDecrypterInfo {
ModuleDefinition module;
TypeDefinition simpleZipType;
MethodDefinition simpleZipTypeDecryptMethod;
public byte[] DES_Key { get; private set; }
public byte[] DES_IV { get; private set; }
@ -33,56 +33,52 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
public byte[] AES_IV { get; private set; }
public bool CanDecrypt {
get { return simpleZipType != null; }
get { return simpleZipTypeDecryptMethod != null; }
}
public ResourceDecrypterInfo(ModuleDefinition module) {
this.module = module;
}
public ResourceDecrypterInfo(ModuleDefinition module, TypeDefinition simpleZipType, ISimpleDeobfuscator simpleDeobfuscator)
public ResourceDecrypterInfo(ModuleDefinition module, MethodDefinition simpleZipTypeDecryptMethod, ISimpleDeobfuscator simpleDeobfuscator)
: this(module) {
setSimpleZipType(simpleZipType, simpleDeobfuscator);
setSimpleZipType(simpleZipTypeDecryptMethod, simpleDeobfuscator);
}
public void setSimpleZipType(TypeDefinition type, ISimpleDeobfuscator simpleDeobfuscator) {
if (simpleZipType != null || type == null)
public void setSimpleZipType(MethodDefinition method, ISimpleDeobfuscator simpleDeobfuscator) {
if (simpleZipTypeDecryptMethod != null || method == null)
return;
simpleZipType = type;
init(simpleDeobfuscator);
simpleZipTypeDecryptMethod = method;
init(simpleDeobfuscator, method);
}
void init(ISimpleDeobfuscator simpleDeobfuscator) {
void init(ISimpleDeobfuscator simpleDeobfuscator, MethodDefinition method) {
var desList = 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;
simpleDeobfuscator.deobfuscate(method);
for (int i = 0; i <= instructions.Count - 2; i++) {
var ldtoken = instructions[i];
if (ldtoken.OpCode.Code != Code.Ldtoken)
continue;
var field = DotNetUtils.getField(module, ldtoken.Operand as FieldReference);
if (field == null)
continue;
if (field.InitialValue == null)
continue;
var instructions = method.Body.Instructions;
simpleDeobfuscator.deobfuscate(method);
for (int i = 0; i <= instructions.Count - 2; i++) {
var ldtoken = instructions[i];
if (ldtoken.OpCode.Code != Code.Ldtoken)
continue;
var field = DotNetUtils.getField(module, ldtoken.Operand as FieldReference);
if (field == null)
continue;
if (field.InitialValue == null)
continue;
var call = instructions[i + 1];
if (call.OpCode.Code != Code.Call)
continue;
var calledMethod = call.Operand as MethodReference;
if (!DotNetUtils.isMethod(calledMethod, "System.Void", "(System.Array,System.RuntimeFieldHandle)"))
continue;
var call = instructions[i + 1];
if (call.OpCode.Code != Code.Call)
continue;
var calledMethod = call.Operand as MethodReference;
if (!DotNetUtils.isMethod(calledMethod, "System.Void", "(System.Array,System.RuntimeFieldHandle)"))
continue;
if (field.InitialValue.Length == 8)
desList.Add(field.InitialValue);
else if (field.InitialValue.Length == 16)
aesList.Add(field.InitialValue);
}
}
if (field.InitialValue.Length == 8)
desList.Add(field.InitialValue);
else if (field.InitialValue.Length == 16)
aesList.Add(field.InitialValue);
}
if (desList.Count >= 2) {

View File

@ -23,18 +23,17 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.SmartAssembly {
class SimpleZipInfo {
public static bool isSimpleZipDecryptMethod_QuickCheck(ModuleDefinition module, MethodReference method, out TypeDefinition simpleZipType) {
simpleZipType = null;
public static bool isSimpleZipDecryptMethod_QuickCheck(ModuleDefinition module, MethodReference method, out MethodDefinition simpleZipTypeMethod) {
simpleZipTypeMethod = null;
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[])"))
return false;
var type = DotNetUtils.getType(module, method.DeclaringType);
var methodDef = DotNetUtils.getMethod(type, method);
var methodDef = DotNetUtils.getMethod(DotNetUtils.getType(module, method.DeclaringType), method);
if (methodDef == null)
return false;
simpleZipType = type;
simpleZipTypeMethod = methodDef;
return true;
}
}

View File

@ -38,7 +38,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
TypeDefinition stringsEncodingClass;
EmbeddedResource stringsResource;
int stringOffset;
TypeDefinition simpleZipType;
MethodDefinition simpleZipTypeMethod;
MethodDefinition stringDecrypterMethod;
StringDecrypterVersion decrypterVersion;
@ -58,8 +58,8 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
get { return resourceDecrypter == null || resourceDecrypter.CanDecrypt; }
}
public TypeDefinition SimpleZipType {
get { return simpleZipType; }
public MethodDefinition SimpleZipTypeMethod {
get { return simpleZipTypeMethod; }
}
public EmbeddedResource StringsResource {
@ -71,7 +71,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
}
public bool StringsEncrypted {
get { return simpleZipType != null; }
get { return simpleZipTypeMethod != null; }
}
public MethodDefinition StringDecrypterMethod {
@ -148,9 +148,9 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
decrypterVersion = StringDecrypterVersion.V4;
}
simpleZipType = findSimpleZipType(cctor) ?? findSimpleZipType(stringDecrypterMethod);
if (simpleZipType != null)
resourceDecrypter = new ResourceDecrypter(new ResourceDecrypterInfo(module, simpleZipType, simpleDeobfuscator));
simpleZipTypeMethod = findSimpleZipTypeMethod(cctor) ?? findSimpleZipTypeMethod(stringDecrypterMethod);
if (simpleZipTypeMethod != null)
resourceDecrypter = new ResourceDecrypter(new ResourceDecrypterInfo(module, simpleZipTypeMethod, simpleDeobfuscator));
return true;
}
@ -292,9 +292,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
return true;
}
// Find SmartAssembly.Zip.SimpleZip, which is the class that decrypts and inflates
// data in the resources.
TypeDefinition findSimpleZipType(MethodDefinition method) {
MethodDefinition findSimpleZipTypeMethod(MethodDefinition method) {
if (method == null || method.Body == null)
return null;
var instructions = method.Body.Instructions;
@ -302,7 +300,9 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
var call = instructions[i];
if (call.OpCode.Code != Code.Call)
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[])"))
continue;
@ -315,11 +315,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
if (!MemberReferenceHelper.compareTypes(stringsEncodingClass, field.DeclaringType))
continue;
var type = DotNetUtils.getType(module, calledMethod.DeclaringType);
if (type == null)
continue;
return type;
return calledMethod;
}
return null;

View File

@ -607,18 +607,16 @@ namespace de4dot.code.renamer.asmmodules {
continue;
if (!resolvedAllInterfaces() || !resolvedBaseClasses())
continue;
string errMsg = string.Format(
"Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})",
Utils.removeNewlines(pair.Key.MethodDefinition),
pair.Key.MethodDefinition.MetadataToken.ToInt32(),
Utils.removeNewlines(TypeDefinition),
TypeDefinition.MetadataToken.ToInt32());
// Ignore if COM class
if (!TypeDefinition.IsImport &&
!hasAttribute("System.Runtime.InteropServices.ComImportAttribute") &&
!hasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute"))
throw new ApplicationException(errMsg);
Log.w("{0}", errMsg);
!hasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute")) {
Log.w("Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})",
Utils.removeNewlines(pair.Key.MethodDefinition),
pair.Key.MethodDefinition.MetadataToken.ToInt32(),
Utils.removeNewlines(TypeDefinition),
TypeDefinition.MetadataToken.ToInt32());
}
}
}

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]

View File

@ -30,5 +30,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.4.2.3405")]
[assembly: AssemblyFileVersion("1.4.2.3405")]
[assembly: AssemblyVersion("1.4.4.3405")]
[assembly: AssemblyFileVersion("1.4.4.3405")]