Re-encrypt x86 methods if any (DNR v4.x)

This commit is contained in:
de4dot 2012-11-17 23:49:19 +01:00
parent d52a1014ef
commit e5ab5ee23c
5 changed files with 73 additions and 49 deletions

View File

@ -608,13 +608,22 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
}
public override void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
if (evt != ModuleWriterEvent.EndWriteChunks)
return;
if (!options.DecryptMethods)
return;
#if PORT
methodsDecrypter.encryptNativeMethods(writer);
#endif
switch (evt) {
case ModuleWriterEvent.Begin:
// The decrypter assumes RVAs are unique so don't share any method bodies
writer.TheOptions.ShareMethodBodies = false;
break;
case ModuleWriterEvent.MDBeginAddResources:
methodsDecrypter.prepareEncryptNativeMethods(writer);
break;
case ModuleWriterEvent.BeginWriteChunks:
methodsDecrypter.encryptNativeMethods(writer);
break;
}
}
}
}

View File

@ -172,16 +172,5 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
}
}
}
public void updateResource(byte[] encryptedData) {
for (int i = 0; i < module.Resources.Count; i++) {
if (module.Resources[i] == encryptedDataResource) {
encryptedDataResource = new EmbeddedResource(encryptedDataResource.Name, encryptedData, encryptedDataResource.Attributes);
module.Resources[i] = encryptedDataResource;
return;
}
}
throw new ApplicationException("Could not find encrypted resource");
}
}
}

View File

@ -98,7 +98,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
uint token = (uint)(int)instrs[i].Operand;
instrs[i] = new Instr(Instruction.Create(OpCodes.Nop));
instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token) as IMethod));
instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token) as ITokenOperand));
}
}
}

View File

@ -20,7 +20,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using dot10.IO;
using dot10.DotNet;
using dot10.DotNet.MD;
using dot10.DotNet.Emit;
using dot10.DotNet.Writer;
using de4dot.blocks;
@ -32,6 +34,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
EncryptedResource encryptedResource;
Dictionary<uint, byte[]> tokenToNativeMethod = new Dictionary<uint, byte[]>();
Dictionary<MethodDef, byte[]> methodToNativeMethod = new Dictionary<MethodDef, byte[]>();
List<MethodDef> validNativeMethods;
int totalEncryptedNativeMethods = 0;
long xorKey;
@ -243,18 +246,15 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
dm.mdSignature = peImage.offsetRead(offset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size);
dm.mdParamList = peImage.offsetRead(offset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size);
if ((peImage.readByte(rva) & 3) == 2) {
dm.mhFlags = 2;
dm.mhMaxStack = 8;
dm.mhCodeSize = (uint)dm.code.Length;
dm.mhLocalVarSigTok = 0;
}
else {
dm.mhFlags = peImage.readUInt16(rva);
dm.mhMaxStack = peImage.readUInt16(rva + 2);
dm.mhCodeSize = (uint)dm.code.Length;
dm.mhLocalVarSigTok = peImage.readUInt32(rva + 8);
}
var codeReader = peImage.Reader;
codeReader.BaseStream.Position = peImage.rvaToOffset(rva);
byte[] code, extraSections;
var mb = MethodBodyParser.parseMethodBody(codeReader, out code, out extraSections);
dm.mhFlags = mb.flags;
dm.mhMaxStack = mb.maxStack;
dm.mhCodeSize = (uint)dm.code.Length;
dm.mhLocalVarSigTok = mb.localVarSigTok;
dm.extraSections = extraSections;
dumpedMethods.add(dm);
}
@ -296,36 +296,56 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
tokenToNativeMethod = null;
}
#if PORT
public void encryptNativeMethods(ModuleWriterBase moduleWriter) {
public void prepareEncryptNativeMethods(ModuleWriterBase moduleWriter) {
if (methodToNativeMethod.Count == 0)
return;
validNativeMethods = new List<MethodDef>(methodToNativeMethod.Count);
int len = 12;
foreach (var kv in methodToNativeMethod) {
if (kv.Key.DeclaringType == null)
continue; // Method was removed
if (kv.Key.DeclaringType.Module != module)
continue; // method.DeclaringType was removed
validNativeMethods.Add(kv.Key);
len += 3 * 4 + kv.Value.Length;
}
if (validNativeMethods.Count == 0)
return;
len = (len & ~15) + 16;
encryptedResource.Resource.Data = MemoryImageStream.Create(new byte[len]);
}
public void encryptNativeMethods(ModuleWriterBase moduleWriter) {
if (validNativeMethods == null || validNativeMethods.Count == 0)
return;
Logger.v("Encrypting native methods");
var stream = new MemoryStream();
var writer = new BinaryWriter(stream);
writer.Write((uint)0); // patch count
writer.Write((uint)0); // mode
writer.Write(methodToNativeMethod.Count);
writer.Write(validNativeMethods.Count);
int index = 0;
var codeWriter = moduleWriter.CodeWriter;
foreach (var pair in methodToNativeMethod) {
var method = pair.Key;
if (method.DeclaringType == null)
continue; // Method was removed
if (method.DeclaringType.Module == null)
continue; // method.DeclaringType was removed
var code = pair.Value;
foreach (var method in validNativeMethods) {
var code = methodToNativeMethod[method];
uint codeRva = moduleWriter.GetMethodBodyRva(method);
if ((codeWriter.ReadByteAtRva(codeRva) & 3) == 2)
var mb = moduleWriter.MetaData.GetMethodBody(method);
if (mb == null) {
Logger.e("Could not find method body for method {0} ({1:X8})", method, method.MDToken.Raw);
continue;
}
uint codeRva = (uint)mb.RVA;
if (mb.IsTiny)
codeRva++;
else
codeRva += 4 * (uint)(codeWriter.ReadByteAtRva(codeRva + 1) >> 4);
codeRva += (uint)(4 * (mb.Code[1] >> 4));
Logger.v("Native method {0:X8}, code RVA {1:X8}", method.MDToken.ToInt32(), codeRva);
Logger.v("Native method {0:X8}, code RVA {1:X8}", new MDToken(Table.Method, moduleWriter.MetaData.GetRid(method)).Raw, codeRva);
writer.Write(codeRva);
writer.Write(0x70000000 + index++);
@ -336,11 +356,17 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
if (index != 0)
Logger.n("Re-encrypted {0}/{1} native methods", index, totalEncryptedNativeMethods);
var encryptedData = stream.ToArray();
xorEncrypt(encryptedData);
encryptedResource.updateResource(encryptedResource.encrypt(encryptedData));
var resourceChunk = moduleWriter.MetaData.GetChunk(encryptedResource.Resource);
var resourceData = resourceChunk.Data;
var encrypted = stream.ToArray();
xorEncrypt(encrypted);
encrypted = encryptedResource.encrypt(encrypted);
if (encrypted.Length != resourceData.Length)
Logger.e("Encrypted native methods array is not same size as original array");
Array.Copy(encrypted, resourceData, resourceData.Length);
}
#endif
public static MethodDef findDnrCompileMethod(TypeDef type) {
foreach (var method in type.Methods) {

2
dot10

@ -1 +1 @@
Subproject commit 361768bfd38e6749d027ea8bf244b0a777c5d0d4
Subproject commit f863f442bac69c0ce647c45ae6d1df8d55757e0c