Support more MaxtoCode runtimes
This commit is contained in:
parent
6f925abab7
commit
7c6005cde5
|
@ -106,7 +106,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
|
|
||||||
var fileData = DeobUtils.ReadModule(module);
|
var fileData = DeobUtils.ReadModule(module);
|
||||||
decrypterInfo = new DecrypterInfo(mainType, fileData);
|
decrypterInfo = new DecrypterInfo(mainType, fileData);
|
||||||
var methodsDecrypter = new MethodsDecrypter(decrypterInfo);
|
var methodsDecrypter = new MethodsDecrypter(module, decrypterInfo);
|
||||||
|
|
||||||
if (!methodsDecrypter.Decrypt(ref dumpedMethods))
|
if (!methodsDecrypter.Decrypt(ref dumpedMethods))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -95,6 +95,21 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
MagicHi = 0x828ECDA3,
|
MagicHi = 0x828ECDA3,
|
||||||
Version = EncryptionVersion.V7,
|
Version = EncryptionVersion.V7,
|
||||||
},
|
},
|
||||||
|
// 513D4492
|
||||||
|
// 51413BD8
|
||||||
|
// 51413D68
|
||||||
|
// 5166DB4F
|
||||||
|
new EncryptionInfo {
|
||||||
|
MagicLo = 0x1A683B87,
|
||||||
|
MagicHi = 0x128ECDA3,
|
||||||
|
Version = EncryptionVersion.V8,
|
||||||
|
},
|
||||||
|
// 51927495
|
||||||
|
new EncryptionInfo {
|
||||||
|
MagicLo = 0x7A643B87,
|
||||||
|
MagicHi = 0x624ECDA3,
|
||||||
|
Version = EncryptionVersion.V8,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly EncryptionInfo[] McKey8C0h = new EncryptionInfo[] {
|
public static readonly EncryptionInfo[] McKey8C0h = new EncryptionInfo[] {
|
||||||
|
@ -149,6 +164,21 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
MagicHi = 0x8723891F,
|
MagicHi = 0x8723891F,
|
||||||
Version = EncryptionVersion.V7,
|
Version = EncryptionVersion.V7,
|
||||||
},
|
},
|
||||||
|
// 513D4492
|
||||||
|
// 51413BD8
|
||||||
|
// 51413D68
|
||||||
|
// 5166DB4F
|
||||||
|
new EncryptionInfo {
|
||||||
|
MagicLo = 0x1A731B13,
|
||||||
|
MagicHi = 0x1723891F,
|
||||||
|
Version = EncryptionVersion.V8,
|
||||||
|
},
|
||||||
|
// 51927495
|
||||||
|
new EncryptionInfo {
|
||||||
|
MagicLo = 0x7A731B13,
|
||||||
|
MagicHi = 0x1723891F,
|
||||||
|
Version = EncryptionVersion.V8,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
TypeDef mcType;
|
TypeDef mcType;
|
||||||
bool isOld;
|
bool isOld;
|
||||||
|
ModuleRef runtimeModule1, runtimeModule2;
|
||||||
|
|
||||||
public bool IsOld {
|
public bool IsOld {
|
||||||
get { return isOld; }
|
get { return isOld; }
|
||||||
|
@ -49,6 +50,15 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ModuleRef> RuntimeModuleRefs {
|
||||||
|
get {
|
||||||
|
if (runtimeModule1 != null)
|
||||||
|
yield return runtimeModule1;
|
||||||
|
if (runtimeModule2 != null)
|
||||||
|
yield return runtimeModule2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool Detected {
|
public bool Detected {
|
||||||
get { return mcType != null; }
|
get { return mcType != null; }
|
||||||
}
|
}
|
||||||
|
@ -80,9 +90,8 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
if (!DotNetUtils.IsMethod(method, "System.Void", "()"))
|
if (!DotNetUtils.IsMethod(method, "System.Void", "()"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ModuleRef module1, module2;
|
|
||||||
bool isOldTmp;
|
bool isOldTmp;
|
||||||
if (!CheckType(method.DeclaringType, out module1, out module2, out isOldTmp))
|
if (!CheckType(method.DeclaringType, out runtimeModule1, out runtimeModule2, out isOldTmp))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mcType = method.DeclaringType;
|
mcType = method.DeclaringType;
|
||||||
|
|
|
@ -21,15 +21,19 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using dnlib.DotNet;
|
||||||
using dnlib.IO;
|
using dnlib.IO;
|
||||||
|
using dnlib.PE;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.MaxtoCode {
|
namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
// Decrypts methods, resources and strings (#US heap)
|
// Decrypts methods, resources and strings (#US heap)
|
||||||
class MethodsDecrypter {
|
class MethodsDecrypter {
|
||||||
|
ModuleDef module;
|
||||||
DecrypterInfo decrypterInfo;
|
DecrypterInfo decrypterInfo;
|
||||||
|
|
||||||
class MethodInfos {
|
class MethodInfos {
|
||||||
|
ModuleDef module;
|
||||||
MainType mainType;
|
MainType mainType;
|
||||||
MyPEImage peImage;
|
MyPEImage peImage;
|
||||||
PeHeader peHeader;
|
PeHeader peHeader;
|
||||||
|
@ -43,16 +47,6 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
const int ENCRYPTED_DATA_INFO_SIZE = 0x13;
|
const int ENCRYPTED_DATA_INFO_SIZE = 0x13;
|
||||||
|
|
||||||
delegate byte[] DecryptFunc(byte[] encrypted);
|
delegate byte[] DecryptFunc(byte[] encrypted);
|
||||||
readonly DecryptFunc[] decryptHandlersV1a;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV1b;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV2;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV3;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV4;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV5a;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV5b;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV5c;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV6;
|
|
||||||
readonly DecryptFunc[] decryptHandlersV7;
|
|
||||||
|
|
||||||
public class DecryptedMethodInfo {
|
public class DecryptedMethodInfo {
|
||||||
public uint bodyRva;
|
public uint bodyRva;
|
||||||
|
@ -64,23 +58,13 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodInfos(MainType mainType, MyPEImage peImage, PeHeader peHeader, McKey mcKey) {
|
public MethodInfos(ModuleDef module, MainType mainType, MyPEImage peImage, PeHeader peHeader, McKey mcKey) {
|
||||||
|
this.module = module;
|
||||||
this.mainType = mainType;
|
this.mainType = mainType;
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
this.peHeader = peHeader;
|
this.peHeader = peHeader;
|
||||||
this.mcKey = mcKey;
|
this.mcKey = mcKey;
|
||||||
|
|
||||||
decryptHandlersV1a = new DecryptFunc[] { Decrypt1_v1, Decrypt4_v1, Decrypt2_v1, Decrypt3_v1, Decrypt5, Decrypt6, Decrypt7 };
|
|
||||||
decryptHandlersV1b = new DecryptFunc[] { Decrypt4_v1, Decrypt1_v1, Decrypt2_v1, Decrypt3_v1, Decrypt5, Decrypt6, Decrypt7 };
|
|
||||||
decryptHandlersV2 = new DecryptFunc[] { Decrypt3_v1, Decrypt2_v1, Decrypt1_v1, Decrypt4_v1, Decrypt5, Decrypt6, Decrypt7 };
|
|
||||||
decryptHandlersV3 = new DecryptFunc[] { Decrypt1_v1, Decrypt2_v1, Decrypt3_v1, Decrypt4_v1, Decrypt5, Decrypt6, Decrypt7 };
|
|
||||||
decryptHandlersV4 = new DecryptFunc[] { Decrypt2_v1, Decrypt1_v1, Decrypt3_v1, Decrypt4_v1, Decrypt5, Decrypt6, Decrypt7 };
|
|
||||||
decryptHandlersV5a = new DecryptFunc[] { Decrypt4_v1, Decrypt2_v1, Decrypt3_v1, Decrypt1_v1, Decrypt5, Decrypt6, Decrypt7 };
|
|
||||||
decryptHandlersV5b = new DecryptFunc[] { Decrypt4_v2, Decrypt2_v2, Decrypt3_v2, Decrypt1_v2, Decrypt6, Decrypt7, Decrypt5 };
|
|
||||||
decryptHandlersV5c = new DecryptFunc[] { Decrypt4_v3, Decrypt2_v3, Decrypt3_v3, Decrypt1_v3, Decrypt6, Decrypt7, Decrypt5 };
|
|
||||||
decryptHandlersV6 = new DecryptFunc[] { Decrypt4_v4, Decrypt2_v4, Decrypt3_v4, Decrypt1_v4, Decrypt6, Decrypt7, Decrypt5 };
|
|
||||||
decryptHandlersV7 = new DecryptFunc[] { Decrypt4_v5, Decrypt2_v5, Decrypt3_v5, Decrypt1_v5, Decrypt6, Decrypt8_v5, Decrypt9_v5, Decrypt7, Decrypt5 };
|
|
||||||
|
|
||||||
structSize = GetStructSize(mcKey);
|
structSize = GetStructSize(mcKey);
|
||||||
|
|
||||||
uint methodInfosRva = peHeader.GetRva(0x0FF8, mcKey.ReadUInt32(0x005A));
|
uint methodInfosRva = peHeader.GetRva(0x0FF8, mcKey.ReadUInt32(0x005A));
|
||||||
|
@ -152,13 +136,20 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
|
|
||||||
interface IDecrypter {
|
interface IDecrypter {
|
||||||
byte[] Decrypt(int type, byte[] encrypted);
|
byte[] Decrypt(int type, byte[] encrypted);
|
||||||
|
bool HasTimeStamp(uint timeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Decrypter : IDecrypter {
|
class Decrypter : IDecrypter {
|
||||||
DecryptFunc[] decrypterHandlers;
|
DecryptFunc[] decrypterHandlers;
|
||||||
|
uint[] timeStamps;
|
||||||
|
|
||||||
public Decrypter(DecryptFunc[] decrypterHandlers) {
|
public Decrypter(DecryptFunc[] decrypterHandlers)
|
||||||
|
: this(decrypterHandlers, null) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Decrypter(DecryptFunc[] decrypterHandlers, uint[] timeStamps) {
|
||||||
this.decrypterHandlers = decrypterHandlers;
|
this.decrypterHandlers = decrypterHandlers;
|
||||||
|
this.timeStamps = timeStamps ?? new uint[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Decrypt(int type, byte[] encrypted) {
|
public byte[] Decrypt(int type, byte[] encrypted) {
|
||||||
|
@ -166,27 +157,42 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return decrypterHandlers[type - 1](encrypted);
|
return decrypterHandlers[type - 1](encrypted);
|
||||||
throw new ApplicationException(string.Format("Invalid encryption type: {0:X2}", type));
|
throw new ApplicationException(string.Format("Invalid encryption type: {0:X2}", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasTimeStamp(uint timeStamp) {
|
||||||
|
foreach (var ts in timeStamps) {
|
||||||
|
if (timeStamp == ts)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeDecrypter() {
|
void InitializeDecrypter() {
|
||||||
switch (GetVersion()) {
|
switch (GetVersion()) {
|
||||||
case EncryptionVersion.V1:
|
case EncryptionVersion.V1:
|
||||||
decrypters.Add(new Decrypter(decryptHandlersV1a));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt1_v1, Decrypt4_v1, Decrypt2_v1, Decrypt3_v1, Decrypt5, Decrypt6, Decrypt7 }));
|
||||||
decrypters.Add(new Decrypter(decryptHandlersV1b));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v1, Decrypt1_v1, Decrypt2_v1, Decrypt3_v1, Decrypt5, Decrypt6, Decrypt7 }));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EncryptionVersion.V2: decrypters.Add(new Decrypter(decryptHandlersV2)); break;
|
case EncryptionVersion.V2: decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt3_v1, Decrypt2_v1, Decrypt1_v1, Decrypt4_v1, Decrypt5, Decrypt6, Decrypt7 })); break;
|
||||||
case EncryptionVersion.V3: decrypters.Add(new Decrypter(decryptHandlersV3)); break;
|
case EncryptionVersion.V3: decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt1_v1, Decrypt2_v1, Decrypt3_v1, Decrypt4_v1, Decrypt5, Decrypt6, Decrypt7 })); break;
|
||||||
case EncryptionVersion.V4: decrypters.Add(new Decrypter(decryptHandlersV4)); break;
|
case EncryptionVersion.V4: decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt2_v1, Decrypt1_v1, Decrypt3_v1, Decrypt4_v1, Decrypt5, Decrypt6, Decrypt7 })); break;
|
||||||
|
|
||||||
case EncryptionVersion.V5:
|
case EncryptionVersion.V5:
|
||||||
decrypters.Add(new Decrypter(decryptHandlersV5a));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v1, Decrypt2_v1, Decrypt3_v1, Decrypt1_v1, Decrypt5, Decrypt6, Decrypt7 }));
|
||||||
decrypters.Add(new Decrypter(decryptHandlersV5b));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v2, Decrypt2_v2, Decrypt3_v2, Decrypt1_v2, Decrypt6, Decrypt7, Decrypt5 }));
|
||||||
decrypters.Add(new Decrypter(decryptHandlersV5c));
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v3, Decrypt2_v3, Decrypt3_v3, Decrypt1_v3, Decrypt6, Decrypt7, Decrypt5 }));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EncryptionVersion.V6: decrypters.Add(new Decrypter(decryptHandlersV6)); break;
|
case EncryptionVersion.V6: decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v4, Decrypt2_v4, Decrypt3_v4, Decrypt1_v4, Decrypt6, Decrypt7, Decrypt5 })); break;
|
||||||
case EncryptionVersion.V7: decrypters.Add(new Decrypter(decryptHandlersV7)); break;
|
case EncryptionVersion.V7: decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v5, Decrypt2_v5, Decrypt3_v5, Decrypt1_v5, Decrypt6, Decrypt8_v5, Decrypt9_v5, Decrypt7, Decrypt5 })); break;
|
||||||
|
|
||||||
|
case EncryptionVersion.V8:
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v6, Decrypt2_v2, Decrypt3_v6, Decrypt1_v6, Decrypt6, Decrypt8_v6, Decrypt9_v6, Decrypt7, Decrypt10, Decrypt5 }, new uint[] { 0x5166DB4F, 0x51927495 }));
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v7, Decrypt2_v2, Decrypt3_v6, Decrypt1_v7, Decrypt6, Decrypt8_v7, Decrypt9_v7, Decrypt7, Decrypt5 }, new uint[] { 0x51413D68 }));
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v7, Decrypt2_v2, Decrypt3_v6, Decrypt1_v7, Decrypt6, Decrypt8_v8, Decrypt9_v8, Decrypt7, Decrypt5 }, new uint[] { 0x513D7124, 0x51413BD8 }));
|
||||||
|
decrypters.Add(new Decrypter(new DecryptFunc[] { Decrypt4_v5, Decrypt2_v2, Decrypt3_v6, Decrypt1_v9, Decrypt6, Decrypt8_v8, Decrypt9_v9, Decrypt7, Decrypt5 }, new uint[] { 0x513D4492 }));
|
||||||
|
break;
|
||||||
|
|
||||||
case EncryptionVersion.Unknown:
|
case EncryptionVersion.Unknown:
|
||||||
default:
|
default:
|
||||||
|
@ -200,7 +206,55 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
throw new ApplicationException("Could not decrypt methods");
|
throw new ApplicationException("Could not decrypt methods");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint GetRuntimeTimeStamp() {
|
||||||
|
string path = module.Location;
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var rtNames = new List<string>();
|
||||||
|
foreach (var rtModRef in mainType.RuntimeModuleRefs) {
|
||||||
|
string dllName = rtModRef.Name;
|
||||||
|
if (!dllName.ToUpperInvariant().EndsWith(".DLL"))
|
||||||
|
dllName += ".dll";
|
||||||
|
rtNames.Add(dllName);
|
||||||
|
}
|
||||||
|
if (rtNames.Count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (var di = new DirectoryInfo(Path.GetDirectoryName(path)); di != null; di = di.Parent) {
|
||||||
|
foreach (var dllName in rtNames) {
|
||||||
|
try {
|
||||||
|
using (var peImage = new PEImage(Path.Combine(di.FullName, dllName))) {
|
||||||
|
if (peImage.ImageNTHeaders.FileHeader.Machine == Machine.I386)
|
||||||
|
return peImage.ImageNTHeaders.FileHeader.TimeDateStamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool InitializeInfos2() {
|
bool InitializeInfos2() {
|
||||||
|
if (decrypters.Count > 1) {
|
||||||
|
uint rtTimeStamp = GetRuntimeTimeStamp();
|
||||||
|
var decrypter = GetCorrectDecrypter(rtTimeStamp);
|
||||||
|
if (decrypter != null) {
|
||||||
|
try {
|
||||||
|
if (InitializeInfos2(decrypter))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var decrypter in decrypters) {
|
foreach (var decrypter in decrypters) {
|
||||||
try {
|
try {
|
||||||
if (InitializeInfos2(decrypter))
|
if (InitializeInfos2(decrypter))
|
||||||
|
@ -212,6 +266,14 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IDecrypter GetCorrectDecrypter(uint timeStamp) {
|
||||||
|
foreach (var decrypter in decrypters) {
|
||||||
|
if (decrypter.HasTimeStamp(timeStamp))
|
||||||
|
return decrypter;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
bool InitializeInfos2(IDecrypter decrypter) {
|
bool InitializeInfos2(IDecrypter decrypter) {
|
||||||
int numMethods = ReadInt32(0) ^ ReadInt32(4);
|
int numMethods = ReadInt32(0) ^ ReadInt32(4);
|
||||||
if (numMethods < 0)
|
if (numMethods < 0)
|
||||||
|
@ -313,6 +375,18 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt1(encrypted, 9, 9, 0x500);
|
return Decrypt1(encrypted, 9, 9, 0x500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt1_v6(byte[] encrypted) {
|
||||||
|
return Decrypt1(encrypted, 0x27, 0x27, 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt1_v7(byte[] encrypted) {
|
||||||
|
return Decrypt1(encrypted, 0x1D, 0x1D, 0x400);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt1_v9(byte[] encrypted) {
|
||||||
|
return Decrypt1(encrypted, 9, 0x13, 0x400);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt1(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt1(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length];
|
var decrypted = new byte[encrypted.Length];
|
||||||
for (int i = 0, ki = keyStart; i < decrypted.Length; i++) {
|
for (int i = 0, ki = keyStart; i < decrypted.Length; i++) {
|
||||||
|
@ -386,6 +460,10 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt3(encrypted, 0x015E + 7);
|
return Decrypt3(encrypted, 0x015E + 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt3_v6(byte[] encrypted) {
|
||||||
|
return Decrypt3(encrypted, 0x015E + 0x7F);
|
||||||
|
}
|
||||||
|
|
||||||
static readonly byte[] decrypt3Shifts = new byte[16] { 5, 11, 14, 21, 6, 20, 17, 29, 4, 10, 3, 2, 7, 1, 26, 18 };
|
static readonly byte[] decrypt3Shifts = new byte[16] { 5, 11, 14, 21, 6, 20, 17, 29, 4, 10, 3, 2, 7, 1, 26, 18 };
|
||||||
byte[] Decrypt3(byte[] encrypted, int offset) {
|
byte[] Decrypt3(byte[] encrypted, int offset) {
|
||||||
if ((encrypted.Length & 7) != 0)
|
if ((encrypted.Length & 7) != 0)
|
||||||
|
@ -435,6 +513,14 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt4(encrypted, 0x15, 0x15, 0x100);
|
return Decrypt4(encrypted, 0x15, 0x15, 0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt4_v6(byte[] encrypted) {
|
||||||
|
return Decrypt4(encrypted, 0x63, 0x63, 0x150);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt4_v7(byte[] encrypted) {
|
||||||
|
return Decrypt4(encrypted, 0x0B, 0x0B, 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt4(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt4(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length / 3 * 2 + 1];
|
var decrypted = new byte[encrypted.Length / 3 * 2 + 1];
|
||||||
|
|
||||||
|
@ -476,6 +562,18 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt8(encrypted, 7, 7, 0x600);
|
return Decrypt8(encrypted, 7, 7, 0x600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt8_v6(byte[] encrypted) {
|
||||||
|
return Decrypt8(encrypted, 0x1B, 0x1B, 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt8_v7(byte[] encrypted) {
|
||||||
|
return Decrypt8(encrypted, 0x0D, 0x0D, 0x600);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt8_v8(byte[] encrypted) {
|
||||||
|
return Decrypt8(encrypted, 0x11, 0x11, 0x600);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt8(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt8(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length];
|
var decrypted = new byte[encrypted.Length];
|
||||||
int ki = keyStart;
|
int ki = keyStart;
|
||||||
|
@ -493,6 +591,22 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return Decrypt9(encrypted, 0x11, 0x11, 0x610);
|
return Decrypt9(encrypted, 0x11, 0x11, 0x610);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt9_v6(byte[] encrypted) {
|
||||||
|
return Decrypt9(encrypted, 0x2E, 0x2E, 0x310);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt9_v7(byte[] encrypted) {
|
||||||
|
return Decrypt9(encrypted, 0x28, 0x28, 0x510);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt9_v8(byte[] encrypted) {
|
||||||
|
return Decrypt9(encrypted, 0x2C, 0x2C, 0x510);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt9_v9(byte[] encrypted) {
|
||||||
|
return Decrypt9(encrypted, 0x10, 0x10, 0x510);
|
||||||
|
}
|
||||||
|
|
||||||
byte[] Decrypt9(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
byte[] Decrypt9(byte[] encrypted, int keyStart, int keyReset, int keyEnd) {
|
||||||
var decrypted = new byte[encrypted.Length];
|
var decrypted = new byte[encrypted.Length];
|
||||||
int ki = keyStart;
|
int ki = keyStart;
|
||||||
|
@ -527,6 +641,31 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return decrypted;
|
return decrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] Decrypt10(byte[] encrypted) {
|
||||||
|
byte[] enc = (byte[])encrypted.Clone();
|
||||||
|
byte[] dest = new byte[enc.Length];
|
||||||
|
int halfSize = enc.Length / 2;
|
||||||
|
|
||||||
|
byte b = enc[0];
|
||||||
|
b ^= 0xA1;
|
||||||
|
dest[0] = b;
|
||||||
|
|
||||||
|
b = enc[enc.Length - 1];
|
||||||
|
b ^= 0x1A;
|
||||||
|
dest[enc.Length - 1] = b;
|
||||||
|
|
||||||
|
enc[0] = dest[0];
|
||||||
|
enc[enc.Length - 1] = b;
|
||||||
|
|
||||||
|
for (int i = 1; i < halfSize; i++)
|
||||||
|
dest[i] = (byte)(enc[i] ^ dest[i - 1]);
|
||||||
|
|
||||||
|
for (int i = enc.Length - 2; i >= halfSize; i--)
|
||||||
|
dest[i] = (byte)(enc[i] ^ dest[i + 1]);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] blowfishKey;
|
byte[] blowfishKey;
|
||||||
byte[] GetBlowfishKey() {
|
byte[] GetBlowfishKey() {
|
||||||
if (blowfishKey != null)
|
if (blowfishKey != null)
|
||||||
|
@ -546,7 +685,8 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodsDecrypter(DecrypterInfo decrypterInfo) {
|
public MethodsDecrypter(ModuleDef module, DecrypterInfo decrypterInfo) {
|
||||||
|
this.module = module;
|
||||||
this.decrypterInfo = decrypterInfo;
|
this.decrypterInfo = decrypterInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +705,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
var dumpedMethods = new DumpedMethods();
|
var dumpedMethods = new DumpedMethods();
|
||||||
|
|
||||||
var peImage = decrypterInfo.peImage;
|
var peImage = decrypterInfo.peImage;
|
||||||
var methodInfos = new MethodInfos(decrypterInfo.mainType, peImage, decrypterInfo.peHeader, decrypterInfo.mcKey);
|
var methodInfos = new MethodInfos(module, decrypterInfo.mainType, peImage, decrypterInfo.peHeader, decrypterInfo.mcKey);
|
||||||
methodInfos.InitializeInfos();
|
methodInfos.InitializeInfos();
|
||||||
|
|
||||||
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
|
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
V5,
|
V5,
|
||||||
V6,
|
V6,
|
||||||
V7,
|
V7,
|
||||||
|
V8,
|
||||||
}
|
}
|
||||||
|
|
||||||
class PeHeader {
|
class PeHeader {
|
||||||
|
@ -44,6 +45,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
public PeHeader(MainType mainType, MyPEImage peImage) {
|
public PeHeader(MainType mainType, MyPEImage peImage) {
|
||||||
uint headerOffset;
|
uint headerOffset;
|
||||||
version = GetHeaderOffsetAndVersion(peImage, out headerOffset);
|
version = GetHeaderOffsetAndVersion(peImage, out headerOffset);
|
||||||
|
headerData = peImage.OffsetReadBytes(headerOffset, 0x1000);
|
||||||
|
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case EncryptionVersion.V1:
|
case EncryptionVersion.V1:
|
||||||
|
@ -62,9 +64,20 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
case EncryptionVersion.V7:
|
case EncryptionVersion.V7:
|
||||||
xorKey = 0x8ABA931;
|
xorKey = 0x8ABA931;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EncryptionVersion.V8:
|
||||||
|
if (CheckMcKeyRva(peImage, 0x99BA9A13))
|
||||||
|
break;
|
||||||
|
if (CheckMcKeyRva(peImage, 0x18ABA931))
|
||||||
|
break;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
headerData = peImage.OffsetReadBytes(headerOffset, 0x1000);
|
bool CheckMcKeyRva(MyPEImage peImage, uint newXorKey) {
|
||||||
|
xorKey = newXorKey;
|
||||||
|
uint rva = GetMcKeyRva();
|
||||||
|
return (rva & 0xFFF) == 0 && peImage.FindSection((RVA)rva) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetMcKeyRva() {
|
public uint GetMcKeyRva() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user