2012-07-21 00:15:40 +08:00
|
|
|
|
/*
|
2013-01-02 00:03:16 +08:00
|
|
|
|
Copyright (C) 2011-2013 de4dot@gmail.com
|
2012-07-21 00:15:40 +08:00
|
|
|
|
|
|
|
|
|
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;
|
2013-01-25 01:33:14 +08:00
|
|
|
|
using dnlib.PE;
|
2012-07-21 00:15:40 +08:00
|
|
|
|
|
|
|
|
|
namespace de4dot.code.deobfuscators.MaxtoCode {
|
|
|
|
|
enum EncryptionVersion {
|
|
|
|
|
Unknown,
|
|
|
|
|
V1,
|
|
|
|
|
V2,
|
|
|
|
|
V3,
|
|
|
|
|
V4,
|
|
|
|
|
V5,
|
2012-12-20 08:34:16 +08:00
|
|
|
|
V6,
|
2013-01-25 01:33:14 +08:00
|
|
|
|
V7,
|
2013-10-21 00:09:38 +08:00
|
|
|
|
V8,
|
2012-07-21 00:15:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PeHeader {
|
|
|
|
|
EncryptionVersion version;
|
|
|
|
|
byte[] headerData;
|
2012-12-20 08:34:16 +08:00
|
|
|
|
uint xorKey;
|
2012-07-21 00:15:40 +08:00
|
|
|
|
|
|
|
|
|
public EncryptionVersion EncryptionVersion {
|
|
|
|
|
get { return version; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-21 18:14:20 +08:00
|
|
|
|
public PeHeader(MainType mainType, MyPEImage peImage) {
|
2012-07-21 00:15:40 +08:00
|
|
|
|
uint headerOffset;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
version = GetHeaderOffsetAndVersion(peImage, out headerOffset);
|
2013-10-21 00:09:38 +08:00
|
|
|
|
headerData = peImage.OffsetReadBytes(headerOffset, 0x1000);
|
2012-12-20 08:34:16 +08:00
|
|
|
|
|
|
|
|
|
switch (version) {
|
|
|
|
|
case EncryptionVersion.V1:
|
|
|
|
|
case EncryptionVersion.V2:
|
|
|
|
|
case EncryptionVersion.V3:
|
|
|
|
|
case EncryptionVersion.V4:
|
|
|
|
|
case EncryptionVersion.V5:
|
|
|
|
|
default:
|
|
|
|
|
xorKey = 0x7ABF931;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case EncryptionVersion.V6:
|
|
|
|
|
xorKey = 0x7ABA931;
|
|
|
|
|
break;
|
2013-01-25 01:33:14 +08:00
|
|
|
|
|
|
|
|
|
case EncryptionVersion.V7:
|
|
|
|
|
xorKey = 0x8ABA931;
|
|
|
|
|
break;
|
2013-10-21 00:09:38 +08:00
|
|
|
|
|
|
|
|
|
case EncryptionVersion.V8:
|
|
|
|
|
if (CheckMcKeyRva(peImage, 0x99BA9A13))
|
|
|
|
|
break;
|
|
|
|
|
if (CheckMcKeyRva(peImage, 0x18ABA931))
|
|
|
|
|
break;
|
2013-11-06 10:20:44 +08:00
|
|
|
|
if (CheckMcKeyRva(peImage, 0x18ABA933))
|
|
|
|
|
break;
|
2013-10-21 00:09:38 +08:00
|
|
|
|
break;
|
2012-12-20 08:34:16 +08:00
|
|
|
|
}
|
2013-10-21 00:09:38 +08:00
|
|
|
|
}
|
2012-12-20 08:34:16 +08:00
|
|
|
|
|
2013-10-21 00:09:38 +08:00
|
|
|
|
bool CheckMcKeyRva(MyPEImage peImage, uint newXorKey) {
|
|
|
|
|
xorKey = newXorKey;
|
|
|
|
|
uint rva = GetMcKeyRva();
|
|
|
|
|
return (rva & 0xFFF) == 0 && peImage.FindSection((RVA)rva) != null;
|
2012-07-21 00:15:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public uint GetMcKeyRva() {
|
|
|
|
|
return GetRva(0x0FFC, xorKey);
|
2012-07-21 00:15:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public uint GetRva(int offset, uint xorKey) {
|
|
|
|
|
return ReadUInt32(offset) ^ xorKey;
|
2012-07-21 00:15:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public uint ReadUInt32(int offset) {
|
2012-07-21 00:15:40 +08:00
|
|
|
|
return BitConverter.ToUInt32(headerData, offset);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static EncryptionVersion GetHeaderOffsetAndVersion(MyPEImage peImage, out uint headerOffset) {
|
2012-07-21 00:15:40 +08:00
|
|
|
|
headerOffset = 0;
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var version = GetVersion(peImage, headerOffset);
|
2012-07-21 00:15:40 +08:00
|
|
|
|
if (version != EncryptionVersion.Unknown)
|
|
|
|
|
return version;
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var section = peImage.FindSection(".rsrc");
|
2013-01-25 01:33:14 +08:00
|
|
|
|
if (section != null) {
|
|
|
|
|
version = GetHeaderOffsetAndVersion(section, peImage, out headerOffset);
|
|
|
|
|
if (version != EncryptionVersion.Unknown)
|
|
|
|
|
return version;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var section2 in peImage.Sections) {
|
|
|
|
|
version = GetHeaderOffsetAndVersion(section2, peImage, out headerOffset);
|
|
|
|
|
if (version != EncryptionVersion.Unknown)
|
|
|
|
|
return version;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EncryptionVersion.Unknown;
|
|
|
|
|
}
|
2012-07-21 00:15:40 +08:00
|
|
|
|
|
2013-01-25 01:33:14 +08:00
|
|
|
|
static EncryptionVersion GetHeaderOffsetAndVersion(ImageSectionHeader section, MyPEImage peImage, out uint headerOffset) {
|
2012-11-21 18:14:20 +08:00
|
|
|
|
headerOffset = section.PointerToRawData;
|
|
|
|
|
uint end = section.PointerToRawData + section.SizeOfRawData - 0x1000 + 1;
|
2012-07-21 00:15:40 +08:00
|
|
|
|
while (headerOffset < end) {
|
2013-01-25 01:33:14 +08:00
|
|
|
|
var version = GetVersion(peImage, headerOffset);
|
2012-07-21 00:15:40 +08:00
|
|
|
|
if (version != EncryptionVersion.Unknown)
|
|
|
|
|
return version;
|
|
|
|
|
headerOffset++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EncryptionVersion.Unknown;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static EncryptionVersion GetVersion(MyPEImage peImage, uint headerOffset) {
|
|
|
|
|
uint m1lo = peImage.OffsetReadUInt32(headerOffset + 0x900);
|
|
|
|
|
uint m1hi = peImage.OffsetReadUInt32(headerOffset + 0x904);
|
2012-07-21 00:15:40 +08:00
|
|
|
|
|
|
|
|
|
foreach (var info in EncryptionInfos.Rva900h) {
|
|
|
|
|
if (info.MagicLo == m1lo && info.MagicHi == m1hi)
|
|
|
|
|
return info.Version;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EncryptionVersion.Unknown;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|