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 desEncryptedFlag;
byte deflatedFlag; byte deflatedFlag;
byte bitwiseNotEncryptedFlag; byte bitwiseNotEncryptedFlag;
DotNetRuntimeType rtType;
public ResourceDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator) { public ResourceDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator) {
this.module = module; this.module = module;
rtType = DotNetUtils.getDotNetRuntimeType(module);
find(simpleDeobfuscator); find(simpleDeobfuscator);
} }
void find(ISimpleDeobfuscator simpleDeobfuscator) { void find(ISimpleDeobfuscator simpleDeobfuscator) {
var requiredTypes = new string[] { switch (rtType) {
"System.IO.MemoryStream", case DotNetRuntimeType.Desktop:
"System.Object", if (module.Runtime >= TargetRuntime.Net_2_0)
"System.Int32", 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; resourceDecrypterType = null;
foreach (var type in module.Types) { foreach (var type in module.Types) {
if (type.Fields.Count != 5) if (type.Fields.Count != 5)
@ -64,10 +90,9 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
continue; continue;
resourceDecrypterType = type; resourceDecrypterType = type;
break; return true;
} }
return false;
initializeDecrypterFlags(simpleDeobfuscator);
} }
bool checkCctor(MethodDefinition cctor) { bool checkCctor(MethodDefinition cctor) {
@ -85,8 +110,65 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return stsfldCount >= cctor.DeclaringType.Fields.Count; 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) { void initializeDecrypterFlags(ISimpleDeobfuscator simpleDeobfuscator) {
if (resourceDecrypterType != null && getPublicKeyTokenMethod() != null) { if (resourceDecrypterType != null) {
if (updateFlags(getDecrypterMethod(), simpleDeobfuscator)) if (updateFlags(getDecrypterMethod(), simpleDeobfuscator))
return; return;
} }
@ -122,10 +204,36 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
constants.Add(flagValue); constants.Add(flagValue);
} }
if (constants.Count == 2) { switch (rtType) {
desEncryptedFlag = (byte)constants[0]; case DotNetRuntimeType.Desktop:
deflatedFlag = (byte)constants[1]; if (module.Runtime >= TargetRuntime.Net_2_0) {
return true; 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; return false;
@ -139,39 +247,18 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return false; return false;
} }
MethodDefinition getPublicKeyTokenMethod() { MethodDefinition getDecrypterMethod() {
foreach (var method in resourceDecrypterType.Methods) { return getDecrypterMethod(resourceDecrypterType);
if (isPublicKeyTokenMethod(method))
return method;
}
return null;
} }
MethodDefinition getDecrypterMethod() { static MethodDefinition getDecrypterMethod(TypeDefinition type) {
foreach (var method in resourceDecrypterType.Methods) { foreach (var method in type.Methods) {
if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.IO.Stream)")) if (DotNetUtils.isMethod(method, "System.Byte[]", "(System.IO.Stream)"))
return method; return method;
} }
return null; 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) { public byte[] decrypt(Stream resourceStream) {
byte flags = (byte)resourceStream.ReadByte(); byte flags = (byte)resourceStream.ReadByte();
Stream sourceStream = resourceStream; Stream sourceStream = resourceStream;

View File

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

View File

@ -25,6 +25,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
ModuleDefinition module; ModuleDefinition module;
TypeDefinition tamperType; TypeDefinition tamperType;
MethodDefinition tamperMethod; MethodDefinition tamperMethod;
DotNetRuntimeType rtType;
public bool Detected { public bool Detected {
get { return tamperMethod != null; } get { return tamperMethod != null; }
@ -40,6 +41,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
public TamperDetection(ModuleDefinition module) { public TamperDetection(ModuleDefinition module) {
this.module = module; this.module = module;
rtType = DotNetUtils.getDotNetRuntimeType(module);
} }
public void find() { public void find() {
@ -54,30 +56,108 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return false; return false;
foreach (var info in DotNetUtils.getCalledMethods(module, methodToCheck)) { foreach (var info in DotNetUtils.getCalledMethods(module, methodToCheck)) {
var type = info.Item1;
var method = info.Item2; var method = info.Item2;
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()")) bool result = false;
continue; switch (rtType) {
if (type.Methods.Count < 3 || type.Methods.Count > 6) case DotNetRuntimeType.Desktop:
continue; result = findDesktop(method);
if (DotNetUtils.getPInvokeMethod(type, "mscoree", "StrongNameSignatureVerificationEx") != null) { break;
case DotNetRuntimeType.Silverlight:
result = findSilverlight(method);
break;
case DotNetRuntimeType.CompactFramework:
result = findCompactFramework(method);
break;
} }
else if (DotNetUtils.getPInvokeMethod(type, "mscoree", "CLRCreateInstance") != null) { if (!result)
if (type.NestedTypes.Count != 3)
continue;
if (!type.NestedTypes[0].IsInterface || !type.NestedTypes[1].IsInterface || !type.NestedTypes[2].IsInterface)
continue;
}
else
continue; continue;
tamperType = type; tamperType = method.DeclaringType;
tamperMethod = method; tamperMethod = method;
return true; return true;
} }
return false; 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;
}
} }
} }