📄 pehandler.cpp
字号:
// PeHandler.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "Common/Buffer.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Windows/PropVariantUtils.h"
#include "Windows/Time.h"
#include "../Common/LimitedStreams.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "../Compress/Copy/CopyCoder.h"
#include "Common/DummyOutStream.h"
#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
using namespace NWindows;
namespace NArchive {
namespace NPe {
#define NUM_SCAN_SECTIONS_MAX (1 << 6)
#define PE_SIG 0x00004550
#define PE_OptHeader_Magic_32 0x10B
#define PE_OptHeader_Magic_64 0x20B
static AString GetDecString(UInt32 v)
{
char sz[32];
ConvertUInt64ToString(v, sz);
return sz;
}
struct CVersion
{
UInt16 Major;
UInt16 Minor;
void Parse(const Byte *buf);
AString GetString() const { return GetDecString(Major) + '.' + GetDecString(Minor); }
};
void CVersion::Parse(const Byte *p)
{
Major = Get16(p);
Minor = Get16(p + 2);
}
static const UInt32 kHeaderSize = 4 + 20;
struct CHeader
{
UInt16 NumSections;
UInt32 Time;
UInt32 PointerToSymbolTable;
UInt32 NumSymbols;
UInt16 OptHeaderSize;
UInt16 Flags;
UInt16 Machine;
bool Parse(const Byte *buf);
};
bool CHeader::Parse(const Byte *p)
{
if (Get32(p) != PE_SIG)
return false;
p += 4;
Machine = Get16(p + 0);
NumSections = Get16(p + 2);
Time = Get32(p + 4);
PointerToSymbolTable = Get32(p + 8);
NumSymbols = Get32(p + 12);
OptHeaderSize = Get16(p + 16);
Flags = Get16(p + 18);
return true;
}
struct CDirLink
{
UInt32 Va;
UInt32 Size;
void Parse(const Byte *p);
};
void CDirLink::Parse(const Byte *p)
{
Va = Get32(p);
Size = Get32(p + 4);
};
enum
{
kDirLink_Certificate = 4,
kDirLink_Debug = 6
};
struct CDebugEntry
{
UInt32 Flags;
UInt32 Time;
CVersion Ver;
UInt32 Type;
UInt32 Size;
UInt32 Va;
UInt32 Pa;
void Parse(const Byte *p);
};
void CDebugEntry::Parse(const Byte *p)
{
Flags = Get32(p);
Time = Get32(p + 4);
Ver.Parse(p + 8);
Type = Get32(p + 12);
Size = Get32(p + 16);
Va = Get32(p + 20);
Pa = Get32(p + 24);
}
static const UInt32 kNumDirItemsMax = 16;
struct COptHeader
{
UInt16 Magic;
Byte LinkerVerMajor;
Byte LinkerVerMinor;
UInt32 CodeSize;
UInt32 InitDataSize;
UInt32 UninitDataSize;
// UInt32 AddressOfEntryPoint;
// UInt32 BaseOfCode;
// UInt32 BaseOfData32;
// UInt64 ImageBase;
UInt32 SectAlign;
UInt32 FileAlign;
CVersion OsVer;
CVersion ImageVer;
CVersion SubsysVer;
UInt32 ImageSize;
UInt32 HeadersSize;
UInt32 CheckSum;
UInt16 SubSystem;
UInt16 DllCharacts;
UInt64 StackReserve;
UInt64 StackCommit;
UInt64 HeapReserve;
UInt64 HeapCommit;
UInt32 NumDirItems;
CDirLink DirItems[kNumDirItemsMax];
bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; }
bool Parse(const Byte *p, UInt32 size);
};
bool COptHeader::Parse(const Byte *p, UInt32 size)
{
Magic = Get16(p);
switch (Magic)
{
case PE_OptHeader_Magic_32:
case PE_OptHeader_Magic_64:
break;
default:
return false;
}
LinkerVerMajor = p[2];
LinkerVerMinor = p[3];
bool hdr64 = Is64Bit();
CodeSize = Get32(p + 4);
InitDataSize = Get32(p + 8);
UninitDataSize = Get32(p + 12);
// AddressOfEntryPoint = Get32(p + 16);
// BaseOfCode = Get32(p + 20);
// BaseOfData32 = Get32(p + 24);
// ImageBase = hdr64 ? GetUi64(p + 24) :Get32(p + 28);
SectAlign = Get32(p + 32);
FileAlign = Get32(p + 36);
OsVer.Parse(p + 40);
ImageVer.Parse(p + 44);
SubsysVer.Parse(p + 48);
// reserved = Get32(p + 52);
ImageSize = Get32(p + 56);
HeadersSize = Get32(p + 60);
CheckSum = Get32(p + 64);
SubSystem = Get16(p + 68);
DllCharacts = Get16(p + 70);
if (hdr64)
{
StackReserve = Get64(p + 72);
StackCommit = Get64(p + 80);
HeapReserve = Get64(p + 88);
HeapCommit = Get64(p + 96);
}
else
{
StackReserve = Get32(p + 72);
StackCommit = Get32(p + 76);
HeapReserve = Get32(p + 80);
HeapCommit = Get32(p + 84);
}
UInt32 pos = (hdr64 ? 108 : 92);
NumDirItems = Get32(p + pos);
pos += 4;
if (pos + 8 * NumDirItems != size)
return false;
for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++)
DirItems[i].Parse(p + pos + i * 8);
return true;
}
static const UInt32 kSectionSize = 40;
struct CSection
{
AString Name;
UInt32 VSize;
UInt32 Va;
UInt32 PSize;
UInt32 Pa;
UInt32 Flags;
UInt32 Time;
// UInt16 NumRelocs;
bool IsDebug;
bool IsRealSect;
CSection(): IsRealSect(false), IsDebug(false) {}
UInt64 GetPackSize() const { return PSize; }
void UpdateTotalSize(UInt32 &totalSize)
{
UInt32 t = Pa + PSize;
if (t > totalSize)
totalSize = t;
}
void Parse(const Byte *p);
};
static AString GetName(const Byte *name)
{
const int kNameSize = 8;
AString res;
char *p = res.GetBuffer(kNameSize);
memcpy(p, name, kNameSize);
p[kNameSize] = 0;
res.ReleaseBuffer();
return res;
}
void CSection::Parse(const Byte *p)
{
Name = GetName(p);
VSize = Get32(p + 8);
Va = Get32(p + 12);
PSize = Get32(p + 16);
Pa = Get32(p + 20);
// NumRelocs = Get16(p + 32);
Flags = Get32(p + 36);
}
static const CUInt32PCharPair g_HeaderCharacts[] =
{
{ 1 << 1, "Executable" },
{ 1 << 13, "DLL" },
{ 1 << 8, "32-bit" },
{ 1 << 5, "LargeAddress" },
{ 1 << 0, "NoRelocs" },
{ 1 << 2, "NoLineNums" },
{ 1 << 3, "NoLocalSyms" },
{ 1 << 4, "AggressiveWsTrim" },
{ 1 << 9, "NoDebugInfo" },
{ 1 << 10, "RemovableRun" },
{ 1 << 11, "NetRun" },
{ 1 << 12, "System" },
{ 1 << 14, "UniCPU" },
{ 1 << 7, "Little-Endian" },
{ 1 << 15, "Big-Endian" }
};
static const CUInt32PCharPair g_DllCharacts[] =
{
{ 1 << 6, "Relocated" },
{ 1 << 7, "Integrity" },
{ 1 << 8, "NX-Compatible" },
{ 1 << 9, "NoIsolation" },
{ 1 << 10, "NoSEH" },
{ 1 << 11, "NoBind" },
{ 1 << 13, "WDM" },
{ 1 << 15, "TerminalServerAware" }
};
static const CUInt32PCharPair g_SectFlags[] =
{
{ 1 << 3, "NoPad" },
{ 1 << 5, "Code" },
{ 1 << 6, "InitializedData" },
{ 1 << 7, "UninitializedData" },
{ 1 << 9, "Comments" },
{ 1 << 11, "Remove" },
{ 1 << 12, "COMDAT" },
{ 1 << 15, "GP" },
{ 1 << 24, "ExtendedRelocations" },
{ 1 << 25, "Discardable" },
{ 1 << 26, "NotCached" },
{ 1 << 27, "NotPaged" },
{ 1 << 28, "Shared" },
{ 1 << 29, "Execute" },
{ 1 << 30, "Read" },
{ (UInt32)1 << 31, "Write" }
};
static const CUInt32PCharPair g_MachinePairs[] =
{
{ 0x014C, "x86" },
{ 0x0162, "MIPS-R3000" },
{ 0x0166, "MIPS-R4000" },
{ 0x0168, "MIPS-R10000" },
{ 0x0169, "MIPS-V2" },
{ 0x0184, "Alpha" },
{ 0x01A2, "SH3" },
{ 0x01A3, "SH3-DSP" },
{ 0x01A4, "SH3E" },
{ 0x01A6, "SH4" },
{ 0x01A8, "SH5" },
{ 0x01C0, "ARM" },
{ 0x01C2, "ARM-Thumb" },
{ 0x01F0, "PPC" },
{ 0x01F1, "PPC-FP" },
{ 0x0200, "IA-64" },
{ 0x0284, "Alpha-64" },
{ 0x0200, "IA-64" },
{ 0x0366, "MIPSFPU" },
{ 0x8664, "x64" },
{ 0x0EBC, "EFI" }
};
static const CUInt32PCharPair g_SubSystems[] =
{
{ 0, "Unknown" },
{ 1, "Native" },
{ 2, "Windows GUI" },
{ 3, "Windows CUI" },
{ 7, "Posix" },
{ 9, "Windows CE" },
{ 10, "EFI" },
{ 11, "EFI Boot" },
{ 12, "EFI Runtime" },
{ 13, "EFI ROM" },
{ 14, "XBOX" }
};
class CHandler:
public IInArchive,
public CMyUnknownImp
{
CMyComPtr<IInStream> _inStream;
CObjectVector<CSection> _sections;
UInt32 _peOffset;
CHeader _header;
COptHeader _optHeader;
UInt32 _totalSize;
UInt32 _totalSizeLimited;
HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);
HRESULT Open2(IInStream *stream);
bool Parse(const Byte *buf, UInt32 size);
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
};
bool CHandler::Parse(const Byte *buf, UInt32 size)
{
UInt32 i;
if (size < 512)
return false;
_peOffset = Get32(buf + 0x3C);
if (_peOffset >= 0x1000 || _peOffset + 512 > size || (_peOffset & 7) != 0)
return false;
UInt32 pos = _peOffset;
if (!_header.Parse(buf + pos))
return false;
if (_header.OptHeaderSize > 512 || _header.NumSections > NUM_SCAN_SECTIONS_MAX)
return false;
pos += kHeaderSize;
if (!_optHeader.Parse(buf + pos, _header.OptHeaderSize))
return false;
pos += _header.OptHeaderSize;
_totalSize = pos;
for (i = 0; i < _header.NumSections; i++, pos += kSectionSize)
{
CSection sect;
if (pos + kSectionSize > size)
return false;
sect.Parse(buf + pos);
sect.IsRealSect = true;
sect.UpdateTotalSize(_totalSize);
_sections.Add(sect);
}
return true;
}
enum
{
kpidSectAlign = kpidUserDefined,
kpidFileAlign,
kpidLinkerVer,
kpidOsVer,
kpidImageVer,
kpidSubsysVer,
kpidCodeSize,
kpidImageSize,
kpidInitDataSize,
kpidUnInitDataSize,
kpidHeadersSizeUnInitDataSize,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -