Decrypt V4 resources

This commit is contained in:
de4dot 2012-01-24 03:22:59 +01:00
parent 2c8e685910
commit 6ceea06f5b
4 changed files with 119 additions and 35 deletions

View File

@ -41,8 +41,8 @@ namespace de4dot.code.deobfuscators.DeepSea {
}
}
public AssemblyResolver(ModuleDefinition module)
: base(module) {
public AssemblyResolver(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob)
: base(module, simpleDeobfuscator, deob) {
}
static string[] handlerLocalTypes = new string[] {
@ -78,7 +78,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
AssemblyInfo getAssemblyInfos(EmbeddedResource resource) {
try {
var decrypted = decryptResource(resource);
var decrypted = decryptResourceV3(resource);
var asm = AssemblyDefinition.ReadAssembly(new MemoryStream(decrypted));
var fullName = asm.Name.FullName;
var simpleName = asm.Name.Name;

View File

@ -126,9 +126,9 @@ namespace de4dot.code.deobfuscators.DeepSea {
protected override void scanForObfuscator() {
stringDecrypter = new StringDecrypter(module);
stringDecrypter.find(DeobfuscatedFile);
resourceResolver = new ResourceResolver(module);
resourceResolver = new ResourceResolver(module, DeobfuscatedFile, this);
resourceResolver.find();
assemblyResolver = new AssemblyResolver(module);
assemblyResolver = new AssemblyResolver(module, DeobfuscatedFile, this);
assemblyResolver.find();
obfuscatorName = detectVersion();
}
@ -177,7 +177,7 @@ done:
}
DeobfuscatedFile.stringDecryptersAdded();
resourceResolver.initialize(DeobfuscatedFile, this);
resourceResolver.initialize();
decryptResources();
dumpEmbeddedAssemblies();
@ -188,8 +188,8 @@ done:
void decryptResources() {
if (!options.DecryptResources)
return;
var rsrc = resourceResolver.mergeResources();
if (rsrc == null)
EmbeddedResource rsrc;
if (!resourceResolver.mergeResources(out rsrc))
return;
addResourceToBeRemoved(rsrc, "Encrypted resources");
addCctorInitCallToBeRemoved(resourceResolver.InitMethod);

View File

@ -25,6 +25,8 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.DeepSea {
abstract class ResolverBase {
protected ModuleDefinition module;
protected ISimpleDeobfuscator simpleDeobfuscator;
protected IDeobfuscator deob;
protected MethodDefinition initMethod;
protected MethodDefinition resolveHandler;
@ -40,8 +42,10 @@ namespace de4dot.code.deobfuscators.DeepSea {
get { return initMethod != null; }
}
public ResolverBase(ModuleDefinition module) {
public ResolverBase(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
this.module = module;
this.simpleDeobfuscator = simpleDeobfuscator;
this.deob = deob;
}
public void find() {
@ -106,17 +110,27 @@ namespace de4dot.code.deobfuscators.DeepSea {
protected abstract bool checkHandlerMethodInternal(MethodDefinition handler);
protected static byte[] decryptResource(EmbeddedResource resource) {
var data = resource.GetResourceData();
const int baseIndex = 1;
for (int i = baseIndex; i < data.Length; i++)
data[i] ^= (byte)((i - baseIndex) + data[0]);
protected static byte[] decryptResourceV3(EmbeddedResource resource) {
return decryptResourceV3(resource.GetResourceData());
}
if (BitConverter.ToInt16(data, baseIndex) != 0x5A4D)
return DeobUtils.inflate(data, 1, data.Length - 1, true);
protected static byte[] decryptResourceV3(byte[] data) {
return decryptResource(data, 1, data.Length - 1, data[0]);
}
var data2 = new byte[data.Length - baseIndex];
Array.Copy(data, baseIndex, data2, 0, data2.Length);
protected static byte[] decryptResourceV4(byte[] data, int magic) {
return decryptResource(data, 0, data.Length, magic);
}
protected static byte[] decryptResource(byte[] data, int start, int len, int magic) {
for (int i = start; i < start + len; i++)
data[i] ^= (byte)(i - start + magic);
if (BitConverter.ToInt16(data, start) != 0x5A4D)
return DeobUtils.inflate(data, start, len, true);
var data2 = new byte[len];
Array.Copy(data, start, data2, 0, data2.Length);
return data2;
}
}

View File

@ -18,20 +18,42 @@
*/
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.DeepSea {
class ResourceResolver : ResolverBase {
EmbeddedResource resource;
FieldDefinition resourceField;
int magicV4;
bool isV3;
public EmbeddedResource Resource {
get { return resource; }
}
public ResourceResolver(ModuleDefinition module)
: base(module) {
public ResourceResolver(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob)
: base(module, simpleDeobfuscator, deob) {
}
static string[] handlerLocalTypes = new string[] {
protected override bool checkHandlerMethodInternal(MethodDefinition handler) {
if (checkHandlerV3(handler)) {
isV3 = true;
return true;
}
FieldDefinition resourceFieldTmp;
simpleDeobfuscator.deobfuscate(handler);
if (checkHandlerV4(handler, out resourceFieldTmp, out magicV4)) {
isV3 = false;
resourceField = resourceFieldTmp;
return true;
}
return false;
}
static string[] handlerLocalTypes_V3 = new string[] {
"System.AppDomain",
"System.Byte[]",
"System.Collections.Generic.Dictionary`2<System.String,System.String>",
@ -42,29 +64,77 @@ namespace de4dot.code.deobfuscators.DeepSea {
"System.String",
"System.String[]",
};
protected override bool checkHandlerMethodInternal(MethodDefinition handler) {
return new LocalTypes(handler).all(handlerLocalTypes);
static bool checkHandlerV3(MethodDefinition handler) {
return new LocalTypes(handler).all(handlerLocalTypes_V3);
}
public void initialize(ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
static bool checkHandlerV4(MethodDefinition handler, out FieldDefinition resourceField, out int magic) {
magic = 0;
resourceField = getResourceField(handler);
if (resourceField == null)
return false;
bool foundFieldLen = false;
foreach (var instr in handler.Body.Instructions) {
if (!DotNetUtils.isLdcI4(instr))
continue;
int constant = DotNetUtils.getLdcI4Value(instr);
if (constant == resourceField.InitialValue.Length && !foundFieldLen) {
foundFieldLen = true;
continue;
}
magic = constant;
return true;
}
return false;
}
static FieldDefinition getResourceField(MethodDefinition method) {
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Ldtoken)
continue;
var field = instr.Operand as FieldDefinition;
if (field == null || field.InitialValue == null || field.InitialValue.Length == 0)
continue;
return field;
}
return null;
}
public void initialize() {
if (resolveHandler == null)
return;
simpleDeobfuscator.deobfuscate(resolveHandler);
simpleDeobfuscator.decryptStrings(resolveHandler, deob);
resource = DeobUtils.getEmbeddedResourceFromCodeStrings(module, resolveHandler);
if (resource == null) {
Log.w("Could not find resource of encrypted resources");
return;
if (isV3) {
simpleDeobfuscator.deobfuscate(resolveHandler);
simpleDeobfuscator.decryptStrings(resolveHandler, deob);
resource = DeobUtils.getEmbeddedResourceFromCodeStrings(module, resolveHandler);
if (resource == null) {
Log.w("Could not find resource of encrypted resources");
return;
}
}
}
public EmbeddedResource mergeResources() {
if (resource == null)
return null;
public bool mergeResources(out EmbeddedResource rsrc) {
rsrc = null;
DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResource(resource));
return resource;
if (isV3) {
if (resource == null)
return false;
DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResourceV3(resource));
}
else {
if (resourceField == null)
return false;
string name = string.Format("Embedded data field {0:X8} RVA {0:X8}", resourceField.MetadataToken.ToInt32(), resourceField.RVA);
DeobUtils.decryptAndAddResources(module, name, () => decryptResourceV4(resourceField.InitialValue, magicV4));
resourceField.InitialValue = new byte[0];
}
return true;
}
}
}