Support CO obfuscated SL/CF assemblies

This commit is contained in:
de4dot 2012-03-15 22:36:23 +01:00
parent a0db68742f
commit ce9add13cb
3 changed files with 222 additions and 53 deletions

View File

@ -36,19 +36,45 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
byte desEncryptedFlag;
byte deflatedFlag;
byte bitwiseNotEncryptedFlag;
DotNetRuntimeType rtType;
public ResourceDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator) {
this.module = module;
rtType = DotNetUtils.getDotNetRuntimeType(module);
find(simpleDeobfuscator);
}
void find(ISimpleDeobfuscator simpleDeobfuscator) {
var requiredTypes = new string[] {
"System.IO.MemoryStream",
"System.Object",
"System.Int32",
};
switch (rtType) {
case DotNetRuntimeType.Desktop:
if (module.Runtime >= TargetRuntime.Net_2_0)
findDesktopOrCompactFramework();
else
findDesktopOrCompactFrameworkV1();
break;
case DotNetRuntimeType.Silverlight:
findSilverlight();
break;
case DotNetRuntimeType.CompactFramework:
if (module.Runtime >= TargetRuntime.Net_2_0) {
if (findDesktopOrCompactFramework())
break;
}
findDesktopOrCompactFrameworkV1();
break;
}
initializeDecrypterFlags(simpleDeobfuscator);
}
static string[] requiredTypes = new string[] {
"System.IO.MemoryStream",
"System.Object",
"System.Int32",
};
bool findDesktopOrCompactFramework() {
resourceDecrypterType = null;
foreach (var type in module.Types) {
if (type.Fields.Count != 5)
@ -64,10 +90,9 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
continue;
resourceDecrypterType = type;
break;
return true;
}
initializeDecrypterFlags(simpleDeobfuscator);
return false;
}
bool checkCctor(MethodDefinition cctor) {
@ -85,8 +110,65 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return stsfldCount >= cctor.DeclaringType.Fields.Count;
}
static string[] requiredLocals_v1 = new string[] {
"System.Boolean",
"System.Byte",
"System.Byte[]",
"System.Int32",
"System.Security.Cryptography.DESCryptoServiceProvider",
};
bool findDesktopOrCompactFrameworkV1() {
resourceDecrypterType = null;
foreach (var type in module.Types) {
if (type.Fields.Count != 0)
continue;
var method = getDecrypterMethod(type);
if (method == null)
continue;
if (!new LocalTypes(method).exactly(requiredLocals_v1))
continue;
if (!DotNetUtils.callsMethod(method, "System.Int64", "()"))
continue;
if (!DotNetUtils.callsMethod(method, "System.Int32", "(System.Byte[],System.Int32,System.Int32)"))
continue;
if (!DotNetUtils.callsMethod(method, "System.Void", "(System.Array,System.Int32,System.Array,System.Int32,System.Int32)"))
continue;
if (!DotNetUtils.callsMethod(method, "System.Security.Cryptography.ICryptoTransform", "()"))
continue;
if (!DotNetUtils.callsMethod(method, "System.Byte[]", "(System.Byte[],System.Int32,System.Int32)"))
continue;
resourceDecrypterType = type;
return true;
}
return false;
}
static string[] requiredLocals_sl = new string[] {
"System.Byte",
"System.Byte[]",
"System.Int32",
};
void findSilverlight() {
foreach (var type in module.Types) {
if (type.Fields.Count > 0)
continue;
if (type.HasNestedTypes || type.HasGenericParameters)
continue;
var method = getDecrypterMethod(type);
if (method == null)
continue;
if (!new LocalTypes(method).exactly(requiredLocals_sl))
continue;
resourceDecrypterType = type;
break;
}
}
void initializeDecrypterFlags(ISimpleDeobfuscator simpleDeobfuscator) {
if (resourceDecrypterType != null && getPublicKeyTokenMethod() != null) {
if (resourceDecrypterType != null) {
if (updateFlags(getDecrypterMethod(), simpleDeobfuscator))
return;
}
@ -122,10 +204,36 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
constants.Add(flagValue);
}
if (constants.Count == 2) {
desEncryptedFlag = (byte)constants[0];
deflatedFlag = (byte)constants[1];
return true;
switch (rtType) {
case DotNetRuntimeType.Desktop:
if (module.Runtime >= TargetRuntime.Net_2_0) {
if (constants.Count == 2) {
desEncryptedFlag = (byte)constants[0];
deflatedFlag = (byte)constants[1];
return true;
}
}
else {
if (constants.Count == 1) {
desEncryptedFlag = (byte)constants[0];
return true;
}
}
break;
case DotNetRuntimeType.Silverlight:
if (constants.Count == 1) {
bitwiseNotEncryptedFlag = (byte)constants[0];
return true;
}
break;
case DotNetRuntimeType.CompactFramework:
if (constants.Count == 1) {
desEncryptedFlag = (byte)constants[0];
return true;
}
break;
}
return false;
@ -139,39 +247,18 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return false;
}
MethodDefinition getPublicKeyTokenMethod() {
foreach (var method in resourceDecrypterType.Methods) {
if (isPublicKeyTokenMethod(method))
return method;
}
return null;
MethodDefinition getDecrypterMethod() {
return getDecrypterMethod(resourceDecrypterType);
}
MethodDefinition getDecrypterMethod() {
foreach (var method in resourceDecrypterType.Methods) {
static MethodDefinition getDecrypterMethod(TypeDefinition type) {
foreach (var method in type.Methods) {
if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.IO.Stream)"))
return method;
}
return null;
}
bool isPublicKeyTokenMethod(MethodDefinition method) {
if (!method.IsStatic)
return false;
if (method.Body == null)
return false;
if (method.Body.ExceptionHandlers.Count < 1)
return false;
if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Reflection.Assembly)"))
return false;
foreach (var s in DotNetUtils.getCodeStrings(method)) {
if (s.ToLowerInvariant() == "publickeytoken=")
return true;
}
return false;
}
public byte[] decrypt(Stream resourceStream) {
byte flags = (byte)resourceStream.ReadByte();
Stream sourceStream = resourceStream;

View File

@ -81,6 +81,8 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return defaultName;
foreach (var s in DotNetUtils.getCodeStrings(cctor)) {
if (DotNetUtils.getResource(module, s) != null)
return s;
try {
return Encoding.UTF8.GetString(Convert.FromBase64String(s));
}
@ -107,7 +109,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
continue;
if (DotNetUtils.findFieldType(type, "System.Byte[]", true) == null)
continue;
if (type.Methods.Count != 3)
if (type.Methods.Count != 2 && type.Methods.Count != 3)
continue;
if (type.NestedTypes.Count > 0)
continue;

View File

@ -25,6 +25,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
ModuleDefinition module;
TypeDefinition tamperType;
MethodDefinition tamperMethod;
DotNetRuntimeType rtType;
public bool Detected {
get { return tamperMethod != null; }
@ -40,6 +41,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
public TamperDetection(ModuleDefinition module) {
this.module = module;
rtType = DotNetUtils.getDotNetRuntimeType(module);
}
public void find() {
@ -54,30 +56,108 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return false;
foreach (var info in DotNetUtils.getCalledMethods(module, methodToCheck)) {
var type = info.Item1;
var method = info.Item2;
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
continue;
if (type.Methods.Count < 3 || type.Methods.Count > 6)
continue;
if (DotNetUtils.getPInvokeMethod(type, "mscoree", "StrongNameSignatureVerificationEx") != null) {
bool result = false;
switch (rtType) {
case DotNetRuntimeType.Desktop:
result = findDesktop(method);
break;
case DotNetRuntimeType.Silverlight:
result = findSilverlight(method);
break;
case DotNetRuntimeType.CompactFramework:
result = findCompactFramework(method);
break;
}
else if (DotNetUtils.getPInvokeMethod(type, "mscoree", "CLRCreateInstance") != null) {
if (type.NestedTypes.Count != 3)
continue;
if (!type.NestedTypes[0].IsInterface || !type.NestedTypes[1].IsInterface || !type.NestedTypes[2].IsInterface)
continue;
}
else
if (!result)
continue;
tamperType = type;
tamperType = method.DeclaringType;
tamperMethod = method;
return true;
}
return false;
}
bool findDesktop(MethodDefinition method) {
var type = method.DeclaringType;
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
return false;
if (type.Methods.Count < 3 || type.Methods.Count > 6)
return false;
if (DotNetUtils.getPInvokeMethod(type, "mscoree", "StrongNameSignatureVerificationEx") != null) {
}
else if (DotNetUtils.getPInvokeMethod(type, "mscoree", "CLRCreateInstance") != null) {
if (type.NestedTypes.Count != 3)
return false;
if (!type.NestedTypes[0].IsInterface || !type.NestedTypes[1].IsInterface || !type.NestedTypes[2].IsInterface)
return false;
}
else
return false;
return true;
}
static string[] requiredLocals_sl = new string[] {
"System.Boolean",
"System.Byte[]",
"System.Int32",
"System.Reflection.AssemblyName",
"System.String",
};
bool findSilverlight(MethodDefinition method) {
if (!new LocalTypes(method).exactly(requiredLocals_sl))
return false;
if (!DotNetUtils.callsMethod(method, "System.Int32 System.String::get_Length()"))
return false;
if (!DotNetUtils.callsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)"))
return false;
if (!DotNetUtils.callsMethod(method, "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()"))
return false;
if (!DotNetUtils.callsMethod(method, "System.String System.Reflection.Assembly::get_FullName()"))
return false;
if (!DotNetUtils.callsMethod(method, "System.Byte[] System.Reflection.AssemblyName::GetPublicKeyToken()"))
return false;
if (DotNetUtils.callsMethod(method, "System.String", "(System.Reflection.Assembly)")) {
}
else if (DotNetUtils.callsMethod(method, "System.String System.Reflection.AssemblyName::get_Name()")) {
}
else
return false;
return true;
}
static string[] requiredLocals_cf = new string[] {
"System.Boolean",
"System.Byte[]",
"System.Int32",
"System.String",
};
bool findCompactFramework(MethodDefinition method) {
if (!new LocalTypes(method).exactly(requiredLocals_cf))
return false;
if (!DotNetUtils.callsMethod(method, "System.Int32 System.String::get_Length()"))
return false;
if (!DotNetUtils.callsMethod(method, "System.Byte[] System.Convert::FromBase64String(System.String)"))
return false;
if (!DotNetUtils.callsMethod(method, "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()"))
return false;
if (DotNetUtils.callsMethod(method, "System.Byte[]", "(System.Reflection.Assembly)") &&
DotNetUtils.callsMethod(method, "System.String", "(System.Reflection.Assembly)")) {
}
else if (DotNetUtils.callsMethod(method, "System.Reflection.AssemblyName System.Reflection.Assembly::GetName()") &&
DotNetUtils.callsMethod(method, "System.Byte[] System.Reflection.AssemblyName::GetPublicKeyToken()")) {
}
else
return false;
return true;
}
}
}