diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index 3dcd2afe..796b3536 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -61,6 +61,7 @@
+
diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs b/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
index aa39c88b..7e040e9e 100644
--- a/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
+++ b/de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
@@ -58,6 +58,7 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
ResourceDecrypter resourceDecrypter;
ResourceResolver resourceResolver;
AssemblyResolver assemblyResolver;
+ StringDecrypter stringDecrypter;
internal class Options : OptionsBase {
}
@@ -88,6 +89,8 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
val += 100;
else if (foundObfuscatedSymbols)
val += 10;
+ if (stringDecrypter.Detected)
+ val += 10;
return val;
}
@@ -102,6 +105,9 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
}
if (checkCryptoObfuscator())
foundObfuscatedSymbols = true;
+
+ stringDecrypter = new StringDecrypter(module);
+ stringDecrypter.detect();
}
void initializeVersion(TypeDefinition attr) {
@@ -140,9 +146,24 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
resourceResolver.find();
assemblyResolver.find();
+ decryptResources();
+ stringDecrypter.init(resourceDecrypter);
+ if (stringDecrypter.StringDecrypterMethod != null) {
+ staticStringDecrypter.add(stringDecrypter.StringDecrypterMethod, (method, args) => {
+ return stringDecrypter.decrypt((int)args[0]);
+ });
+ }
+
dumpEmbeddedAssemblies();
}
+ void decryptResources() {
+ var rsrc = resourceResolver.mergeResources();
+ if (rsrc == null)
+ return;
+ addResourceToBeRemoved(rsrc, "Encrypted resources");
+ }
+
void dumpEmbeddedAssemblies() {
foreach (var info in assemblyResolver.AssemblyInfos) {
dumpEmbeddedFile(info.resource, info.assemblyName, true);
@@ -155,7 +176,16 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
void dumpEmbeddedFile(EmbeddedResource resource, string assemblyName, bool isAssembly) {
string extension = isAssembly ? ".dll" : ".pdb";
DeobfuscatedFile.createAssemblyFile(resourceDecrypter.decrypt(resource.GetResourceStream()), Utils.getAssemblySimpleName(assemblyName), extension);
- addResourceToBeRemoved(resource, string.Format("Embedded assembly{0}: {1}", isAssembly ? "" : " (pdb)", assemblyName));
+ string reason = isAssembly ? string.Format("Embedded assembly: {0}", assemblyName) :
+ string.Format("Embedded pdb: {0}", assemblyName);
+ addResourceToBeRemoved(resource, reason);
+ }
+
+ public override IEnumerable getStringDecrypterMethods() {
+ var list = new List();
+ if (stringDecrypter.StringDecrypterMethod != null)
+ list.Add(stringDecrypter.StringDecrypterMethod.MetadataToken.ToInt32().ToString("X8"));
+ return list;
}
}
}
diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/ResourceResolver.cs b/de4dot.code/deobfuscators/CryptoObfuscator/ResourceResolver.cs
index f7cb3f05..5b2790a2 100644
--- a/de4dot.code/deobfuscators/CryptoObfuscator/ResourceResolver.cs
+++ b/de4dot.code/deobfuscators/CryptoObfuscator/ResourceResolver.cs
@@ -17,6 +17,7 @@
along with de4dot. If not, see .
*/
+using System;
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
@@ -26,6 +27,7 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
ModuleDefinition module;
ResourceDecrypter resourceDecrypter;
TypeDefinition resolverType;
+ bool mergedIt = false;
public ResourceResolver(ModuleDefinition module, ResourceDecrypter resourceDecrypter) {
this.module = module;
@@ -48,6 +50,19 @@ namespace de4dot.deobfuscators.CryptoObfuscator {
}
}
+ public EmbeddedResource mergeResources() {
+ if (mergedIt)
+ return null;
+
+ var resource = DotNetUtils.getResource(module, module.Assembly.Name.Name) as EmbeddedResource;
+ if (resource == null)
+ throw new ApplicationException("Could not find encrypted resources");
+
+ DeobUtils.decryptAndAddResources(module, resource.Name, () => resourceDecrypter.decrypt(resource.GetResourceStream()));
+ mergedIt = true;
+ return resource;
+ }
+
bool checkType(TypeDefinition type, MethodDefinition initMethod) {
if (!initMethod.HasBody)
return false;
diff --git a/de4dot.code/deobfuscators/CryptoObfuscator/StringDecrypter.cs b/de4dot.code/deobfuscators/CryptoObfuscator/StringDecrypter.cs
new file mode 100644
index 00000000..55257218
--- /dev/null
+++ b/de4dot.code/deobfuscators/CryptoObfuscator/StringDecrypter.cs
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2011 de4dot@gmail.com
+
+ This file is part of de4dot.
+
+ de4dot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ de4dot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with de4dot. If not, see .
+*/
+
+using System.Text;
+using Mono.Cecil;
+using de4dot.blocks;
+
+namespace de4dot.deobfuscators.CryptoObfuscator {
+ class StringDecrypter {
+ ModuleDefinition module;
+ EmbeddedResource stringResource;
+ TypeDefinition stringDecrypterType;
+ MethodDefinition stringDecrypterMethod;
+ byte[] decryptedData;
+
+ public bool Detected {
+ get { return stringDecrypterType != null; }
+ }
+
+ public MethodDefinition StringDecrypterMethod {
+ get { return stringDecrypterMethod; }
+ }
+
+ public StringDecrypter(ModuleDefinition module) {
+ this.module = module;
+ }
+
+ public void detect() {
+ TypeDefinition type;
+ MethodDefinition method;
+ if (!findStringDecrypterType(out type, out method))
+ return;
+
+ stringDecrypterType = type;
+ stringDecrypterMethod = method;
+ }
+
+ public void init(ResourceDecrypter resourceDecrypter) {
+ if (decryptedData != null)
+ return;
+
+ var resourceName = module.Assembly.Name.Name + module.Assembly.Name.Name;
+ stringResource = DotNetUtils.getResource(module, resourceName) as EmbeddedResource;
+ if (stringResource == null)
+ return;
+
+ decryptedData = resourceDecrypter.decrypt(stringResource.GetResourceStream());
+ }
+
+ public string decrypt(int index) {
+ int len;
+ byte b = decryptedData[index++];
+ if ((b & 0x80) == 0)
+ len = b;
+ else if ((b & 0x40) == 0)
+ len = ((b & 0x3F) << 8) + decryptedData[index++];
+ else {
+ len = ((b & 0x3F) << 24) +
+ ((int)decryptedData[index++] << 16) +
+ ((int)decryptedData[index++] << 8) +
+ decryptedData[index++];
+ }
+
+ return Encoding.Unicode.GetString(decryptedData, index, len);
+ }
+
+ bool findStringDecrypterType(out TypeDefinition theType, out MethodDefinition theMethod) {
+ theType = null;
+ theMethod = null;
+
+ foreach (var type in module.Types) {
+ if (type.IsPublic)
+ continue;
+ if (type.Fields.Count != 1)
+ continue;
+ if (DotNetUtils.findFieldType(type, "System.Byte[]", true) == null)
+ continue;
+ if (type.Methods.Count != 3)
+ continue;
+ if (type.HasEvents || type.HasProperties)
+ continue;
+
+ MethodDefinition method = null;
+ foreach (var m in type.Methods) {
+ if (m.Name == ".ctor" || m.Name == ".cctor")
+ continue;
+ if (DotNetUtils.isMethod(m, "System.String", "(System.Int32)")) {
+ method = m;
+ continue;
+ }
+ break;
+ }
+ if (method == null)
+ continue;
+
+ theType = type;
+ theMethod = method;
+ return true;
+ }
+
+ return false;
+ }
+ }
+}