Merge branch 'master' into cs
This commit is contained in:
commit
9754b01ba9
|
@ -71,6 +71,14 @@ namespace de4dot.PE {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SectionHeader findSection(string displayName) {
|
||||||
|
foreach (var section in sectionHeaders) {
|
||||||
|
if (section.displayName == displayName)
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
void seek(uint position) {
|
void seek(uint position) {
|
||||||
reader.BaseStream.Position = position;
|
reader.BaseStream.Position = position;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,17 +36,17 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
class PeHeader {
|
class PeHeader {
|
||||||
const int XOR_KEY = 0x7ABF931;
|
const int XOR_KEY = 0x7ABF931;
|
||||||
|
|
||||||
|
EncryptionVersion version;
|
||||||
byte[] headerData;
|
byte[] headerData;
|
||||||
uint rvaDispl1;
|
|
||||||
uint rvaDispl2;
|
public EncryptionVersion EncryptionVersion {
|
||||||
|
get { return version; }
|
||||||
|
}
|
||||||
|
|
||||||
public PeHeader(MainType mainType, PeImage peImage) {
|
public PeHeader(MainType mainType, PeImage peImage) {
|
||||||
headerData = getPeHeaderData(peImage);
|
uint headerOffset;
|
||||||
|
version = getHeaderOffsetAndVersion(peImage, out headerOffset);
|
||||||
if (!mainType.IsOld && peImage.readUInt32(0x2008) != 0x48) {
|
headerData = peImage.offsetReadBytes(headerOffset, 0x1000);
|
||||||
rvaDispl1 = readUInt32(0x0FB0) ^ XOR_KEY;
|
|
||||||
rvaDispl2 = readUInt32(0x0FB4) ^ XOR_KEY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint getMcKeyRva() {
|
public uint getMcKeyRva() {
|
||||||
|
@ -54,39 +54,50 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint getRva1(int offset, uint xorKey) {
|
public uint getRva1(int offset, uint xorKey) {
|
||||||
return (readUInt32(offset) ^ xorKey) - rvaDispl1;
|
return (readUInt32(offset) ^ xorKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint getRva2(int offset, uint xorKey) {
|
public uint getRva2(int offset, uint xorKey) {
|
||||||
return (readUInt32(offset) ^ xorKey) - rvaDispl2;
|
return (readUInt32(offset) ^ xorKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint readUInt32(int offset) {
|
public uint readUInt32(int offset) {
|
||||||
return BitConverter.ToUInt32(headerData, offset);
|
return BitConverter.ToUInt32(headerData, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte[] getPeHeaderData(PeImage peImage) {
|
static EncryptionVersion getHeaderOffsetAndVersion(PeImage peImage, out uint headerOffset) {
|
||||||
var data = new byte[0x1000];
|
headerOffset = 0;
|
||||||
|
|
||||||
var firstSection = peImage.Sections[0];
|
var version = getVersion(peImage, headerOffset);
|
||||||
readTo(peImage, data, 0, 0, firstSection.pointerToRawData);
|
if (version != EncryptionVersion.Unknown)
|
||||||
|
return version;
|
||||||
|
|
||||||
foreach (var section in peImage.Sections) {
|
var section = peImage.findSection(".rsrc");
|
||||||
if (section.virtualAddress >= data.Length)
|
if (section == null)
|
||||||
continue;
|
return EncryptionVersion.Unknown;
|
||||||
int offset = (int)section.virtualAddress;
|
|
||||||
readTo(peImage, data, offset, section.pointerToRawData, section.sizeOfRawData);
|
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 data;
|
return EncryptionVersion.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readTo(PeImage peImage, byte[] data, int destOffset, uint imageOffset, uint maxLength) {
|
static EncryptionVersion getVersion(PeImage peImage, uint headerOffset) {
|
||||||
if (destOffset > data.Length)
|
uint m1lo = peImage.offsetReadUInt32(headerOffset + 0x900);
|
||||||
return;
|
uint m1hi = peImage.offsetReadUInt32(headerOffset + 0x904);
|
||||||
int len = Math.Min(data.Length - destOffset, (int)maxLength);
|
|
||||||
var newData = peImage.offsetReadBytes(imageOffset, len);
|
foreach (var info in encryptionInfos_Rva900h) {
|
||||||
Array.Copy(newData, 0, data, destOffset, newData.Length);
|
if (info.MagicLo == m1lo && info.MagicHi == m1hi)
|
||||||
|
return info.Version;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EncryptionVersion.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +129,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
V2,
|
V2,
|
||||||
V3,
|
V3,
|
||||||
V4,
|
V4,
|
||||||
|
V5,
|
||||||
}
|
}
|
||||||
|
|
||||||
class EncryptionInfo {
|
class EncryptionInfo {
|
||||||
|
@ -126,7 +138,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
public EncryptionVersion Version { get; set; }
|
public EncryptionVersion Version { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
static EncryptionInfo[] encryptionInfos_Rva900h = new EncryptionInfo[] {
|
static readonly EncryptionInfo[] encryptionInfos_Rva900h = new EncryptionInfo[] {
|
||||||
// PE header timestamp
|
// PE header timestamp
|
||||||
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
|
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
|
||||||
new EncryptionInfo {
|
new EncryptionInfo {
|
||||||
|
@ -176,9 +188,15 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
MagicHi = 0xF28EE0A3,
|
MagicHi = 0xF28EE0A3,
|
||||||
Version = EncryptionVersion.V4,
|
Version = EncryptionVersion.V4,
|
||||||
},
|
},
|
||||||
|
// 4F8E262C = Wed, 18 Apr 2012 02:25:48
|
||||||
|
new EncryptionInfo {
|
||||||
|
MagicLo = 0xBA983B87,
|
||||||
|
MagicHi = 0xF28EDDA3,
|
||||||
|
Version = EncryptionVersion.V5,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static EncryptionInfo[] encryptionInfos_McKey8C0h = new EncryptionInfo[] {
|
static readonly EncryptionInfo[] encryptionInfos_McKey8C0h = new EncryptionInfo[] {
|
||||||
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
|
// 462FA2D2 = Wed, 25 Apr 2007 18:49:54 (3.20)
|
||||||
new EncryptionInfo {
|
new EncryptionInfo {
|
||||||
MagicLo = 0x6AA13B13,
|
MagicLo = 0x6AA13B13,
|
||||||
|
@ -217,6 +235,12 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
MagicHi = 0xD72B8A1F,
|
MagicHi = 0xD72B8A1F,
|
||||||
Version = EncryptionVersion.V4,
|
Version = EncryptionVersion.V4,
|
||||||
},
|
},
|
||||||
|
// 4F8E262C = Wed, 18 Apr 2012 02:25:48
|
||||||
|
new EncryptionInfo {
|
||||||
|
MagicLo = 0xAA731B13,
|
||||||
|
MagicHi = 0xD723891F,
|
||||||
|
Version = EncryptionVersion.V5,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
class MethodInfos {
|
class MethodInfos {
|
||||||
|
@ -268,8 +292,9 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
EncryptionVersion getVersion() {
|
EncryptionVersion getVersion() {
|
||||||
uint m1lo = peHeader.readUInt32(0x900);
|
if (peHeader.EncryptionVersion != EncryptionVersion.Unknown)
|
||||||
uint m1hi = peHeader.readUInt32(0x904);
|
return peHeader.EncryptionVersion;
|
||||||
|
|
||||||
uint m2lo = mcKey.readUInt32(0x8C0);
|
uint m2lo = mcKey.readUInt32(0x8C0);
|
||||||
uint m2hi = mcKey.readUInt32(0x8C4);
|
uint m2hi = mcKey.readUInt32(0x8C4);
|
||||||
|
|
||||||
|
@ -278,12 +303,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return info.Version;
|
return info.Version;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var info in encryptionInfos_Rva900h) {
|
Log.w("Could not detect MC version. Magic2: {0:X8} {1:X8}", m2lo, m2hi);
|
||||||
if (info.MagicLo == m1lo && info.MagicHi == m1hi)
|
|
||||||
return info.Version;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.w("Could not detect MC version. Magic1: {0:X8} {1:X8}, Magic2: {2:X8} {3:X8}", m1lo, m1hi, m2lo, m2hi);
|
|
||||||
return EncryptionVersion.Unknown;
|
return EncryptionVersion.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,12 +374,14 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
static readonly int[] typeToTypesV2 = new int[] { -1, 3, 2, 1, 4, 5, 6, 7 };
|
static readonly int[] typeToTypesV2 = new int[] { -1, 3, 2, 1, 4, 5, 6, 7 };
|
||||||
static readonly int[] typeToTypesV3 = new int[] { -1, 1, 2, 3, 4, 5, 6, 7 };
|
static readonly int[] typeToTypesV3 = new int[] { -1, 1, 2, 3, 4, 5, 6, 7 };
|
||||||
static readonly int[] typeToTypesV4 = new int[] { -1, 2, 1, 3, 4, 5, 6, 7 };
|
static readonly int[] typeToTypesV4 = new int[] { -1, 2, 1, 3, 4, 5, 6, 7 };
|
||||||
|
static readonly int[] typeToTypesV5 = new int[] { -1, 4, 2, 3, 1, 5, 6, 7 };
|
||||||
void initializeDecrypter() {
|
void initializeDecrypter() {
|
||||||
switch (getVersion()) {
|
switch (getVersion()) {
|
||||||
case EncryptionVersion.V1: decrypter = new Decrypter(this, typeToTypesV1); break;
|
case EncryptionVersion.V1: decrypter = new Decrypter(this, typeToTypesV1); break;
|
||||||
case EncryptionVersion.V2: decrypter = new Decrypter(this, typeToTypesV2); break;
|
case EncryptionVersion.V2: decrypter = new Decrypter(this, typeToTypesV2); break;
|
||||||
case EncryptionVersion.V3: decrypter = new Decrypter(this, typeToTypesV3); break;
|
case EncryptionVersion.V3: decrypter = new Decrypter(this, typeToTypesV3); break;
|
||||||
case EncryptionVersion.V4: decrypter = new Decrypter(this, typeToTypesV4); break;
|
case EncryptionVersion.V4: decrypter = new Decrypter(this, typeToTypesV4); break;
|
||||||
|
case EncryptionVersion.V5: decrypter = new Decrypter(this, typeToTypesV5); break;
|
||||||
|
|
||||||
case EncryptionVersion.Unknown:
|
case EncryptionVersion.Unknown:
|
||||||
default:
|
default:
|
||||||
|
@ -375,15 +397,14 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
throw new ApplicationException("Invalid number of encrypted methods");
|
throw new ApplicationException("Invalid number of encrypted methods");
|
||||||
|
|
||||||
xorKey = (uint)numMethods;
|
xorKey = (uint)numMethods;
|
||||||
uint rvaDispl = !mainType.IsOld && peImage.readUInt32(0x2008) != 0x48 ? 0x1000U : 0;
|
|
||||||
int numEncryptedDataInfos = ((int)structSize - 0xC) / ENCRYPTED_DATA_INFO_SIZE;
|
int numEncryptedDataInfos = ((int)structSize - 0xC) / ENCRYPTED_DATA_INFO_SIZE;
|
||||||
var encryptedDataInfos = new byte[numEncryptedDataInfos][];
|
var encryptedDataInfos = new byte[numEncryptedDataInfos][];
|
||||||
|
|
||||||
uint offset = 8;
|
uint offset = 8;
|
||||||
for (int i = 0; i < numMethods; i++, offset += structSize) {
|
for (int i = 0; i < numMethods; i++, offset += structSize) {
|
||||||
uint methodBodyRva = readEncryptedUInt32(offset) - rvaDispl;
|
uint methodBodyRva = readEncryptedUInt32(offset);
|
||||||
uint totalSize = readEncryptedUInt32(offset + 4);
|
uint totalSize = readEncryptedUInt32(offset + 4);
|
||||||
uint methodInstructionRva = readEncryptedUInt32(offset + 8) - rvaDispl;
|
uint methodInstructionRva = readEncryptedUInt32(offset + 8);
|
||||||
|
|
||||||
var decryptedData = new byte[totalSize];
|
var decryptedData = new byte[totalSize];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user