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 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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user