mirror of
https://github.com/QuasarApp/pe-parse.git
synced 2025-04-26 20:34:31 +00:00
Merge pull request #9 from wxsBSD/pe32_plus_and_more
Implement PE32+ and error reporting.
This commit is contained in:
commit
f59587712e
@ -29,20 +29,12 @@ THE SOFTWARE.
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
template <class T>
|
||||
static
|
||||
string to_string(T t, ios_base & (*f)(ios_base&)) {
|
||||
ostringstream oss;
|
||||
oss << f << t;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
int printExps(void *N, VA funcAddr, std::string &mod, std::string &func) {
|
||||
cout << "EXP: ";
|
||||
cout << mod;
|
||||
cout << "!";
|
||||
cout << func;
|
||||
cout << ":";
|
||||
cout << ": 0x";
|
||||
cout << to_string<uint32_t>(funcAddr, hex);
|
||||
cout << endl;
|
||||
return 0;
|
||||
@ -95,16 +87,16 @@ int printRsrc(void *N,
|
||||
if (r.type_str.length())
|
||||
cout << "Type (string): " << r.type_str << endl;
|
||||
else
|
||||
cout << "Type: " << to_string<uint32_t>(r.type, hex) << endl;
|
||||
cout << "Type: 0x" << to_string<uint32_t>(r.type, hex) << endl;
|
||||
if (r.name_str.length())
|
||||
cout << "Name (string): " << r.name_str << endl;
|
||||
else
|
||||
cout << "Name: " << to_string<uint32_t>(r.name, hex) << endl;
|
||||
cout << "Name: 0x" << to_string<uint32_t>(r.name, hex) << endl;
|
||||
if (r.lang_str.length())
|
||||
cout << "Lang (string): " << r.lang_str << endl;
|
||||
else
|
||||
cout << "Lang: " << to_string<uint32_t>(r.lang, hex) << endl;
|
||||
cout << "Codepage: " << to_string<uint32_t>(r.codepage, hex) << endl;
|
||||
cout << "Lang: 0x" << to_string<uint32_t>(r.lang, hex) << endl;
|
||||
cout << "Codepage: 0x" << to_string<uint32_t>(r.codepage, hex) << endl;
|
||||
cout << "RVA: " << to_string<uint32_t>(r.RVA, dec) << endl;
|
||||
cout << "Size: " << to_string<uint32_t>(r.size, dec) << endl;
|
||||
return 0;
|
||||
@ -117,7 +109,7 @@ int printSecs(void *N,
|
||||
bounded_buffer *data)
|
||||
{
|
||||
cout << "Sec Name: " << secName << endl;
|
||||
cout << "Sec Base: " << to_string<uint64_t>(secBase, hex) << endl;
|
||||
cout << "Sec Base: 0x" << to_string<uint64_t>(secBase, hex) << endl;
|
||||
cout << "Sec Size: " << to_string<uint64_t>(data->bufLen, dec) << endl;
|
||||
return 0;
|
||||
}
|
||||
@ -130,45 +122,73 @@ int main(int argc, char *argv[]) {
|
||||
//print out some things
|
||||
#define DUMP_FIELD(x) \
|
||||
cout << "" #x << ": 0x"; \
|
||||
cout << to_string<uint32_t>(p->peHeader.x, hex) << endl;
|
||||
cout << to_string<uint32_t>(p->peHeader.nt.x, hex) << endl;
|
||||
#define DUMP_DEC_FIELD(x) \
|
||||
cout << "" #x << ": "; \
|
||||
cout << to_string<uint32_t>(p->peHeader.x, dec) << endl;
|
||||
cout << to_string<uint32_t>(p->peHeader.nt.x, dec) << endl;
|
||||
|
||||
DUMP_FIELD(nt.Signature);
|
||||
DUMP_FIELD(nt.FileHeader.Machine);
|
||||
DUMP_FIELD(nt.FileHeader.NumberOfSections);
|
||||
DUMP_DEC_FIELD(nt.FileHeader.TimeDateStamp);
|
||||
DUMP_FIELD(nt.FileHeader.PointerToSymbolTable);
|
||||
DUMP_DEC_FIELD(nt.FileHeader.NumberOfSymbols);
|
||||
DUMP_FIELD(nt.FileHeader.SizeOfOptionalHeader);
|
||||
DUMP_FIELD(nt.FileHeader.Characteristics);
|
||||
DUMP_FIELD(nt.OptionalHeader.Magic);
|
||||
DUMP_DEC_FIELD(nt.OptionalHeader.MajorLinkerVersion);
|
||||
DUMP_DEC_FIELD(nt.OptionalHeader.MinorLinkerVersion);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfCode);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfInitializedData);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfUninitializedData);
|
||||
DUMP_FIELD(nt.OptionalHeader.AddressOfEntryPoint);
|
||||
DUMP_FIELD(nt.OptionalHeader.BaseOfCode);
|
||||
DUMP_FIELD(nt.OptionalHeader.BaseOfData);
|
||||
DUMP_FIELD(nt.OptionalHeader.ImageBase);
|
||||
DUMP_FIELD(nt.OptionalHeader.SectionAlignment);
|
||||
DUMP_FIELD(nt.OptionalHeader.FileAlignment);
|
||||
DUMP_DEC_FIELD(nt.OptionalHeader.MajorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(nt.OptionalHeader.MinorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(nt.OptionalHeader.Win32VersionValue);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfImage);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfHeaders);
|
||||
DUMP_FIELD(nt.OptionalHeader.CheckSum);
|
||||
DUMP_FIELD(nt.OptionalHeader.Subsystem);
|
||||
DUMP_FIELD(nt.OptionalHeader.DllCharacteristics);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfStackReserve);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfStackCommit);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfHeapReserve);
|
||||
DUMP_FIELD(nt.OptionalHeader.SizeOfHeapCommit);
|
||||
DUMP_FIELD(nt.OptionalHeader.LoaderFlags);
|
||||
DUMP_DEC_FIELD(nt.OptionalHeader.NumberOfRvaAndSizes);
|
||||
DUMP_FIELD(Signature);
|
||||
DUMP_FIELD(FileHeader.Machine);
|
||||
DUMP_FIELD(FileHeader.NumberOfSections);
|
||||
DUMP_DEC_FIELD(FileHeader.TimeDateStamp);
|
||||
DUMP_FIELD(FileHeader.PointerToSymbolTable);
|
||||
DUMP_DEC_FIELD(FileHeader.NumberOfSymbols);
|
||||
DUMP_FIELD(FileHeader.SizeOfOptionalHeader);
|
||||
DUMP_FIELD(FileHeader.Characteristics);
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
DUMP_FIELD(OptionalHeader.Magic);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MajorLinkerVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MinorLinkerVersion);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfCode);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfInitializedData);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfUninitializedData);
|
||||
DUMP_FIELD(OptionalHeader.AddressOfEntryPoint);
|
||||
DUMP_FIELD(OptionalHeader.BaseOfCode);
|
||||
DUMP_FIELD(OptionalHeader.BaseOfData);
|
||||
DUMP_FIELD(OptionalHeader.ImageBase);
|
||||
DUMP_FIELD(OptionalHeader.SectionAlignment);
|
||||
DUMP_FIELD(OptionalHeader.FileAlignment);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MajorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MinorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.Win32VersionValue);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfImage);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeaders);
|
||||
DUMP_FIELD(OptionalHeader.CheckSum);
|
||||
DUMP_FIELD(OptionalHeader.Subsystem);
|
||||
DUMP_FIELD(OptionalHeader.DllCharacteristics);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfStackReserve);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfStackCommit);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeapReserve);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeapCommit);
|
||||
DUMP_FIELD(OptionalHeader.LoaderFlags);
|
||||
DUMP_DEC_FIELD(OptionalHeader.NumberOfRvaAndSizes);
|
||||
} else {
|
||||
DUMP_FIELD(OptionalHeader64.Magic);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MajorLinkerVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MinorLinkerVersion);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfCode);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfInitializedData);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfUninitializedData);
|
||||
DUMP_FIELD(OptionalHeader64.AddressOfEntryPoint);
|
||||
DUMP_FIELD(OptionalHeader64.BaseOfCode);
|
||||
DUMP_FIELD(OptionalHeader64.ImageBase);
|
||||
DUMP_FIELD(OptionalHeader64.SectionAlignment);
|
||||
DUMP_FIELD(OptionalHeader64.FileAlignment);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MajorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MinorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.Win32VersionValue);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfImage);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeaders);
|
||||
DUMP_FIELD(OptionalHeader64.CheckSum);
|
||||
DUMP_FIELD(OptionalHeader64.Subsystem);
|
||||
DUMP_FIELD(OptionalHeader64.DllCharacteristics);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfStackReserve);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfStackCommit);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeapReserve);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeapCommit);
|
||||
DUMP_FIELD(OptionalHeader64.LoaderFlags);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.NumberOfRvaAndSizes);
|
||||
}
|
||||
|
||||
#undef DUMP_FIELD
|
||||
#undef DUMP_DEC_FIELD
|
||||
@ -198,9 +218,14 @@ int main(int argc, char *argv[]) {
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
cout << "Resources: " << endl;
|
||||
IterRsrc(p, printRsrc, NULL);
|
||||
DestructParsedPE(p);
|
||||
}
|
||||
else {
|
||||
cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")" << endl;
|
||||
cout << "Location: " << GetPEErrLoc() << endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -38,6 +38,9 @@ THE SOFTWARE.
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
extern ::uint32_t err;
|
||||
extern ::string err_loc;
|
||||
|
||||
struct buffer_detail {
|
||||
#ifdef WIN32
|
||||
HANDLE file;
|
||||
@ -94,6 +97,21 @@ bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO: perform endian swap as needed
|
||||
bool readQword(bounded_buffer *b, ::uint32_t offset, ::uint64_t &out) {
|
||||
if(b == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(offset >= b->bufLen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
::uint64_t *tmp = (::uint64_t *)(b->buf+offset);
|
||||
out = *tmp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
#ifdef WIN32
|
||||
@ -120,6 +138,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
int fd = open(filePath, O_RDONLY);
|
||||
|
||||
if(fd == -1) {
|
||||
PE_ERR(PEERR_OPEN);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@ -128,6 +147,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
bounded_buffer *p = new bounded_buffer();
|
||||
|
||||
if(p == NULL) {
|
||||
PE_ERR(PEERR_MEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -136,6 +156,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
|
||||
if(d == NULL) {
|
||||
delete p;
|
||||
PE_ERR(PEERR_MEM);
|
||||
return NULL;
|
||||
}
|
||||
memset(d, 0, sizeof(buffer_detail));
|
||||
@ -149,6 +170,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
|
||||
if(hMap == NULL) {
|
||||
CloseHandle(h);
|
||||
PE_ERR(PEERR_MEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -157,6 +179,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
LPVOID ptr = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
|
||||
if(ptr == NULL) {
|
||||
PE_ERR(PEERR_MEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -172,6 +195,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
close(fd);
|
||||
delete d;
|
||||
delete p;
|
||||
PE_ERR(PEERR_STAT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -181,6 +205,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
close(fd);
|
||||
delete d;
|
||||
delete p;
|
||||
PE_ERR(PEERR_MEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ const boost::uint16_t MZ_MAGIC = 0x5A4D;
|
||||
const boost::uint32_t NT_MAGIC = 0x00004550;
|
||||
const boost::uint16_t NUM_DIR_ENTRIES = 16;
|
||||
const boost::uint16_t NT_OPTIONAL_32_MAGIC = 0x10B;
|
||||
const boost::uint16_t NT_OPTIONAL_64_MAGIC = 0x20B;
|
||||
const boost::uint16_t NT_SHORT_NAME_LEN = 8;
|
||||
const boost::uint16_t DIR_EXPORT = 0;
|
||||
const boost::uint16_t DIR_IMPORT = 1;
|
||||
@ -162,10 +163,49 @@ struct optional_header_32 {
|
||||
data_directory DataDirectory[NUM_DIR_ENTRIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* This is used for PE32+ binaries. It is similar to optional_header_32
|
||||
* except some fields don't exist here (BaseOfData), and others are bigger.
|
||||
*/
|
||||
struct optional_header_64 {
|
||||
boost::uint16_t Magic;
|
||||
boost::uint8_t MajorLinkerVersion;
|
||||
boost::uint8_t MinorLinkerVersion;
|
||||
boost::uint32_t SizeOfCode;
|
||||
boost::uint32_t SizeOfInitializedData;
|
||||
boost::uint32_t SizeOfUninitializedData;
|
||||
boost::uint32_t AddressOfEntryPoint;
|
||||
boost::uint32_t BaseOfCode;
|
||||
boost::uint64_t ImageBase;
|
||||
boost::uint32_t SectionAlignment;
|
||||
boost::uint32_t FileAlignment;
|
||||
boost::uint16_t MajorOperatingSystemVersion;
|
||||
boost::uint16_t MinorOperatingSystemVersion;
|
||||
boost::uint16_t MajorImageVersion;
|
||||
boost::uint16_t MinorImageVersion;
|
||||
boost::uint16_t MajorSubsystemVersion;
|
||||
boost::uint16_t MinorSubsystemVersion;
|
||||
boost::uint32_t Win32VersionValue;
|
||||
boost::uint32_t SizeOfImage;
|
||||
boost::uint32_t SizeOfHeaders;
|
||||
boost::uint32_t CheckSum;
|
||||
boost::uint16_t Subsystem;
|
||||
boost::uint16_t DllCharacteristics;
|
||||
boost::uint64_t SizeOfStackReserve;
|
||||
boost::uint64_t SizeOfStackCommit;
|
||||
boost::uint64_t SizeOfHeapReserve;
|
||||
boost::uint64_t SizeOfHeapCommit;
|
||||
boost::uint32_t LoaderFlags;
|
||||
boost::uint32_t NumberOfRvaAndSizes;
|
||||
data_directory DataDirectory[NUM_DIR_ENTRIES];
|
||||
};
|
||||
|
||||
struct nt_header_32 {
|
||||
boost::uint32_t Signature;
|
||||
file_header FileHeader;
|
||||
optional_header_32 OptionalHeader;
|
||||
optional_header_64 OptionalHeader64;
|
||||
boost::uint16_t OptionalMagic;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -32,7 +32,7 @@ using namespace boost;
|
||||
|
||||
struct section {
|
||||
string sectionName;
|
||||
::uint32_t sectionBase;
|
||||
::uint64_t sectionBase;
|
||||
bounded_buffer *sectionData;
|
||||
image_section_header sec;
|
||||
};
|
||||
@ -62,6 +62,34 @@ struct parsed_pe_internal {
|
||||
list<exportent> exports;
|
||||
};
|
||||
|
||||
::uint32_t err = 0;
|
||||
std::string err_loc;
|
||||
|
||||
static const char *pe_err_str[] = {
|
||||
"None",
|
||||
"Out of memory",
|
||||
"Invalid header",
|
||||
"Invalid section",
|
||||
"Invalid resource",
|
||||
"Unable to get section for VA",
|
||||
"Unable to read data",
|
||||
"Unable to open",
|
||||
"Unable to stat",
|
||||
"Bad magic"
|
||||
};
|
||||
|
||||
int GetPEErr() {
|
||||
return err;
|
||||
}
|
||||
|
||||
string GetPEErrString() {
|
||||
return pe_err_str[err];
|
||||
}
|
||||
|
||||
string GetPEErrLoc() {
|
||||
return err_loc;
|
||||
}
|
||||
|
||||
bool getSecForVA(list<section> &secs, VA v, section &sec) {
|
||||
for(list<section>::iterator it = secs.begin(), e = secs.end();
|
||||
it != e;
|
||||
@ -69,8 +97,8 @@ bool getSecForVA(list<section> &secs, VA v, section &sec) {
|
||||
{
|
||||
section s = *it;
|
||||
|
||||
::uint32_t low = s.sectionBase;
|
||||
::uint32_t high = low + s.sec.Misc.VirtualSize;
|
||||
::uint64_t low = s.sectionBase;
|
||||
::uint64_t high = low + s.sec.Misc.VirtualSize;
|
||||
|
||||
if(v >= low && v < high) {
|
||||
sec = s;
|
||||
@ -286,7 +314,14 @@ bool getSections( bounded_buffer *b,
|
||||
thisSec.sectionName.push_back((char)c);
|
||||
}
|
||||
|
||||
if (nthdr.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
thisSec.sectionBase = nthdr.OptionalHeader.ImageBase + curSec.VirtualAddress;
|
||||
} else if (nthdr.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
thisSec.sectionBase = nthdr.OptionalHeader64.ImageBase + curSec.VirtualAddress;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
}
|
||||
|
||||
thisSec.sec = curSec;
|
||||
::uint32_t lowOff = curSec.PointerToRawData;
|
||||
::uint32_t highOff = lowOff+curSec.SizeOfRawData;
|
||||
@ -301,10 +336,6 @@ bool getSections( bounded_buffer *b,
|
||||
bool readOptionalHeader(bounded_buffer *b, optional_header_32 &header) {
|
||||
READ_WORD(b, 0, header, Magic);
|
||||
|
||||
if(header.Magic != NT_OPTIONAL_32_MAGIC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
READ_BYTE(b, 0, header, MajorLinkerVersion);
|
||||
READ_BYTE(b, 0, header, MinorLinkerVersion);
|
||||
READ_DWORD(b, 0, header, SizeOfCode);
|
||||
@ -354,6 +385,57 @@ bool readOptionalHeader(bounded_buffer *b, optional_header_32 &header) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readOptionalHeader64(bounded_buffer *b, optional_header_64 &header) {
|
||||
READ_WORD(b, 0, header, Magic);
|
||||
|
||||
READ_BYTE(b, 0, header, MajorLinkerVersion);
|
||||
READ_BYTE(b, 0, header, MinorLinkerVersion);
|
||||
READ_DWORD(b, 0, header, SizeOfCode);
|
||||
READ_DWORD(b, 0, header, SizeOfInitializedData);
|
||||
READ_DWORD(b, 0, header, SizeOfUninitializedData);
|
||||
READ_DWORD(b, 0, header, AddressOfEntryPoint);
|
||||
READ_DWORD(b, 0, header, BaseOfCode);
|
||||
READ_QWORD(b, 0, header, ImageBase);
|
||||
READ_DWORD(b, 0, header, SectionAlignment);
|
||||
READ_DWORD(b, 0, header, FileAlignment);
|
||||
READ_WORD(b, 0, header, MajorOperatingSystemVersion);
|
||||
READ_WORD(b, 0, header, MinorOperatingSystemVersion);
|
||||
READ_WORD(b, 0, header, MajorImageVersion);
|
||||
READ_WORD(b, 0, header, MinorImageVersion);
|
||||
READ_WORD(b, 0, header, MajorSubsystemVersion);
|
||||
READ_WORD(b, 0, header, MinorSubsystemVersion);
|
||||
READ_DWORD(b, 0, header, Win32VersionValue);
|
||||
READ_DWORD(b, 0, header, SizeOfImage);
|
||||
READ_DWORD(b, 0, header, SizeOfHeaders);
|
||||
READ_DWORD(b, 0, header, CheckSum);
|
||||
READ_WORD(b, 0, header, Subsystem);
|
||||
READ_WORD(b, 0, header, DllCharacteristics);
|
||||
READ_QWORD(b, 0, header, SizeOfStackReserve);
|
||||
READ_QWORD(b, 0, header, SizeOfStackCommit);
|
||||
READ_QWORD(b, 0, header, SizeOfHeapReserve);
|
||||
READ_QWORD(b, 0, header, SizeOfHeapCommit);
|
||||
READ_DWORD(b, 0, header, LoaderFlags);
|
||||
READ_DWORD(b, 0, header, NumberOfRvaAndSizes);
|
||||
|
||||
for(::uint32_t i = 0; i < header.NumberOfRvaAndSizes; i++) {
|
||||
::uint32_t c = (i*sizeof(data_directory));
|
||||
c += _offset(optional_header_64, DataDirectory[0]);
|
||||
::uint32_t o;
|
||||
|
||||
o = c + _offset(data_directory, VirtualAddress);
|
||||
if(readDword(b, o, header.DataDirectory[i].VirtualAddress) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
o = c + _offset(data_directory, Size);
|
||||
if(readDword(b, o, header.DataDirectory[i].Size) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readFileHeader(bounded_buffer *b, file_header &header) {
|
||||
READ_WORD(b, 0, header, Machine);
|
||||
READ_WORD(b, 0, header, NumberOfSections);
|
||||
@ -374,6 +456,7 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
||||
::uint32_t pe_magic;
|
||||
::uint32_t curOffset =0;
|
||||
if(readDword(b, curOffset, pe_magic) == false || pe_magic != NT_MAGIC) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -382,6 +465,7 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
||||
splitBuffer(b, _offset(nt_header_32, FileHeader), b->bufLen);
|
||||
|
||||
if(fhb == NULL) {
|
||||
PE_ERR(PEERR_MEM);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -390,19 +474,43 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The buffer is split using the OptionalHeader offset, even if it turns
|
||||
* out to be a PE32+. The start of the buffer is at the same spot in the
|
||||
* buffer regardless.
|
||||
*/
|
||||
bounded_buffer *ohb =
|
||||
splitBuffer(b, _offset(nt_header_32, OptionalHeader), b->bufLen);
|
||||
|
||||
if(ohb == NULL) {
|
||||
deleteBuffer(fhb);
|
||||
PE_ERR(PEERR_MEM);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the Magic to determine if it is 32 or 64.
|
||||
*/
|
||||
if (readWord(ohb, 0, header.OptionalMagic) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return false;
|
||||
}
|
||||
if (header.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
if(readOptionalHeader(ohb, header.OptionalHeader) == false) {
|
||||
deleteBuffer(ohb);
|
||||
deleteBuffer(fhb);
|
||||
return false;
|
||||
}
|
||||
} else if (header.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
if(readOptionalHeader64(ohb, header.OptionalHeader64) == false) {
|
||||
deleteBuffer(ohb);
|
||||
deleteBuffer(fhb);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return false;
|
||||
}
|
||||
|
||||
deleteBuffer(ohb);
|
||||
deleteBuffer(fhb);
|
||||
@ -419,15 +527,18 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
||||
::uint16_t tmp = 0;
|
||||
::uint32_t curOffset = 0;
|
||||
if(readWord(file, curOffset, tmp) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return false;
|
||||
}
|
||||
if(tmp != MZ_MAGIC) {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return false;
|
||||
}
|
||||
|
||||
//read the offset to the NT headers
|
||||
::uint32_t offset;
|
||||
if(readDword(file, _offset(dos_header, e_lfanew), offset) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return false;
|
||||
}
|
||||
curOffset += offset;
|
||||
@ -435,11 +546,28 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
||||
//now, we can read out the fields of the NT headers
|
||||
bounded_buffer *ntBuf = splitBuffer(file, curOffset, file->bufLen);
|
||||
if(readNtHeader(ntBuf, p.nt) == false) {
|
||||
// err is set by readNtHeader
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to determine if this is a PE32 or PE32+ binary and use the
|
||||
# correct size.
|
||||
*/
|
||||
::uint32_t rem_size;
|
||||
if (p.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
// signature + file_header + optional_header_32
|
||||
rem_size = sizeof(::uint32_t) + sizeof(file_header) + sizeof(optional_header_32);
|
||||
} else if (p.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
// signature + file_header + optional_header_64
|
||||
rem_size = sizeof(::uint32_t) + sizeof(file_header) + sizeof(optional_header_64);
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return false;
|
||||
}
|
||||
|
||||
//update 'rem' to point to the space after the header
|
||||
rem = splitBuffer(ntBuf, sizeof(nt_header_32), ntBuf->bufLen);
|
||||
rem = splitBuffer(ntBuf, rem_size, ntBuf->bufLen);
|
||||
deleteBuffer(ntBuf);
|
||||
|
||||
return true;
|
||||
@ -450,6 +578,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
parsed_pe *p = new parsed_pe();
|
||||
|
||||
if(p == NULL) {
|
||||
PE_ERR(PEERR_MEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -458,6 +587,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
|
||||
if(p->fileBuffer == NULL) {
|
||||
delete p;
|
||||
// err is set by readFileToFileBuffer
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -466,6 +596,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
if(p->internal == NULL) {
|
||||
deleteBuffer(p->fileBuffer);
|
||||
delete p;
|
||||
PE_ERR(PEERR_MEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -474,6 +605,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
if(getHeader(p->fileBuffer, p->peHeader, remaining) == false) {
|
||||
deleteBuffer(p->fileBuffer);
|
||||
delete p;
|
||||
// err is set by getHeader
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -482,6 +614,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
deleteBuffer(remaining);
|
||||
deleteBuffer(p->fileBuffer);
|
||||
delete p;
|
||||
PE_ERR(PEERR_SECT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -489,18 +622,35 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
deleteBuffer(remaining);
|
||||
deleteBuffer(p->fileBuffer);
|
||||
delete p;
|
||||
PE_ERR(PEERR_RESC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//get exports
|
||||
data_directory exportDir =
|
||||
p->peHeader.nt.OptionalHeader.DataDirectory[DIR_EXPORT];
|
||||
data_directory exportDir;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
exportDir = p->peHeader.nt.OptionalHeader.DataDirectory[DIR_EXPORT];
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
exportDir = p->peHeader.nt.OptionalHeader64.DataDirectory[DIR_EXPORT];
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(exportDir.Size != 0) {
|
||||
section s;
|
||||
::uint32_t addr =
|
||||
exportDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
VA addr;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
addr = exportDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
addr = exportDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(getSecForVA(p->internal->secs, addr, s) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -512,13 +662,23 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
rvaofft+_offset(export_dir_table, NameRVA),
|
||||
nameRva) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t nameVA = nameRva + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
VA nameVA;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
nameVA = nameRva + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
nameVA = nameRva + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
section nameSec;
|
||||
if(getSecForVA(p->internal->secs, nameVA, nameSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -527,6 +687,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
::uint8_t c;
|
||||
do {
|
||||
if(readByte(nameSec.sectionData, nameOff, c) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -544,6 +705,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
rvaofft+_offset(export_dir_table, NumberOfNamePointers),
|
||||
numNames) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -554,14 +716,23 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
rvaofft+_offset(export_dir_table, NamePointerRVA),
|
||||
namesRVA) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t namesVA =
|
||||
namesRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section namesSec;
|
||||
VA namesVA;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
namesVA = namesRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
namesVA = namesRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
section namesSec;
|
||||
if(getSecForVA(p->internal->secs, namesVA, namesSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -573,13 +744,23 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
rvaofft+_offset(export_dir_table, ExportAddressTableRVA),
|
||||
eatRVA) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VA eatVA;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
eatVA = eatRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
eatVA = eatRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t eatVA =
|
||||
eatRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section eatSec;
|
||||
if(getSecForVA(p->internal->secs, eatVA, eatSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -591,6 +772,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
rvaofft+_offset(export_dir_table, OrdinalBase),
|
||||
ordinalBase) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -601,13 +783,23 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
ordinalTableRVA) == false)
|
||||
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VA ordinalTableVA;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
ordinalTableVA = ordinalTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
ordinalTableVA = ordinalTableRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t ordinalTableVA =
|
||||
ordinalTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section ordinalTableSec;
|
||||
if(getSecForVA(p->internal->secs, ordinalTableVA, ordinalTableSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -619,14 +811,24 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
namesOff+(i*sizeof(::uint32_t)),
|
||||
curNameRVA) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VA curNameVA;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
curNameVA = curNameRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
curNameVA = curNameRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t curNameVA =
|
||||
curNameRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section curNameSec;
|
||||
|
||||
if(getSecForVA(p->internal->secs, curNameVA, curNameSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -636,6 +838,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
|
||||
do {
|
||||
if(readByte(curNameSec.sectionData, curNameOff, d) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -653,6 +856,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
ordinalOff+(i*sizeof(uint16_t)),
|
||||
ordinal) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -661,6 +865,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
|
||||
::uint32_t symRVA;
|
||||
if(readDword(eatSec.sectionData, eatOff+eatIdx, symRVA) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -669,7 +874,16 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
(symRVA < exportDir.VirtualAddress+exportDir.Size));
|
||||
|
||||
if(isForwarded == false) {
|
||||
::uint32_t symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
::uint32_t symVA;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
symVA = symRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
exportent a;
|
||||
|
||||
a.addr = symVA;
|
||||
@ -682,17 +896,33 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
}
|
||||
|
||||
//get relocations, if exist
|
||||
data_directory relocDir =
|
||||
p->peHeader.nt.OptionalHeader.DataDirectory[DIR_BASERELOC];
|
||||
data_directory relocDir;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
relocDir = p->peHeader.nt.OptionalHeader.DataDirectory[DIR_BASERELOC];
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
relocDir = p->peHeader.nt.OptionalHeader64.DataDirectory[DIR_BASERELOC];
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(relocDir.Size != 0) {
|
||||
section d;
|
||||
::uint32_t vaAddr =
|
||||
relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
VA vaAddr;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
vaAddr = relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
vaAddr = relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(getSecForVA(p->internal->secs, vaAddr, d) == false) {
|
||||
deleteBuffer(remaining);
|
||||
deleteBuffer(p->fileBuffer);
|
||||
delete p;
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -704,6 +934,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
rvaofft+_offset(reloc_block, PageRVA),
|
||||
pageRva) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -711,6 +942,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
rvaofft+_offset(reloc_block, BlockSize),
|
||||
blockSize) == false)
|
||||
{
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -725,6 +957,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
::uint16_t offset;
|
||||
|
||||
if(readWord(d.sectionData, rvaofft, block) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -734,8 +967,15 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
offset = block & ~0xf000;
|
||||
|
||||
//produce the VA of the relocation
|
||||
::uint32_t relocVA = pageRva + offset +
|
||||
p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
::uint32_t relocVA;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
relocVA = pageRva + offset + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
relocVA = pageRva + offset + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//store in our list
|
||||
reloc r;
|
||||
@ -750,18 +990,34 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
}
|
||||
|
||||
//get imports
|
||||
data_directory importDir =
|
||||
p->peHeader.nt.OptionalHeader.DataDirectory[DIR_IMPORT];
|
||||
data_directory importDir;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
importDir = p->peHeader.nt.OptionalHeader.DataDirectory[DIR_IMPORT];
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
importDir = p->peHeader.nt.OptionalHeader64.DataDirectory[DIR_IMPORT];
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(importDir.Size != 0) {
|
||||
//get section for the RVA in importDir
|
||||
section c;
|
||||
::uint32_t addr =
|
||||
importDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
VA addr;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
addr = importDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
addr = importDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(getSecForVA(p->internal->secs, addr, c) == false) {
|
||||
deleteBuffer(remaining);
|
||||
deleteBuffer(p->fileBuffer);
|
||||
delete p;
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -785,11 +1041,19 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
}
|
||||
|
||||
//then, try and get the name of this particular module...
|
||||
::uint32_t name =
|
||||
curEnt.NameRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
VA name;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
name = curEnt.NameRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
name = curEnt.NameRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
section nameSec;
|
||||
if(getSecForVA(p->internal->secs, name, nameSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -798,6 +1062,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
::uint8_t c;
|
||||
do {
|
||||
if(readByte(nameSec.sectionData, nameOff, c) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -810,39 +1075,75 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
}while(true);
|
||||
|
||||
//then, try and get all of the sub-symbols
|
||||
::uint32_t lookupVA;
|
||||
VA lookupVA;
|
||||
if(curEnt.LookupTableRVA != 0) {
|
||||
lookupVA =
|
||||
curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
lookupVA = curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
lookupVA = curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
} else if(curEnt.AddressRVA != 0 ) {
|
||||
lookupVA =
|
||||
curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
lookupVA = curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
lookupVA = curEnt.AddressRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
section lookupSec;
|
||||
if(getSecForVA(p->internal->secs, lookupVA, lookupSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t lookupOff = lookupVA - lookupSec.sectionBase;
|
||||
::uint64_t lookupOff = lookupVA - lookupSec.sectionBase;
|
||||
::uint32_t offInTable = 0;
|
||||
do {
|
||||
::uint32_t val;
|
||||
if(readDword(lookupSec.sectionData, lookupOff, val) == false) {
|
||||
VA valVA = 0;
|
||||
::uint8_t ord = 0;
|
||||
::uint16_t oval = 0;
|
||||
::uint32_t val32 = 0;
|
||||
::uint64_t val64 = 0;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
if(readDword(lookupSec.sectionData, lookupOff, val32) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
if(val32 == 0) {
|
||||
break;
|
||||
}
|
||||
ord = (val32 >> 31);
|
||||
oval = (val32 & ~0xFFFF0000);
|
||||
valVA = val32 + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
if(readQword(lookupSec.sectionData, lookupOff, val64) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
if(val64 == 0) {
|
||||
break;
|
||||
}
|
||||
ord = (val64 >> 63);
|
||||
oval = (val64 & ~0xFFFF0000);
|
||||
valVA = val64 + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(val == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
//check and see if high bit is set
|
||||
if(val >> 31 == 0) {
|
||||
if(ord == 0) {
|
||||
//import by name
|
||||
string symName;
|
||||
section symNameSec;
|
||||
::uint32_t valVA = val + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
|
||||
if(getSecForVA(p->internal->secs, valVA, symNameSec) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -852,6 +1153,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
::uint8_t d;
|
||||
|
||||
if(readByte(symNameSec.sectionData, nameOff, d) == false) {
|
||||
PE_ERR(PEERR_READ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -866,23 +1168,32 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
//okay now we know the pair... add it
|
||||
importent ent;
|
||||
|
||||
ent.addr = offInTable +
|
||||
curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ent.symbolName = symName;
|
||||
ent.moduleName = modName;
|
||||
p->internal->imports.push_back(ent);
|
||||
} else {
|
||||
//import by ordinal
|
||||
//mask out 'val' so that oval is the low 16 bits of 'val'
|
||||
::uint16_t oval = (val & ~0xFFFF0000);
|
||||
string symName =
|
||||
"ORDINAL_" + modName + "_" + to_string<uint32_t>(oval, dec);
|
||||
|
||||
importent ent;
|
||||
|
||||
ent.addr = offInTable +
|
||||
curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ent.symbolName = symName;
|
||||
ent.moduleName = modName;
|
||||
@ -890,8 +1201,16 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
p->internal->imports.push_back(ent);
|
||||
}
|
||||
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
lookupOff += sizeof(::uint32_t);
|
||||
offInTable += sizeof(::uint32_t);
|
||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
lookupOff += sizeof(::uint64_t);
|
||||
offInTable += sizeof(::uint64_t);
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return NULL;
|
||||
}
|
||||
} while(true);
|
||||
|
||||
offt += sizeof(import_dir_entry);
|
||||
@ -978,6 +1297,7 @@ bool ReadByteAtVA(parsed_pe *pe, VA v, ::uint8_t &b) {
|
||||
section s;
|
||||
|
||||
if(getSecForVA(pe->internal->secs, v, s) == false) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -991,7 +1311,14 @@ bool GetEntryPoint(parsed_pe *pe, VA &v) {
|
||||
if(pe != NULL) {
|
||||
nt_header_32 *nthdr = &pe->peHeader.nt;
|
||||
|
||||
if (nthdr->OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
v = nthdr->OptionalHeader.AddressOfEntryPoint + nthdr->OptionalHeader.ImageBase;
|
||||
} else if (nthdr->OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
v = nthdr->OptionalHeader64.AddressOfEntryPoint + nthdr->OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
PE_ERR(PEERR_MAGIC);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -28,30 +28,47 @@ THE SOFTWARE.
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
#include "nt-headers.h"
|
||||
#include "to_string.h"
|
||||
|
||||
#define PE_ERR(x) \
|
||||
err = (pe_err) x; \
|
||||
err_loc.assign(__func__); \
|
||||
err_loc += ":" + to_string<std::uint32_t>(__LINE__, dec);
|
||||
|
||||
#define READ_WORD(b, o, inst, member) \
|
||||
if(readWord(b, o+_offset(__typeof__(inst), member), inst.member) == false) { \
|
||||
PE_ERR(PEERR_READ); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define READ_DWORD(b, o, inst, member) \
|
||||
if(readDword(b, o+_offset(__typeof__(inst), member), inst.member) == false) { \
|
||||
PE_ERR(PEERR_READ); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define READ_QWORD(b, o, inst, member) \
|
||||
if(readQword(b, o+_offset(__typeof__(inst), member), inst.member) == false) { \
|
||||
PE_ERR(PEERR_READ); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define READ_DWORD_PTR(b, o, inst, member) \
|
||||
if(readDword(b, o+_offset(__typeof__(*inst), member), inst->member) == false) { \
|
||||
PE_ERR(PEERR_READ); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define READ_BYTE(b, o, inst, member) \
|
||||
if(readByte(b, o+_offset(__typeof__(inst), member), inst.member) == false) { \
|
||||
PE_ERR(PEERR_READ); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
/* This variant returns NULL instead of false. */
|
||||
#define READ_DWORD_NULL(b, o, inst, member) \
|
||||
if(readDword(b, o+_offset(__typeof__(inst), member), inst.member) == false) { \
|
||||
PE_ERR(PEERR_READ); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
@ -105,9 +122,23 @@ enum resource_type {
|
||||
RT_MANIFEST = 24
|
||||
};
|
||||
|
||||
enum pe_err {
|
||||
PEERR_NONE = 0,
|
||||
PEERR_MEM = 1,
|
||||
PEERR_HDR = 2,
|
||||
PEERR_SECT = 3,
|
||||
PEERR_RESC = 4,
|
||||
PEERR_SECTVA = 5,
|
||||
PEERR_READ = 6,
|
||||
PEERR_OPEN = 7,
|
||||
PEERR_STAT = 8,
|
||||
PEERR_MAGIC = 9
|
||||
};
|
||||
|
||||
bool readByte(bounded_buffer *b, boost::uint32_t offset, boost::uint8_t &out);
|
||||
bool readWord(bounded_buffer *b, boost::uint32_t offset, boost::uint16_t &out);
|
||||
bool readDword(bounded_buffer *b, boost::uint32_t offset, boost::uint32_t &out);
|
||||
bool readQword(bounded_buffer *b, boost::uint32_t offset, boost::uint64_t &out);
|
||||
|
||||
bounded_buffer *readFileToFileBuffer(const char *filePath);
|
||||
bounded_buffer *splitBuffer(bounded_buffer *b, boost::uint32_t from, boost::uint32_t to);
|
||||
@ -126,6 +157,15 @@ typedef struct _parsed_pe {
|
||||
pe_header peHeader;
|
||||
} parsed_pe;
|
||||
|
||||
// get parser error status as integer
|
||||
int GetPEErr();
|
||||
|
||||
// get parser error status as string
|
||||
std::string GetPEErrString();
|
||||
|
||||
// get parser error location as string
|
||||
std::string GetPEErrLoc();
|
||||
|
||||
//get a PE parse context from a file
|
||||
parsed_pe *ParsePEFromFile(const char *filePath);
|
||||
|
||||
|
195
python/pepy.cpp
195
python/pepy.cpp
@ -29,7 +29,7 @@
|
||||
#include <structmember.h>
|
||||
#include "parse.h"
|
||||
|
||||
#define PEPY_VERSION "0.1"
|
||||
#define PEPY_VERSION "0.2"
|
||||
|
||||
/* These are used to across multiple objects. */
|
||||
#define PEPY_OBJECT_GET(OBJ, ATTR) \
|
||||
@ -43,6 +43,12 @@ static PyObject *pepy_##OBJ##_get_##ATTR(PyObject *self, void *closure) { \
|
||||
(setter) pepy_attr_not_writable, \
|
||||
(char *) #DOC, NULL }
|
||||
|
||||
/* 'OPTIONAL' references the fact that these are from the Optional Header */
|
||||
#define OBJECTGETTER_OPTIONAL(ATTR, DOC) \
|
||||
{ (char *) #ATTR, (getter) pepy_parsed_get_optional_##ATTR, \
|
||||
(setter) pepy_attr_not_writable, \
|
||||
(char *) #DOC, NULL }
|
||||
|
||||
static PyObject *pepy_error;
|
||||
|
||||
typedef struct {
|
||||
@ -103,7 +109,7 @@ typedef struct {
|
||||
|
||||
/* None of the attributes in these objects are writable. */
|
||||
static int pepy_attr_not_writable(PyObject *self, PyObject *value, void *closure) {
|
||||
PyErr_SetString(PyExc_TypeError, "Attribute not writable");
|
||||
PyErr_SetString(PyExc_TypeError, "Attribute not writable.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -761,7 +767,7 @@ int section_callback(void *cbd, VA base, std::string &name, image_section_header
|
||||
}
|
||||
|
||||
if (pepy_section_init((pepy_section *) sect, tuple, NULL) == -1) {
|
||||
PyErr_SetString(pepy_error, "Unable to init new section");
|
||||
PyErr_SetString(pepy_error, "Unable to init new section.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -806,7 +812,7 @@ int resource_callback(void *cbd, resource r) {
|
||||
}
|
||||
|
||||
if (pepy_resource_init((pepy_resource *) rsrc, tuple, NULL) == -1) {
|
||||
PyErr_SetString(pepy_error, "Unable to init new resource");
|
||||
PyErr_SetString(pepy_error, "Unable to init new resource.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -851,7 +857,7 @@ int import_callback(void *cbd, VA addr, std::string &name, std::string &sym) {
|
||||
}
|
||||
|
||||
if (pepy_import_init((pepy_import *) imp, tuple, NULL) == -1) {
|
||||
PyErr_SetString(pepy_error, "Unable to init new section");
|
||||
PyErr_SetString(pepy_error, "Unable to init new section.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -896,7 +902,7 @@ int export_callback(void *cbd, VA addr, std::string &mod, std::string &func) {
|
||||
}
|
||||
|
||||
if (pepy_export_init((pepy_export *) exp, tuple, NULL) == -1) {
|
||||
PyErr_SetString(pepy_error, "Unable to init new section");
|
||||
PyErr_SetString(pepy_error, "Unable to init new section.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -945,7 +951,7 @@ int reloc_callback(void *cbd, VA addr, reloc_type type) {
|
||||
}
|
||||
|
||||
if (pepy_relocation_init((pepy_relocation *) reloc, tuple, NULL) == -1) {
|
||||
PyErr_SetString(pepy_error, "Unable to init new section");
|
||||
PyErr_SetString(pepy_error, "Unable to init new section.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -972,44 +978,86 @@ static PyObject *pepy_parsed_get_relocations(PyObject *self, PyObject *args) {
|
||||
|
||||
#define PEPY_PARSED_GET(ATTR, VAL) \
|
||||
static PyObject *pepy_parsed_get_##ATTR(PyObject *self, void *closure) { \
|
||||
PyObject *ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.VAL); \
|
||||
PyObject *ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.VAL); \
|
||||
if (!ret) \
|
||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute"); \
|
||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
PEPY_PARSED_GET(signature, nt.Signature)
|
||||
PEPY_PARSED_GET(machine, nt.FileHeader.Machine)
|
||||
PEPY_PARSED_GET(numberofsections, nt.FileHeader.NumberOfSections)
|
||||
PEPY_PARSED_GET(timedatestamp, nt.FileHeader.TimeDateStamp)
|
||||
PEPY_PARSED_GET(numberofsymbols, nt.FileHeader.NumberOfSymbols)
|
||||
PEPY_PARSED_GET(characteristics, nt.FileHeader.Characteristics)
|
||||
PEPY_PARSED_GET(magic, nt.OptionalHeader.Magic)
|
||||
PEPY_PARSED_GET(majorlinkerver, nt.OptionalHeader.MajorLinkerVersion)
|
||||
PEPY_PARSED_GET(minorlinkerver, nt.OptionalHeader.MinorLinkerVersion)
|
||||
PEPY_PARSED_GET(codesize, nt.OptionalHeader.SizeOfCode);
|
||||
PEPY_PARSED_GET(initdatasize, nt.OptionalHeader.SizeOfInitializedData);
|
||||
PEPY_PARSED_GET(uninitdatasize, nt.OptionalHeader.SizeOfUninitializedData);
|
||||
PEPY_PARSED_GET(entrypointaddr, nt.OptionalHeader.AddressOfEntryPoint);
|
||||
PEPY_PARSED_GET(baseofcode, nt.OptionalHeader.BaseOfCode);
|
||||
PEPY_PARSED_GET(baseofdata, nt.OptionalHeader.BaseOfData);
|
||||
PEPY_PARSED_GET(imagebase, nt.OptionalHeader.ImageBase);
|
||||
PEPY_PARSED_GET(sectionalignement, nt.OptionalHeader.SectionAlignment);
|
||||
PEPY_PARSED_GET(filealingment, nt.OptionalHeader.FileAlignment);
|
||||
PEPY_PARSED_GET(majorosver, nt.OptionalHeader.MajorOperatingSystemVersion);
|
||||
PEPY_PARSED_GET(minorosver, nt.OptionalHeader.MinorOperatingSystemVersion);
|
||||
PEPY_PARSED_GET(win32ver, nt.OptionalHeader.Win32VersionValue);
|
||||
PEPY_PARSED_GET(imagesize, nt.OptionalHeader.SizeOfImage);
|
||||
PEPY_PARSED_GET(headersize, nt.OptionalHeader.SizeOfHeaders);
|
||||
PEPY_PARSED_GET(checksum, nt.OptionalHeader.CheckSum);
|
||||
PEPY_PARSED_GET(subsystem, nt.OptionalHeader.Subsystem);
|
||||
PEPY_PARSED_GET(dllcharacteristics, nt.OptionalHeader.DllCharacteristics);
|
||||
PEPY_PARSED_GET(stackreservesize, nt.OptionalHeader.SizeOfStackReserve);
|
||||
PEPY_PARSED_GET(stackcommitsize, nt.OptionalHeader.SizeOfStackCommit);
|
||||
PEPY_PARSED_GET(heapreservesize, nt.OptionalHeader.SizeOfHeapReserve);
|
||||
PEPY_PARSED_GET(heapcommitsize, nt.OptionalHeader.SizeOfHeapCommit);
|
||||
PEPY_PARSED_GET(loaderflags, nt.OptionalHeader.LoaderFlags);
|
||||
PEPY_PARSED_GET(rvasandsize, nt.OptionalHeader.NumberOfRvaAndSizes);
|
||||
PEPY_PARSED_GET(signature, Signature)
|
||||
PEPY_PARSED_GET(machine, FileHeader.Machine)
|
||||
PEPY_PARSED_GET(numberofsections, FileHeader.NumberOfSections)
|
||||
PEPY_PARSED_GET(timedatestamp, FileHeader.TimeDateStamp)
|
||||
PEPY_PARSED_GET(numberofsymbols, FileHeader.NumberOfSymbols)
|
||||
PEPY_PARSED_GET(characteristics, FileHeader.Characteristics)
|
||||
PEPY_PARSED_GET(magic, OptionalMagic)
|
||||
|
||||
/*
|
||||
* This is used to get things from the optional header, which can be either
|
||||
* the PE32 or PE32+ version, depending upon the magic value. Technically
|
||||
* the magic is stored in the OptionalHeader, but to make life easier pe-parse
|
||||
* stores the value in nt_header_32 along with the appropriate optional header.
|
||||
* This is why "magic" is handled above, and not here.
|
||||
*/
|
||||
#define PEPY_PARSED_GET_OPTIONAL(ATTR, VAL) \
|
||||
static PyObject *pepy_parsed_get_optional_##ATTR(PyObject *self, void *closure) { \
|
||||
PyObject *ret = NULL; \
|
||||
if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) { \
|
||||
ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader.VAL); \
|
||||
if (!ret) \
|
||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
||||
} else if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) { \
|
||||
ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader64.VAL); \
|
||||
if (!ret) \
|
||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
||||
} else { \
|
||||
PyErr_SetString(pepy_error, "Bad magic value."); \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
PEPY_PARSED_GET_OPTIONAL(majorlinkerver, MajorLinkerVersion)
|
||||
PEPY_PARSED_GET_OPTIONAL(minorlinkerver, MinorLinkerVersion)
|
||||
PEPY_PARSED_GET_OPTIONAL(codesize, SizeOfCode);
|
||||
PEPY_PARSED_GET_OPTIONAL(initdatasize, SizeOfInitializedData);
|
||||
PEPY_PARSED_GET_OPTIONAL(uninitdatasize, SizeOfUninitializedData);
|
||||
PEPY_PARSED_GET_OPTIONAL(entrypointaddr, AddressOfEntryPoint);
|
||||
PEPY_PARSED_GET_OPTIONAL(baseofcode, BaseOfCode);
|
||||
PEPY_PARSED_GET_OPTIONAL(imagebase, ImageBase);
|
||||
PEPY_PARSED_GET_OPTIONAL(sectionalignement, SectionAlignment);
|
||||
PEPY_PARSED_GET_OPTIONAL(filealingment, FileAlignment);
|
||||
PEPY_PARSED_GET_OPTIONAL(majorosver, MajorOperatingSystemVersion);
|
||||
PEPY_PARSED_GET_OPTIONAL(minorosver, MinorOperatingSystemVersion);
|
||||
PEPY_PARSED_GET_OPTIONAL(win32ver, Win32VersionValue);
|
||||
PEPY_PARSED_GET_OPTIONAL(imagesize, SizeOfImage);
|
||||
PEPY_PARSED_GET_OPTIONAL(headersize, SizeOfHeaders);
|
||||
PEPY_PARSED_GET_OPTIONAL(checksum, CheckSum);
|
||||
PEPY_PARSED_GET_OPTIONAL(subsystem, Subsystem);
|
||||
PEPY_PARSED_GET_OPTIONAL(dllcharacteristics, DllCharacteristics);
|
||||
PEPY_PARSED_GET_OPTIONAL(stackreservesize, SizeOfStackReserve);
|
||||
PEPY_PARSED_GET_OPTIONAL(stackcommitsize, SizeOfStackCommit);
|
||||
PEPY_PARSED_GET_OPTIONAL(heapreservesize, SizeOfHeapReserve);
|
||||
PEPY_PARSED_GET_OPTIONAL(heapcommitsize, SizeOfHeapCommit);
|
||||
PEPY_PARSED_GET_OPTIONAL(loaderflags, LoaderFlags);
|
||||
PEPY_PARSED_GET_OPTIONAL(rvasandsize, NumberOfRvaAndSizes);
|
||||
|
||||
/*
|
||||
* BaseOfData is only in PE32, not PE32+. Thus, it uses a non-standard
|
||||
* getter function compared to the other shared fields.
|
||||
*/
|
||||
static PyObject *pepy_parsed_get_optional_baseofdata(PyObject *self, void *closure) {
|
||||
PyObject *ret = NULL;
|
||||
if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader.BaseOfData);
|
||||
if (!ret)
|
||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute.");
|
||||
} else if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||
PyErr_SetString(PyExc_AttributeError, "Not available on PE32+.");
|
||||
} else {
|
||||
PyErr_SetString(pepy_error, "Bad magic value.");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyGetSetDef pepy_parsed_getseters[] = {
|
||||
OBJECTGETTER(parsed, signature, "PE Signature"),
|
||||
@ -1019,31 +1067,34 @@ static PyGetSetDef pepy_parsed_getseters[] = {
|
||||
OBJECTGETTER(parsed, numberofsymbols, "Number of symbols"),
|
||||
OBJECTGETTER(parsed, characteristics, "Characteristics"),
|
||||
OBJECTGETTER(parsed, magic, "Magic"),
|
||||
OBJECTGETTER(parsed, majorlinkerver, "Major linker version"),
|
||||
OBJECTGETTER(parsed, minorlinkerver, "Minor linker version"),
|
||||
OBJECTGETTER(parsed, codesize, "Size of code"),
|
||||
OBJECTGETTER(parsed, initdatasize, "Size of initialized data"),
|
||||
OBJECTGETTER(parsed, uninitdatasize, "Size of uninitialized data"),
|
||||
OBJECTGETTER(parsed, entrypointaddr, "Address of entry point"),
|
||||
OBJECTGETTER(parsed, baseofcode, "Base address of code"),
|
||||
OBJECTGETTER(parsed, baseofdata, "Base address of data"),
|
||||
OBJECTGETTER(parsed, imagebase, "Image base address"),
|
||||
OBJECTGETTER(parsed, sectionalignement, "Section alignment"),
|
||||
OBJECTGETTER(parsed, filealingment, "File alignment"),
|
||||
OBJECTGETTER(parsed, majorosver, "Major OS version"),
|
||||
OBJECTGETTER(parsed, minorosver, "Minor OS version"),
|
||||
OBJECTGETTER(parsed, win32ver, "Win32 version"),
|
||||
OBJECTGETTER(parsed, imagesize, "Size of image"),
|
||||
OBJECTGETTER(parsed, headersize, "Size of headers"),
|
||||
OBJECTGETTER(parsed, checksum, "Checksum"),
|
||||
OBJECTGETTER(parsed, subsystem, "Subsystem"),
|
||||
OBJECTGETTER(parsed, dllcharacteristics, "DLL characteristics"),
|
||||
OBJECTGETTER(parsed, stackreservesize, "Size of stack reserve"),
|
||||
OBJECTGETTER(parsed, stackcommitsize, "Size of stack commit"),
|
||||
OBJECTGETTER(parsed, heapreservesize, "Size of heap reserve"),
|
||||
OBJECTGETTER(parsed, heapcommitsize, "Size of heap commit"),
|
||||
OBJECTGETTER(parsed, loaderflags, "Loader flags"),
|
||||
OBJECTGETTER(parsed, rvasandsize, "Number of RVA and sizes"),
|
||||
OBJECTGETTER_OPTIONAL(majorlinkerver, "Major linker version"),
|
||||
OBJECTGETTER_OPTIONAL(minorlinkerver, "Minor linker version"),
|
||||
OBJECTGETTER_OPTIONAL(codesize, "Size of code"),
|
||||
OBJECTGETTER_OPTIONAL(initdatasize, "Size of initialized data"),
|
||||
OBJECTGETTER_OPTIONAL(uninitdatasize, "Size of uninitialized data"),
|
||||
OBJECTGETTER_OPTIONAL(entrypointaddr, "Address of entry point"),
|
||||
OBJECTGETTER_OPTIONAL(baseofcode, "Base address of code"),
|
||||
OBJECTGETTER_OPTIONAL(imagebase, "Image base address"),
|
||||
OBJECTGETTER_OPTIONAL(sectionalignement, "Section alignment"),
|
||||
OBJECTGETTER_OPTIONAL(filealingment, "File alignment"),
|
||||
OBJECTGETTER_OPTIONAL(majorosver, "Major OS version"),
|
||||
OBJECTGETTER_OPTIONAL(minorosver, "Minor OS version"),
|
||||
OBJECTGETTER_OPTIONAL(win32ver, "Win32 version"),
|
||||
OBJECTGETTER_OPTIONAL(imagesize, "Size of image"),
|
||||
OBJECTGETTER_OPTIONAL(headersize, "Size of headers"),
|
||||
OBJECTGETTER_OPTIONAL(checksum, "Checksum"),
|
||||
OBJECTGETTER_OPTIONAL(subsystem, "Subsystem"),
|
||||
OBJECTGETTER_OPTIONAL(dllcharacteristics, "DLL characteristics"),
|
||||
OBJECTGETTER_OPTIONAL(stackreservesize, "Size of stack reserve"),
|
||||
OBJECTGETTER_OPTIONAL(stackcommitsize, "Size of stack commit"),
|
||||
OBJECTGETTER_OPTIONAL(heapreservesize, "Size of heap reserve"),
|
||||
OBJECTGETTER_OPTIONAL(heapcommitsize, "Size of heap commit"),
|
||||
OBJECTGETTER_OPTIONAL(loaderflags, "Loader flags"),
|
||||
OBJECTGETTER_OPTIONAL(rvasandsize, "Number of RVA and sizes"),
|
||||
/* Base of data is only available in PE32, not PE32+. */
|
||||
{ (char *) "baseofdata", (getter) pepy_parsed_get_optional_baseofdata,
|
||||
(setter) pepy_attr_not_writable,
|
||||
(char *) "Base address of data", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -1110,6 +1161,7 @@ static PyTypeObject pepy_parsed_type = {
|
||||
static PyObject *pepy_parse(PyObject *self, PyObject *args) {
|
||||
PyObject *parsed;
|
||||
int ret;
|
||||
char *err_str = NULL;
|
||||
|
||||
parsed = pepy_parsed_new(&pepy_parsed_type, NULL, NULL);
|
||||
if (!parsed) {
|
||||
@ -1119,8 +1171,15 @@ static PyObject *pepy_parse(PyObject *self, PyObject *args) {
|
||||
|
||||
ret = pepy_parsed_init((pepy_parsed *) parsed, args, NULL);
|
||||
if (ret < 0) {
|
||||
if (ret == -2)
|
||||
PyErr_SetString(pepy_error, "Unable to parse PE file.");
|
||||
if (ret == -2) {
|
||||
// error (loc)
|
||||
size_t len = GetPEErrString().length() + GetPEErrLoc().length() + 4;
|
||||
err_str = (char *) malloc(len);
|
||||
if (!err_str)
|
||||
return PyErr_NoMemory();
|
||||
snprintf(err_str, len, "%s (%s)", GetPEErrString().c_str(), GetPEErrLoc().c_str());
|
||||
PyErr_SetString(pepy_error, err_str);
|
||||
}
|
||||
else
|
||||
PyErr_SetString(pepy_error, "Unable to init new parsed object.");
|
||||
return NULL;
|
||||
|
@ -7,7 +7,12 @@ import binascii
|
||||
|
||||
from hashlib import md5
|
||||
|
||||
try:
|
||||
p = pepy.parse(sys.argv[1])
|
||||
except pepy.error as e:
|
||||
print e
|
||||
sys.exit(1)
|
||||
|
||||
print "Magic: %s" % hex(p.magic)
|
||||
print "Signature: %s" % hex(p.signature)
|
||||
print "Machine: %s" % hex(p.machine)
|
||||
@ -22,7 +27,11 @@ print "Size of initialized data: %s" % hex(p.initdatasize)
|
||||
print "Size of uninitialized data: %s" % hex(p.uninitdatasize)
|
||||
print "Address of entry point: %s" % hex(p.entrypointaddr)
|
||||
print "Base address of code: %s" % hex(p.baseofcode)
|
||||
try:
|
||||
print "Base address of data: %s" % hex(p.baseofdata)
|
||||
except:
|
||||
# Not available on PE32+, ignore it.
|
||||
pass
|
||||
print "Image base address: %s" % hex(p.imagebase)
|
||||
print "Section alignment: %s" % hex(p.sectionalignement)
|
||||
print "File alignment: %s" % hex(p.filealingment)
|
||||
|
Loading…
x
Reference in New Issue
Block a user