Update deobfuscator

This commit is contained in:
de4dot 2011-12-15 16:16:21 +01:00
parent 0b5d4d864c
commit 929d943112
7 changed files with 192 additions and 20 deletions

View File

@ -43,11 +43,16 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
}
public void find() {
var mainMethod = module.EntryPoint;
if (mainMethod == null)
if (find(module.EntryPoint))
return;
if (find(DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor")))
return;
}
foreach (var info in DotNetUtils.getCalledMethods(module, mainMethod)) {
bool find(MethodDefinition methodToCheck) {
if (methodToCheck == null)
return false;
foreach (var info in DotNetUtils.getCalledMethods(module, methodToCheck)) {
var type = info.Item1;
var method = info.Item2;
@ -58,13 +63,15 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
if (DotNetUtils.getPInvokeMethod(type, "kernel32", "GetProcAddress") == null)
continue;
deobfuscate(method);
if (!containsString(method, "debugger was detected"))
if (!containsString(method, "debugger is active"))
continue;
antiDebuggerType = type;
antiDebuggerMethod = method;
return;
return true;
}
return false;
}
void deobfuscate(MethodDefinition method) {

View File

@ -184,7 +184,9 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
addModuleCctorInitCallToBeRemoved(resourceResolver.Method);
addModuleCctorInitCallToBeRemoved(assemblyResolver.Method);
addCallToBeRemoved(module.EntryPoint, tamperDetection.Method);
addModuleCctorInitCallToBeRemoved(tamperDetection.Method);
addCallToBeRemoved(module.EntryPoint, antiDebugger.Method);
addModuleCctorInitCallToBeRemoved(antiDebugger.Method);
addTypeToBeRemoved(resourceResolver.Type, "Resource resolver type");
addTypeToBeRemoved(assemblyResolver.Type, "Assembly resolver type");
addTypeToBeRemoved(tamperDetection.Type, "Tamper detection type");

View File

@ -138,7 +138,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
createMethod = m;
continue;
}
return null;
continue;
}
if (createMethod == null || !createMethod.HasBody)
return null;

View File

@ -22,16 +22,118 @@ using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.CryptoObfuscator {
class ResourceDecrypter {
const int BUFLEN = 0x8000;
ModuleDefinition module;
DecrypterVersion decrypterVersion = DecrypterVersion.V1;
TypeDefinition resourceDecrypterType;
byte[] buffer1 = new byte[BUFLEN];
byte[] buffer2 = new byte[BUFLEN];
byte desEncryptedFlag;
byte deflatedFlag;
byte bitwiseNotEncryptedFlag;
enum DecrypterVersion {
V1,
V2,
}
public ResourceDecrypter(ModuleDefinition module) {
this.module = module;
find();
}
void find() {
var requiredTypes = new string[] {
"System.IO.MemoryStream",
"System.Object",
"System.Int32",
};
resourceDecrypterType = null;
foreach (var type in module.Types) {
if (type.Fields.Count != 5)
continue;
if (!new FieldTypes(type).exactly(requiredTypes))
continue;
var cctor = DotNetUtils.getMethod(type, ".cctor");
if (cctor == null)
continue;
if (!checkCctor(cctor))
continue;
resourceDecrypterType = type;
break;
}
initializeVersion();
}
bool checkCctor(MethodDefinition cctor) {
if (cctor.Body == null)
return false;
int stsfldCount = 0;
foreach (var instr in cctor.Body.Instructions) {
if (instr.OpCode.Code == Code.Stsfld) {
var field = instr.Operand as FieldReference;
if (!MemberReferenceHelper.compareTypes(cctor.DeclaringType, field.DeclaringType))
return false;
stsfldCount++;
}
}
return stsfldCount == cctor.DeclaringType.Fields.Count;
}
void initializeVersion() {
decrypterVersion = DecrypterVersion.V1;
if (resourceDecrypterType != null) {
foreach (var method in resourceDecrypterType.Methods) {
if (isPublicKeyTokenMethod(method)) {
decrypterVersion = DecrypterVersion.V2;
break;
}
}
}
switch (decrypterVersion) {
case DecrypterVersion.V1:
desEncryptedFlag = 1;
deflatedFlag = 2;
bitwiseNotEncryptedFlag = 4;
break;
case DecrypterVersion.V2:
desEncryptedFlag = 2;
deflatedFlag = 8;
//TODO: bitwiseNotEncryptedFlag = ???;
break;
default:
throw new ApplicationException("Invalid version");
}
}
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) {
@ -40,7 +142,11 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
int sourceStreamOffset = 1;
bool didSomething = false;
if ((flags & 1) != 0) {
byte allFlags = (byte)(desEncryptedFlag | deflatedFlag | bitwiseNotEncryptedFlag);
if ((flags & ~allFlags) != 0)
Log.w("Found unknown resource encryption flags: 0x{0:X2}", flags);
if ((flags & desEncryptedFlag) != 0) {
var memStream = new MemoryStream((int)resourceStream.Length);
using (var provider = new DESCryptoServiceProvider()) {
var iv = new byte[8];
@ -65,7 +171,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
didSomething = true;
}
if ((flags & 2) != 0) {
if ((flags & deflatedFlag) != 0) {
var memStream = new MemoryStream((int)resourceStream.Length);
sourceStream.Position = sourceStreamOffset;
using (var inflater = new DeflateStream(sourceStream, CompressionMode.Decompress)) {
@ -82,7 +188,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
didSomething = true;
}
if ((flags & 4) != 0) {
if ((flags & bitwiseNotEncryptedFlag) != 0) {
var memStream = new MemoryStream((int)resourceStream.Length);
sourceStream.Position = sourceStreamOffset;
for (int i = sourceStreamOffset; i < sourceStream.Length; i++)

View File

@ -28,8 +28,14 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
ResourceDecrypter resourceDecrypter;
TypeDefinition resolverType;
MethodDefinition resolverMethod;
ResolverVersion resolverVersion = ResolverVersion.V1;
bool mergedIt = false;
enum ResolverVersion {
V1,
V2,
}
public TypeDefinition Type {
get { return resolverType; }
}
@ -63,7 +69,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
if (mergedIt)
return null;
var resource = DotNetUtils.getResource(module, module.Assembly.Name.Name) as EmbeddedResource;
var resource = DotNetUtils.getResource(module, getResourceName()) as EmbeddedResource;
if (resource == null)
return null;
@ -72,6 +78,14 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return resource;
}
string getResourceName() {
switch (resolverVersion) {
case ResolverVersion.V1: return module.Assembly.Name.Name;
case ResolverVersion.V2: return string.Format("{0}{0}{0}", module.Assembly.Name.Name);
default: throw new ApplicationException("Unknown version");
}
}
bool checkType(TypeDefinition type, MethodDefinition initMethod) {
if (!initMethod.HasBody)
return false;
@ -79,6 +93,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return false;
var instructions = initMethod.Body.Instructions;
int foundCount = 0;
for (int i = 0; i < instructions.Count; i++) {
var instrs = DotNetUtils.getInstructions(instructions, i, OpCodes.Ldnull, OpCodes.Ldftn, OpCodes.Newobj);
if (instrs == null)
@ -96,12 +111,25 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
if (methodRef == null || methodRef.FullName != "System.Void System.ResolveEventHandler::.ctor(System.Object,System.IntPtr)")
continue;
resolverType = type;
resolverMethod = initMethod;
return true;
foundCount++;
}
if (foundCount == 0)
return false;
switch (foundCount) {
case 1:
resolverVersion = ResolverVersion.V1;
break;
case 2:
resolverVersion = ResolverVersion.V2;
break;
default:
return false;
}
return false;
resolverType = type;
resolverMethod = initMethod;
return true;
}
}
}

View File

@ -17,6 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using Mono.Cecil;
using de4dot.blocks;
@ -63,7 +64,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
if (decryptedData != null)
return;
var resourceName = module.Assembly.Name.Name + module.Assembly.Name.Name;
var resourceName = getResourceName();
stringResource = DotNetUtils.getResource(module, resourceName) as EmbeddedResource;
if (stringResource == null)
return;
@ -72,6 +73,24 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
decryptedData = resourceDecrypter.decrypt(stringResource.GetResourceStream());
}
string getResourceName() {
var defaultName = module.Assembly.Name.Name + module.Assembly.Name.Name;
var cctor = DotNetUtils.getMethod(stringDecrypterType, ".cctor");
if (cctor == null)
return defaultName;
foreach (var s in DotNetUtils.getCodeStrings(cctor)) {
try {
return Encoding.UTF8.GetString(Convert.FromBase64String(s));
}
catch {
}
}
return defaultName;
}
public string decrypt(int index) {
int len;
byte b = decryptedData[index++];

View File

@ -43,25 +43,35 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
}
public void find() {
var mainMethod = module.EntryPoint;
if (mainMethod == null)
if (find(module.EntryPoint))
return;
if (find(DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor")))
return;
}
foreach (var info in DotNetUtils.getCalledMethods(module, mainMethod)) {
bool find(MethodDefinition methodToCheck) {
if (methodToCheck == null)
return false;
foreach (var info in DotNetUtils.getCalledMethods(module, methodToCheck)) {
var type = info.Item1;
var method = info.Item2;
if (type.HasProperties || type.HasEvents)
continue;
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
continue;
if (type.Methods.Count != 3)
if (type.Methods.Count < 3 || type.Methods.Count > 6)
continue;
if (DotNetUtils.getPInvokeMethod(type, "mscoree", "StrongNameSignatureVerificationEx") == null)
continue;
tamperType = type;
tamperMethod = method;
return;
return true;
}
return false;
}
}
}