mirror of
https://github.com/0xd4d/de4dot
synced 2026-06-08 10:09:02 +00:00
Create DNR3 dir
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
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 Mono.Cecil;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor3 {
|
||||
class ApplicationModeDecrypter {
|
||||
ModuleDefinition module;
|
||||
AssemblyResolver assemblyResolver;
|
||||
MemoryPatcher memoryPatcher;
|
||||
|
||||
public byte[] AssemblyKey {
|
||||
get { return assemblyResolver.Key; }
|
||||
}
|
||||
|
||||
public byte[] AssemblyIv {
|
||||
get { return assemblyResolver.Iv; }
|
||||
}
|
||||
|
||||
public MemoryPatcher MemoryPatcher {
|
||||
get { return memoryPatcher; }
|
||||
}
|
||||
|
||||
public bool Detected {
|
||||
get { return assemblyResolver != null; }
|
||||
}
|
||||
|
||||
public ApplicationModeDecrypter(ModuleDefinition module) {
|
||||
this.module = module;
|
||||
find();
|
||||
}
|
||||
|
||||
void find() {
|
||||
var cflowDeobfuscator = new CflowDeobfuscator() {
|
||||
InlineMethods = true,
|
||||
InlineInstanceMethods = true,
|
||||
};
|
||||
|
||||
foreach (var type in module.Types) {
|
||||
if (DotNetUtils.getPInvokeMethod(type, "kernel32", "CloseHandle") == null)
|
||||
continue;
|
||||
|
||||
var resolver = new AssemblyResolver(type, cflowDeobfuscator);
|
||||
if (!resolver.Detected)
|
||||
continue;
|
||||
var patcher = new MemoryPatcher(type, cflowDeobfuscator);
|
||||
if (!patcher.Detected)
|
||||
continue;
|
||||
|
||||
assemblyResolver = resolver;
|
||||
memoryPatcher = patcher;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Mono.Cecil;
|
||||
using de4dot.code.PE;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor3 {
|
||||
class IniFile {
|
||||
Dictionary<string, string> nameToValue = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public string this[string name] {
|
||||
get {
|
||||
string value;
|
||||
nameToValue.TryGetValue(name, out value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public IniFile(byte[] data) {
|
||||
using (var reader = new StreamReader(new MemoryStream(data), Encoding.UTF8)) {
|
||||
while (true) {
|
||||
var line = reader.ReadLine();
|
||||
if (line == null)
|
||||
break;
|
||||
var match = Regex.Match(line, @"^([^=]+)=([^;]+);?\s*$");
|
||||
if (match.Groups.Count < 3)
|
||||
continue;
|
||||
var name = match.Groups[1].ToString().Trim();
|
||||
var value = match.Groups[2].ToString().Trim();
|
||||
nameToValue[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unpacks "application mode" files (DNR 3.x)
|
||||
class ApplicationModeUnpacker {
|
||||
static byte[] key1 = new byte[32] {
|
||||
0x6B, 0x6C, 0xA7, 0x24, 0x25, 0x37, 0x67, 0x68,
|
||||
0x4A, 0x2F, 0x28, 0x29, 0x33, 0x77, 0x34, 0x35,
|
||||
0x5A, 0x5A, 0x48, 0x57, 0x24, 0x35, 0x24, 0x25,
|
||||
0x26, 0x67, 0x77, 0x53, 0x41, 0x44, 0x46, 0x32,
|
||||
};
|
||||
static byte[] iv1 = new byte[16] {
|
||||
0x73, 0x64, 0xA7, 0x35, 0x24, 0xA7, 0x26, 0x67,
|
||||
0x34, 0x35, 0x37, 0x21, 0x32, 0x33, 0x6E, 0x6D,
|
||||
};
|
||||
static byte[] key2 = new byte[32] {
|
||||
0x28, 0x24, 0x29, 0x28, 0x2F, 0x29, 0x28, 0x29,
|
||||
0x3D, 0x66, 0x67, 0x35, 0x35, 0x6A, 0x6D, 0x2C,
|
||||
0xA7, 0x39, 0x38, 0x2A, 0x6A, 0x67, 0x74, 0x36,
|
||||
0x35, 0x3D, 0xA7, 0x43, 0x33, 0x33, 0x24, 0x74,
|
||||
};
|
||||
static byte[] iv2 = new byte[16] {
|
||||
0x67, 0x26, 0x35, 0xA7, 0x24, 0xA7, 0x37, 0x21,
|
||||
0x73, 0x33, 0x6E, 0x6D, 0x34, 0x32, 0x64, 0x35,
|
||||
};
|
||||
|
||||
PeImage peImage;
|
||||
List<UnpackedFile> satelliteAssemblies = new List<UnpackedFile>();
|
||||
uint[] sizes;
|
||||
string[] filenames;
|
||||
|
||||
public IEnumerable<UnpackedFile> EmbeddedAssemblies {
|
||||
get { return satelliteAssemblies; }
|
||||
}
|
||||
|
||||
public ApplicationModeUnpacker(PeImage peImage) {
|
||||
this.peImage = peImage;
|
||||
}
|
||||
|
||||
public byte[] unpack() {
|
||||
try {
|
||||
return unpack2();
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] unpack2() {
|
||||
uint headerOffset = peImage.ImageLength - 12;
|
||||
uint offsetEncryptedAssembly = checkOffset(peImage.offsetReadUInt32(headerOffset));
|
||||
uint ezencryptionLibLength = peImage.offsetReadUInt32(headerOffset + 4);
|
||||
uint iniFileLength = peImage.offsetReadUInt32(headerOffset + 8);
|
||||
|
||||
uint offsetClrVersionNumber = checked(offsetEncryptedAssembly - 12);
|
||||
uint iniFileOffset = checked(headerOffset - iniFileLength);
|
||||
uint ezencryptionLibOffset = checked(iniFileOffset - ezencryptionLibLength);
|
||||
|
||||
uint clrVerMajor = peImage.offsetReadUInt32(offsetClrVersionNumber);
|
||||
uint clrVerMinor = peImage.offsetReadUInt32(offsetClrVersionNumber + 4);
|
||||
uint clrVerBuild = peImage.offsetReadUInt32(offsetClrVersionNumber + 8);
|
||||
if (clrVerMajor <= 0 || clrVerMajor >= 20 || clrVerMinor >= 20 || clrVerBuild >= 1000000)
|
||||
return null;
|
||||
|
||||
var settings = new IniFile(decompress2(peImage.offsetReadBytes(iniFileOffset, (int)iniFileLength)));
|
||||
sizes = getSizes(settings["General_App_Satellite_Assemblies_Sizes"]);
|
||||
if (sizes == null || sizes.Length <= 1)
|
||||
return null;
|
||||
if (sizes[0] != offsetEncryptedAssembly)
|
||||
return null;
|
||||
filenames = settings["General_App_Satellite_Assemblies"].Split('|');
|
||||
if (sizes.Length - 1 != filenames.Length)
|
||||
return null;
|
||||
|
||||
byte[] ezencryptionLibData = decompress1(peImage.offsetReadBytes(ezencryptionLibOffset, (int)ezencryptionLibLength));
|
||||
var ezencryptionLibModule = ModuleDefinition.ReadModule(new MemoryStream(ezencryptionLibData));
|
||||
var decrypter = new ApplicationModeDecrypter(ezencryptionLibModule);
|
||||
if (!decrypter.Detected)
|
||||
return null;
|
||||
|
||||
var mainAssembly = unpackEmbeddedFile(0, decrypter);
|
||||
decrypter.MemoryPatcher.patch(mainAssembly.data);
|
||||
for (int i = 1; i < filenames.Length; i++)
|
||||
satelliteAssemblies.Add(unpackEmbeddedFile(i, decrypter));
|
||||
|
||||
return mainAssembly.data;
|
||||
}
|
||||
|
||||
UnpackedFile unpackEmbeddedFile(int index, ApplicationModeDecrypter decrypter) {
|
||||
uint offset = 0;
|
||||
for (int i = 0; i < index + 1; i++)
|
||||
offset += sizes[i];
|
||||
string filename = Path.GetFileName(filenames[index]);
|
||||
var data = peImage.offsetReadBytes(offset, (int)sizes[index + 1]);
|
||||
data = DeobUtils.decrypt(data, decrypter.AssemblyKey, decrypter.AssemblyIv);
|
||||
data = decompress(data);
|
||||
return new UnpackedFile(filename, data);
|
||||
}
|
||||
|
||||
static uint[] getSizes(string sizes) {
|
||||
if (sizes == null)
|
||||
return null;
|
||||
var list = new List<uint>();
|
||||
foreach (var num in sizes.Split('|'))
|
||||
list.Add(uint.Parse(num));
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
uint checkOffset(uint offset) {
|
||||
if (offset >= peImage.ImageLength)
|
||||
throw new Exception();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static byte[] decompress1(byte[] data) {
|
||||
return decompress(decrypt1(data));
|
||||
}
|
||||
|
||||
static byte[] decompress2(byte[] data) {
|
||||
return decompress(decrypt2(data));
|
||||
}
|
||||
|
||||
static byte[] decompress(byte[] data) {
|
||||
if (!QuickLZ.isCompressed(data))
|
||||
return data;
|
||||
return QuickLZ.decompress(data);
|
||||
}
|
||||
|
||||
static byte[] decrypt1(byte[] data) {
|
||||
return DeobUtils.decrypt(data, key1, iv1);
|
||||
}
|
||||
|
||||
static byte[] decrypt2(byte[] data) {
|
||||
return DeobUtils.decrypt(data, key2, iv2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
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.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor3 {
|
||||
class AssemblyResolver {
|
||||
DecryptMethod decryptMethod = new DecryptMethod();
|
||||
|
||||
public byte[] Key {
|
||||
get { return decryptMethod.Key; }
|
||||
}
|
||||
|
||||
public byte[] Iv {
|
||||
get { return decryptMethod.Iv; }
|
||||
}
|
||||
|
||||
public bool Detected {
|
||||
get { return decryptMethod.Detected; }
|
||||
}
|
||||
|
||||
public AssemblyResolver(TypeDefinition type, ICflowDeobfuscator cflowDeobfuscator) {
|
||||
find(type, cflowDeobfuscator);
|
||||
}
|
||||
|
||||
void find(TypeDefinition type, ICflowDeobfuscator cflowDeobfuscator) {
|
||||
var additionalTypes = new List<string> {
|
||||
"System.IO.BinaryReader",
|
||||
"System.IO.FileStream",
|
||||
"System.Reflection.Assembly",
|
||||
"System.Reflection.Assembly[]",
|
||||
"System.String",
|
||||
};
|
||||
foreach (var method in type.Methods) {
|
||||
if (!DotNetUtils.isMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
|
||||
continue;
|
||||
if (!DecryptMethod.couldBeDecryptMethod(method, additionalTypes))
|
||||
continue;
|
||||
cflowDeobfuscator.deobfuscateCflow(method);
|
||||
if (!decryptMethod.getKey(method))
|
||||
continue;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
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 System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor3 {
|
||||
class DecryptMethod {
|
||||
MethodDefinition decryptionMethod;
|
||||
byte[] key;
|
||||
byte[] iv;
|
||||
|
||||
public byte[] Key {
|
||||
get { return key; }
|
||||
}
|
||||
|
||||
public byte[] Iv {
|
||||
get { return iv; }
|
||||
}
|
||||
|
||||
public bool Detected {
|
||||
get { return decryptionMethod != null; }
|
||||
}
|
||||
|
||||
public static bool couldBeDecryptMethod(MethodDefinition method, IEnumerable<string> additionalTypes) {
|
||||
if (method.Body == null)
|
||||
return false;
|
||||
|
||||
var localTypes = new LocalTypes(method);
|
||||
var requiredTypes = new List<string> {
|
||||
"System.Byte[]",
|
||||
"System.IO.MemoryStream",
|
||||
"System.Security.Cryptography.CryptoStream",
|
||||
"System.Security.Cryptography.ICryptoTransform",
|
||||
};
|
||||
requiredTypes.AddRange(additionalTypes);
|
||||
if (!localTypes.all(requiredTypes))
|
||||
return false;
|
||||
if (!localTypes.exists("System.Security.Cryptography.RijndaelManaged") &&
|
||||
!localTypes.exists("System.Security.Cryptography.AesManaged"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool getKey(MethodDefinition method) {
|
||||
var tmpKey = ArrayFinder.getInitializedByteArray(method, 32);
|
||||
if (tmpKey == null)
|
||||
return false;
|
||||
var tmpIv = ArrayFinder.getInitializedByteArray(method, 16);
|
||||
if (tmpIv == null)
|
||||
return false;
|
||||
|
||||
decryptionMethod = method;
|
||||
key = tmpKey;
|
||||
iv = tmpIv;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.MyStuff;
|
||||
using de4dot.blocks;
|
||||
using de4dot.code.PE;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor3 {
|
||||
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||
public const string THE_NAME = ".NET Reactor";
|
||||
public const string THE_TYPE = "dr3";
|
||||
const string DEFAULT_REGEX = DeobfuscatorBase.DEFAULT_VALID_NAME_REGEX;
|
||||
BoolOption restoreTypes;
|
||||
BoolOption inlineMethods;
|
||||
BoolOption removeInlinedMethods;
|
||||
BoolOption removeNamespaces;
|
||||
BoolOption removeAntiStrongName;
|
||||
|
||||
public DeobfuscatorInfo()
|
||||
: base(DEFAULT_REGEX) {
|
||||
restoreTypes = new BoolOption(null, makeArgName("types"), "Restore types (object -> real type)", true);
|
||||
inlineMethods = new BoolOption(null, makeArgName("inline"), "Inline short methods", true);
|
||||
removeInlinedMethods = new BoolOption(null, makeArgName("remove-inlined"), "Remove inlined methods", true);
|
||||
removeNamespaces = new BoolOption(null, makeArgName("ns1"), "Clear namespace if there's only one class in it", true);
|
||||
removeAntiStrongName = new BoolOption(null, makeArgName("sn"), "Remove anti strong name code", true);
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return THE_NAME; }
|
||||
}
|
||||
|
||||
public override string Type {
|
||||
get { return THE_TYPE; }
|
||||
}
|
||||
|
||||
public override IDeobfuscator createDeobfuscator() {
|
||||
return new Deobfuscator(new Deobfuscator.Options {
|
||||
ValidNameRegex = validNameRegex.get(),
|
||||
RestoreTypes = restoreTypes.get(),
|
||||
InlineMethods = inlineMethods.get(),
|
||||
RemoveInlinedMethods = removeInlinedMethods.get(),
|
||||
RemoveNamespaces = removeNamespaces.get(),
|
||||
RemoveAntiStrongName = removeAntiStrongName.get(),
|
||||
});
|
||||
}
|
||||
|
||||
protected override IEnumerable<Option> getOptionsInternal() {
|
||||
return new List<Option>() {
|
||||
restoreTypes,
|
||||
inlineMethods,
|
||||
removeInlinedMethods,
|
||||
removeNamespaces,
|
||||
removeAntiStrongName,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Deobfuscator : DeobfuscatorBase {
|
||||
Options options;
|
||||
string obfuscatorName = DeobfuscatorInfo.THE_NAME;
|
||||
|
||||
List<UnpackedFile> unpackedFiles = new List<UnpackedFile>();
|
||||
|
||||
bool unpackedNativeFile = false;
|
||||
bool startedDeobfuscating = false;
|
||||
|
||||
internal class Options : OptionsBase {
|
||||
public bool RestoreTypes { get; set; }
|
||||
public bool InlineMethods { get; set; }
|
||||
public bool RemoveInlinedMethods { get; set; }
|
||||
public bool RemoveNamespaces { get; set; }
|
||||
public bool RemoveAntiStrongName { get; set; }
|
||||
}
|
||||
|
||||
public override string Type {
|
||||
get { return DeobfuscatorInfo.THE_TYPE; }
|
||||
}
|
||||
|
||||
public override string TypeLong {
|
||||
get { return DeobfuscatorInfo.THE_NAME + " 3.x"; }
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return obfuscatorName; }
|
||||
}
|
||||
|
||||
public override bool CanInlineMethods {
|
||||
get { return startedDeobfuscating ? options.InlineMethods : true; }
|
||||
}
|
||||
|
||||
public Deobfuscator(Options options)
|
||||
: base(options) {
|
||||
this.options = options;
|
||||
|
||||
if (options.RemoveNamespaces)
|
||||
this.RenamingOptions |= RenamingOptions.RemoveNamespaceIfOneType;
|
||||
else
|
||||
this.RenamingOptions &= ~RenamingOptions.RemoveNamespaceIfOneType;
|
||||
}
|
||||
|
||||
public override byte[] unpackNativeFile(PeImage peImage) {
|
||||
var unpackerv3 = new ApplicationModeUnpacker(peImage);
|
||||
var data = unpackerv3.unpack();
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
unpackedFiles.AddRange(unpackerv3.EmbeddedAssemblies);
|
||||
unpackedNativeFile = true;
|
||||
ModuleBytes = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
public override void init(ModuleDefinition module) {
|
||||
base.init(module);
|
||||
}
|
||||
|
||||
static Regex isRandomName = new Regex(@"^[A-Z]{30,40}$");
|
||||
static Regex isRandomNameMembers = new Regex(@"^[a-zA-Z0-9]{9,11}$"); // methods, fields, props, events
|
||||
static Regex isRandomNameTypes = new Regex(@"^[a-zA-Z0-9]{18,19}(?:`\d+)?$"); // types, namespaces
|
||||
|
||||
bool checkValidName(string name, Regex regex) {
|
||||
if (isRandomName.IsMatch(name))
|
||||
return false;
|
||||
if (regex.IsMatch(name)) {
|
||||
if (RandomNameChecker.isRandom(name))
|
||||
return false;
|
||||
if (!RandomNameChecker.isNonRandom(name))
|
||||
return false;
|
||||
}
|
||||
return checkValidName(name);
|
||||
}
|
||||
|
||||
public override bool isValidNamespaceName(string ns) {
|
||||
if (ns == null)
|
||||
return false;
|
||||
if (ns.Contains("."))
|
||||
return base.isValidNamespaceName(ns);
|
||||
return checkValidName(ns, isRandomNameTypes);
|
||||
}
|
||||
|
||||
public override bool isValidTypeName(string name) {
|
||||
return name != null && checkValidName(name, isRandomNameTypes);
|
||||
}
|
||||
|
||||
public override bool isValidMethodName(string name) {
|
||||
return name != null && checkValidName(name, isRandomNameMembers);
|
||||
}
|
||||
|
||||
public override bool isValidPropertyName(string name) {
|
||||
return name != null && checkValidName(name, isRandomNameMembers);
|
||||
}
|
||||
|
||||
public override bool isValidEventName(string name) {
|
||||
return name != null && checkValidName(name, isRandomNameMembers);
|
||||
}
|
||||
|
||||
public override bool isValidFieldName(string name) {
|
||||
return name != null && checkValidName(name, isRandomNameMembers);
|
||||
}
|
||||
|
||||
public override bool isValidGenericParamName(string name) {
|
||||
return name != null && checkValidName(name, isRandomNameMembers);
|
||||
}
|
||||
|
||||
public override bool isValidMethodArgName(string name) {
|
||||
return name != null && checkValidName(name, isRandomNameMembers);
|
||||
}
|
||||
|
||||
protected override int detectInternal() {
|
||||
int val = 0;
|
||||
|
||||
if (unpackedNativeFile)
|
||||
val += 100;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int convert(bool b) {
|
||||
return b ? 1 : 0;
|
||||
}
|
||||
|
||||
protected override void scanForObfuscator() {
|
||||
obfuscatorName = detectVersion();
|
||||
if (unpackedNativeFile)
|
||||
obfuscatorName += " (native)";
|
||||
}
|
||||
|
||||
string detectVersion() {
|
||||
return DeobfuscatorInfo.THE_NAME + " 3.x";
|
||||
}
|
||||
|
||||
public override void deobfuscateBegin() {
|
||||
base.deobfuscateBegin();
|
||||
|
||||
dumpUnpackedFiles();
|
||||
|
||||
startedDeobfuscating = true;
|
||||
}
|
||||
|
||||
void dumpUnpackedFiles() {
|
||||
foreach (var unpackedFile in unpackedFiles)
|
||||
DeobfuscatedFile.createAssemblyFile(unpackedFile.data, Path.GetFileNameWithoutExtension(unpackedFile.filename), Path.GetExtension(unpackedFile.filename));
|
||||
}
|
||||
|
||||
public override void deobfuscateEnd() {
|
||||
removeInlinedMethods();
|
||||
if (options.RestoreTypes)
|
||||
new TypesRestorer(module).deobfuscate();
|
||||
|
||||
base.deobfuscateEnd();
|
||||
}
|
||||
|
||||
void removeInlinedMethods() {
|
||||
if (!options.InlineMethods || !options.RemoveInlinedMethods)
|
||||
return;
|
||||
findAndRemoveInlinedMethods();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> getStringDecrypterMethods() {
|
||||
var list = new List<string>();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
using de4dot.code.PE;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor3 {
|
||||
class MemoryPatcher {
|
||||
DecryptMethod decryptMethod = new DecryptMethod();
|
||||
List<PatchInfo> patchInfos = new List<PatchInfo>();
|
||||
|
||||
class PatchInfo {
|
||||
public int[] offsets;
|
||||
public int[] values;
|
||||
public PatchInfo(int[] offsets, int[] values) {
|
||||
this.offsets = offsets;
|
||||
this.values = values;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Detected {
|
||||
get { return decryptMethod.Detected; }
|
||||
}
|
||||
|
||||
public MemoryPatcher(TypeDefinition type, ICflowDeobfuscator cflowDeobfuscator) {
|
||||
find(type, cflowDeobfuscator);
|
||||
}
|
||||
|
||||
void find(TypeDefinition type, ICflowDeobfuscator cflowDeobfuscator) {
|
||||
var additionalTypes = new List<string> {
|
||||
"System.IO.BinaryWriter",
|
||||
};
|
||||
foreach (var method in type.Methods) {
|
||||
if (!DotNetUtils.isMethod(method, "System.Void", "(System.Int32[],System.UInt32[])"))
|
||||
continue;
|
||||
if (!DecryptMethod.couldBeDecryptMethod(method, additionalTypes))
|
||||
continue;
|
||||
cflowDeobfuscator.deobfuscateCflow(method);
|
||||
if (!decryptMethod.getKey(method))
|
||||
continue;
|
||||
|
||||
findPatchData(type, cflowDeobfuscator);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void findPatchData(TypeDefinition type, ICflowDeobfuscator cflowDeobfuscator) {
|
||||
var locals = new List<string> {
|
||||
"System.Int32[]",
|
||||
"System.UInt32[]",
|
||||
};
|
||||
foreach (var method in type.Methods) {
|
||||
if (method.Attributes != MethodAttributes.Private)
|
||||
continue;
|
||||
if (!DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||
continue;
|
||||
if (!new LocalTypes(method).exactly(locals))
|
||||
continue;
|
||||
cflowDeobfuscator.deobfuscateCflow(method);
|
||||
var patchInfo = getPatchInfo(method);
|
||||
if (patchInfo == null)
|
||||
continue;
|
||||
|
||||
patchInfos.Add(patchInfo);
|
||||
}
|
||||
}
|
||||
|
||||
PatchInfo getPatchInfo(MethodDefinition method) {
|
||||
int index1 = 0, index2, index3, size1, size2, size3;
|
||||
if (!ArrayFinder.findNewarr(method, ref index1, out size1))
|
||||
return null;
|
||||
index2 = index1 + 1;
|
||||
if (!ArrayFinder.findNewarr(method, ref index2, out size2))
|
||||
return null;
|
||||
index3 = index2 + 1;
|
||||
if (ArrayFinder.findNewarr(method, ref index3, out size3))
|
||||
return null;
|
||||
|
||||
if (size1 <= 0 || size1 > 35)
|
||||
return null;
|
||||
|
||||
var ary1 = ArrayFinder.getInitializedInt32Array(size1, method, ref index1);
|
||||
var ary2 = ArrayFinder.getInitializedInt32Array(size2, method, ref index2);
|
||||
if (ary1 == null || ary2 == null)
|
||||
return null;
|
||||
ary2 = decrypt(ary2);
|
||||
if (ary2 == null || ary2.Length != ary2.Length)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < ary1.Length; i++)
|
||||
ary1[i] = -ary1[i];
|
||||
|
||||
return new PatchInfo(ary1, ary2);
|
||||
}
|
||||
|
||||
int[] decrypt(int[] data) {
|
||||
var memStream = new MemoryStream();
|
||||
var writer = new BinaryWriter(memStream);
|
||||
foreach (var value in data)
|
||||
writer.Write(value);
|
||||
byte[] decrypted;
|
||||
try {
|
||||
decrypted = DeobUtils.decrypt(memStream.ToArray(), decryptMethod.Key, decryptMethod.Iv);
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
if (decrypted.Length / 4 * 4 != decrypted.Length)
|
||||
return null;
|
||||
var newData = new int[decrypted.Length / 4];
|
||||
for (int i = 0; i < newData.Length; i++)
|
||||
newData[i] = BitConverter.ToInt32(decrypted, i * 4);
|
||||
return newData;
|
||||
}
|
||||
|
||||
public void patch(byte[] peImageData) {
|
||||
var peImage = new PeImage(peImageData);
|
||||
foreach (var info in patchInfos) {
|
||||
for (int i = 0; i < info.offsets.Length; i++)
|
||||
peImage.dotNetSafeWriteOffset((uint)info.offsets[i], BitConverter.GetBytes(info.values[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user