Decrypt V4 resources
This commit is contained in:
parent
2c8e685910
commit
6ceea06f5b
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user