Added support for Eazfuscator.NET 5.0

This commit is contained in:
saneki 2015-08-04 17:52:02 -05:00
parent 828a1ab398
commit 94596d6fb7
3 changed files with 97 additions and 6 deletions

View File

@ -118,7 +118,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
base.DeobfuscateBegin();
stringDecrypter.Initialize(DeobfuscatedFile);
staticStringInliner.Add(stringDecrypter.Method, (method2, gim, args) => {
staticStringInliner.Add(stringDecrypter.RealMethod, (method2, gim, args) => {
return stringDecrypter.Decrypt((int)args[0]);
});
DeobfuscatedFile.StringDecryptersAdded();

View File

@ -46,8 +46,10 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
StreamHelperType streamHelperType;
EfConstantsReader stringMethodConsts;
bool isV32OrLater;
bool isV50OrLater;
int? validStringDecrypterValue;
DynamicDynocodeIterator dynocode;
MethodDef realMethod;
class StreamHelperType {
public TypeDef type;
@ -112,6 +114,18 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
get { return stringType != null; }
}
/// <summary>
/// In 5.0, the actual string decrypter method doesn't do much, calls a helper method which
/// does most of the work (and is mostly the same as the stringMethod from 4.9 and below).
/// </summary>
public bool HasRealMethod {
get { return realMethod != null; }
}
public MethodDef RealMethod {
get { return (realMethod != null ? realMethod : stringMethod); }
}
public StringDecrypter(ModuleDefMD module, DecrypterType decrypterType) {
this.module = module;
this.decrypterType = decrypterType;
@ -135,8 +149,15 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
if (!CheckDecrypterMethod(method))
continue;
// 5.0
if (CheckIfHelperMethod(method)) {
stringMethod = method;
realMethod = GetRealDecrypterMethod(method);
isV50OrLater = true;
}
else stringMethod = method;
stringType = type;
stringMethod = method;
isV32OrLater = CheckIfV32OrLater(stringType);
return;
}
@ -211,9 +232,33 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
if (calledMethod != null && calledMethod.FullName == "System.IO.Stream System.Reflection.Assembly::GetManifestResourceStream(System.String)")
return true;
}
return false;
}
/// <remarks>5.0</remarks>
static bool CheckIfHelperMethod(MethodDef method) {
// Helper method will be `private static`, instead of `internal static`
return method.DeclaringType.Methods.Count == 4 && !method.IsAssembly;
}
/// <summary>
/// Get the real decrypter method from a found helper method.
/// </summary>
/// <remarks>5.0</remarks>
static MethodDef GetRealDecrypterMethod(MethodDef helper) {
var methods = helper.DeclaringType.Methods;
var sigComparer = new SigComparer();
foreach (var method in methods) {
if (method.MDToken != helper.MDToken &&
method.IsAssembly &&
sigComparer.Equals(method.MethodSig, helper.MethodSig))
return method;
}
return null;
}
public void Initialize(ISimpleDeobfuscator simpleDeobfuscator) {
if (stringType == null)
return;
@ -250,9 +295,14 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
return false;
if (checkMinus2 && !FindInt5())
return false;
dataDecrypterType = FindDataDecrypterType(stringMethod);
if (dataDecrypterType == null)
return false;
// The method body of the data decrypter method has been moved into
// the string decrypter helper method in 5.0
if (!isV50OrLater) {
dataDecrypterType = FindDataDecrypterType(stringMethod);
if (dataDecrypterType == null)
return false;
}
if (isV32OrLater) {
bool initializedAll;

View File

@ -777,7 +777,48 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
decryptStringMethod.Body.ExceptionHandlers.Count >= 2 &&
new LocalTypes(decryptStringMethod).All(locals43) &&
CheckTypeFields2(fields43)) {
return "4.3";
return "4.3 - 4.9";
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
var fields50 = new string[] {
GetNestedTypeName(0),
GetNestedTypeName(1),
"System.Byte[]",
"System.Int16",
"System.Int32",
"System.Byte[]",
"System.Int32",
"System.Int32",
GetNestedTypeName(2),
};
var locals50 = CreateLocalsArray(
// GetNestedTypeName(2) // One of the nested types is the first local (non-enum type)
"System.String",
"System.String"
);
var otherMethod50 = otherMethods.Find((m) => {
return DotNetUtils.IsMethod(m, "System.Void", "(System.Byte[],System.Int32,System.Byte[])");
});
decryptStringMethod = stringDecrypter.RealMethod;
if (stringDecrypter.HasRealMethod &&
otherMethods.Count == 2 &&
otherMethod50 != null &&
decryptStringType.NestedTypes.Count == 3 &&
otherMethod50.IsPrivate &&
otherMethod50.IsStatic &&
decryptStringMethod.IsNoInlining &&
decryptStringMethod.IsAssembly &&
!decryptStringMethod.IsSynchronized &&
decryptStringMethod.Body.MaxStack >= 1 &&
decryptStringMethod.Body.MaxStack <= 8 &&
decryptStringMethod.Body.ExceptionHandlers.Count == 1 &&
new LocalTypes(decryptStringMethod).All(locals50) &&
CheckTypeFields2(fields50)) {
return "5.0";
}
}