diff --git a/de4dot.code/deobfuscators/MaxtoCode/FileDecrypter.cs b/de4dot.code/deobfuscators/MaxtoCode/FileDecrypter.cs index 2e17f180..6ace5b34 100644 --- a/de4dot.code/deobfuscators/MaxtoCode/FileDecrypter.cs +++ b/de4dot.code/deobfuscators/MaxtoCode/FileDecrypter.cs @@ -35,10 +35,10 @@ namespace de4dot.code.deobfuscators.MaxtoCode { uint rvaDispl1; uint rvaDispl2; - public PeHeader(PeImage peImage) { + public PeHeader(MainType mainType, PeImage peImage) { headerData = getPeHeaderData(peImage); - if (peImage.readUInt32(0x2008) != 0x48) { + if (!mainType.IsOld && peImage.readUInt32(0x2008) != 0x48) { rvaDispl1 = readUInt32(0x0FB0) ^ XOR_KEY; rvaDispl2 = readUInt32(0x0FB4) ^ XOR_KEY; } @@ -98,10 +98,6 @@ namespace de4dot.code.deobfuscators.MaxtoCode { this.data = peImage.readBytes(peHeader.getMcHeaderRva(), 0x2000); } - public bool hasMagic(int offset, uint magic1, uint magic2) { - return readUInt32(offset) == magic1 && readUInt32(offset + 4) == magic2; - } - public byte readByte(int offset) { return data[offset]; } @@ -129,6 +125,12 @@ namespace de4dot.code.deobfuscators.MaxtoCode { static EncryptionInfo[] encryptionInfos_Rva900h = new EncryptionInfo[] { // PE header timestamp + // 482384FB = Thu, 08 May 2008 22:55:55 (3.36) + new EncryptionInfo { + MagicLo = 0xAA98B387, + MagicHi = 0x1E8EECA3, + Version = EncryptionVersion.V1, + }, // 4C622357 = Wed, 11 Aug 2010 04:13:11 // 4C6220EC = Wed, 11 Aug 2010 04:02:52 // 4A5EEC64 = Thu, 16 Jul 2009 09:01:24 @@ -162,6 +164,12 @@ namespace de4dot.code.deobfuscators.MaxtoCode { }; static EncryptionInfo[] encryptionInfos_McHeader8C0h = new EncryptionInfo[] { + // 482384FB = Thu, 08 May 2008 22:55:55 (3.36) + new EncryptionInfo { + MagicLo = 0x6A713B13, + MagicHi = 0xD72B891F, + Version = EncryptionVersion.V1, + }, // 4DFA3D5D = Thu, 16 Jun 2011 17:29:01 // 4DC2FE0C = Thu, 05 May 2011 19:44:12 // 4DC2FC75 = Thu, 05 May 2011 19:37:25 @@ -185,6 +193,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode { }; class MethodInfos { + MainType mainType; PeImage peImage; PeHeader peHeader; McHeader mcHeader; @@ -206,7 +215,8 @@ namespace de4dot.code.deobfuscators.MaxtoCode { } } - public MethodInfos(PeImage peImage, PeHeader peHeader, McHeader mcHeader) { + public MethodInfos(MainType mainType, PeImage peImage, PeHeader peHeader, McHeader mcHeader) { + this.mainType = mainType; this.peImage = peImage; this.peHeader = peHeader; this.mcHeader = mcHeader; @@ -221,8 +231,10 @@ namespace de4dot.code.deobfuscators.MaxtoCode { } static uint getStructSize(McHeader mcHeader) { + uint magicLo = mcHeader.readUInt32(0x8C0); + uint magicHi = mcHeader.readUInt32(0x8C4); foreach (var info in encryptionInfos_McHeader8C0h) { - if (mcHeader.hasMagic(0x08C0, info.MagicLo, info.MagicHi)) + if (magicLo == info.MagicLo && magicHi == info.MagicHi) return 0xC + 6 * ENCRYPTED_DATA_INFO_SIZE; } return 0xC + 3 * ENCRYPTED_DATA_INFO_SIZE; @@ -352,7 +364,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode { throw new ApplicationException("Invalid number of encrypted methods"); xorKey = (uint)numMethods; - uint rvaDispl = peImage.readUInt32(0x2008) != 0x48 ? 0x1000U : 0; + uint rvaDispl = !mainType.IsOld && peImage.readUInt32(0x2008) != 0x48 ? 0x1000U : 0; int numEncryptedDataInfos = ((int)structSize - 0xC) / ENCRYPTED_DATA_INFO_SIZE; var encryptedDataInfos = new byte[numEncryptedDataInfos][]; @@ -521,7 +533,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode { public bool decrypt(byte[] fileData, ref Dictionary dumpedMethods) { var peImage = new PeImage(fileData); - var peHeader = new PeHeader(peImage); + var peHeader = new PeHeader(mainType, peImage); var mcHeader = new McHeader(peImage, peHeader); dumpedMethods = decryptMethods(peImage, peHeader, mcHeader); @@ -536,7 +548,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode { Dictionary decryptMethods(PeImage peImage, PeHeader peHeader, McHeader mcHeader) { var dumpedMethods = new Dictionary(); - var methodInfos = new MethodInfos(peImage, peHeader, mcHeader); + var methodInfos = new MethodInfos(mainType, peImage, peHeader, mcHeader); methodInfos.initializeInfos(); var metadataTables = peImage.Cor20Header.createMetadataTables(); diff --git a/de4dot.code/deobfuscators/MaxtoCode/MainType.cs b/de4dot.code/deobfuscators/MaxtoCode/MainType.cs index cde2a78c..37184301 100644 --- a/de4dot.code/deobfuscators/MaxtoCode/MainType.cs +++ b/de4dot.code/deobfuscators/MaxtoCode/MainType.cs @@ -27,6 +27,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode { ModuleDefinition module; TypeDefinition mcType; ModuleReference mcModule1, mcModule2; + bool isOld; + + public bool IsOld { + get { return isOld; } + } public TypeDefinition Type { get { return mcType; } @@ -88,12 +93,14 @@ namespace de4dot.code.deobfuscators.MaxtoCode { continue; ModuleReference module1, module2; - if (!checkType(method.DeclaringType, out module1, out module2)) + bool isOldTmp; + if (!checkType(method.DeclaringType, out module1, out module2, out isOldTmp)) return; mcType = method.DeclaringType; mcModule1 = module1; mcModule2 = module2; + isOld = isOldTmp; break; } } @@ -110,8 +117,9 @@ namespace de4dot.code.deobfuscators.MaxtoCode { return null; } - static bool checkType(TypeDefinition type, out ModuleReference module1, out ModuleReference module2) { + static bool checkType(TypeDefinition type, out ModuleReference module1, out ModuleReference module2, out bool isOld) { module1 = module2 = null; + isOld = false; if (DotNetUtils.getMethod(type, "Startup") == null) return false; @@ -122,8 +130,9 @@ namespace de4dot.code.deobfuscators.MaxtoCode { return false; if (getPinvokeList(pinvokes, "MainDLL") == null) return false; - if (getPinvokeList(pinvokes, "GetModuleBase") == null) - return false; + + // Newer versions (3.4+ ???) also have GetModuleBase() + isOld = getPinvokeList(pinvokes, "GetModuleBase") == null; module1 = pinvokeList[0].PInvokeInfo.Module; module2 = pinvokeList[1].PInvokeInfo.Module;