This commit is contained in:
de4dot 2012-07-20 18:15:40 +02:00
parent 8b82f8b47d
commit 9b48632354
7 changed files with 356 additions and 240 deletions

View File

@ -70,6 +70,10 @@
<Compile Include="deobfuscators\DeepSea\ArrayBlockState.cs" />
<Compile Include="deobfuscators\MaxtoCode\CryptDecrypter.cs" />
<Compile Include="deobfuscators\MaxtoCode\Decrypter6.cs" />
<Compile Include="deobfuscators\MaxtoCode\DecrypterInfo.cs" />
<Compile Include="deobfuscators\MaxtoCode\EncryptionInfos.cs" />
<Compile Include="deobfuscators\MaxtoCode\McKey.cs" />
<Compile Include="deobfuscators\MaxtoCode\PeHeader.cs" />
<Compile Include="deobfuscators\MethodBodyReaderBase.cs" />
<Compile Include="deobfuscators\Babel_NET\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\Babel_NET\ProxyDelegateFinder.cs" />

View File

@ -0,0 +1,38 @@
/*
Copyright (C) 2011-2012 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 de4dot.PE;
namespace de4dot.code.deobfuscators.MaxtoCode {
class DecrypterInfo {
public readonly MainType mainType;
public readonly PeImage peImage;
public readonly PeHeader peHeader;
public readonly McKey mcKey;
public readonly byte[] fileData;
public DecrypterInfo(MainType mainType, byte[] fileData) {
this.mainType = mainType;
this.peImage = new PeImage(fileData);
this.peHeader = new PeHeader(mainType, peImage);
this.mcKey = new McKey(peImage, peHeader);
this.fileData = fileData;
}
}
}

View File

@ -49,6 +49,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
class Deobfuscator : DeobfuscatorBase {
Options options;
MainType mainType;
DecrypterInfo decrypterInfo;
internal class Options : OptionsBase {
}
@ -88,10 +89,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
if (!mainType.Detected)
return false;
var fileDecrypter = new FileDecrypter(mainType);
var fileData = DeobUtils.readModule(module);
if (!fileDecrypter.decrypt(fileData, ref dumpedMethods))
decrypterInfo = new DecrypterInfo(mainType, fileData);
var fileDecrypter = new FileDecrypter(decrypterInfo);
if (!fileDecrypter.decrypt(ref dumpedMethods))
return false;
newFileData = fileData;
@ -102,6 +104,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
var newOne = new Deobfuscator(options);
newOne.setModule(module);
newOne.mainType = new MainType(module, mainType);
newOne.decrypterInfo = decrypterInfo;
return newOne;
}

View File

@ -0,0 +1,133 @@
/*
Copyright (C) 2011-2012 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.MaxtoCode {
class EncryptionInfo {
public uint MagicLo { get; set; }
public uint MagicHi { get; set; }
public EncryptionVersion Version { get; set; }
}
static class EncryptionInfos {
public static readonly EncryptionInfo[] Rva900h = new EncryptionInfo[] {
// PE header timestamp
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
new EncryptionInfo {
MagicLo = 0xA098B387,
MagicHi = 0x1E8EBCA3,
Version = EncryptionVersion.V1,
},
// 482384FB = Thu, 08 May 2008 22:55:55 (3.36)
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0x1E8EECA3,
Version = EncryptionVersion.V2,
},
// 4A5EEC64 = Thu, 16 Jul 2009 09:01:24
// 4C6220EC = Wed, 11 Aug 2010 04:02:52
// 4C622357 = Wed, 11 Aug 2010 04:13:11
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0x128EECA3,
Version = EncryptionVersion.V2,
},
// 4C6E4605 = Fri, 20 Aug 2010 09:08:21
// 4D0E220D = Sun, 19 Dec 2010 15:17:33
// 4DC2FC75 = Thu, 05 May 2011 19:37:25
// 4DFA3D5D = Thu, 16 Jun 2011 17:29:01
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0xF28EECA3,
Version = EncryptionVersion.V2,
},
// 4DC2FE0C = Thu, 05 May 2011 19:44:12
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0xF28EEAA3,
Version = EncryptionVersion.V2,
},
// 4ED76740 = Thu, 01 Dec 2011 11:38:40
// 4EE1FAD1 = Fri, 09 Dec 2011 12:10:57
new EncryptionInfo {
MagicLo = 0xAA983B87,
MagicHi = 0xF28EECA3,
Version = EncryptionVersion.V3,
},
// 4F832868 = Mon, Apr 09 2012 20:20:24
new EncryptionInfo {
MagicLo = 0xAA913B87,
MagicHi = 0xF28EE0A3,
Version = EncryptionVersion.V4,
},
// 4F8E262C = Wed, 18 Apr 2012 02:25:48
new EncryptionInfo {
MagicLo = 0xBA983B87,
MagicHi = 0xF28EDDA3,
Version = EncryptionVersion.V5,
},
};
public static readonly EncryptionInfo[] McKey8C0h = new EncryptionInfo[] {
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
new EncryptionInfo {
MagicLo = 0x6AA13B13,
MagicHi = 0xD72B991F,
Version = EncryptionVersion.V1,
},
// 482384FB = Thu, 08 May 2008 22:55:55 (3.36)
new EncryptionInfo {
MagicLo = 0x6A713B13,
MagicHi = 0xD72B891F,
Version = EncryptionVersion.V2,
},
// 4A5EEC64 = Thu, 16 Jul 2009 09:01:24
// 4C6220EC = Wed, 11 Aug 2010 04:02:52
// 4C622357 = Wed, 11 Aug 2010 04:13:11
// 4C6E4605 = Fri, 20 Aug 2010 09:08:21
// 4D0E220D = Sun, 19 Dec 2010 15:17:33
// 4DC2FC75 = Thu, 05 May 2011 19:37:25
// 4DC2FE0C = Thu, 05 May 2011 19:44:12
// 4DFA3D5D = Thu, 16 Jun 2011 17:29:01
new EncryptionInfo {
MagicLo = 0x6A713B13,
MagicHi = 0xD72B891F,
Version = EncryptionVersion.V2,
},
// 4ED76740 = Thu, 01 Dec 2011 11:38:40
// 4EE1FAD1 = Fri, 09 Dec 2011 12:10:57
new EncryptionInfo {
MagicLo = 0x6A731B13,
MagicHi = 0xD72B891F,
Version = EncryptionVersion.V3,
},
// 4F832868 = Mon, Apr 09 2012 20:20:24
new EncryptionInfo {
MagicLo = 0x6AD31B13,
MagicHi = 0xD72B8A1F,
Version = EncryptionVersion.V4,
},
// 4F8E262C = Wed, 18 Apr 2012 02:25:48
new EncryptionInfo {
MagicLo = 0xAA731B13,
MagicHi = 0xD723891F,
Version = EncryptionVersion.V5,
},
};
}
}

View File

@ -27,232 +27,7 @@ using de4dot.PE;
namespace de4dot.code.deobfuscators.MaxtoCode {
// Decrypts methods and resources
class FileDecrypter {
MainType mainType;
PeImage peImage;
PeHeader peHeader;
McKey mcKey;
byte[] fileData;
class PeHeader {
const int XOR_KEY = 0x7ABF931;
EncryptionVersion version;
byte[] headerData;
public EncryptionVersion EncryptionVersion {
get { return version; }
}
public PeHeader(MainType mainType, PeImage peImage) {
uint headerOffset;
version = getHeaderOffsetAndVersion(peImage, out headerOffset);
headerData = peImage.offsetReadBytes(headerOffset, 0x1000);
}
public uint getMcKeyRva() {
return getRva2(0x0FFC, XOR_KEY);
}
public uint getRva1(int offset, uint xorKey) {
return (readUInt32(offset) ^ xorKey);
}
public uint getRva2(int offset, uint xorKey) {
return (readUInt32(offset) ^ xorKey);
}
public uint readUInt32(int offset) {
return BitConverter.ToUInt32(headerData, offset);
}
static EncryptionVersion getHeaderOffsetAndVersion(PeImage peImage, out uint headerOffset) {
headerOffset = 0;
var version = getVersion(peImage, headerOffset);
if (version != EncryptionVersion.Unknown)
return version;
var section = peImage.findSection(".rsrc");
if (section == null)
return EncryptionVersion.Unknown;
headerOffset = section.pointerToRawData;
uint end = section.pointerToRawData + section.sizeOfRawData - 0x1000 + 1;
while (headerOffset < end) {
version = getVersion(peImage, headerOffset);
if (version != EncryptionVersion.Unknown)
return version;
headerOffset++;
}
return EncryptionVersion.Unknown;
}
static EncryptionVersion getVersion(PeImage peImage, uint headerOffset) {
uint m1lo = peImage.offsetReadUInt32(headerOffset + 0x900);
uint m1hi = peImage.offsetReadUInt32(headerOffset + 0x904);
foreach (var info in encryptionInfos_Rva900h) {
if (info.MagicLo == m1lo && info.MagicHi == m1hi)
return info.Version;
}
return EncryptionVersion.Unknown;
}
}
class McKey {
PeHeader peHeader;
byte[] data;
public byte this[int index] {
get { return data[index]; }
}
public McKey(PeImage peImage, PeHeader peHeader) {
this.peHeader = peHeader;
try {
this.data = peImage.readBytes(peHeader.getMcKeyRva(), 0x2000);
}
catch (IOException) {
this.data = peImage.readBytes(peHeader.getMcKeyRva(), 0x1000);
}
}
public byte[] readBytes(int offset, int len) {
byte[] bytes = new byte[len];
Array.Copy(data, offset, bytes, 0, len);
return bytes;
}
public byte readByte(int offset) {
return data[offset];
}
public uint readUInt32(int offset) {
return BitConverter.ToUInt32(data, offset);
}
}
enum EncryptionVersion {
Unknown,
V1,
V2,
V3,
V4,
V5,
}
class EncryptionInfo {
public uint MagicLo { get; set; }
public uint MagicHi { get; set; }
public EncryptionVersion Version { get; set; }
}
static readonly EncryptionInfo[] encryptionInfos_Rva900h = new EncryptionInfo[] {
// PE header timestamp
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
new EncryptionInfo {
MagicLo = 0xA098B387,
MagicHi = 0x1E8EBCA3,
Version = EncryptionVersion.V1,
},
// 482384FB = Thu, 08 May 2008 22:55:55 (3.36)
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0x1E8EECA3,
Version = EncryptionVersion.V2,
},
// 4A5EEC64 = Thu, 16 Jul 2009 09:01:24
// 4C6220EC = Wed, 11 Aug 2010 04:02:52
// 4C622357 = Wed, 11 Aug 2010 04:13:11
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0x128EECA3,
Version = EncryptionVersion.V2,
},
// 4C6E4605 = Fri, 20 Aug 2010 09:08:21
// 4D0E220D = Sun, 19 Dec 2010 15:17:33
// 4DC2FC75 = Thu, 05 May 2011 19:37:25
// 4DFA3D5D = Thu, 16 Jun 2011 17:29:01
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0xF28EECA3,
Version = EncryptionVersion.V2,
},
// 4DC2FE0C = Thu, 05 May 2011 19:44:12
new EncryptionInfo {
MagicLo = 0xAA98B387,
MagicHi = 0xF28EEAA3,
Version = EncryptionVersion.V2,
},
// 4ED76740 = Thu, 01 Dec 2011 11:38:40
// 4EE1FAD1 = Fri, 09 Dec 2011 12:10:57
new EncryptionInfo {
MagicLo = 0xAA983B87,
MagicHi = 0xF28EECA3,
Version = EncryptionVersion.V3,
},
// 4F832868 = Mon, Apr 09 2012 20:20:24
new EncryptionInfo {
MagicLo = 0xAA913B87,
MagicHi = 0xF28EE0A3,
Version = EncryptionVersion.V4,
},
// 4F8E262C = Wed, 18 Apr 2012 02:25:48
new EncryptionInfo {
MagicLo = 0xBA983B87,
MagicHi = 0xF28EDDA3,
Version = EncryptionVersion.V5,
},
};
static readonly EncryptionInfo[] encryptionInfos_McKey8C0h = new EncryptionInfo[] {
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
new EncryptionInfo {
MagicLo = 0x6AA13B13,
MagicHi = 0xD72B991F,
Version = EncryptionVersion.V1,
},
// 482384FB = Thu, 08 May 2008 22:55:55 (3.36)
new EncryptionInfo {
MagicLo = 0x6A713B13,
MagicHi = 0xD72B891F,
Version = EncryptionVersion.V2,
},
// 4A5EEC64 = Thu, 16 Jul 2009 09:01:24
// 4C6220EC = Wed, 11 Aug 2010 04:02:52
// 4C622357 = Wed, 11 Aug 2010 04:13:11
// 4C6E4605 = Fri, 20 Aug 2010 09:08:21
// 4D0E220D = Sun, 19 Dec 2010 15:17:33
// 4DC2FC75 = Thu, 05 May 2011 19:37:25
// 4DC2FE0C = Thu, 05 May 2011 19:44:12
// 4DFA3D5D = Thu, 16 Jun 2011 17:29:01
new EncryptionInfo {
MagicLo = 0x6A713B13,
MagicHi = 0xD72B891F,
Version = EncryptionVersion.V2,
},
// 4ED76740 = Thu, 01 Dec 2011 11:38:40
// 4EE1FAD1 = Fri, 09 Dec 2011 12:10:57
new EncryptionInfo {
MagicLo = 0x6A731B13,
MagicHi = 0xD72B891F,
Version = EncryptionVersion.V3,
},
// 4F832868 = Mon, Apr 09 2012 20:20:24
new EncryptionInfo {
MagicLo = 0x6AD31B13,
MagicHi = 0xD72B8A1F,
Version = EncryptionVersion.V4,
},
// 4F8E262C = Wed, 18 Apr 2012 02:25:48
new EncryptionInfo {
MagicLo = 0xAA731B13,
MagicHi = 0xD723891F,
Version = EncryptionVersion.V5,
},
};
DecrypterInfo decrypterInfo;
class MethodInfos {
MainType mainType;
@ -310,7 +85,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
static uint getStructSize(McKey mcKey) {
uint magicLo = mcKey.readUInt32(0x8C0);
uint magicHi = mcKey.readUInt32(0x8C4);
foreach (var info in encryptionInfos_McKey8C0h) {
foreach (var info in EncryptionInfos.McKey8C0h) {
if (magicLo == info.MagicLo && magicHi == info.MagicHi)
return 0xC + 6 * ENCRYPTED_DATA_INFO_SIZE;
}
@ -324,7 +99,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
uint m2lo = mcKey.readUInt32(0x8C0);
uint m2hi = mcKey.readUInt32(0x8C4);
foreach (var info in encryptionInfos_McKey8C0h) {
foreach (var info in EncryptionInfos.McKey8C0h) {
if (info.MagicLo == m2lo && info.MagicHi == m2hi)
return info.Version;
}
@ -647,16 +422,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
}
}
public FileDecrypter(MainType mainType) {
this.mainType = mainType;
public FileDecrypter(DecrypterInfo decrypterInfo) {
this.decrypterInfo = decrypterInfo;
}
public bool decrypt(byte[] fileData, ref DumpedMethods dumpedMethods) {
peImage = new PeImage(fileData);
peHeader = new PeHeader(mainType, peImage);
mcKey = new McKey(peImage, peHeader);
this.fileData = fileData;
public bool decrypt(ref DumpedMethods dumpedMethods) {
dumpedMethods = decryptMethods();
if (dumpedMethods == null)
return false;
@ -670,7 +440,8 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
DumpedMethods decryptMethods() {
var dumpedMethods = new DumpedMethods();
var methodInfos = new MethodInfos(mainType, peImage, peHeader, mcKey);
var peImage = decrypterInfo.peImage;
var methodInfos = new MethodInfos(decrypterInfo.mainType, peImage, decrypterInfo.peHeader, decrypterInfo.mcKey);
methodInfos.initializeInfos();
var metadataTables = peImage.Cor20Header.createMetadataTables();
@ -729,6 +500,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
}
void decryptResources() {
var peHeader = decrypterInfo.peHeader;
var mcKey = decrypterInfo.mcKey;
var peImage = decrypterInfo.peImage;
var fileData = decrypterInfo.fileData;
uint resourceRva = peHeader.getRva1(0x0E10, mcKey.readUInt32(0x00A0));
uint resourceSize = peHeader.readUInt32(0x0E14) ^ mcKey.readUInt32(0x00AA);
if (resourceRva == 0 || resourceSize == 0)
@ -746,6 +522,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
}
void decryptStrings() {
var peHeader = decrypterInfo.peHeader;
var mcKey = decrypterInfo.mcKey;
var peImage = decrypterInfo.peImage;
var fileData = decrypterInfo.fileData;
uint usHeapRva = peHeader.getRva1(0x0E00, mcKey.readUInt32(0x0078));
uint usHeapSize = peHeader.readUInt32(0x0E04) ^ mcKey.readUInt32(0x0082);
if (usHeapRva == 0 || usHeapSize == 0)

View File

@ -0,0 +1,57 @@
/*
Copyright (C) 2011-2012 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.IO;
using de4dot.PE;
namespace de4dot.code.deobfuscators.MaxtoCode {
class McKey {
PeHeader peHeader;
byte[] data;
public byte this[int index] {
get { return data[index]; }
}
public McKey(PeImage peImage, PeHeader peHeader) {
this.peHeader = peHeader;
try {
this.data = peImage.readBytes(peHeader.getMcKeyRva(), 0x2000);
}
catch (IOException) {
this.data = peImage.readBytes(peHeader.getMcKeyRva(), 0x1000);
}
}
public byte[] readBytes(int offset, int len) {
byte[] bytes = new byte[len];
Array.Copy(data, offset, bytes, 0, len);
return bytes;
}
public byte readByte(int offset) {
return data[offset];
}
public uint readUInt32(int offset) {
return BitConverter.ToUInt32(data, offset);
}
}
}

View File

@ -0,0 +1,100 @@
/*
Copyright (C) 2011-2012 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 de4dot.PE;
namespace de4dot.code.deobfuscators.MaxtoCode {
enum EncryptionVersion {
Unknown,
V1,
V2,
V3,
V4,
V5,
}
class PeHeader {
const int XOR_KEY = 0x7ABF931;
EncryptionVersion version;
byte[] headerData;
public EncryptionVersion EncryptionVersion {
get { return version; }
}
public PeHeader(MainType mainType, PeImage peImage) {
uint headerOffset;
version = getHeaderOffsetAndVersion(peImage, out headerOffset);
headerData = peImage.offsetReadBytes(headerOffset, 0x1000);
}
public uint getMcKeyRva() {
return getRva2(0x0FFC, XOR_KEY);
}
public uint getRva1(int offset, uint xorKey) {
return (readUInt32(offset) ^ xorKey);
}
public uint getRva2(int offset, uint xorKey) {
return (readUInt32(offset) ^ xorKey);
}
public uint readUInt32(int offset) {
return BitConverter.ToUInt32(headerData, offset);
}
static EncryptionVersion getHeaderOffsetAndVersion(PeImage peImage, out uint headerOffset) {
headerOffset = 0;
var version = getVersion(peImage, headerOffset);
if (version != EncryptionVersion.Unknown)
return version;
var section = peImage.findSection(".rsrc");
if (section == null)
return EncryptionVersion.Unknown;
headerOffset = section.pointerToRawData;
uint end = section.pointerToRawData + section.sizeOfRawData - 0x1000 + 1;
while (headerOffset < end) {
version = getVersion(peImage, headerOffset);
if (version != EncryptionVersion.Unknown)
return version;
headerOffset++;
}
return EncryptionVersion.Unknown;
}
static EncryptionVersion getVersion(PeImage peImage, uint headerOffset) {
uint m1lo = peImage.offsetReadUInt32(headerOffset + 0x900);
uint m1hi = peImage.offsetReadUInt32(headerOffset + 0x904);
foreach (var info in EncryptionInfos.Rva900h) {
if (info.MagicLo == m1lo && info.MagicHi == m1hi)
return info.Version;
}
return EncryptionVersion.Unknown;
}
}
}