Support EF 3.3

This commit is contained in:
de4dot 2012-03-06 08:17:55 +01:00
parent 5c943d759d
commit b4525ed58d
3 changed files with 291 additions and 28 deletions

View File

@ -30,7 +30,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
MethodDefinition int64Method;
bool initialized;
ulong l1;
int i1, i2;
int i1, i2, i3;
int m1_i1, m2_i1, m2_i2, m3_i1;
int token1, token2, token3, token4, token5, token6;
@ -56,9 +56,9 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
if (int64Method == null)
return false;
if (!findInt1())
if (!findInt1And2())
return false;
if (!findInt2())
if (!findInt3())
return false;
if (!findMethodInts())
return false;
@ -110,19 +110,20 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
return false;
}
bool findInt1() {
bool findInt1And2() {
var consts = getConstants(findNestedTypeMethod(1294352278));
if (consts.Count != 2)
return false;
i1 = consts[1];
i1 = consts[0];
i2 = consts[1];
return true;
}
bool findInt2() {
bool findInt3() {
var consts = getConstants(findNestedTypeMethod(1106695601));
if (consts.Count != 1)
return false;
i2 = consts[0];
i3 = consts[0];
return true;
}
@ -277,7 +278,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
}
int constMethod3() {
return binOp3(binOp1(constMethod2() ^ 0x1F74F46E, token4), binOp2(token1 ^ token6, i1));
return binOp3(binOp1(constMethod2() ^ i1, token4), binOp2(token1 ^ token6, i2));
}
int constMethod4() {
@ -289,7 +290,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
}
int constMethod6() {
return binOp1(token6, binOp3(binOp2(token5, token1), binOp3(token3 ^ i2, constMethod5())));
return binOp1(token6, binOp3(binOp2(token5, token1), binOp3(token3 ^ i3, constMethod5())));
}
public ulong getMagic() {

View File

@ -40,6 +40,37 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
EmbeddedResource encryptedResource;
BinaryReader reader;
DecrypterType decrypterType;
StreamHelperType streamHelperType;
class StreamHelperType {
public TypeDefinition type;
public MethodDefinition readInt16Method;
public MethodDefinition readInt32Method;
public MethodDefinition readBytesMethod;
public bool Detected {
get {
return readInt16Method != null &&
readInt32Method != null &&
readBytesMethod != null;
}
}
public StreamHelperType(TypeDefinition type) {
this.type = type;
foreach (var method in type.Methods) {
if (method.IsStatic || method.Body == null || method.IsPrivate || method.GenericParameters.Count > 0)
continue;
if (DotNetUtils.isMethod(method, "System.Int16", "()"))
readInt16Method = method;
else if (DotNetUtils.isMethod(method, "System.Int32", "()"))
readInt32Method = method;
else if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.Int32)"))
readBytesMethod = method;
}
}
}
public TypeDefinition Type {
get { return stringType; }
@ -73,9 +104,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
public void find() {
foreach (var type in module.Types) {
if (DotNetUtils.findFieldType(type, "System.IO.BinaryReader", true) == null)
continue;
if (DotNetUtils.findFieldType(type, "System.Collections.Generic.Dictionary`2<System.Int32,System.String>", true) == null)
if (!checkType(type))
continue;
foreach (var method in type.Methods) {
@ -89,6 +118,44 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
}
}
bool checkType(TypeDefinition type) {
if (type.NestedTypes.Count == 0) {
return DotNetUtils.findFieldType(type, "System.IO.BinaryReader", true) != null &&
DotNetUtils.findFieldType(type, "System.Collections.Generic.Dictionary`2<System.Int32,System.String>", true) != null;
}
else if (type.NestedTypes.Count == 3) {
streamHelperType = findStreamHelperType(type);
return streamHelperType != null;
}
else if (type.NestedTypes.Count == 1) {
return type.NestedTypes[0].IsEnum;
}
else
return false;
}
static string[] streamHelperTypeFields = new string[] {
"System.IO.Stream",
"System.Byte[]",
};
static StreamHelperType findStreamHelperType(TypeDefinition type) {
foreach (var field in type.Fields) {
var nested = field.FieldType as TypeDefinition;
if (nested == null)
continue;
if (nested.DeclaringType != type)
continue;
if (!new FieldTypes(nested).exactly(streamHelperTypeFields))
continue;
var streamHelperType = new StreamHelperType(nested);
if (!streamHelperType.Detected)
continue;
return streamHelperType;
}
return null;
}
static bool checkDecrypterMethod(MethodDefinition method) {
if (method == null || !method.IsStatic || method.Body == null)
return false;
@ -144,8 +211,17 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
return false;
if (decrypterType.Detected) {
if (!findInts(stringMethod))
bool initializedAll;
if (!findInts(stringMethod, out initializedAll))
return false;
var cctor = DotNetUtils.getMethod(stringType, ".cctor");
if (!initializedAll && cctor != null) {
simpleDeobfuscator.deobfuscate(cctor);
if (!findIntsCctor(cctor))
return false;
}
if (!decrypterType.initialize())
return false;
}
@ -315,19 +391,61 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
return EfUtils.getInt16(method, ref index, ref s);
}
bool findInts(MethodDefinition method) {
int index = findIndexFirstIntegerConstant(method);
if (index < 0)
bool findInts(MethodDefinition method, out bool initializedAll) {
initializedAll = false;
// <= 3.2
int index = findIndexInt64Method_v1(method);
if (index >= 0) {
if (!EfUtils.getNextInt32(method, ref index, out i1))
return false;
int tmp;
if (!EfUtils.getNextInt32(method, ref index, out tmp))
return false;
if (!EfUtils.getNextInt32(method, ref index, out i2))
return false;
initializedAll = true;
return true;
}
// 3.3
index = findIndexInt64Method_v2(method);
if (index >= 0) {
if (!EfUtils.getNextInt32(method, ref index, out i2))
return false;
return true;
}
return false;
}
bool findIntsCctor(MethodDefinition cctor) {
int index = 0;
if (!findCallGetFrame(cctor, ref index))
return false;
if (!EfUtils.getNextInt32(method, ref index, out i1))
int tmp1, tmp2, tmp3;
if (!EfUtils.getNextInt32(cctor, ref index, out tmp1))
return false;
int tmp;
if (!EfUtils.getNextInt32(method, ref index, out tmp))
return false;
if (!EfUtils.getNextInt32(method, ref index, out i2))
if (!EfUtils.getNextInt32(cctor, ref index, out tmp2))
return false;
index = 0;
while (true) {
if (!EfUtils.getNextInt32(cctor, ref index, out tmp3))
return false;
int nextIndex = index;
int tmp4;
if (!EfUtils.getNextInt32(cctor, ref index, out tmp4))
return false;
if (tmp4 == 16)
break;
index = nextIndex;
}
i1 = tmp1 ^ tmp2 ^ tmp3;
return true;
}
@ -424,7 +542,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
}
}
static int findIndexFirstIntegerConstant(MethodDefinition method) {
static int findIndexInt64Method_v1(MethodDefinition method) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 2; i++) {
var ldci4 = instrs[i];
@ -450,21 +568,42 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
return -1;
}
static int findIndexInt64Method_v2(MethodDefinition method) {
var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) {
var call = instrs[i];
if (call.OpCode.Code != Code.Call)
continue;
var calledMethod = call.Operand as MethodDefinition;
if (calledMethod == null)
continue;
if (!DotNetUtils.isMethod(calledMethod, "System.Int64", "()"))
continue;
return i;
}
return -1;
}
static bool callsGetPublicKeyToken(MethodDefinition method) {
int index = 0;
return findCall(method, ref index, "System.Byte[] System.Reflection.AssemblyName::GetPublicKeyToken()");
}
static bool findCallReadInt16(MethodDefinition method, ref int index) {
return findCall(method, ref index, "System.Int16 System.IO.BinaryReader::ReadInt16()");
bool findCallReadInt16(MethodDefinition method, ref int index) {
return findCall(method, ref index, streamHelperType == null ? "System.Int16 System.IO.BinaryReader::ReadInt16()" : streamHelperType.readInt16Method.FullName);
}
static bool findCallReadInt32(MethodDefinition method, ref int index) {
return findCall(method, ref index, "System.Int32 System.IO.BinaryReader::ReadInt32()");
bool findCallReadInt32(MethodDefinition method, ref int index) {
return findCall(method, ref index, streamHelperType == null ? "System.Int32 System.IO.BinaryReader::ReadInt32()" : streamHelperType.readInt32Method.FullName);
}
static bool findCallReadBytes(MethodDefinition method, ref int index) {
return findCall(method, ref index, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)");
bool findCallReadBytes(MethodDefinition method, ref int index) {
return findCall(method, ref index, streamHelperType == null ? "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)" : streamHelperType.readBytesMethod.FullName);
}
static bool findCallGetFrame(MethodDefinition method, ref int index) {
return findCall(method, ref index, "System.Diagnostics.StackFrame System.Diagnostics.StackTrace::GetFrame(System.Int32)");
}
static bool findCall(MethodDefinition method, ref int index, string methodFullName) {

View File

@ -71,6 +71,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.String",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
!decryptStringMethod.NoInlining &&
decryptStringMethod.IsPublic &&
@ -106,6 +107,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.String",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
!decryptStringMethod.NoInlining &&
decryptStringMethod.IsPublic &&
@ -141,6 +143,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.String",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
!decryptStringMethod.NoInlining &&
decryptStringMethod.IsPublic &&
@ -177,6 +180,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.String",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
!decryptStringMethod.NoInlining &&
decryptStringMethod.IsPublic &&
@ -214,6 +218,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.String",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
!decryptStringMethod.NoInlining &&
decryptStringMethod.IsPublic &&
@ -251,6 +256,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.String",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
decryptStringMethod.NoInlining &&
decryptStringMethod.IsPublic &&
@ -289,6 +295,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.String",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
decryptStringMethod.NoInlining &&
decryptStringMethod.IsAssembly &&
@ -331,6 +338,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.Type",
};
if (otherMethods.Count == 0 &&
decryptStringType.NestedTypes.Count == 0 &&
!hasConstantM2 &&
decryptStringMethod.NoInlining &&
decryptStringMethod.IsAssembly &&
@ -376,6 +384,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.Int32",
};
if (otherMethods.Count == 1 &&
decryptStringType.NestedTypes.Count == 0 &&
DotNetUtils.isMethod(otherMethods[0], "System.Int32", "(System.Byte[],System.Int32,System.Byte[])") &&
otherMethods[0].IsPrivate &&
otherMethods[0].IsStatic &&
@ -425,6 +434,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.Int32",
};
if (otherMethods.Count == 1 &&
decryptStringType.NestedTypes.Count == 0 &&
DotNetUtils.isMethod(otherMethods[0], "System.Int32", "(System.Byte[],System.Int32,System.Byte[])") &&
otherMethods[0].IsPrivate &&
otherMethods[0].IsStatic &&
@ -476,6 +486,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
"System.Int32",
};
if (otherMethods.Count == 1 &&
decryptStringType.NestedTypes.Count == 0 &&
DotNetUtils.isMethod(otherMethods[0], "System.Void", "(System.Byte[],System.Int32,System.Byte[])") &&
otherMethods[0].IsPrivate &&
otherMethods[0].IsStatic &&
@ -492,6 +503,118 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
return "3.2";
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
if (decryptStringType.NestedTypes.Count == 1) {
var fields33 = new string[] {
"System.Collections.Generic.Dictionary`2<System.Int32,System.String>",
"System.IO.BinaryReader",
"System.Byte[]",
"System.Int16",
"System.Int32",
"System.Byte[]",
"System.Int32",
"System.Int32",
decryptStringType.NestedTypes[0].FullName,
};
var locals33 = new string[] {
"System.Boolean",
"System.Byte",
"System.Byte[]",
"System.Char[]",
"System.Collections.Generic.Dictionary`2<System.Int32,System.String>",
"System.Diagnostics.StackFrame",
"System.Diagnostics.StackTrace",
"System.Int16",
"System.Int32",
"System.Int64",
"System.IO.Stream",
"System.Reflection.Assembly",
"System.Reflection.AssemblyName",
"System.Reflection.MethodBase",
"System.String",
"System.Type",
};
var olocals33 = new string[] {
"System.Int32",
};
if (otherMethods.Count == 1 &&
decryptStringType.NestedTypes.Count == 1 &&
DotNetUtils.isMethod(otherMethods[0], "System.Void", "(System.Byte[],System.Int32,System.Byte[])") &&
otherMethods[0].IsPrivate &&
otherMethods[0].IsStatic &&
new LocalTypes(otherMethods[0]).exactly(olocals33) &&
hasConstantM2 &&
decryptStringMethod.NoInlining &&
decryptStringMethod.IsAssembly &&
!decryptStringMethod.IsSynchronized &&
decryptStringMethod.Body.MaxStackSize >= 1 &&
decryptStringMethod.Body.MaxStackSize <= 8 &&
decryptStringMethod.Body.ExceptionHandlers.Count == 2 &&
new LocalTypes(decryptStringMethod).exactly(locals33) &&
checkTypeFields(fields33)) {
return "3.3.29 - 3.3.57 (BETA)";
}
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
if (decryptStringType.NestedTypes.Count == 3) {
var fields33 = new string[] {
decryptStringType.NestedTypes[0].FullName,
decryptStringType.NestedTypes[1].FullName,
"System.Byte[]",
"System.Int16",
"System.Int32",
"System.Byte[]",
"System.Int32",
"System.Int32",
decryptStringType.NestedTypes[2].FullName,
};
var locals33 = new string[] {
"System.Boolean",
"System.Byte",
"System.Byte[]",
"System.Char[]",
decryptStringType.NestedTypes[0].FullName,
"System.Diagnostics.StackFrame",
"System.Diagnostics.StackTrace",
"System.Int16",
"System.Int32",
"System.Int64",
"System.IO.Stream",
"System.Reflection.Assembly",
"System.Reflection.AssemblyName",
"System.Reflection.MethodBase",
"System.String",
"System.Type",
};
var olocals33 = new string[] {
"System.Int32",
};
if (otherMethods.Count == 1 &&
decryptStringType.NestedTypes.Count == 3 &&
DotNetUtils.isMethod(otherMethods[0], "System.Void", "(System.Byte[],System.Int32,System.Byte[])") &&
otherMethods[0].IsPrivate &&
otherMethods[0].IsStatic &&
new LocalTypes(otherMethods[0]).exactly(olocals33) &&
hasConstantM2 &&
decryptStringMethod.NoInlining &&
decryptStringMethod.IsAssembly &&
!decryptStringMethod.IsSynchronized &&
decryptStringMethod.Body.MaxStackSize >= 1 &&
decryptStringMethod.Body.MaxStackSize <= 8 &&
decryptStringMethod.Body.ExceptionHandlers.Count == 2 &&
new LocalTypes(decryptStringMethod).exactly(locals33) &&
checkTypeFields(fields33)) {
return "3.3";
}
}
return null;
}