Add DNR 3.x application mode unpacker
This commit is contained in:
parent
4a0a3fb2fc
commit
746997dfe3
|
@ -77,6 +77,8 @@
|
|||
<Compile Include="deobfuscators\DeobfuscatorInfoBase.cs" />
|
||||
<Compile Include="deobfuscators\DeobUtils.cs" />
|
||||
<Compile Include="deobfuscators\Dotfuscator\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeUnpacker.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\AssemblyResolver.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\BooleanDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\BoolValueInliner.cs" />
|
||||
|
@ -91,6 +93,9 @@
|
|||
<Compile Include="deobfuscators\dotNET_Reactor\ResourceResolver.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\StringDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\AntiStrongName.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\AssemblyResolver.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\DecryptMethod.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\MemoryPatcher.cs" />
|
||||
<Compile Include="deobfuscators\Eazfuscator\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\ExceptionLoggerRemover.cs" />
|
||||
<Compile Include="deobfuscators\IDeobfuscatedFile.cs" />
|
||||
|
@ -119,6 +124,7 @@
|
|||
<Compile Include="deobfuscators\SmartAssembly\TamperProtectionRemover.cs" />
|
||||
<Compile Include="deobfuscators\TypesRestorer.cs" />
|
||||
<Compile Include="deobfuscators\Unknown\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\UnpackedFile.cs" />
|
||||
<Compile Include="deobfuscators\Xenocode\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\Xenocode\StringDecrypter.cs" />
|
||||
<Compile Include="IObfuscatedFile.cs" />
|
||||
|
|
34
de4dot.code/deobfuscators/UnpackedFile.cs
Normal file
34
de4dot.code/deobfuscators/UnpackedFile.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
class UnpackedFile {
|
||||
public string filename;
|
||||
public byte[] data;
|
||||
|
||||
public UnpackedFile(string filename, byte[] data) {
|
||||
this.filename = filename;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return string.Format("{0:X8} - {1}", data.Length, filename);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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_Reactor.v3 {
|
||||
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_Reactor.v3 {
|
||||
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_Reactor.v3 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
de4dot.code/deobfuscators/dotNET_Reactor/v3/DecryptMethod.cs
Normal file
77
de4dot.code/deobfuscators/dotNET_Reactor/v3/DecryptMethod.cs
Normal file
|
@ -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_Reactor.v3 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
146
de4dot.code/deobfuscators/dotNET_Reactor/v3/MemoryPatcher.cs
Normal file
146
de4dot.code/deobfuscators/dotNET_Reactor/v3/MemoryPatcher.cs
Normal file
|
@ -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_Reactor.v3 {
|
||||
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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user