mirror of
https://github.com/QuasarApp/pe-parse.git
synced 2025-05-11 18:59:34 +00:00
.
This commit is contained in:
parent
42cf2a4bb0
commit
5531d3a249
@ -1,7 +1,7 @@
|
||||
include_directories(${pe-parse_SOURCE_DIR}/parser-library)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../parser-library)
|
||||
|
||||
add_executable( dump-prog
|
||||
dump.cpp )
|
||||
|
||||
target_link_libraries( dump-prog
|
||||
parser-library )
|
||||
pe-parser-library )
|
||||
|
@ -37,14 +37,25 @@ string to_string(T t, ios_base & (*f)(ios_base&)) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void printImports(void *N, VA impAddr, string &modName, string &symName) {
|
||||
int printExps(void *N, VA funcAddr, std::string &mod, std::string &func) {
|
||||
cout << "EXP: ";
|
||||
cout << mod;
|
||||
cout << "!";
|
||||
cout << func;
|
||||
cout << ":";
|
||||
cout << to_string<uint32_t>(funcAddr, hex);
|
||||
cout << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int printImports(void *N, VA impAddr, string &modName, string &symName) {
|
||||
cout << "0x" << to_string<uint32_t>(impAddr, hex);
|
||||
cout << " " << modName << "!" << symName;
|
||||
cout << endl;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printRelocs(void *N, VA relocAddr, reloc_type type) {
|
||||
int printRelocs(void *N, VA relocAddr, reloc_type type) {
|
||||
cout << "TYPE: ";
|
||||
switch(type) {
|
||||
case ABSOLUTE:
|
||||
@ -75,14 +86,19 @@ void printRelocs(void *N, VA relocAddr, reloc_type type) {
|
||||
|
||||
cout << " VA: 0x" << to_string<VA>(relocAddr, hex) << endl;
|
||||
|
||||
return;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
void printSecs(void *N, RVA secBase, string &secName, bounded_buffer *data) {
|
||||
int printSecs(void *N,
|
||||
VA secBase,
|
||||
string &secName,
|
||||
image_section_header s,
|
||||
bounded_buffer *data)
|
||||
{
|
||||
cout << "Sec Name: " << secName << endl;
|
||||
cout << "Sec Base: " << to_string<uint64_t>(secBase, hex) << endl;
|
||||
cout << "Sec Size: " << to_string<uint64_t>(data->bufLen, dec) << endl;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@ -136,23 +152,30 @@ int main(int argc, char *argv[]) {
|
||||
#undef DUMP_FIELD
|
||||
#undef DUMP_DEC_FIELD
|
||||
|
||||
cout << "Imports: " << endl;
|
||||
IterImpVAString(p, printImports, NULL);
|
||||
cout << "Relocations: " << endl;
|
||||
IterRelocs(p, printRelocs, NULL);
|
||||
cout << "Sections: " << endl;
|
||||
IterSec(p, printSecs, NULL);
|
||||
cout << "Exports: " << endl;
|
||||
IterExpVA(p, printExps, NULL);
|
||||
|
||||
//read the first 8 bytes from the entry point and print them
|
||||
cout << "First 8 bytes from entry point (0x";
|
||||
VA entryPoint = p->peHeader.nt.OptionalHeader.AddressOfEntryPoint +
|
||||
p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
cout << to_string<VA>(entryPoint, hex);
|
||||
cout << "):" << endl;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
::uint8_t b;
|
||||
ReadByteAtVA(p, i+entryPoint, b);
|
||||
cout << " 0x" << to_string<uint32_t>(b, hex);
|
||||
}
|
||||
VA entryPoint;
|
||||
if(GetEntryPoint(p, entryPoint)) {
|
||||
cout << "First 8 bytes from entry point (0x";
|
||||
|
||||
cout << to_string<VA>(entryPoint, hex);
|
||||
cout << "):" << endl;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
::uint8_t b;
|
||||
ReadByteAtVA(p, i+entryPoint, b);
|
||||
cout << " 0x" << to_string<uint32_t>(b, hex);
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
DestructParsedPE(p);
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
add_library(parser-library
|
||||
add_library(pe-parser-library
|
||||
buffer.cpp
|
||||
parse.cpp)
|
||||
|
@ -26,21 +26,32 @@ THE SOFTWARE.
|
||||
#include <string.h>
|
||||
#include "parse.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
struct buffer_detail {
|
||||
#if 1
|
||||
int fd;
|
||||
#ifdef WIN32
|
||||
HANDLE file;
|
||||
HANDLE sec;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool readByte(bounded_buffer *b, ::uint32_t offset, ::uint8_t &out) {
|
||||
if(b == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(offset >= b->bufLen) {
|
||||
return false;
|
||||
}
|
||||
@ -53,6 +64,10 @@ bool readByte(bounded_buffer *b, ::uint32_t offset, ::uint8_t &out) {
|
||||
|
||||
//TODO: perform endian swap as needed
|
||||
bool readWord(bounded_buffer *b, ::uint32_t offset, ::uint16_t &out) {
|
||||
if(b == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(offset >= b->bufLen) {
|
||||
return false;
|
||||
}
|
||||
@ -65,6 +80,10 @@ bool readWord(bounded_buffer *b, ::uint32_t offset, ::uint16_t &out) {
|
||||
|
||||
//TODO: perform endian swap as needed
|
||||
bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) {
|
||||
if(b == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(offset >= b->bufLen) {
|
||||
return false;
|
||||
}
|
||||
@ -77,7 +96,26 @@ bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) {
|
||||
|
||||
|
||||
bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
#if 1
|
||||
#ifdef WIN32
|
||||
HANDLE h = CreateFileA(filePath,
|
||||
GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if(h == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD fileSize = GetFileSize(h, NULL);
|
||||
|
||||
if(fileSize == INVALID_FILE_SIZE) {
|
||||
CloseHandle(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
//only where we have mmap / open / etc
|
||||
int fd = open(filePath, O_RDONLY);
|
||||
|
||||
@ -104,7 +142,28 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
p->detail = d;
|
||||
|
||||
//only where we have mmap / open / etc
|
||||
#if 1
|
||||
#ifdef WIN32
|
||||
p->detail->file = h;
|
||||
|
||||
HANDLE hMap = CreateFileMapping(h, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
|
||||
if(hMap == NULL) {
|
||||
CloseHandle(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->detail->sec = hMap;
|
||||
|
||||
LPVOID ptr = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
|
||||
if(ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->buf = (::uint8_t *)ptr;
|
||||
p->bufLen = fileSize;
|
||||
p->copy = false;
|
||||
#else
|
||||
p->detail->fd = fd;
|
||||
|
||||
struct stat s = {0};
|
||||
@ -130,44 +189,15 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
||||
p->copy = false;
|
||||
#endif
|
||||
|
||||
#ifdef BUF_RAW
|
||||
//open the file in binary mode
|
||||
ifstream inFile(filePath, ios::in|ios::binary|ios::ate);
|
||||
|
||||
if(inFile.is_open()) {
|
||||
size_t fileSize = inFile.tellg();
|
||||
|
||||
if(fileSize == 0) {
|
||||
delete p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->buf = (::uint8_t *)malloc(fileSize);
|
||||
|
||||
if(p->buf == NULL) {
|
||||
delete p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(p->buf, 0, fileSize);
|
||||
p->bufLen = fileSize;
|
||||
p->copy = false;
|
||||
|
||||
inFile.seekg(0, ios::beg);
|
||||
inFile.read((char *)p->buf, fileSize);
|
||||
inFile.close();
|
||||
} else {
|
||||
delete p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
//split buffer inclusively from from to to by offset
|
||||
bounded_buffer *splitBuffer(bounded_buffer *b, ::uint32_t from, ::uint32_t to) {
|
||||
if(b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//safety checks
|
||||
if(to < from || to > b->bufLen) {
|
||||
return NULL;
|
||||
@ -193,10 +223,13 @@ void deleteBuffer(bounded_buffer *b) {
|
||||
}
|
||||
|
||||
if(b->copy == false) {
|
||||
#ifdef WIN32
|
||||
UnmapViewOfFile(b->buf);
|
||||
CloseHandle(b->detail->sec);
|
||||
CloseHandle(b->detail->file);
|
||||
#else
|
||||
munmap(b->buf, b->bufLen);
|
||||
close(b->detail->fd);
|
||||
#ifdef BUF_RAW
|
||||
free(b->buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -205,3 +238,6 @@ void deleteBuffer(bounded_buffer *b) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t bufLen(bounded_buffer *b) {
|
||||
return b->bufLen;
|
||||
}
|
||||
|
@ -52,6 +52,45 @@ const boost::uint16_t DIR_IAT = 12;
|
||||
const boost::uint16_t DIR_DELAY_IMPORT = 13;
|
||||
const boost::uint16_t DIR_COM_DESCRIPTOR = 14;
|
||||
|
||||
const boost::uint32_t IMAGE_SCN_TYPE_NO_PAD = 0x00000008;
|
||||
const boost::uint32_t IMAGE_SCN_CNT_CODE = 0x00000020;
|
||||
const boost::uint32_t IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040;
|
||||
const boost::uint32_t IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080;
|
||||
const boost::uint32_t IMAGE_SCN_LNK_OTHER = 0x00000100;
|
||||
const boost::uint32_t IMAGE_SCN_LNK_INFO = 0x00000200;
|
||||
const boost::uint32_t IMAGE_SCN_LNK_REMOVE = 0x00000800;
|
||||
const boost::uint32_t IMAGE_SCN_LNK_COMDAT = 0x00001000;
|
||||
const boost::uint32_t IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000;
|
||||
const boost::uint32_t IMAGE_SCN_GPREL = 0x00008000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_FARDATA = 0x00008000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_PURGEABLE = 0x00020000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_16BIT = 0x00020000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_LOCKED = 0x00040000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_PRELOAD = 0x00080000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_1BYTES = 0x00100000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_2BYTES = 0x00200000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_4BYTES = 0x00300000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_8BYTES = 0x00400000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_16BYTES = 0x00500000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_32BYTES = 0x00600000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_64BYTES = 0x00700000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_128BYTES = 0x00800000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_256BYTES = 0x00900000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_512BYTES = 0x00A00000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000;
|
||||
const boost::uint32_t IMAGE_SCN_ALIGN_MASK = 0x00F00000;
|
||||
const boost::uint32_t IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_DISCARDABLE = 0x02000000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_NOT_CACHED = 0x04000000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_NOT_PAGED = 0x08000000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_SHARED = 0x10000000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_EXECUTE = 0x20000000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_READ = 0x40000000;
|
||||
const boost::uint32_t IMAGE_SCN_MEM_WRITE = 0x80000000;
|
||||
|
||||
struct dos_header {
|
||||
boost::uint16_t e_magic;
|
||||
boost::uint16_t e_cblp;
|
||||
@ -153,6 +192,20 @@ struct import_dir_entry {
|
||||
boost::uint32_t AddressRVA;
|
||||
};
|
||||
|
||||
struct export_dir_table {
|
||||
boost::uint32_t ExportFlags;
|
||||
boost::uint32_t TimeDateStamp;
|
||||
boost::uint16_t MajorVersion;
|
||||
boost::uint16_t MinorVersion;
|
||||
boost::uint32_t NameRVA;
|
||||
boost::uint32_t OrdinalBase;
|
||||
boost::uint32_t AddressTableEntries;
|
||||
boost::uint32_t NumberOfNamePointers;
|
||||
boost::uint32_t ExportAddressTableRVA;
|
||||
boost::uint32_t NamePointerRVA;
|
||||
boost::uint32_t OrdinalTableRVA;
|
||||
};
|
||||
|
||||
enum reloc_type {
|
||||
ABSOLUTE = 0,
|
||||
HIGH = 1,
|
||||
|
@ -25,6 +25,7 @@ THE SOFTWARE.
|
||||
#include <list>
|
||||
#include "parse.h"
|
||||
#include "nt-headers.h"
|
||||
#include <to_string.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
@ -42,6 +43,12 @@ struct importent {
|
||||
string moduleName;
|
||||
};
|
||||
|
||||
struct exportent {
|
||||
VA addr;
|
||||
string symbolName;
|
||||
string moduleName;
|
||||
};
|
||||
|
||||
struct reloc {
|
||||
VA shiftedAddr;
|
||||
reloc_type type;
|
||||
@ -51,6 +58,7 @@ struct parsed_pe_internal {
|
||||
list<section> secs;
|
||||
list<importent> imports;
|
||||
list<reloc> relocs;
|
||||
list<exportent> exports;
|
||||
};
|
||||
|
||||
bool getSecForVA(list<section> &secs, VA v, section &sec) {
|
||||
@ -86,7 +94,9 @@ bool getSections( bounded_buffer *b,
|
||||
|
||||
::uint32_t o = i*sizeof(image_section_header);
|
||||
for(::uint32_t k = 0; k < NT_SHORT_NAME_LEN; k++) {
|
||||
readByte(b, o+k, curSec.Name[k]);
|
||||
if(readByte(b, o+k, curSec.Name[k]) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#define READ_WORD(x) \
|
||||
if(readWord(b, o+_offset(image_section_header, x), curSec.x) == false) { \
|
||||
@ -281,7 +291,9 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
||||
//start by reading MZ
|
||||
::uint16_t tmp = 0;
|
||||
::uint32_t curOffset = 0;
|
||||
readWord(file, curOffset, tmp);
|
||||
if(readWord(file, curOffset, tmp) == false) {
|
||||
return false;
|
||||
}
|
||||
if(tmp != MZ_MAGIC) {
|
||||
return false;
|
||||
}
|
||||
@ -345,6 +357,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
delete p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//get exports
|
||||
data_directory exportDir =
|
||||
p->peHeader.nt.OptionalHeader.DataDirectory[DIR_EXPORT];
|
||||
@ -357,6 +370,181 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t rvaofft = addr - s.sectionBase;
|
||||
|
||||
//get the name of this module
|
||||
::uint32_t nameRva;
|
||||
if(readDword( s.sectionData,
|
||||
rvaofft+_offset(export_dir_table, NameRVA),
|
||||
nameRva) == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t nameVA = nameRva + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
|
||||
section nameSec;
|
||||
if(getSecForVA(p->internal->secs, nameVA, nameSec) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t nameOff = nameVA - nameSec.sectionBase;
|
||||
string modName;
|
||||
::uint8_t c;
|
||||
do {
|
||||
if(readByte(nameSec.sectionData, nameOff, c) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(c == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
modName.push_back(c);
|
||||
nameOff++;
|
||||
}while(true);
|
||||
|
||||
//now, get all the named export symbols
|
||||
::uint32_t numNames;
|
||||
if(readDword( s.sectionData,
|
||||
rvaofft+_offset(export_dir_table, NumberOfNamePointers),
|
||||
numNames) == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(numNames > 0) {
|
||||
//get the names section
|
||||
::uint32_t namesRVA;
|
||||
if(readDword( s.sectionData,
|
||||
rvaofft+_offset(export_dir_table, NamePointerRVA),
|
||||
namesRVA) == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t namesVA =
|
||||
namesRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section namesSec;
|
||||
|
||||
if(getSecForVA(p->internal->secs, namesVA, namesSec) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t namesOff = namesVA - namesSec.sectionBase;
|
||||
|
||||
//get the EAT section
|
||||
::uint32_t eatRVA;
|
||||
if(readDword( s.sectionData,
|
||||
rvaofft+_offset(export_dir_table, ExportAddressTableRVA),
|
||||
eatRVA) == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t eatVA =
|
||||
eatRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section eatSec;
|
||||
if(getSecForVA(p->internal->secs, eatVA, eatSec) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t eatOff = eatVA - eatSec.sectionBase;
|
||||
|
||||
//get the ordinal base
|
||||
::uint32_t ordinalBase;
|
||||
if(readDword( s.sectionData,
|
||||
rvaofft+_offset(export_dir_table, OrdinalBase),
|
||||
ordinalBase) == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//get the ordinal table
|
||||
::uint32_t ordinalTableRVA;
|
||||
if(readDword( s.sectionData,
|
||||
rvaofft+_offset(export_dir_table, OrdinalTableRVA),
|
||||
ordinalTableRVA) == false)
|
||||
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t ordinalTableVA =
|
||||
ordinalTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section ordinalTableSec;
|
||||
if(getSecForVA(p->internal->secs, ordinalTableVA, ordinalTableSec) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t ordinalOff = ordinalTableVA - ordinalTableSec.sectionBase;
|
||||
|
||||
for(::uint32_t i = 0; i < numNames; i++) {
|
||||
::uint32_t curNameRVA;
|
||||
if(readDword( namesSec.sectionData,
|
||||
namesOff+(i*sizeof(::uint32_t)),
|
||||
curNameRVA) == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t curNameVA =
|
||||
curNameRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
section curNameSec;
|
||||
|
||||
if(getSecForVA(p->internal->secs, curNameVA, curNameSec) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
::uint32_t curNameOff = curNameVA - curNameSec.sectionBase;
|
||||
string symName;
|
||||
::uint8_t d;
|
||||
|
||||
do {
|
||||
if(readByte(curNameSec.sectionData, curNameOff, d) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(d == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
symName.push_back(d);
|
||||
curNameOff++;
|
||||
}while(true);
|
||||
|
||||
//now, for this i, look it up in the ExportOrdinalTable
|
||||
::uint16_t ordinal;
|
||||
if(readWord(ordinalTableSec.sectionData,
|
||||
ordinalOff+(i*sizeof(uint16_t)),
|
||||
ordinal) == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//::uint32_t eatIdx = ordinal - ordinalBase;
|
||||
::uint32_t eatIdx = (ordinal*sizeof(uint32_t));
|
||||
|
||||
::uint32_t symRVA;
|
||||
if(readDword(eatSec.sectionData, eatOff+eatIdx, symRVA) == false) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool isForwarded =
|
||||
((symRVA >= exportDir.VirtualAddress) &&
|
||||
(symRVA < exportDir.VirtualAddress+exportDir.Size));
|
||||
|
||||
if(isForwarded == false) {
|
||||
::uint32_t symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||
exportent a;
|
||||
|
||||
a.addr = symVA;
|
||||
a.symbolName = symName;
|
||||
a.moduleName = modName;
|
||||
p->internal->exports.push_back(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//get relocations, if exist
|
||||
@ -487,7 +675,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
break;
|
||||
}
|
||||
|
||||
modName.push_back(c);
|
||||
modName.push_back(toupper(c));
|
||||
nameOff++;
|
||||
}while(true);
|
||||
|
||||
@ -556,6 +744,20 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
||||
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;
|
||||
|
||||
ent.symbolName = symName;
|
||||
ent.moduleName = modName;
|
||||
|
||||
p->internal->imports.push_back(ent);
|
||||
}
|
||||
|
||||
lookupOff += sizeof(::uint32_t);
|
||||
@ -584,7 +786,9 @@ void IterImpVAString(parsed_pe *pe, iterVAStr cb, void *cbd) {
|
||||
|
||||
for(list<importent>::iterator it = l.begin(), e = l.end(); it != e; ++it) {
|
||||
importent i = *it;
|
||||
cb(cbd, i.addr, i.moduleName, i.symbolName);
|
||||
if(cb(cbd, i.addr, i.moduleName, i.symbolName) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -596,7 +800,9 @@ void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd) {
|
||||
|
||||
for(list<reloc>::iterator it = l.begin(), e = l.end(); it != e; ++it) {
|
||||
reloc r = *it;
|
||||
cb(cbd, r.shiftedAddr, r.type);
|
||||
if(cb(cbd, r.shiftedAddr, r.type) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -604,6 +810,15 @@ void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd) {
|
||||
|
||||
//iterate over the exports by VA
|
||||
void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) {
|
||||
list<exportent> &l = pe->internal->exports;
|
||||
|
||||
for(list<exportent>::iterator it = l.begin(), e = l.end(); it != e; ++it) {
|
||||
exportent i = *it;
|
||||
|
||||
if(cb(cbd, i.addr, i.moduleName, i.symbolName)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -617,7 +832,9 @@ void IterSec(parsed_pe *pe, iterSec cb, void *cbd) {
|
||||
++sit)
|
||||
{
|
||||
section s = *sit;
|
||||
cb(cbd, s.sectionBase, s.sectionName, s.sectionData);
|
||||
if(cb(cbd, s.sectionBase, s.sectionName, s.sec, s.sectionData) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -635,3 +852,16 @@ bool ReadByteAtVA(parsed_pe *pe, VA v, ::uint8_t &b) {
|
||||
|
||||
return readByte(s.sectionData, off, b);
|
||||
}
|
||||
|
||||
bool GetEntryPoint(parsed_pe *pe, VA &v) {
|
||||
|
||||
if(pe != NULL) {
|
||||
nt_header_32 *nthdr = &pe->peHeader.nt;
|
||||
|
||||
v = nthdr->OptionalHeader.AddressOfEntryPoint + nthdr->OptionalHeader.ImageBase;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ THE SOFTWARE.
|
||||
#include "nt-headers.h"
|
||||
|
||||
typedef boost::uint32_t RVA;
|
||||
typedef boost::uint32_t VA;
|
||||
typedef boost::uint64_t VA;
|
||||
|
||||
struct buffer_detail;
|
||||
|
||||
@ -48,6 +48,7 @@ bool readDword(bounded_buffer *b, boost::uint32_t offset, boost::uint32_t &out);
|
||||
bounded_buffer *readFileToFileBuffer(const char *filePath);
|
||||
bounded_buffer *splitBuffer(bounded_buffer *b, boost::uint32_t from, boost::uint32_t to);
|
||||
void deleteBuffer(bounded_buffer *b);
|
||||
uint64_t bufLen(bounded_buffer *b);
|
||||
|
||||
struct parsed_pe_internal;
|
||||
|
||||
@ -68,22 +69,25 @@ parsed_pe *ParsePEFromFile(const char *filePath);
|
||||
void DestructParsedPE(parsed_pe *pe);
|
||||
|
||||
//iterate over the imports by RVA and string
|
||||
typedef void (*iterVAStr)(void *, VA, std::string &, std::string &);
|
||||
typedef int (*iterVAStr)(void *, VA, std::string &, std::string &);
|
||||
void IterImpVAString(parsed_pe *pe, iterVAStr cb, void *cbd);
|
||||
|
||||
//iterate over relocations in the PE file
|
||||
typedef void (*iterReloc)(void *, VA, reloc_type);
|
||||
typedef int (*iterReloc)(void *, VA, reloc_type);
|
||||
void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd);
|
||||
|
||||
//iterate over the exports
|
||||
typedef void (*iterExp)(void *, VA, std::string &, std::string &);
|
||||
typedef int (*iterExp)(void *, VA, std::string &, std::string &);
|
||||
void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd);
|
||||
|
||||
//iterate over sections
|
||||
typedef void (*iterSec)(void *, RVA secBase, std::string &, bounded_buffer *b);
|
||||
typedef int (*iterSec)(void *, VA secBase, std::string &, image_section_header, bounded_buffer *b);
|
||||
void IterSec(parsed_pe *pe, iterSec cb, void *cbd);
|
||||
|
||||
//get byte at VA in PE
|
||||
bool ReadByteAtVA(parsed_pe *pe, VA v, boost::uint8_t &b);
|
||||
|
||||
//get entry point into PE
|
||||
bool GetEntryPoint(parsed_pe *pe, VA &v);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user