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)
|
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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user