Re-encrypt x86 methods if any (DNR v4.x)
This commit is contained in:
parent
d52a1014ef
commit
e5ab5ee23c
|
@ -608,13 +608,22 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
|
public override void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
|
||||||
if (evt != ModuleWriterEvent.EndWriteChunks)
|
|
||||||
return;
|
|
||||||
if (!options.DecryptMethods)
|
if (!options.DecryptMethods)
|
||||||
return;
|
return;
|
||||||
#if PORT
|
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);
|
methodsDecrypter.encryptNativeMethods(writer);
|
||||||
#endif
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
|
|
||||||
uint token = (uint)(int)instrs[i].Operand;
|
uint token = (uint)(int)instrs[i].Operand;
|
||||||
instrs[i] = new Instr(Instruction.Create(OpCodes.Nop));
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using dot10.IO;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
|
using dot10.DotNet.MD;
|
||||||
using dot10.DotNet.Emit;
|
using dot10.DotNet.Emit;
|
||||||
using dot10.DotNet.Writer;
|
using dot10.DotNet.Writer;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
@ -32,6 +34,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
EncryptedResource encryptedResource;
|
EncryptedResource encryptedResource;
|
||||||
Dictionary<uint, byte[]> tokenToNativeMethod = new Dictionary<uint, byte[]>();
|
Dictionary<uint, byte[]> tokenToNativeMethod = new Dictionary<uint, byte[]>();
|
||||||
Dictionary<MethodDef, byte[]> methodToNativeMethod = new Dictionary<MethodDef, byte[]>();
|
Dictionary<MethodDef, byte[]> methodToNativeMethod = new Dictionary<MethodDef, byte[]>();
|
||||||
|
List<MethodDef> validNativeMethods;
|
||||||
int totalEncryptedNativeMethods = 0;
|
int totalEncryptedNativeMethods = 0;
|
||||||
long xorKey;
|
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.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);
|
dm.mdParamList = peImage.offsetRead(offset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size);
|
||||||
|
|
||||||
if ((peImage.readByte(rva) & 3) == 2) {
|
var codeReader = peImage.Reader;
|
||||||
dm.mhFlags = 2;
|
codeReader.BaseStream.Position = peImage.rvaToOffset(rva);
|
||||||
dm.mhMaxStack = 8;
|
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.mhCodeSize = (uint)dm.code.Length;
|
||||||
dm.mhLocalVarSigTok = 0;
|
dm.mhLocalVarSigTok = mb.localVarSigTok;
|
||||||
}
|
dm.extraSections = extraSections;
|
||||||
else {
|
|
||||||
dm.mhFlags = peImage.readUInt16(rva);
|
|
||||||
dm.mhMaxStack = peImage.readUInt16(rva + 2);
|
|
||||||
dm.mhCodeSize = (uint)dm.code.Length;
|
|
||||||
dm.mhLocalVarSigTok = peImage.readUInt32(rva + 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
dumpedMethods.add(dm);
|
dumpedMethods.add(dm);
|
||||||
}
|
}
|
||||||
|
@ -296,36 +296,56 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
tokenToNativeMethod = null;
|
tokenToNativeMethod = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PORT
|
public void prepareEncryptNativeMethods(ModuleWriterBase moduleWriter) {
|
||||||
public void encryptNativeMethods(ModuleWriterBase moduleWriter) {
|
|
||||||
if (methodToNativeMethod.Count == 0)
|
if (methodToNativeMethod.Count == 0)
|
||||||
return;
|
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");
|
Logger.v("Encrypting native methods");
|
||||||
|
|
||||||
var stream = new MemoryStream();
|
var stream = new MemoryStream();
|
||||||
var writer = new BinaryWriter(stream);
|
var writer = new BinaryWriter(stream);
|
||||||
writer.Write((uint)0); // patch count
|
writer.Write((uint)0); // patch count
|
||||||
writer.Write((uint)0); // mode
|
writer.Write((uint)0); // mode
|
||||||
writer.Write(methodToNativeMethod.Count);
|
writer.Write(validNativeMethods.Count);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
var codeWriter = moduleWriter.CodeWriter;
|
foreach (var method in validNativeMethods) {
|
||||||
foreach (var pair in methodToNativeMethod) {
|
var code = methodToNativeMethod[method];
|
||||||
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;
|
|
||||||
|
|
||||||
uint codeRva = moduleWriter.GetMethodBodyRva(method);
|
var mb = moduleWriter.MetaData.GetMethodBody(method);
|
||||||
if ((codeWriter.ReadByteAtRva(codeRva) & 3) == 2)
|
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++;
|
codeRva++;
|
||||||
else
|
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(codeRva);
|
||||||
writer.Write(0x70000000 + index++);
|
writer.Write(0x70000000 + index++);
|
||||||
|
@ -336,11 +356,17 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (index != 0)
|
if (index != 0)
|
||||||
Logger.n("Re-encrypted {0}/{1} native methods", index, totalEncryptedNativeMethods);
|
Logger.n("Re-encrypted {0}/{1} native methods", index, totalEncryptedNativeMethods);
|
||||||
|
|
||||||
var encryptedData = stream.ToArray();
|
var resourceChunk = moduleWriter.MetaData.GetChunk(encryptedResource.Resource);
|
||||||
xorEncrypt(encryptedData);
|
var resourceData = resourceChunk.Data;
|
||||||
encryptedResource.updateResource(encryptedResource.encrypt(encryptedData));
|
|
||||||
|
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) {
|
public static MethodDef findDnrCompileMethod(TypeDef type) {
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
|
|
2
dot10
2
dot10
|
@ -1 +1 @@
|
||||||
Subproject commit 361768bfd38e6749d027ea8bf244b0a777c5d0d4
|
Subproject commit f863f442bac69c0ce647c45ae6d1df8d55757e0c
|
Loading…
Reference in New Issue
Block a user