Merge pull request #110 from saneki/eaz_5
Added support for Eazfuscator.NET 5.0 (string decryption)
This commit is contained in:
commit
dfbbfc3fe0
|
@ -118,7 +118,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
base.DeobfuscateBegin();
|
base.DeobfuscateBegin();
|
||||||
|
|
||||||
stringDecrypter.Initialize(DeobfuscatedFile);
|
stringDecrypter.Initialize(DeobfuscatedFile);
|
||||||
staticStringInliner.Add(stringDecrypter.Method, (method2, gim, args) => {
|
staticStringInliner.Add(stringDecrypter.RealMethod, (method2, gim, args) => {
|
||||||
return stringDecrypter.Decrypt((int)args[0]);
|
return stringDecrypter.Decrypt((int)args[0]);
|
||||||
});
|
});
|
||||||
DeobfuscatedFile.StringDecryptersAdded();
|
DeobfuscatedFile.StringDecryptersAdded();
|
||||||
|
|
|
@ -46,8 +46,10 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
StreamHelperType streamHelperType;
|
StreamHelperType streamHelperType;
|
||||||
EfConstantsReader stringMethodConsts;
|
EfConstantsReader stringMethodConsts;
|
||||||
bool isV32OrLater;
|
bool isV32OrLater;
|
||||||
|
bool isV50OrLater;
|
||||||
int? validStringDecrypterValue;
|
int? validStringDecrypterValue;
|
||||||
DynamicDynocodeIterator dynocode;
|
DynamicDynocodeIterator dynocode;
|
||||||
|
MethodDef realMethod;
|
||||||
|
|
||||||
class StreamHelperType {
|
class StreamHelperType {
|
||||||
public TypeDef type;
|
public TypeDef type;
|
||||||
|
@ -112,6 +114,18 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
get { return stringType != null; }
|
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) {
|
public StringDecrypter(ModuleDefMD module, DecrypterType decrypterType) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.decrypterType = decrypterType;
|
this.decrypterType = decrypterType;
|
||||||
|
@ -135,8 +149,15 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
if (!CheckDecrypterMethod(method))
|
if (!CheckDecrypterMethod(method))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// 5.0
|
||||||
|
if (CheckIfHelperMethod(method)) {
|
||||||
|
stringMethod = method;
|
||||||
|
realMethod = GetRealDecrypterMethod(method);
|
||||||
|
isV50OrLater = true;
|
||||||
|
}
|
||||||
|
else stringMethod = method;
|
||||||
|
|
||||||
stringType = type;
|
stringType = type;
|
||||||
stringMethod = method;
|
|
||||||
isV32OrLater = CheckIfV32OrLater(stringType);
|
isV32OrLater = CheckIfV32OrLater(stringType);
|
||||||
return;
|
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)")
|
if (calledMethod != null && calledMethod.FullName == "System.IO.Stream System.Reflection.Assembly::GetManifestResourceStream(System.String)")
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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) {
|
public void Initialize(ISimpleDeobfuscator simpleDeobfuscator) {
|
||||||
if (stringType == null)
|
if (stringType == null)
|
||||||
return;
|
return;
|
||||||
|
@ -250,9 +295,14 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
return false;
|
return false;
|
||||||
if (checkMinus2 && !FindInt5())
|
if (checkMinus2 && !FindInt5())
|
||||||
return false;
|
return false;
|
||||||
dataDecrypterType = FindDataDecrypterType(stringMethod);
|
|
||||||
if (dataDecrypterType == null)
|
// The method body of the data decrypter method has been moved into
|
||||||
return false;
|
// the string decrypter helper method in 5.0
|
||||||
|
if (!isV50OrLater) {
|
||||||
|
dataDecrypterType = FindDataDecrypterType(stringMethod);
|
||||||
|
if (dataDecrypterType == null)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (isV32OrLater) {
|
if (isV32OrLater) {
|
||||||
bool initializedAll;
|
bool initializedAll;
|
||||||
|
|
|
@ -777,7 +777,48 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
|
||||||
decryptStringMethod.Body.ExceptionHandlers.Count >= 2 &&
|
decryptStringMethod.Body.ExceptionHandlers.Count >= 2 &&
|
||||||
new LocalTypes(decryptStringMethod).All(locals43) &&
|
new LocalTypes(decryptStringMethod).All(locals43) &&
|
||||||
CheckTypeFields2(fields43)) {
|
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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user