Add code to unpack DNR 4.0/4.1 + .NET 2.0+ native files
This commit is contained in:
parent
f567e09845
commit
b7a44b459d
|
@ -85,6 +85,8 @@
|
|||
<Compile Include="deobfuscators\dotNET_Reactor\EncryptedResource.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\MetadataTokenObfuscator.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\MethodsDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\NativeFileDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\NativeImageUnpacker.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\QuickLZ.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\ResourceResolver.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\StringDecrypter.cs" />
|
||||
|
@ -137,6 +139,10 @@
|
|||
<Compile Include="PE\MetadataTypeBuilder.cs" />
|
||||
<Compile Include="PE\OptionalHeader.cs" />
|
||||
<Compile Include="PE\PeImage.cs" />
|
||||
<Compile Include="PE\ResourceData.cs" />
|
||||
<Compile Include="PE\ResourceDirectory.cs" />
|
||||
<Compile Include="PE\ResourceDirectoryEntry.cs" />
|
||||
<Compile Include="PE\Resources.cs" />
|
||||
<Compile Include="PE\SectionHeader.cs" />
|
||||
<Compile Include="PE\DotNetStream.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
|
|
|
@ -25,6 +25,7 @@ using Mono.Cecil;
|
|||
using Mono.Cecil.Cil;
|
||||
using Mono.MyStuff;
|
||||
using de4dot.blocks;
|
||||
using de4dot.PE;
|
||||
|
||||
namespace de4dot.deobfuscators.dotNET_Reactor {
|
||||
class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||
|
@ -100,7 +101,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
Options options;
|
||||
string obfuscatorName = ".NET Reactor";
|
||||
|
||||
PE.PeImage peImage;
|
||||
PeImage peImage;
|
||||
byte[] fileData;
|
||||
MethodsDecrypter methodsDecrypter;
|
||||
StringDecrypter stringDecrypter;
|
||||
|
@ -112,6 +113,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
AntiStrongName antiStrongname;
|
||||
EmptyClass emptyClass;
|
||||
|
||||
bool unpackedNativeFile = false;
|
||||
bool canRemoveDecrypterType = true;
|
||||
bool startedDeobfuscating = false;
|
||||
|
||||
|
@ -154,6 +156,11 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
this.RenamingOptions &= ~RenamingOptions.RemoveNamespaceIfOneType;
|
||||
}
|
||||
|
||||
public override byte[] unpackNativeFile(PeImage peImage) {
|
||||
unpackedNativeFile = true;
|
||||
return new NativeImageUnpacker(peImage).unpack();
|
||||
}
|
||||
|
||||
public override void init(ModuleDefinition module) {
|
||||
base.init(module);
|
||||
}
|
||||
|
@ -243,6 +250,8 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
assemblyResolver = new AssemblyResolver(module);
|
||||
assemblyResolver.find(DeobfuscatedFile);
|
||||
obfuscatorName = detectVersion();
|
||||
if (unpackedNativeFile)
|
||||
obfuscatorName += " (native)";
|
||||
resourceResolver = new ResourceResolver(module);
|
||||
resourceResolver.find(DeobfuscatedFile);
|
||||
}
|
||||
|
@ -366,7 +375,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
|
||||
public override bool getDecryptedModule(ref byte[] newFileData, ref Dictionary<uint, DumpedMethod> dumpedMethods) {
|
||||
fileData = DeobUtils.readModule(module);
|
||||
peImage = new PE.PeImage(fileData);
|
||||
peImage = new PeImage(fileData);
|
||||
|
||||
if (!options.DecryptMethods)
|
||||
return false;
|
||||
|
@ -398,7 +407,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
var newOne = new Deobfuscator(options);
|
||||
newOne.setModule(module);
|
||||
newOne.fileData = fileData;
|
||||
newOne.peImage = new PE.PeImage(fileData);
|
||||
newOne.peImage = new PeImage(fileData);
|
||||
newOne.methodsDecrypter = new MethodsDecrypter(module, methodsDecrypter);
|
||||
newOne.stringDecrypter = new StringDecrypter(module, stringDecrypter);
|
||||
newOne.booleanDecrypter = new BooleanDecrypter(module, booleanDecrypter);
|
||||
|
|
|
@ -24,6 +24,7 @@ using Mono.Cecil;
|
|||
using Mono.Cecil.Cil;
|
||||
using Mono.MyStuff;
|
||||
using de4dot.blocks;
|
||||
using de4dot.PE;
|
||||
|
||||
namespace de4dot.deobfuscators.dotNET_Reactor {
|
||||
class MethodsDecrypter {
|
||||
|
@ -31,7 +32,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
EncryptedResource encryptedResource;
|
||||
Dictionary<uint, byte[]> tokenToNativeMethod = new Dictionary<uint, byte[]>();
|
||||
Dictionary<MethodDefinition, byte[]> methodToNativeMethod = new Dictionary<MethodDefinition, byte[]>();
|
||||
int totalEncryptedMethods = 0;
|
||||
int totalEncryptedNativeMethods = 0;
|
||||
long xorKey;
|
||||
|
||||
public bool Detected {
|
||||
|
@ -63,13 +64,12 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
this.module = module;
|
||||
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
||||
this.tokenToNativeMethod = oldOne.tokenToNativeMethod;
|
||||
this.totalEncryptedMethods = oldOne.totalEncryptedMethods;
|
||||
this.totalEncryptedNativeMethods = oldOne.totalEncryptedNativeMethods;
|
||||
this.xorKey = oldOne.xorKey;
|
||||
}
|
||||
|
||||
public void find() {
|
||||
var additionalTypes = new string[] {
|
||||
// "System.Diagnostics.StackFrame", //TODO: Not in DNR <= 3.7.0.3
|
||||
"System.IntPtr",
|
||||
// "System.Reflection.Assembly", //TODO: Not in unknown DNR version with jitter support
|
||||
};
|
||||
|
@ -123,7 +123,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
|
||||
static short[] nativeLdci4 = new short[] { 0x55, 0x8B, 0xEC, 0xB8, -1, -1, -1, -1, 0x5D, 0xC3 };
|
||||
static short[] nativeLdci4_0 = new short[] { 0x55, 0x8B, 0xEC, 0x33, 0xC0, 0x5D, 0xC3 };
|
||||
public bool decrypt(PE.PeImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref Dictionary<uint, DumpedMethod> dumpedMethods, Dictionary<uint,byte[]> tokenToNativeCode) {
|
||||
public bool decrypt(PeImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref Dictionary<uint, DumpedMethod> dumpedMethods, Dictionary<uint,byte[]> tokenToNativeCode) {
|
||||
if (encryptedResource.Method == null)
|
||||
return false;
|
||||
|
||||
|
@ -205,7 +205,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
uint methodToken = 0x06000001 + (uint)methodIndex;
|
||||
|
||||
if (isNativeCode) {
|
||||
totalEncryptedMethods++;
|
||||
totalEncryptedNativeMethods++;
|
||||
if (tokenToNativeCode != null)
|
||||
tokenToNativeCode[methodToken] = methodData;
|
||||
|
||||
|
@ -276,7 +276,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void patchDwords(PE.PeImage peImage, BinaryReader reader, int count) {
|
||||
static void patchDwords(PeImage peImage, BinaryReader reader, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
uint rva = reader.ReadUInt32();
|
||||
uint data = reader.ReadUInt32();
|
||||
|
@ -346,7 +346,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
}
|
||||
|
||||
if (index != 0)
|
||||
Log.n("Re-encrypted {0}/{1} native methods", index, totalEncryptedMethods);
|
||||
Log.n("Re-encrypted {0}/{1} native methods", index, totalEncryptedNativeMethods);
|
||||
|
||||
var encryptedData = stream.ToArray();
|
||||
xorEncrypt(encryptedData);
|
||||
|
|
104
de4dot.code/deobfuscators/dotNET_Reactor/NativeFileDecrypter.cs
Normal file
104
de4dot.code/deobfuscators/dotNET_Reactor/NativeFileDecrypter.cs
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace de4dot.deobfuscators.dotNET_Reactor {
|
||||
class NativeFileDecrypter {
|
||||
byte[] key;
|
||||
byte kb = 0;
|
||||
byte[,] transform = new byte[256, 256];
|
||||
|
||||
public NativeFileDecrypter(byte[] keyData) {
|
||||
var keyInit = new byte[] {
|
||||
0x78, 0x61, 0x32, keyData[0], keyData[2],
|
||||
0x62, keyData[3], keyData[0], keyData[1], keyData[1],
|
||||
0x66, keyData[1], keyData[5], 0x33, keyData[2],
|
||||
keyData[4], 0x74, 0x32, keyData[3], keyData[2],
|
||||
};
|
||||
key = new byte[32];
|
||||
for (int i = 0; i < 32; i++) {
|
||||
key[i] = (byte)(i + keyInit[i % keyInit.Length] * keyInit[((i + 0x0B) | 0x1F) % keyInit.Length]);
|
||||
kb += key[i];
|
||||
}
|
||||
|
||||
var transformTemp = new ushort[256, 256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
for (int j = 0; j < 256; j++)
|
||||
transformTemp[i, j] = 0x400;
|
||||
int counter = 0x0B;
|
||||
byte newByte = 0;
|
||||
int ki = 0;
|
||||
for (int i = 0; i < 256; i++) {
|
||||
while (true) {
|
||||
for (int j = key.Length - 1; j >= ki; j--)
|
||||
newByte += (byte)(key[j] + counter);
|
||||
bool done = true;
|
||||
ki = (ki + 1) % key.Length;
|
||||
for (int k = 0; k <= i; k++) {
|
||||
if (newByte == transformTemp[k, 0]) {
|
||||
done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
counter++;
|
||||
}
|
||||
transformTemp[i, 0] = newByte;
|
||||
}
|
||||
|
||||
counter = ki = 0;
|
||||
for (int i = 1; i < 256; i++) {
|
||||
ki++;
|
||||
int i1;
|
||||
do {
|
||||
counter++;
|
||||
i1 = 1 + (this.key[(i + 37 + counter) % key.Length] + counter + kb) % 255;
|
||||
} while (transformTemp[0, i1] != 0x400);
|
||||
for (int i0 = 0; i0 < 256; i0++)
|
||||
transformTemp[i0, i1] = transformTemp[(i0 + ki) % 256, 0];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
for (int j = 0; j < 256; j++)
|
||||
transform[(byte)transformTemp[i, j], j] = (byte)i;
|
||||
}
|
||||
}
|
||||
|
||||
public void decrypt(byte[] data, int offset, int count) {
|
||||
for (int i = 0; i < count; i += 1024, offset += 1024) {
|
||||
int blockLen = Math.Min(1024, count - i);
|
||||
|
||||
if (blockLen == 1) {
|
||||
data[offset] = transform[data[offset], kb];
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < blockLen - 1; j++)
|
||||
data[offset + j] = transform[data[offset + j], data[offset + j + 1]];
|
||||
data[offset + blockLen - 1] = transform[data[offset + blockLen - 1], kb ^ 0x55];
|
||||
|
||||
for (int j = blockLen - 1; j > 0; j--)
|
||||
data[offset + j] = transform[data[offset + j], data[offset + j - 1]];
|
||||
data[offset] = transform[data[offset], kb];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
using de4dot.PE;
|
||||
|
||||
namespace de4dot.deobfuscators.dotNET_Reactor {
|
||||
class NativeImageUnpacker {
|
||||
PeImage peImage;
|
||||
|
||||
public NativeImageUnpacker(PeImage peImage) {
|
||||
this.peImage = peImage;
|
||||
}
|
||||
|
||||
public byte[] unpack() {
|
||||
var resources = peImage.Resources;
|
||||
var dir = resources.getRoot();
|
||||
if ((dir = dir.getDirectory(10)) == null)
|
||||
return null;
|
||||
if ((dir = dir.getDirectory("__")) == null)
|
||||
return null;
|
||||
var dataEntry = dir.getData(0);
|
||||
if (dataEntry == null)
|
||||
return null;
|
||||
|
||||
var encryptedData = peImage.readBytes(dataEntry.RVA, (int)dataEntry.Size);
|
||||
if (encryptedData.Length != dataEntry.Size)
|
||||
return null;
|
||||
|
||||
//TODO: Hard coded offsets: DNR 4.0/4.1 + .NET 2.0+
|
||||
var keyData = new byte[6] {
|
||||
peImage.offsetReadByte(7173),
|
||||
peImage.offsetReadByte(7183),
|
||||
peImage.offsetReadByte(7256),
|
||||
peImage.offsetReadByte(7277),
|
||||
peImage.offsetReadByte(7320),
|
||||
peImage.offsetReadByte(7334),
|
||||
};
|
||||
var decrypter = new NativeFileDecrypter(keyData);
|
||||
decrypter.decrypt(encryptedData, 0, encryptedData.Length);
|
||||
|
||||
int inflatedSize = BitConverter.ToInt32(encryptedData, 0);
|
||||
var inflater = new Inflater();
|
||||
byte[] inflatedData = new byte[inflatedSize];
|
||||
inflater.SetInput(encryptedData, 4, encryptedData.Length - 4);
|
||||
int count = inflater.Inflate(inflatedData);
|
||||
if (count != inflatedSize)
|
||||
return null;
|
||||
|
||||
return inflatedData;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ using System.Security.Cryptography;
|
|||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
using de4dot.PE;
|
||||
|
||||
namespace de4dot.deobfuscators.dotNET_Reactor {
|
||||
class StringDecrypter {
|
||||
|
@ -32,7 +33,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
List<DecrypterInfo> decrypterInfos = new List<DecrypterInfo>();
|
||||
MethodDefinition otherStringDecrypter;
|
||||
byte[] decryptedData;
|
||||
PE.PeImage peImage;
|
||||
PeImage peImage;
|
||||
byte[] fileData;
|
||||
StringDecrypterVersion stringDecrypterVersion;
|
||||
|
||||
|
@ -150,7 +151,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
|
|||
}
|
||||
}
|
||||
|
||||
public void init(PE.PeImage peImage, byte[] fileData, ISimpleDeobfuscator simpleDeobfuscator) {
|
||||
public void init(PeImage peImage, byte[] fileData, ISimpleDeobfuscator simpleDeobfuscator) {
|
||||
if (encryptedResource.Method == null)
|
||||
return;
|
||||
this.peImage = peImage;
|
||||
|
|
Loading…
Reference in New Issue
Block a user