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

View File

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

View File

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

View File

@ -18,20 +18,42 @@
*/ */
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
namespace de4dot.code.deobfuscators.DeepSea { namespace de4dot.code.deobfuscators.DeepSea {
class ResourceResolver : ResolverBase { class ResourceResolver : ResolverBase {
EmbeddedResource resource; EmbeddedResource resource;
FieldDefinition resourceField;
int magicV4;
bool isV3;
public EmbeddedResource Resource { public EmbeddedResource Resource {
get { return resource; } get { return resource; }
} }
public ResourceResolver(ModuleDefinition module) public ResourceResolver(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob)
: base(module) { : 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.AppDomain",
"System.Byte[]", "System.Byte[]",
"System.Collections.Generic.Dictionary`2<System.String,System.String>", "System.Collections.Generic.Dictionary`2<System.String,System.String>",
@ -42,29 +64,77 @@ namespace de4dot.code.deobfuscators.DeepSea {
"System.String", "System.String",
"System.String[]", "System.String[]",
}; };
protected override bool checkHandlerMethodInternal(MethodDefinition handler) { static bool checkHandlerV3(MethodDefinition handler) {
return new LocalTypes(handler).all(handlerLocalTypes); 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) if (resolveHandler == null)
return; return;
simpleDeobfuscator.deobfuscate(resolveHandler); if (isV3) {
simpleDeobfuscator.decryptStrings(resolveHandler, deob); simpleDeobfuscator.deobfuscate(resolveHandler);
resource = DeobUtils.getEmbeddedResourceFromCodeStrings(module, resolveHandler); simpleDeobfuscator.decryptStrings(resolveHandler, deob);
if (resource == null) { resource = DeobUtils.getEmbeddedResourceFromCodeStrings(module, resolveHandler);
Log.w("Could not find resource of encrypted resources"); if (resource == null) {
return; Log.w("Could not find resource of encrypted resources");
return;
}
} }
} }
public EmbeddedResource mergeResources() { public bool mergeResources(out EmbeddedResource rsrc) {
if (resource == null) rsrc = null;
return null;
DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResource(resource)); if (isV3) {
return resource; 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;
} }
} }
} }