Skip to content

Commit

Permalink
Added support for Eazfuscator.NET 5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
saneki committed Aug 4, 2015
1 parent 828a1ab commit 94596d6
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 6 deletions.
2 changes: 1 addition & 1 deletion de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public override void DeobfuscateBegin() {
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();
Expand Down
58 changes: 54 additions & 4 deletions de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ class StringDecrypter : IDisposable {
StreamHelperType streamHelperType;
EfConstantsReader stringMethodConsts;
bool isV32OrLater;
bool isV50OrLater;
int? validStringDecrypterValue;
DynamicDynocodeIterator dynocode;
MethodDef realMethod;

class StreamHelperType {
public TypeDef type;
Expand Down Expand Up @@ -112,6 +114,18 @@ public bool Detected {
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;
Expand All @@ -135,8 +149,15 @@ public void Find() {
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;
}
Expand Down Expand Up @@ -211,9 +232,33 @@ static bool CheckDecrypterMethod(MethodDef method) {
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;
Expand Down Expand Up @@ -250,9 +295,14 @@ bool FindConstants(ISimpleDeobfuscator simpleDeobfuscator) {
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;
Expand Down
43 changes: 42 additions & 1 deletion de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,48 @@ public string Detect() {
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";
}
}

Expand Down

0 comments on commit 94596d6

Please sign in to comment.