Support CO obfuscated SL/CF assemblies
This commit is contained in:
parent
a0db68742f
commit
ce9add13cb
|
@ -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[] {
|
||||
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,11 +204,37 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
|||
constants.Add(flagValue);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user