mirror of
https://github.com/QuasarApp/pe-parse.git
synced 2025-05-08 17:49:32 +00:00
Added clang-format spec - issue #35
This commit is contained in:
parent
e3f63e11cb
commit
cb2fd5736f
19
.clang-format
Normal file
19
.clang-format
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
AlignEscapedNewlinesLeft: true
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
ColumnLimit: 80
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentWidth: 2
|
||||||
|
Language: Cpp
|
||||||
|
PointerAlignment: Right
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 2
|
||||||
|
UseTab: Never
|
@ -22,9 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "parse.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace peparse;
|
using namespace peparse;
|
||||||
@ -49,7 +49,7 @@ int printImports(void *N, VA impAddr, string &modName, string &symName) {
|
|||||||
|
|
||||||
int printRelocs(void *N, VA relocAddr, reloc_type type) {
|
int printRelocs(void *N, VA relocAddr, reloc_type type) {
|
||||||
cout << "TYPE: ";
|
cout << "TYPE: ";
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case ABSOLUTE:
|
case ABSOLUTE:
|
||||||
cout << "ABSOLUTE";
|
cout << "ABSOLUTE";
|
||||||
break;
|
break;
|
||||||
@ -78,11 +78,15 @@ int printRelocs(void *N, VA relocAddr, reloc_type type) {
|
|||||||
|
|
||||||
cout << " VA: 0x" << to_string<VA>(relocAddr, hex) << endl;
|
cout << " VA: 0x" << to_string<VA>(relocAddr, hex) << endl;
|
||||||
|
|
||||||
return 0 ;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int printSymbols(void *N, std::string &strName, uint32_t &value,
|
int printSymbols(void *N,
|
||||||
int16_t §ionNumber, uint16_t &type, uint8_t &storageClass,
|
std::string &strName,
|
||||||
|
uint32_t &value,
|
||||||
|
int16_t §ionNumber,
|
||||||
|
uint16_t &type,
|
||||||
|
uint8_t &storageClass,
|
||||||
uint8_t &numberOfAuxSymbols) {
|
uint8_t &numberOfAuxSymbols) {
|
||||||
cout << "Symbol Name: " << strName << endl;
|
cout << "Symbol Name: " << strName << endl;
|
||||||
cout << "Symbol Value: 0x" << to_string<uint32_t>(value, hex) << endl;
|
cout << "Symbol Value: 0x" << to_string<uint32_t>(value, hex) << endl;
|
||||||
@ -192,14 +196,13 @@ int printSymbols(void *N, std::string &strName, uint32_t &value,
|
|||||||
}
|
}
|
||||||
cout << endl;
|
cout << endl;
|
||||||
|
|
||||||
cout << "Symbol Number of Aux Symbols: " << (uint32_t) numberOfAuxSymbols << endl;
|
cout << "Symbol Number of Aux Symbols: " << (uint32_t) numberOfAuxSymbols
|
||||||
|
<< endl;
|
||||||
|
|
||||||
return 0 ;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int printRsrc(void *N,
|
int printRsrc(void *N, resource r) {
|
||||||
resource r)
|
|
||||||
{
|
|
||||||
if (r.type_str.length())
|
if (r.type_str.length())
|
||||||
cout << "Type (string): " << r.type_str << endl;
|
cout << "Type (string): " << r.type_str << endl;
|
||||||
else
|
else
|
||||||
@ -222,8 +225,7 @@ int printSecs(void *N,
|
|||||||
VA secBase,
|
VA secBase,
|
||||||
string &secName,
|
string &secName,
|
||||||
image_section_header s,
|
image_section_header s,
|
||||||
bounded_buffer *data)
|
bounded_buffer *data) {
|
||||||
{
|
|
||||||
cout << "Sec Name: " << secName << endl;
|
cout << "Sec Name: " << secName << endl;
|
||||||
cout << "Sec Base: 0x" << to_string<uint64_t>(secBase, hex) << endl;
|
cout << "Sec Base: 0x" << to_string<uint64_t>(secBase, hex) << endl;
|
||||||
if (data)
|
if (data)
|
||||||
@ -234,11 +236,11 @@ int printSecs(void *N,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if(argc == 2) {
|
if (argc == 2) {
|
||||||
parsed_pe *p = ParsePEFromFile(argv[1]);
|
parsed_pe *p = ParsePEFromFile(argv[1]);
|
||||||
|
|
||||||
if(p != NULL) {
|
if (p != NULL) {
|
||||||
//print out some things
|
// print out some things
|
||||||
#define DUMP_FIELD(x) \
|
#define DUMP_FIELD(x) \
|
||||||
cout << "" #x << ": 0x"; \
|
cout << "" #x << ": 0x"; \
|
||||||
cout << to_string<uint32_t>(p->peHeader.nt.x, hex) << endl;
|
cout << to_string<uint32_t>(p->peHeader.nt.x, hex) << endl;
|
||||||
@ -323,16 +325,16 @@ int main(int argc, char *argv[]) {
|
|||||||
cout << "Exports: " << endl;
|
cout << "Exports: " << endl;
|
||||||
IterExpVA(p, printExps, NULL);
|
IterExpVA(p, printExps, NULL);
|
||||||
|
|
||||||
//read the first 8 bytes from the entry point and print them
|
// read the first 8 bytes from the entry point and print them
|
||||||
VA entryPoint;
|
VA entryPoint;
|
||||||
if(GetEntryPoint(p, entryPoint)) {
|
if (GetEntryPoint(p, entryPoint)) {
|
||||||
cout << "First 8 bytes from entry point (0x";
|
cout << "First 8 bytes from entry point (0x";
|
||||||
|
|
||||||
cout << to_string<VA>(entryPoint, hex);
|
cout << to_string<VA>(entryPoint, hex);
|
||||||
cout << "):" << endl;
|
cout << "):" << endl;
|
||||||
for(int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
::uint8_t b;
|
::uint8_t b;
|
||||||
ReadByteAtVA(p, i+entryPoint, b);
|
ReadByteAtVA(p, i + entryPoint, b);
|
||||||
cout << " 0x" << to_string<uint32_t>(b, hex);
|
cout << " 0x" << to_string<uint32_t>(b, hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,9 +344,9 @@ int main(int argc, char *argv[]) {
|
|||||||
cout << "Resources: " << endl;
|
cout << "Resources: " << endl;
|
||||||
IterRsrc(p, printRsrc, NULL);
|
IterRsrc(p, printRsrc, NULL);
|
||||||
DestructParsedPE(p);
|
DestructParsedPE(p);
|
||||||
}
|
} else {
|
||||||
else {
|
cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
|
||||||
cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")" << endl;
|
<< endl;
|
||||||
cout << "Location: " << GetPEErrLoc() << endl;
|
cout << "Location: " << GetPEErrLoc() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "parse.h"
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -53,63 +53,63 @@ struct buffer_detail {
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool readByte(bounded_buffer *b, ::uint32_t offset, ::uint8_t &out) {
|
bool readByte(bounded_buffer *b, ::uint32_t offset, ::uint8_t &out) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(offset >= b->bufLen) {
|
if (offset >= b->bufLen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::uint8_t *tmp = (b->buf+offset);
|
::uint8_t *tmp = (b->buf + offset);
|
||||||
out = *tmp;
|
out = *tmp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: perform endian swap as needed
|
// TODO: perform endian swap as needed
|
||||||
bool readWord(bounded_buffer *b, ::uint32_t offset, ::uint16_t &out) {
|
bool readWord(bounded_buffer *b, ::uint32_t offset, ::uint16_t &out) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(offset >= b->bufLen) {
|
if (offset >= b->bufLen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::uint16_t *tmp = reinterpret_cast<uint16_t *>(b->buf+offset);
|
::uint16_t *tmp = reinterpret_cast<uint16_t *>(b->buf + offset);
|
||||||
out = *tmp;
|
out = *tmp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: perform endian swap as needed
|
// TODO: perform endian swap as needed
|
||||||
bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) {
|
bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(offset >= b->bufLen) {
|
if (offset >= b->bufLen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::uint32_t *tmp = reinterpret_cast<uint32_t *>(b->buf+offset);
|
::uint32_t *tmp = reinterpret_cast<uint32_t *>(b->buf + offset);
|
||||||
out = *tmp;
|
out = *tmp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: perform endian swap as needed
|
// TODO: perform endian swap as needed
|
||||||
bool readQword(bounded_buffer *b, ::uint32_t offset, ::uint64_t &out) {
|
bool readQword(bounded_buffer *b, ::uint32_t offset, ::uint64_t &out) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(offset >= b->bufLen) {
|
if (offset >= b->bufLen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::uint64_t *tmp = reinterpret_cast<uint64_t *>(b->buf+offset);
|
::uint64_t *tmp = reinterpret_cast<uint64_t *>(b->buf + offset);
|
||||||
out = *tmp;
|
out = *tmp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -119,44 +119,44 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
HANDLE h = CreateFileA(filePath,
|
HANDLE h = CreateFileA(filePath,
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
nullptr,
|
nullptr,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
nullptr);
|
nullptr);
|
||||||
if(h == INVALID_HANDLE_VALUE) {
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD fileSize = GetFileSize(h, nullptr);
|
DWORD fileSize = GetFileSize(h, nullptr);
|
||||||
|
|
||||||
if(fileSize == INVALID_FILE_SIZE) {
|
if (fileSize == INVALID_FILE_SIZE) {
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
//only where we have mmap / open / etc
|
// only where we have mmap / open / etc
|
||||||
int fd = open(filePath, O_RDONLY);
|
int fd = open(filePath, O_RDONLY);
|
||||||
|
|
||||||
if(fd == -1) {
|
if (fd == -1) {
|
||||||
PE_ERR(PEERR_OPEN);
|
PE_ERR(PEERR_OPEN);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//make a buffer object
|
// make a buffer object
|
||||||
bounded_buffer *p = new(std::nothrow) bounded_buffer();
|
bounded_buffer *p = new (std::nothrow) bounded_buffer();
|
||||||
|
|
||||||
if(p == nullptr) {
|
if (p == nullptr) {
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(p, 0, sizeof(bounded_buffer));
|
memset(p, 0, sizeof(bounded_buffer));
|
||||||
buffer_detail *d = new(std::nothrow) buffer_detail();
|
buffer_detail *d = new (std::nothrow) buffer_detail();
|
||||||
|
|
||||||
if(d == nullptr) {
|
if (d == nullptr) {
|
||||||
delete p;
|
delete p;
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -164,13 +164,13 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
|||||||
memset(d, 0, sizeof(buffer_detail));
|
memset(d, 0, sizeof(buffer_detail));
|
||||||
p->detail = d;
|
p->detail = d;
|
||||||
|
|
||||||
//only where we have mmap / open / etc
|
// only where we have mmap / open / etc
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
p->detail->file = h;
|
p->detail->file = h;
|
||||||
|
|
||||||
HANDLE hMap = CreateFileMapping(h, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
HANDLE hMap = CreateFileMapping(h, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||||
|
|
||||||
if(hMap == nullptr) {
|
if (hMap == nullptr) {
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -180,12 +180,12 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
|||||||
|
|
||||||
LPVOID ptr = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
LPVOID ptr = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||||
|
|
||||||
if(ptr == nullptr) {
|
if (ptr == nullptr) {
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->buf = (::uint8_t *)ptr;
|
p->buf = (::uint8_t *) ptr;
|
||||||
p->bufLen = fileSize;
|
p->bufLen = fileSize;
|
||||||
p->copy = false;
|
p->copy = false;
|
||||||
#else
|
#else
|
||||||
@ -193,7 +193,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
|||||||
|
|
||||||
struct stat s = {0};
|
struct stat s = {0};
|
||||||
|
|
||||||
if(fstat(fd, &s) != 0) {
|
if (fstat(fd, &s) != 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
delete d;
|
delete d;
|
||||||
delete p;
|
delete p;
|
||||||
@ -203,7 +203,7 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
|||||||
|
|
||||||
void *maddr = mmap(nullptr, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
void *maddr = mmap(nullptr, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
|
||||||
if(maddr == MAP_FAILED) {
|
if (maddr == MAP_FAILED) {
|
||||||
close(fd);
|
close(fd);
|
||||||
delete d;
|
delete d;
|
||||||
delete p;
|
delete p;
|
||||||
@ -219,37 +219,37 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
//split buffer inclusively from from to to by offset
|
// split buffer inclusively from from to to by offset
|
||||||
bounded_buffer *splitBuffer(bounded_buffer *b, ::uint32_t from, ::uint32_t to) {
|
bounded_buffer *splitBuffer(bounded_buffer *b, ::uint32_t from, ::uint32_t to) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//safety checks
|
// safety checks
|
||||||
if(to < from || to > b->bufLen) {
|
if (to < from || to > b->bufLen) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//make a new buffer
|
// make a new buffer
|
||||||
bounded_buffer *newBuff = new(std::nothrow) bounded_buffer();
|
bounded_buffer *newBuff = new (std::nothrow) bounded_buffer();
|
||||||
|
|
||||||
if(newBuff == nullptr) {
|
if (newBuff == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
newBuff->copy = true;
|
newBuff->copy = true;
|
||||||
newBuff->buf = b->buf+from;
|
newBuff->buf = b->buf + from;
|
||||||
newBuff->bufLen = (to-from);
|
newBuff->bufLen = (to - from);
|
||||||
|
|
||||||
return newBuff;
|
return newBuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteBuffer(bounded_buffer *b) {
|
void deleteBuffer(bounded_buffer *b) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!b->copy) {
|
if (!b->copy) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
UnmapViewOfFile(b->buf);
|
UnmapViewOfFile(b->buf);
|
||||||
CloseHandle(b->detail->sec);
|
CloseHandle(b->detail->sec);
|
||||||
|
@ -26,11 +26,11 @@ THE SOFTWARE.
|
|||||||
#define _NT_HEADERS
|
#define _NT_HEADERS
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#define _offset(t, f) ((std::uint32_t)(ptrdiff_t)&(((t*)0)->f))
|
#define _offset(t, f) ((std::uint32_t)(ptrdiff_t) & (((t *) 0)->f))
|
||||||
|
|
||||||
//need to pack these structure definitions
|
// need to pack these structure definitions
|
||||||
|
|
||||||
//some constant definitions
|
// some constant definitions
|
||||||
namespace peparse {
|
namespace peparse {
|
||||||
const std::uint16_t MZ_MAGIC = 0x5A4D;
|
const std::uint16_t MZ_MAGIC = 0x5A4D;
|
||||||
const std::uint32_t NT_MAGIC = 0x00004550;
|
const std::uint32_t NT_MAGIC = 0x00004550;
|
||||||
@ -278,12 +278,8 @@ struct resource_dir_entry_sz {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct resource_dir_entry {
|
struct resource_dir_entry {
|
||||||
inline resource_dir_entry(void)
|
inline resource_dir_entry(void) : ID(0), RVA(0), type(0), name(0), lang(0) {
|
||||||
: ID(0),
|
}
|
||||||
RVA(0),
|
|
||||||
type(0),
|
|
||||||
name(0),
|
|
||||||
lang(0) {}
|
|
||||||
|
|
||||||
std::uint32_t ID;
|
std::uint32_t ID;
|
||||||
std::uint32_t RVA;
|
std::uint32_t RVA;
|
||||||
|
@ -22,13 +22,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <list>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "nt-headers.h"
|
#include "nt-headers.h"
|
||||||
#include "to_string.h"
|
#include "to_string.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <list>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ struct reloc {
|
|||||||
reloc_type type;
|
reloc_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SYMBOL_NAME_OFFSET(sn) ((uint32_t) (sn.data >> 32))
|
#define SYMBOL_NAME_OFFSET(sn) ((uint32_t)(sn.data >> 32))
|
||||||
#define SYMBOL_TYPE_HI(x) (x.type >> 8)
|
#define SYMBOL_TYPE_HI(x) (x.type >> 8)
|
||||||
|
|
||||||
union symbol_name {
|
union symbol_name {
|
||||||
@ -125,8 +125,7 @@ struct parsed_pe_internal {
|
|||||||
::uint32_t err = 0;
|
::uint32_t err = 0;
|
||||||
std::string err_loc;
|
std::string err_loc;
|
||||||
|
|
||||||
static const char *pe_err_str[] = {
|
static const char *pe_err_str[] = {"None",
|
||||||
"None",
|
|
||||||
"Out of memory",
|
"Out of memory",
|
||||||
"Invalid header",
|
"Invalid header",
|
||||||
"Invalid section",
|
"Invalid section",
|
||||||
@ -135,8 +134,7 @@ static const char *pe_err_str[] = {
|
|||||||
"Unable to read data",
|
"Unable to read data",
|
||||||
"Unable to open",
|
"Unable to open",
|
||||||
"Unable to stat",
|
"Unable to stat",
|
||||||
"Bad magic"
|
"Bad magic"};
|
||||||
};
|
|
||||||
|
|
||||||
int GetPEErr() {
|
int GetPEErr() {
|
||||||
return err;
|
return err;
|
||||||
@ -150,9 +148,8 @@ string GetPEErrLoc() {
|
|||||||
return err_loc;
|
return err_loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool readCString(const bounded_buffer &buffer, ::uint32_t off,
|
static bool
|
||||||
string &result)
|
readCString(const bounded_buffer &buffer, ::uint32_t off, string &result) {
|
||||||
{
|
|
||||||
if (off < buffer.bufLen) {
|
if (off < buffer.bufLen) {
|
||||||
::uint8_t *p = buffer.buf;
|
::uint8_t *p = buffer.buf;
|
||||||
::uint32_t n = buffer.bufLen;
|
::uint32_t n = buffer.bufLen;
|
||||||
@ -210,7 +207,12 @@ bool parse_resource_id(bounded_buffer *data, ::uint32_t id, string &result) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_resource_table(bounded_buffer *sectionData, ::uint32_t o, ::uint32_t virtaddr, ::uint32_t depth, resource_dir_entry *dirent, list<resource> &rsrcs) {
|
bool parse_resource_table(bounded_buffer *sectionData,
|
||||||
|
::uint32_t o,
|
||||||
|
::uint32_t virtaddr,
|
||||||
|
::uint32_t depth,
|
||||||
|
resource_dir_entry *dirent,
|
||||||
|
list<resource> &rsrcs) {
|
||||||
::uint32_t i = 0;
|
::uint32_t i = 0;
|
||||||
resource_dir_table rdt;
|
resource_dir_table rdt;
|
||||||
|
|
||||||
@ -245,21 +247,24 @@ bool parse_resource_table(bounded_buffer *sectionData, ::uint32_t o, ::uint32_t
|
|||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
rde->type = rde->ID;
|
rde->type = rde->ID;
|
||||||
if (i < rdt.NameEntries) {
|
if (i < rdt.NameEntries) {
|
||||||
if (!parse_resource_id(sectionData, rde->ID & 0x0FFFFFFF, rde->type_str)) {
|
if (!parse_resource_id(
|
||||||
|
sectionData, rde->ID & 0x0FFFFFFF, rde->type_str)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth == 1) {
|
} else if (depth == 1) {
|
||||||
rde->name = rde->ID;
|
rde->name = rde->ID;
|
||||||
if (i < rdt.NameEntries) {
|
if (i < rdt.NameEntries) {
|
||||||
if (!parse_resource_id(sectionData, rde->ID & 0x0FFFFFFF, rde->name_str)) {
|
if (!parse_resource_id(
|
||||||
|
sectionData, rde->ID & 0x0FFFFFFF, rde->name_str)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth == 2) {
|
} else if (depth == 2) {
|
||||||
rde->lang = rde->ID;
|
rde->lang = rde->ID;
|
||||||
if (i < rdt.NameEntries) {
|
if (i < rdt.NameEntries) {
|
||||||
if (!parse_resource_id(sectionData, rde->ID & 0x0FFFFFFF, rde->lang_str)) {
|
if (!parse_resource_id(
|
||||||
|
sectionData, rde->ID & 0x0FFFFFFF, rde->lang_str)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,7 +273,12 @@ bool parse_resource_table(bounded_buffer *sectionData, ::uint32_t o, ::uint32_t
|
|||||||
// High bit 0 = RVA to RDT.
|
// High bit 0 = RVA to RDT.
|
||||||
// High bit 1 = RVA to RDE.
|
// High bit 1 = RVA to RDE.
|
||||||
if (rde->RVA & 0x80000000) {
|
if (rde->RVA & 0x80000000) {
|
||||||
if (!parse_resource_table(sectionData, rde->RVA & 0x0FFFFFFF, virtaddr, depth + 1, rde, rsrcs)) {
|
if (!parse_resource_table(sectionData,
|
||||||
|
rde->RVA & 0x0FFFFFFF,
|
||||||
|
virtaddr,
|
||||||
|
depth + 1,
|
||||||
|
rde,
|
||||||
|
rsrcs)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -336,7 +346,10 @@ bool parse_resource_table(bounded_buffer *sectionData, ::uint32_t o, ::uint32_t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getResources(bounded_buffer *b, bounded_buffer *fileBegin, list<section> secs, list<resource> &rsrcs) {
|
bool getResources(bounded_buffer *b,
|
||||||
|
bounded_buffer *fileBegin,
|
||||||
|
list<section> secs,
|
||||||
|
list<resource> &rsrcs) {
|
||||||
|
|
||||||
if (b == nullptr)
|
if (b == nullptr)
|
||||||
return false;
|
return false;
|
||||||
@ -346,7 +359,8 @@ bool getResources(bounded_buffer *b, bounded_buffer *fileBegin, list<section> se
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parse_resource_table(s.sectionData, 0, s.sec.VirtualAddress, 0, nullptr, rsrcs)) {
|
if (!parse_resource_table(
|
||||||
|
s.sectionData, 0, s.sec.VirtualAddress, 0, nullptr, rsrcs)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,21 +370,21 @@ bool getResources(bounded_buffer *b, bounded_buffer *fileBegin, list<section> se
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getSections( bounded_buffer *b,
|
bool getSections(bounded_buffer *b,
|
||||||
bounded_buffer *fileBegin,
|
bounded_buffer *fileBegin,
|
||||||
nt_header_32 &nthdr,
|
nt_header_32 &nthdr,
|
||||||
list<section> &secs) {
|
list<section> &secs) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get each of the sections...
|
// get each of the sections...
|
||||||
for(::uint32_t i = 0; i < nthdr.FileHeader.NumberOfSections; i++) {
|
for (::uint32_t i = 0; i < nthdr.FileHeader.NumberOfSections; i++) {
|
||||||
image_section_header curSec;
|
image_section_header curSec;
|
||||||
|
|
||||||
::uint32_t o = i*sizeof(image_section_header);
|
::uint32_t o = i * sizeof(image_section_header);
|
||||||
for(::uint32_t k = 0; k < NT_SHORT_NAME_LEN; k++) {
|
for (::uint32_t k = 0; k < NT_SHORT_NAME_LEN; k++) {
|
||||||
if(!readByte(b, o+k, curSec.Name[k])) {
|
if (!readByte(b, o + k, curSec.Name[k])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,29 +399,31 @@ bool getSections( bounded_buffer *b,
|
|||||||
READ_WORD(b, o, curSec, NumberOfLinenumbers);
|
READ_WORD(b, o, curSec, NumberOfLinenumbers);
|
||||||
READ_DWORD(b, o, curSec, Characteristics);
|
READ_DWORD(b, o, curSec, Characteristics);
|
||||||
|
|
||||||
//now we have the section header information, so fill in a section
|
// now we have the section header information, so fill in a section
|
||||||
//object appropriately
|
// object appropriately
|
||||||
section thisSec;
|
section thisSec;
|
||||||
for(::uint32_t i = 0; i < NT_SHORT_NAME_LEN; i++) {
|
for (::uint32_t i = 0; i < NT_SHORT_NAME_LEN; i++) {
|
||||||
::uint8_t c = curSec.Name[i];
|
::uint8_t c = curSec.Name[i];
|
||||||
if(c == 0) {
|
if (c == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
thisSec.sectionName.push_back((char)c);
|
thisSec.sectionName.push_back((char) c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nthdr.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (nthdr.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
thisSec.sectionBase = nthdr.OptionalHeader.ImageBase + curSec.VirtualAddress;
|
thisSec.sectionBase =
|
||||||
|
nthdr.OptionalHeader.ImageBase + curSec.VirtualAddress;
|
||||||
} else if (nthdr.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (nthdr.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
thisSec.sectionBase = nthdr.OptionalHeader64.ImageBase + curSec.VirtualAddress;
|
thisSec.sectionBase =
|
||||||
|
nthdr.OptionalHeader64.ImageBase + curSec.VirtualAddress;
|
||||||
} else {
|
} else {
|
||||||
PE_ERR(PEERR_MAGIC);
|
PE_ERR(PEERR_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
thisSec.sec = curSec;
|
thisSec.sec = curSec;
|
||||||
::uint32_t lowOff = curSec.PointerToRawData;
|
::uint32_t lowOff = curSec.PointerToRawData;
|
||||||
::uint32_t highOff = lowOff+curSec.SizeOfRawData;
|
::uint32_t highOff = lowOff + curSec.SizeOfRawData;
|
||||||
thisSec.sectionData = splitBuffer(fileBegin, lowOff, highOff);
|
thisSec.sectionData = splitBuffer(fileBegin, lowOff, highOff);
|
||||||
|
|
||||||
secs.push_back(thisSec);
|
secs.push_back(thisSec);
|
||||||
@ -453,18 +469,18 @@ bool readOptionalHeader(bounded_buffer *b, optional_header_32 &header) {
|
|||||||
header.NumberOfRvaAndSizes = NUM_DIR_ENTRIES;
|
header.NumberOfRvaAndSizes = NUM_DIR_ENTRIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(::uint32_t i = 0; i < header.NumberOfRvaAndSizes; i++) {
|
for (::uint32_t i = 0; i < header.NumberOfRvaAndSizes; i++) {
|
||||||
::uint32_t c = (i*sizeof(data_directory));
|
::uint32_t c = (i * sizeof(data_directory));
|
||||||
c+= _offset(optional_header_32, DataDirectory[0]);
|
c += _offset(optional_header_32, DataDirectory[0]);
|
||||||
::uint32_t o;
|
::uint32_t o;
|
||||||
|
|
||||||
o = c + _offset(data_directory, VirtualAddress);
|
o = c + _offset(data_directory, VirtualAddress);
|
||||||
if(!readDword(b, o, header.DataDirectory[i].VirtualAddress)) {
|
if (!readDword(b, o, header.DataDirectory[i].VirtualAddress)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
o = c + _offset(data_directory, Size);
|
o = c + _offset(data_directory, Size);
|
||||||
if(!readDword(b, o, header.DataDirectory[i].Size)) {
|
if (!readDword(b, o, header.DataDirectory[i].Size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,18 +524,18 @@ bool readOptionalHeader64(bounded_buffer *b, optional_header_64 &header) {
|
|||||||
header.NumberOfRvaAndSizes = NUM_DIR_ENTRIES;
|
header.NumberOfRvaAndSizes = NUM_DIR_ENTRIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(::uint32_t i = 0; i < header.NumberOfRvaAndSizes; i++) {
|
for (::uint32_t i = 0; i < header.NumberOfRvaAndSizes; i++) {
|
||||||
::uint32_t c = (i*sizeof(data_directory));
|
::uint32_t c = (i * sizeof(data_directory));
|
||||||
c += _offset(optional_header_64, DataDirectory[0]);
|
c += _offset(optional_header_64, DataDirectory[0]);
|
||||||
::uint32_t o;
|
::uint32_t o;
|
||||||
|
|
||||||
o = c + _offset(data_directory, VirtualAddress);
|
o = c + _offset(data_directory, VirtualAddress);
|
||||||
if(!readDword(b, o, header.DataDirectory[i].VirtualAddress)) {
|
if (!readDword(b, o, header.DataDirectory[i].VirtualAddress)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
o = c + _offset(data_directory, Size);
|
o = c + _offset(data_directory, Size);
|
||||||
if(!readDword(b, o, header.DataDirectory[i].Size)) {
|
if (!readDword(b, o, header.DataDirectory[i].Size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -540,13 +556,13 @@ bool readFileHeader(bounded_buffer *b, file_header &header) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
||||||
if(b == nullptr) {
|
if (b == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::uint32_t pe_magic;
|
::uint32_t pe_magic;
|
||||||
::uint32_t curOffset =0;
|
::uint32_t curOffset = 0;
|
||||||
if(!readDword(b, curOffset, pe_magic) || pe_magic != NT_MAGIC) {
|
if (!readDword(b, curOffset, pe_magic) || pe_magic != NT_MAGIC) {
|
||||||
PE_ERR(PEERR_READ);
|
PE_ERR(PEERR_READ);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -555,12 +571,12 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
|||||||
bounded_buffer *fhb =
|
bounded_buffer *fhb =
|
||||||
splitBuffer(b, _offset(nt_header_32, FileHeader), b->bufLen);
|
splitBuffer(b, _offset(nt_header_32, FileHeader), b->bufLen);
|
||||||
|
|
||||||
if(fhb == nullptr) {
|
if (fhb == nullptr) {
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!readFileHeader(fhb, header.FileHeader)) {
|
if (!readFileHeader(fhb, header.FileHeader)) {
|
||||||
deleteBuffer(fhb);
|
deleteBuffer(fhb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -573,7 +589,7 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
|||||||
bounded_buffer *ohb =
|
bounded_buffer *ohb =
|
||||||
splitBuffer(b, _offset(nt_header_32, OptionalHeader), b->bufLen);
|
splitBuffer(b, _offset(nt_header_32, OptionalHeader), b->bufLen);
|
||||||
|
|
||||||
if(ohb == nullptr) {
|
if (ohb == nullptr) {
|
||||||
deleteBuffer(fhb);
|
deleteBuffer(fhb);
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return false;
|
return false;
|
||||||
@ -584,20 +600,20 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
|||||||
*/
|
*/
|
||||||
if (!readWord(ohb, 0, header.OptionalMagic)) {
|
if (!readWord(ohb, 0, header.OptionalMagic)) {
|
||||||
PE_ERR(PEERR_READ);
|
PE_ERR(PEERR_READ);
|
||||||
if(ohb != nullptr) {
|
if (ohb != nullptr) {
|
||||||
deleteBuffer(ohb);
|
deleteBuffer(ohb);
|
||||||
}
|
}
|
||||||
deleteBuffer(fhb);
|
deleteBuffer(fhb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (header.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (header.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
if(!readOptionalHeader(ohb, header.OptionalHeader)) {
|
if (!readOptionalHeader(ohb, header.OptionalHeader)) {
|
||||||
deleteBuffer(ohb);
|
deleteBuffer(ohb);
|
||||||
deleteBuffer(fhb);
|
deleteBuffer(fhb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (header.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (header.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
if(!readOptionalHeader64(ohb, header.OptionalHeader64)) {
|
if (!readOptionalHeader64(ohb, header.OptionalHeader64)) {
|
||||||
deleteBuffer(ohb);
|
deleteBuffer(ohb);
|
||||||
deleteBuffer(fhb);
|
deleteBuffer(fhb);
|
||||||
return false;
|
return false;
|
||||||
@ -616,36 +632,36 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
||||||
if(file == nullptr) {
|
if (file == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//start by reading MZ
|
// start by reading MZ
|
||||||
::uint16_t tmp = 0;
|
::uint16_t tmp = 0;
|
||||||
::uint32_t curOffset = 0;
|
::uint32_t curOffset = 0;
|
||||||
if(!readWord(file, curOffset, tmp)) {
|
if (!readWord(file, curOffset, tmp)) {
|
||||||
PE_ERR(PEERR_READ);
|
PE_ERR(PEERR_READ);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(tmp != MZ_MAGIC) {
|
if (tmp != MZ_MAGIC) {
|
||||||
PE_ERR(PEERR_MAGIC);
|
PE_ERR(PEERR_MAGIC);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//read the offset to the NT headers
|
// read the offset to the NT headers
|
||||||
::uint32_t offset;
|
::uint32_t offset;
|
||||||
if(!readDword(file, _offset(dos_header, e_lfanew), offset)) {
|
if (!readDword(file, _offset(dos_header, e_lfanew), offset)) {
|
||||||
PE_ERR(PEERR_READ);
|
PE_ERR(PEERR_READ);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
curOffset += offset;
|
curOffset += offset;
|
||||||
|
|
||||||
//now, we can read out the fields of the NT headers
|
// now, we can read out the fields of the NT headers
|
||||||
bounded_buffer *ntBuf = splitBuffer(file, curOffset, file->bufLen);
|
bounded_buffer *ntBuf = splitBuffer(file, curOffset, file->bufLen);
|
||||||
|
|
||||||
if(!readNtHeader(ntBuf, p.nt)) {
|
if (!readNtHeader(ntBuf, p.nt)) {
|
||||||
// err is set by readNtHeader
|
// err is set by readNtHeader
|
||||||
if(ntBuf != nullptr) {
|
if (ntBuf != nullptr) {
|
||||||
deleteBuffer(ntBuf);
|
deleteBuffer(ntBuf);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -658,17 +674,19 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
|
|||||||
::uint32_t rem_size;
|
::uint32_t rem_size;
|
||||||
if (p.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
// signature + file_header + optional_header_32
|
// signature + file_header + optional_header_32
|
||||||
rem_size = sizeof(::uint32_t) + sizeof(file_header) + sizeof(optional_header_32);
|
rem_size =
|
||||||
|
sizeof(::uint32_t) + sizeof(file_header) + sizeof(optional_header_32);
|
||||||
} else if (p.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
// signature + file_header + optional_header_64
|
// signature + file_header + optional_header_64
|
||||||
rem_size = sizeof(::uint32_t) + sizeof(file_header) + sizeof(optional_header_64);
|
rem_size =
|
||||||
|
sizeof(::uint32_t) + sizeof(file_header) + sizeof(optional_header_64);
|
||||||
} else {
|
} else {
|
||||||
PE_ERR(PEERR_MAGIC);
|
PE_ERR(PEERR_MAGIC);
|
||||||
deleteBuffer(ntBuf);
|
deleteBuffer(ntBuf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//update 'rem' to point to the space after the header
|
// update 'rem' to point to the space after the header
|
||||||
rem = splitBuffer(ntBuf, rem_size, ntBuf->bufLen);
|
rem = splitBuffer(ntBuf, rem_size, ntBuf->bufLen);
|
||||||
deleteBuffer(ntBuf);
|
deleteBuffer(ntBuf);
|
||||||
|
|
||||||
@ -691,7 +709,8 @@ bool getExports(parsed_pe *p) {
|
|||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
addr = exportDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
addr = exportDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
addr = exportDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
addr =
|
||||||
|
exportDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -702,10 +721,10 @@ bool getExports(parsed_pe *p) {
|
|||||||
|
|
||||||
::uint32_t rvaofft = addr - s.sectionBase;
|
::uint32_t rvaofft = addr - s.sectionBase;
|
||||||
|
|
||||||
//get the name of this module
|
// get the name of this module
|
||||||
::uint32_t nameRva;
|
::uint32_t nameRva;
|
||||||
if (!readDword(s.sectionData,
|
if (!readDword(s.sectionData,
|
||||||
rvaofft+_offset(export_dir_table, NameRVA),
|
rvaofft + _offset(export_dir_table, NameRVA),
|
||||||
nameRva)) {
|
nameRva)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -730,19 +749,19 @@ bool getExports(parsed_pe *p) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//now, get all the named export symbols
|
// now, get all the named export symbols
|
||||||
::uint32_t numNames;
|
::uint32_t numNames;
|
||||||
if (!readDword(s.sectionData,
|
if (!readDword(s.sectionData,
|
||||||
rvaofft+_offset(export_dir_table, NumberOfNamePointers),
|
rvaofft + _offset(export_dir_table, NumberOfNamePointers),
|
||||||
numNames)) {
|
numNames)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numNames > 0) {
|
if (numNames > 0) {
|
||||||
//get the names section
|
// get the names section
|
||||||
::uint32_t namesRVA;
|
::uint32_t namesRVA;
|
||||||
if(!readDword(s.sectionData,
|
if (!readDword(s.sectionData,
|
||||||
rvaofft+_offset(export_dir_table, NamePointerRVA),
|
rvaofft + _offset(export_dir_table, NamePointerRVA),
|
||||||
namesRVA)) {
|
namesRVA)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -757,16 +776,16 @@ bool getExports(parsed_pe *p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
section namesSec;
|
section namesSec;
|
||||||
if(!getSecForVA(p->internal->secs, namesVA, namesSec)) {
|
if (!getSecForVA(p->internal->secs, namesVA, namesSec)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
::uint32_t namesOff = namesVA - namesSec.sectionBase;
|
::uint32_t namesOff = namesVA - namesSec.sectionBase;
|
||||||
|
|
||||||
//get the EAT section
|
// get the EAT section
|
||||||
::uint32_t eatRVA;
|
::uint32_t eatRVA;
|
||||||
if (!readDword(s.sectionData,
|
if (!readDword(s.sectionData,
|
||||||
rvaofft+_offset(export_dir_table, ExportAddressTableRVA),
|
rvaofft + _offset(export_dir_table, ExportAddressTableRVA),
|
||||||
eatRVA)) {
|
eatRVA)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -787,27 +806,29 @@ bool getExports(parsed_pe *p) {
|
|||||||
|
|
||||||
::uint32_t eatOff = eatVA - eatSec.sectionBase;
|
::uint32_t eatOff = eatVA - eatSec.sectionBase;
|
||||||
|
|
||||||
//get the ordinal base
|
// get the ordinal base
|
||||||
::uint32_t ordinalBase;
|
::uint32_t ordinalBase;
|
||||||
if (!readDword(s.sectionData,
|
if (!readDword(s.sectionData,
|
||||||
rvaofft+_offset(export_dir_table, OrdinalBase),
|
rvaofft + _offset(export_dir_table, OrdinalBase),
|
||||||
ordinalBase)) {
|
ordinalBase)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the ordinal table
|
// get the ordinal table
|
||||||
::uint32_t ordinalTableRVA;
|
::uint32_t ordinalTableRVA;
|
||||||
if (!readDword(s.sectionData,
|
if (!readDword(s.sectionData,
|
||||||
rvaofft+_offset(export_dir_table, OrdinalTableRVA),
|
rvaofft + _offset(export_dir_table, OrdinalTableRVA),
|
||||||
ordinalTableRVA)) {
|
ordinalTableRVA)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VA ordinalTableVA;
|
VA ordinalTableVA;
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
ordinalTableVA = ordinalTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
ordinalTableVA =
|
||||||
|
ordinalTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
ordinalTableVA = ordinalTableRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
ordinalTableVA =
|
||||||
|
ordinalTableRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -822,7 +843,7 @@ bool getExports(parsed_pe *p) {
|
|||||||
for (::uint32_t i = 0; i < numNames; i++) {
|
for (::uint32_t i = 0; i < numNames; i++) {
|
||||||
::uint32_t curNameRVA;
|
::uint32_t curNameRVA;
|
||||||
if (!readDword(namesSec.sectionData,
|
if (!readDword(namesSec.sectionData,
|
||||||
namesOff+(i*sizeof(::uint32_t)),
|
namesOff + (i * sizeof(::uint32_t)),
|
||||||
curNameRVA)) {
|
curNameRVA)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -859,25 +880,25 @@ bool getExports(parsed_pe *p) {
|
|||||||
curNameOff++;
|
curNameOff++;
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
//now, for this i, look it up in the ExportOrdinalTable
|
// now, for this i, look it up in the ExportOrdinalTable
|
||||||
::uint16_t ordinal;
|
::uint16_t ordinal;
|
||||||
if (!readWord(ordinalTableSec.sectionData,
|
if (!readWord(ordinalTableSec.sectionData,
|
||||||
ordinalOff+(i*sizeof(uint16_t)),
|
ordinalOff + (i * sizeof(uint16_t)),
|
||||||
ordinal)) {
|
ordinal)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//::uint32_t eatIdx = ordinal - ordinalBase;
|
//::uint32_t eatIdx = ordinal - ordinalBase;
|
||||||
::uint32_t eatIdx = (ordinal*sizeof(uint32_t));
|
::uint32_t eatIdx = (ordinal * sizeof(uint32_t));
|
||||||
|
|
||||||
::uint32_t symRVA;
|
::uint32_t symRVA;
|
||||||
if (!readDword(eatSec.sectionData, eatOff+eatIdx, symRVA)) {
|
if (!readDword(eatSec.sectionData, eatOff + eatIdx, symRVA)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isForwarded =
|
bool isForwarded =
|
||||||
((symRVA >= exportDir.VirtualAddress) &&
|
((symRVA >= exportDir.VirtualAddress) &&
|
||||||
(symRVA < exportDir.VirtualAddress+exportDir.Size));
|
(symRVA < exportDir.VirtualAddress + exportDir.Size));
|
||||||
|
|
||||||
if (!isForwarded) {
|
if (!isForwarded) {
|
||||||
::uint32_t symVA;
|
::uint32_t symVA;
|
||||||
@ -917,9 +938,11 @@ bool getRelocations(parsed_pe *p) {
|
|||||||
section d;
|
section d;
|
||||||
VA vaAddr;
|
VA vaAddr;
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
vaAddr = relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
vaAddr =
|
||||||
|
relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
vaAddr = relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
vaAddr =
|
||||||
|
relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -935,13 +958,13 @@ bool getRelocations(parsed_pe *p) {
|
|||||||
::uint32_t blockSize;
|
::uint32_t blockSize;
|
||||||
|
|
||||||
if (!readDword(d.sectionData,
|
if (!readDword(d.sectionData,
|
||||||
rvaofft+_offset(reloc_block, PageRVA),
|
rvaofft + _offset(reloc_block, PageRVA),
|
||||||
pageRva)) {
|
pageRva)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!readDword(d.sectionData,
|
if (!readDword(d.sectionData,
|
||||||
rvaofft+_offset(reloc_block, BlockSize),
|
rvaofft + _offset(reloc_block, BlockSize),
|
||||||
blockSize)) {
|
blockSize)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -975,7 +998,8 @@ bool getRelocations(parsed_pe *p) {
|
|||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
relocVA = pageRva + offset + p->peHeader.nt.OptionalHeader.ImageBase;
|
relocVA = pageRva + offset + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
relocVA = pageRva + offset + p->peHeader.nt.OptionalHeader64.ImageBase;
|
relocVA =
|
||||||
|
pageRva + offset + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -984,7 +1008,7 @@ bool getRelocations(parsed_pe *p) {
|
|||||||
reloc r;
|
reloc r;
|
||||||
|
|
||||||
r.shiftedAddr = relocVA;
|
r.shiftedAddr = relocVA;
|
||||||
r.type = (reloc_type)type;
|
r.type = (reloc_type) type;
|
||||||
p->internal->relocs.push_back(r);
|
p->internal->relocs.push_back(r);
|
||||||
|
|
||||||
entryCount--;
|
entryCount--;
|
||||||
@ -1007,13 +1031,14 @@ bool getImports(parsed_pe *p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (importDir.Size != 0) {
|
if (importDir.Size != 0) {
|
||||||
//get section for the RVA in importDir
|
// get section for the RVA in importDir
|
||||||
section c;
|
section c;
|
||||||
VA addr;
|
VA addr;
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
addr = importDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
addr = importDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
addr = importDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
addr =
|
||||||
|
importDir.VirtualAddress + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1022,10 +1047,10 @@ bool getImports(parsed_pe *p) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get import directory from this section
|
// get import directory from this section
|
||||||
::uint32_t offt = addr - c.sectionBase;
|
::uint32_t offt = addr - c.sectionBase;
|
||||||
do {
|
do {
|
||||||
//read each directory entry out
|
// read each directory entry out
|
||||||
import_dir_entry curEnt;
|
import_dir_entry curEnt;
|
||||||
|
|
||||||
READ_DWORD(c.sectionData, offt, curEnt, LookupTableRVA);
|
READ_DWORD(c.sectionData, offt, curEnt, LookupTableRVA);
|
||||||
@ -1034,14 +1059,13 @@ bool getImports(parsed_pe *p) {
|
|||||||
READ_DWORD(c.sectionData, offt, curEnt, NameRVA);
|
READ_DWORD(c.sectionData, offt, curEnt, NameRVA);
|
||||||
READ_DWORD(c.sectionData, offt, curEnt, AddressRVA);
|
READ_DWORD(c.sectionData, offt, curEnt, AddressRVA);
|
||||||
|
|
||||||
//are all the fields in curEnt null? then we break
|
// are all the fields in curEnt null? then we break
|
||||||
if (curEnt.LookupTableRVA == 0 &&
|
if (curEnt.LookupTableRVA == 0 && curEnt.NameRVA == 0 &&
|
||||||
curEnt.NameRVA == 0 &&
|
|
||||||
curEnt.AddressRVA == 0) {
|
curEnt.AddressRVA == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//then, try and get the name of this particular module...
|
// then, try and get the name of this particular module...
|
||||||
VA name;
|
VA name;
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
name = curEnt.NameRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
name = curEnt.NameRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
@ -1061,30 +1085,36 @@ bool getImports(parsed_pe *p) {
|
|||||||
if (!readCString(*nameSec.sectionData, nameOff, modName)) {
|
if (!readCString(*nameSec.sectionData, nameOff, modName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::transform(modName.begin(), modName.end(), modName.begin(), ::toupper);
|
std::transform(
|
||||||
|
modName.begin(), modName.end(), modName.begin(), ::toupper);
|
||||||
|
|
||||||
//then, try and get all of the sub-symbols
|
// then, try and get all of the sub-symbols
|
||||||
VA lookupVA = 0;
|
VA lookupVA = 0;
|
||||||
if (curEnt.LookupTableRVA != 0) {
|
if (curEnt.LookupTableRVA != 0) {
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
lookupVA = curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
lookupVA =
|
||||||
|
curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
lookupVA = curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
lookupVA =
|
||||||
|
curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (curEnt.AddressRVA != 0 ) {
|
} else if (curEnt.AddressRVA != 0) {
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
lookupVA = curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
lookupVA =
|
||||||
|
curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
lookupVA = curEnt.AddressRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
lookupVA =
|
||||||
|
curEnt.AddressRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
section lookupSec;
|
section lookupSec;
|
||||||
if (lookupVA == 0 || !getSecForVA(p->internal->secs, lookupVA, lookupSec)) {
|
if (lookupVA == 0 ||
|
||||||
|
!getSecForVA(p->internal->secs, lookupVA, lookupSec)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1100,7 +1130,7 @@ bool getImports(parsed_pe *p) {
|
|||||||
if (!readDword(lookupSec.sectionData, lookupOff, val32)) {
|
if (!readDword(lookupSec.sectionData, lookupOff, val32)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(val32 == 0) {
|
if (val32 == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ord = (val32 >> 31);
|
ord = (val32 >> 31);
|
||||||
@ -1121,7 +1151,7 @@ bool getImports(parsed_pe *p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ord == 0) {
|
if (ord == 0) {
|
||||||
//import by name
|
// import by name
|
||||||
string symName;
|
string symName;
|
||||||
section symNameSec;
|
section symNameSec;
|
||||||
|
|
||||||
@ -1144,15 +1174,17 @@ bool getImports(parsed_pe *p) {
|
|||||||
|
|
||||||
symName.push_back(d);
|
symName.push_back(d);
|
||||||
nameOff++;
|
nameOff++;
|
||||||
} while(true);
|
} while (true);
|
||||||
|
|
||||||
//okay now we know the pair... add it
|
// okay now we know the pair... add it
|
||||||
importent ent;
|
importent ent;
|
||||||
|
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
ent.addr = offInTable + curEnt.AddressRVA +
|
||||||
|
p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
ent.addr = offInTable + curEnt.AddressRVA +
|
||||||
|
p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1167,9 +1199,11 @@ bool getImports(parsed_pe *p) {
|
|||||||
importent ent;
|
importent ent;
|
||||||
|
|
||||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase;
|
ent.addr = offInTable + curEnt.AddressRVA +
|
||||||
|
p->peHeader.nt.OptionalHeader.ImageBase;
|
||||||
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
ent.addr = offInTable + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader64.ImageBase;
|
ent.addr = offInTable + curEnt.AddressRVA +
|
||||||
|
p->peHeader.nt.OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1189,10 +1223,10 @@ bool getImports(parsed_pe *p) {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while(true);
|
} while (true);
|
||||||
|
|
||||||
offt += sizeof(import_dir_entry);
|
offt += sizeof(import_dir_entry);
|
||||||
} while(true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1203,8 +1237,9 @@ bool getSymbolTable(parsed_pe *p) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t strTableOffset = p->peHeader.nt.FileHeader.PointerToSymbolTable
|
uint32_t strTableOffset =
|
||||||
+ (p->peHeader.nt.FileHeader.NumberOfSymbols * SYMTAB_RECORD_LEN);
|
p->peHeader.nt.FileHeader.PointerToSymbolTable +
|
||||||
|
(p->peHeader.nt.FileHeader.NumberOfSymbols * SYMTAB_RECORD_LEN);
|
||||||
|
|
||||||
uint32_t offset = p->peHeader.nt.FileHeader.PointerToSymbolTable;
|
uint32_t offset = p->peHeader.nt.FileHeader.PointerToSymbolTable;
|
||||||
|
|
||||||
@ -1296,8 +1331,7 @@ bool getSymbolTable(parsed_pe *p) {
|
|||||||
// Read auxiliary symbol records
|
// Read auxiliary symbol records
|
||||||
|
|
||||||
if (sym.storageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
if (sym.storageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
||||||
SYMBOL_TYPE_HI(sym) == 0x20 &&
|
SYMBOL_TYPE_HI(sym) == 0x20 && sym.sectionNumber > 0) {
|
||||||
sym.sectionNumber > 0) {
|
|
||||||
// Auxiliary Format 1: Function Definitions
|
// Auxiliary Format 1: Function Definitions
|
||||||
|
|
||||||
for (uint8_t n = 0; n < sym.numberOfAuxSymbols; n++) {
|
for (uint8_t n = 0; n < sym.numberOfAuxSymbols; n++) {
|
||||||
@ -1369,8 +1403,7 @@ bool getSymbolTable(parsed_pe *p) {
|
|||||||
sym.aux_symbols_f2.push_back(asym);
|
sym.aux_symbols_f2.push_back(asym);
|
||||||
}
|
}
|
||||||
} else if (sym.storageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
} else if (sym.storageClass == IMAGE_SYM_CLASS_EXTERNAL &&
|
||||||
sym.sectionNumber == IMAGE_SYM_UNDEFINED &&
|
sym.sectionNumber == IMAGE_SYM_UNDEFINED && sym.value == 0) {
|
||||||
sym.value == 0) {
|
|
||||||
// Auxiliary Format 3: Weak Externals
|
// Auxiliary Format 3: Weak Externals
|
||||||
|
|
||||||
for (uint8_t n = 0; n < sym.numberOfAuxSymbols; n++) {
|
for (uint8_t n = 0; n < sym.numberOfAuxSymbols; n++) {
|
||||||
@ -1481,9 +1514,9 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
|||||||
// First, create a new parsed_pe structure
|
// First, create a new parsed_pe structure
|
||||||
// We pass std::nothrow parameter to new so in case of failure it returns
|
// We pass std::nothrow parameter to new so in case of failure it returns
|
||||||
// nullptr instead of throwing exception std::bad_alloc.
|
// nullptr instead of throwing exception std::bad_alloc.
|
||||||
parsed_pe *p = new(std::nothrow) parsed_pe();
|
parsed_pe *p = new (std::nothrow) parsed_pe();
|
||||||
|
|
||||||
if(p == nullptr) {
|
if (p == nullptr) {
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1491,24 +1524,24 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
|||||||
// Make a new buffer object to hold just our file data
|
// Make a new buffer object to hold just our file data
|
||||||
p->fileBuffer = readFileToFileBuffer(filePath);
|
p->fileBuffer = readFileToFileBuffer(filePath);
|
||||||
|
|
||||||
if(p->fileBuffer == nullptr) {
|
if (p->fileBuffer == nullptr) {
|
||||||
delete p;
|
delete p;
|
||||||
// err is set by readFileToFileBuffer
|
// err is set by readFileToFileBuffer
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->internal = new(std::nothrow) parsed_pe_internal();
|
p->internal = new (std::nothrow) parsed_pe_internal();
|
||||||
|
|
||||||
if(p->internal == nullptr) {
|
if (p->internal == nullptr) {
|
||||||
deleteBuffer(p->fileBuffer);
|
deleteBuffer(p->fileBuffer);
|
||||||
delete p;
|
delete p;
|
||||||
PE_ERR(PEERR_MEM);
|
PE_ERR(PEERR_MEM);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get header information
|
// get header information
|
||||||
bounded_buffer *remaining = nullptr;
|
bounded_buffer *remaining = nullptr;
|
||||||
if(!getHeader(p->fileBuffer, p->peHeader, remaining)) {
|
if (!getHeader(p->fileBuffer, p->peHeader, remaining)) {
|
||||||
deleteBuffer(p->fileBuffer);
|
deleteBuffer(p->fileBuffer);
|
||||||
delete p;
|
delete p;
|
||||||
// err is set by getHeader
|
// err is set by getHeader
|
||||||
@ -1516,7 +1549,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bounded_buffer *file = p->fileBuffer;
|
bounded_buffer *file = p->fileBuffer;
|
||||||
if(!getSections(remaining, file, p->peHeader.nt, p->internal->secs)) {
|
if (!getSections(remaining, file, p->peHeader.nt, p->internal->secs)) {
|
||||||
deleteBuffer(remaining);
|
deleteBuffer(remaining);
|
||||||
deleteBuffer(p->fileBuffer);
|
deleteBuffer(p->fileBuffer);
|
||||||
delete p;
|
delete p;
|
||||||
@ -1524,7 +1557,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!getResources(remaining, file, p->internal->secs, p->internal->rsrcs)) {
|
if (!getResources(remaining, file, p->internal->secs, p->internal->rsrcs)) {
|
||||||
deleteBuffer(remaining);
|
deleteBuffer(remaining);
|
||||||
deleteBuffer(p->fileBuffer);
|
deleteBuffer(p->fileBuffer);
|
||||||
delete p;
|
delete p;
|
||||||
@ -1572,7 +1605,7 @@ parsed_pe *ParsePEFromFile(const char *filePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DestructParsedPE(parsed_pe *p) {
|
void DestructParsedPE(parsed_pe *p) {
|
||||||
if(p == nullptr) {
|
if (p == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1582,7 +1615,7 @@ void DestructParsedPE(parsed_pe *p) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//iterate over the imports by VA and string
|
// iterate over the imports by VA and string
|
||||||
void IterImpVAString(parsed_pe *pe, iterVAStr cb, void *cbd) {
|
void IterImpVAString(parsed_pe *pe, iterVAStr cb, void *cbd) {
|
||||||
list<importent> &l = pe->internal->imports;
|
list<importent> &l = pe->internal->imports;
|
||||||
|
|
||||||
@ -1595,7 +1628,7 @@ void IterImpVAString(parsed_pe *pe, iterVAStr cb, void *cbd) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//iterate over relocations in the PE file
|
// iterate over relocations in the PE file
|
||||||
void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd) {
|
void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd) {
|
||||||
list<reloc> &l = pe->internal->relocs;
|
list<reloc> &l = pe->internal->relocs;
|
||||||
|
|
||||||
@ -1613,7 +1646,12 @@ void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd) {
|
|||||||
list<symbol> &l = pe->internal->symbols;
|
list<symbol> &l = pe->internal->symbols;
|
||||||
|
|
||||||
for (symbol s : l) {
|
for (symbol s : l) {
|
||||||
if (cb(cbd, s.strName, s.value, s.sectionNumber, s.type, s.storageClass,
|
if (cb(cbd,
|
||||||
|
s.strName,
|
||||||
|
s.value,
|
||||||
|
s.sectionNumber,
|
||||||
|
s.type,
|
||||||
|
s.storageClass,
|
||||||
s.numberOfAuxSymbols) != 0) {
|
s.numberOfAuxSymbols) != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1622,7 +1660,7 @@ void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//iterate over the exports by VA
|
// iterate over the exports by VA
|
||||||
void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) {
|
void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) {
|
||||||
list<exportent> &l = pe->internal->exports;
|
list<exportent> &l = pe->internal->exports;
|
||||||
|
|
||||||
@ -1635,7 +1673,7 @@ void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//iterate over sections
|
// iterate over sections
|
||||||
void IterSec(parsed_pe *pe, iterSec cb, void *cbd) {
|
void IterSec(parsed_pe *pe, iterSec cb, void *cbd) {
|
||||||
parsed_pe_internal *pint = pe->internal;
|
parsed_pe_internal *pint = pe->internal;
|
||||||
|
|
||||||
@ -1649,10 +1687,10 @@ void IterSec(parsed_pe *pe, iterSec cb, void *cbd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ReadByteAtVA(parsed_pe *pe, VA v, ::uint8_t &b) {
|
bool ReadByteAtVA(parsed_pe *pe, VA v, ::uint8_t &b) {
|
||||||
//find this VA in a section
|
// find this VA in a section
|
||||||
section s;
|
section s;
|
||||||
|
|
||||||
if(!getSecForVA(pe->internal->secs, v, s)) {
|
if (!getSecForVA(pe->internal->secs, v, s)) {
|
||||||
PE_ERR(PEERR_SECTVA);
|
PE_ERR(PEERR_SECTVA);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1664,13 +1702,15 @@ bool ReadByteAtVA(parsed_pe *pe, VA v, ::uint8_t &b) {
|
|||||||
|
|
||||||
bool GetEntryPoint(parsed_pe *pe, VA &v) {
|
bool GetEntryPoint(parsed_pe *pe, VA &v) {
|
||||||
|
|
||||||
if(pe != nullptr) {
|
if (pe != nullptr) {
|
||||||
nt_header_32 *nthdr = &pe->peHeader.nt;
|
nt_header_32 *nthdr = &pe->peHeader.nt;
|
||||||
|
|
||||||
if (nthdr->OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (nthdr->OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||||
v = nthdr->OptionalHeader.AddressOfEntryPoint + nthdr->OptionalHeader.ImageBase;
|
v = nthdr->OptionalHeader.AddressOfEntryPoint +
|
||||||
|
nthdr->OptionalHeader.ImageBase;
|
||||||
} else if (nthdr->OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (nthdr->OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
||||||
v = nthdr->OptionalHeader64.AddressOfEntryPoint + nthdr->OptionalHeader64.ImageBase;
|
v = nthdr->OptionalHeader64.AddressOfEntryPoint +
|
||||||
|
nthdr->OptionalHeader64.ImageBase;
|
||||||
} else {
|
} else {
|
||||||
PE_ERR(PEERR_MAGIC);
|
PE_ERR(PEERR_MAGIC);
|
||||||
return false;
|
return false;
|
||||||
|
@ -24,58 +24,57 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
#ifndef _PARSE_H
|
#ifndef _PARSE_H
|
||||||
#define _PARSE_H
|
#define _PARSE_H
|
||||||
#include <string>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "nt-headers.h"
|
#include "nt-headers.h"
|
||||||
#include "to_string.h"
|
#include "to_string.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define __typeof__(x) std::remove_reference<decltype(x)>::type
|
#define __typeof__(x) std::remove_reference < decltype(x) > ::type
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define PE_ERR(x) \
|
#define PE_ERR(x) \
|
||||||
err = (pe_err) x; \
|
err = (pe_err) x; \
|
||||||
err_loc.assign(__func__); \
|
err_loc.assign(__func__); \
|
||||||
err_loc += ":" + to_string<std::uint32_t>(__LINE__, dec);
|
err_loc += ":" + to_string<std::uint32_t>(__LINE__, dec);
|
||||||
|
|
||||||
#define READ_WORD(b, o, inst, member) \
|
#define READ_WORD(b, o, inst, member) \
|
||||||
if (!readWord(b, o+_offset(__typeof__(inst), member), inst.member)) { \
|
if (!readWord(b, o + _offset(__typeof__(inst), member), inst.member)) { \
|
||||||
PE_ERR(PEERR_READ); \
|
PE_ERR(PEERR_READ); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_DWORD(b, o, inst, member) \
|
#define READ_DWORD(b, o, inst, member) \
|
||||||
if (!readDword(b, o+_offset(__typeof__(inst), member), inst.member)) { \
|
if (!readDword(b, o + _offset(__typeof__(inst), member), inst.member)) { \
|
||||||
PE_ERR(PEERR_READ); \
|
PE_ERR(PEERR_READ); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_QWORD(b, o, inst, member) \
|
#define READ_QWORD(b, o, inst, member) \
|
||||||
if (!readQword(b, o+_offset(__typeof__(inst), member), inst.member)) { \
|
if (!readQword(b, o + _offset(__typeof__(inst), member), inst.member)) { \
|
||||||
PE_ERR(PEERR_READ); \
|
PE_ERR(PEERR_READ); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_DWORD_PTR(b, o, inst, member) \
|
#define READ_DWORD_PTR(b, o, inst, member) \
|
||||||
if (!readDword(b, o+_offset(__typeof__(*inst), member), inst->member)) { \
|
if (!readDword(b, o + _offset(__typeof__(*inst), member), inst->member)) { \
|
||||||
PE_ERR(PEERR_READ); \
|
PE_ERR(PEERR_READ); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_BYTE(b, o, inst, member) \
|
#define READ_BYTE(b, o, inst, member) \
|
||||||
if (!readByte(b, o+_offset(__typeof__(inst), member), inst.member)) { \
|
if (!readByte(b, o + _offset(__typeof__(inst), member), inst.member)) { \
|
||||||
PE_ERR(PEERR_READ); \
|
PE_ERR(PEERR_READ); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This variant returns NULL instead of false. */
|
/* This variant returns NULL instead of false. */
|
||||||
#define READ_DWORD_NULL(b, o, inst, member) \
|
#define READ_DWORD_NULL(b, o, inst, member) \
|
||||||
if (!readDword(b, o+_offset(__typeof__(inst), member), inst.member)) { \
|
if (!readDword(b, o + _offset(__typeof__(inst), member), inst.member)) { \
|
||||||
PE_ERR(PEERR_READ); \
|
PE_ERR(PEERR_READ); \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace peparse {
|
namespace peparse {
|
||||||
|
|
||||||
@ -148,15 +147,14 @@ bool readDword(bounded_buffer *b, std::uint32_t offset, std::uint32_t &out);
|
|||||||
bool readQword(bounded_buffer *b, std::uint32_t offset, std::uint64_t &out);
|
bool readQword(bounded_buffer *b, std::uint32_t offset, std::uint64_t &out);
|
||||||
|
|
||||||
bounded_buffer *readFileToFileBuffer(const char *filePath);
|
bounded_buffer *readFileToFileBuffer(const char *filePath);
|
||||||
bounded_buffer *splitBuffer(bounded_buffer *b, std::uint32_t from, std::uint32_t to);
|
bounded_buffer *
|
||||||
|
splitBuffer(bounded_buffer *b, std::uint32_t from, std::uint32_t to);
|
||||||
void deleteBuffer(bounded_buffer *b);
|
void deleteBuffer(bounded_buffer *b);
|
||||||
uint64_t bufLen(bounded_buffer *b);
|
uint64_t bufLen(bounded_buffer *b);
|
||||||
|
|
||||||
struct parsed_pe_internal;
|
struct parsed_pe_internal;
|
||||||
|
|
||||||
typedef struct _pe_header {
|
typedef struct _pe_header { nt_header_32 nt; } pe_header;
|
||||||
nt_header_32 nt;
|
|
||||||
} pe_header;
|
|
||||||
|
|
||||||
typedef struct _parsed_pe {
|
typedef struct _parsed_pe {
|
||||||
bounded_buffer *fileBuffer;
|
bounded_buffer *fileBuffer;
|
||||||
@ -173,40 +171,47 @@ std::string GetPEErrString();
|
|||||||
// get parser error location as string
|
// get parser error location as string
|
||||||
std::string GetPEErrLoc();
|
std::string GetPEErrLoc();
|
||||||
|
|
||||||
//get a PE parse context from a file
|
// get a PE parse context from a file
|
||||||
parsed_pe *ParsePEFromFile(const char *filePath);
|
parsed_pe *ParsePEFromFile(const char *filePath);
|
||||||
|
|
||||||
//destruct a PE context
|
// destruct a PE context
|
||||||
void DestructParsedPE(parsed_pe *p);
|
void DestructParsedPE(parsed_pe *p);
|
||||||
|
|
||||||
//iterate over the resources
|
// iterate over the resources
|
||||||
typedef int (*iterRsrc)(void *, resource);
|
typedef int (*iterRsrc)(void *, resource);
|
||||||
void IterRsrc(parsed_pe *pe, iterRsrc cb, void *cbd);
|
void IterRsrc(parsed_pe *pe, iterRsrc cb, void *cbd);
|
||||||
|
|
||||||
//iterate over the imports by RVA and string
|
// iterate over the imports by RVA and string
|
||||||
typedef int (*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);
|
void IterImpVAString(parsed_pe *pe, iterVAStr cb, void *cbd);
|
||||||
|
|
||||||
//iterate over relocations in the PE file
|
// iterate over relocations in the PE file
|
||||||
typedef int (*iterReloc)(void *, VA, reloc_type);
|
typedef int (*iterReloc)(void *, VA, reloc_type);
|
||||||
void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd);
|
void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd);
|
||||||
|
|
||||||
// Iterate over symbols (symbol table) in the PE file
|
// Iterate over symbols (symbol table) in the PE file
|
||||||
typedef int (*iterSymbol)(void *, std::string &, uint32_t &, int16_t &, uint16_t &, uint8_t &, uint8_t &);
|
typedef int (*iterSymbol)(void *,
|
||||||
|
std::string &,
|
||||||
|
uint32_t &,
|
||||||
|
int16_t &,
|
||||||
|
uint16_t &,
|
||||||
|
uint8_t &,
|
||||||
|
uint8_t &);
|
||||||
void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd);
|
void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd);
|
||||||
|
|
||||||
//iterate over the exports
|
// iterate over the exports
|
||||||
typedef int (*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);
|
void IterExpVA(parsed_pe *pe, iterExp cb, void *cbd);
|
||||||
|
|
||||||
//iterate over sections
|
// iterate over sections
|
||||||
typedef int (*iterSec)(void *, VA secBase, std::string &, image_section_header, 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);
|
void IterSec(parsed_pe *pe, iterSec cb, void *cbd);
|
||||||
|
|
||||||
//get byte at VA in PE
|
// get byte at VA in PE
|
||||||
bool ReadByteAtVA(parsed_pe *pe, VA v, std::uint8_t &b);
|
bool ReadByteAtVA(parsed_pe *pe, VA v, std::uint8_t &b);
|
||||||
|
|
||||||
//get entry point into PE
|
// get entry point into PE
|
||||||
bool GetEntryPoint(parsed_pe *pe, VA &v);
|
bool GetEntryPoint(parsed_pe *pe, VA &v);
|
||||||
} // namespace peparse
|
} // namespace peparse
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@
|
|||||||
|
|
||||||
namespace peparse {
|
namespace peparse {
|
||||||
template <class T>
|
template <class T>
|
||||||
static
|
static std::string to_string(T t, std::ios_base &(*f)(std::ios_base &) ) {
|
||||||
std::string to_string(T t, std::ios_base & (*f)(std::ios_base&)) {
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << f << t;
|
oss << f << t;
|
||||||
return oss.str();
|
return oss.str();
|
||||||
|
339
python/pepy.cpp
339
python/pepy.cpp
@ -25,9 +25,9 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <structmember.h>
|
#include <structmember.h>
|
||||||
#include "parse.h"
|
|
||||||
|
|
||||||
using namespace peparse;
|
using namespace peparse;
|
||||||
|
|
||||||
@ -35,36 +35,32 @@ using namespace peparse;
|
|||||||
|
|
||||||
/* These are used to across multiple objects. */
|
/* These are used to across multiple objects. */
|
||||||
#define PEPY_OBJECT_GET(OBJ, ATTR) \
|
#define PEPY_OBJECT_GET(OBJ, ATTR) \
|
||||||
static PyObject *pepy_##OBJ##_get_##ATTR(PyObject *self, void *closure) { \
|
static PyObject *pepy_##OBJ##_get_##ATTR(PyObject *self, void *closure) { \
|
||||||
Py_INCREF(((pepy_##OBJ *) self)->ATTR); \
|
Py_INCREF(((pepy_##OBJ *) self)->ATTR); \
|
||||||
return ((pepy_##OBJ *) self)->ATTR; \
|
return ((pepy_##OBJ *) self)->ATTR; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OBJECTGETTER(OBJ, ATTR, DOC) \
|
#define OBJECTGETTER(OBJ, ATTR, DOC) \
|
||||||
{ (char *) #ATTR, (getter) pepy_##OBJ##_get_##ATTR, \
|
{ \
|
||||||
(setter) pepy_attr_not_writable, \
|
(char *) #ATTR, (getter) pepy_##OBJ##_get_##ATTR, \
|
||||||
(char *) #DOC, NULL }
|
(setter) pepy_attr_not_writable, (char *) #DOC, NULL \
|
||||||
|
}
|
||||||
|
|
||||||
/* 'OPTIONAL' references the fact that these are from the Optional Header */
|
/* 'OPTIONAL' references the fact that these are from the Optional Header */
|
||||||
#define OBJECTGETTER_OPTIONAL(ATTR, DOC) \
|
#define OBJECTGETTER_OPTIONAL(ATTR, DOC) \
|
||||||
{ (char *) #ATTR, (getter) pepy_parsed_get_optional_##ATTR, \
|
{ \
|
||||||
(setter) pepy_attr_not_writable, \
|
(char *) #ATTR, (getter) pepy_parsed_get_optional_##ATTR, \
|
||||||
(char *) #DOC, NULL }
|
(setter) pepy_attr_not_writable, (char *) #DOC, NULL \
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *pepy_error;
|
static PyObject *pepy_error;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct { PyObject_HEAD } pepy;
|
||||||
PyObject_HEAD
|
|
||||||
} pepy;
|
typedef struct { PyObject_HEAD parsed_pe *pe; } pepy_parsed;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD PyObject *name;
|
||||||
parsed_pe *pe;
|
|
||||||
} pepy_parsed;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
PyObject *name;
|
|
||||||
PyObject *base;
|
PyObject *base;
|
||||||
PyObject *length;
|
PyObject *length;
|
||||||
PyObject *virtaddr;
|
PyObject *virtaddr;
|
||||||
@ -76,8 +72,7 @@ typedef struct {
|
|||||||
} pepy_section;
|
} pepy_section;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD PyObject *type_str;
|
||||||
PyObject *type_str;
|
|
||||||
PyObject *name_str;
|
PyObject *name_str;
|
||||||
PyObject *lang_str;
|
PyObject *lang_str;
|
||||||
PyObject *type;
|
PyObject *type;
|
||||||
@ -90,32 +85,31 @@ typedef struct {
|
|||||||
} pepy_resource;
|
} pepy_resource;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD PyObject *name;
|
||||||
PyObject *name;
|
|
||||||
PyObject *sym;
|
PyObject *sym;
|
||||||
PyObject *addr;
|
PyObject *addr;
|
||||||
} pepy_import;
|
} pepy_import;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD PyObject *mod;
|
||||||
PyObject *mod;
|
|
||||||
PyObject *func;
|
PyObject *func;
|
||||||
PyObject *addr;
|
PyObject *addr;
|
||||||
} pepy_export;
|
} pepy_export;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD PyObject *type;
|
||||||
PyObject *type;
|
|
||||||
PyObject *addr;
|
PyObject *addr;
|
||||||
} pepy_relocation;
|
} pepy_relocation;
|
||||||
|
|
||||||
/* None of the attributes in these objects are writable. */
|
/* None of the attributes in these objects are writable. */
|
||||||
static int pepy_attr_not_writable(PyObject *self, PyObject *value, void *closure) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *pepy_import_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
static PyObject *
|
||||||
|
pepy_import_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||||
pepy_import *self;
|
pepy_import *self;
|
||||||
|
|
||||||
self = (pepy_import *) type->tp_alloc(type, 0);
|
self = (pepy_import *) type->tp_alloc(type, 0);
|
||||||
@ -124,7 +118,8 @@ static PyObject *pepy_import_new(PyTypeObject *type, PyObject *args, PyObject *k
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int pepy_import_init(pepy_import *self, PyObject *args, PyObject *kwds) {
|
static int pepy_import_init(pepy_import *self, PyObject *args, PyObject *kwds) {
|
||||||
if (!PyArg_ParseTuple(args, "OOO:pepy_import_init", &self->name, &self->sym, &self->addr))
|
if (!PyArg_ParseTuple(
|
||||||
|
args, "OOO:pepy_import_init", &self->name, &self->sym, &self->addr))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -144,12 +139,10 @@ static PyGetSetDef pepy_import_getseters[] = {
|
|||||||
OBJECTGETTER(import, name, "Name"),
|
OBJECTGETTER(import, name, "Name"),
|
||||||
OBJECTGETTER(import, sym, "Symbol"),
|
OBJECTGETTER(import, sym, "Symbol"),
|
||||||
OBJECTGETTER(import, addr, "Address"),
|
OBJECTGETTER(import, addr, "Address"),
|
||||||
{ NULL }
|
{NULL}};
|
||||||
};
|
|
||||||
|
|
||||||
static PyTypeObject pepy_import_type = {
|
static PyTypeObject pepy_import_type = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyObject_HEAD_INIT(NULL) 0, /* ob_size */
|
||||||
0, /* ob_size */
|
|
||||||
"pepy.import", /* tp_name */
|
"pepy.import", /* tp_name */
|
||||||
sizeof(pepy_import), /* tp_basicsize */
|
sizeof(pepy_import), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
@ -189,7 +182,8 @@ static PyTypeObject pepy_import_type = {
|
|||||||
pepy_import_new /* tp_new */
|
pepy_import_new /* tp_new */
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *pepy_export_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
static PyObject *
|
||||||
|
pepy_export_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||||
pepy_export *self;
|
pepy_export *self;
|
||||||
|
|
||||||
self = (pepy_export *) type->tp_alloc(type, 0);
|
self = (pepy_export *) type->tp_alloc(type, 0);
|
||||||
@ -198,7 +192,8 @@ static PyObject *pepy_export_new(PyTypeObject *type, PyObject *args, PyObject *k
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int pepy_export_init(pepy_export *self, PyObject *args, PyObject *kwds) {
|
static int pepy_export_init(pepy_export *self, PyObject *args, PyObject *kwds) {
|
||||||
if (!PyArg_ParseTuple(args, "OOO:pepy_export_init", &self->mod, &self->func, &self->addr))
|
if (!PyArg_ParseTuple(
|
||||||
|
args, "OOO:pepy_export_init", &self->mod, &self->func, &self->addr))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -218,12 +213,10 @@ static PyGetSetDef pepy_export_getseters[] = {
|
|||||||
OBJECTGETTER(export, mod, "Module"),
|
OBJECTGETTER(export, mod, "Module"),
|
||||||
OBJECTGETTER(export, func, "Function"),
|
OBJECTGETTER(export, func, "Function"),
|
||||||
OBJECTGETTER(export, addr, "Address"),
|
OBJECTGETTER(export, addr, "Address"),
|
||||||
{ NULL }
|
{NULL}};
|
||||||
};
|
|
||||||
|
|
||||||
static PyTypeObject pepy_export_type = {
|
static PyTypeObject pepy_export_type = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyObject_HEAD_INIT(NULL) 0, /* ob_size */
|
||||||
0, /* ob_size */
|
|
||||||
"pepy.export", /* tp_name */
|
"pepy.export", /* tp_name */
|
||||||
sizeof(pepy_export), /* tp_basicsize */
|
sizeof(pepy_export), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
@ -263,7 +256,8 @@ static PyTypeObject pepy_export_type = {
|
|||||||
pepy_export_new /* tp_new */
|
pepy_export_new /* tp_new */
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *pepy_relocation_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
static PyObject *
|
||||||
|
pepy_relocation_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||||
pepy_relocation *self;
|
pepy_relocation *self;
|
||||||
|
|
||||||
self = (pepy_relocation *) type->tp_alloc(type, 0);
|
self = (pepy_relocation *) type->tp_alloc(type, 0);
|
||||||
@ -271,8 +265,10 @@ static PyObject *pepy_relocation_new(PyTypeObject *type, PyObject *args, PyObjec
|
|||||||
return (PyObject *) self;
|
return (PyObject *) self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pepy_relocation_init(pepy_relocation *self, PyObject *args, PyObject *kwds) {
|
static int
|
||||||
if (!PyArg_ParseTuple(args, "OO:pepy_relocation_init", &self->type, &self->addr))
|
pepy_relocation_init(pepy_relocation *self, PyObject *args, PyObject *kwds) {
|
||||||
|
if (!PyArg_ParseTuple(
|
||||||
|
args, "OO:pepy_relocation_init", &self->type, &self->addr))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -289,12 +285,10 @@ PEPY_OBJECT_GET(relocation, addr)
|
|||||||
static PyGetSetDef pepy_relocation_getseters[] = {
|
static PyGetSetDef pepy_relocation_getseters[] = {
|
||||||
OBJECTGETTER(relocation, type, "Type"),
|
OBJECTGETTER(relocation, type, "Type"),
|
||||||
OBJECTGETTER(relocation, addr, "Address"),
|
OBJECTGETTER(relocation, addr, "Address"),
|
||||||
{ NULL }
|
{NULL}};
|
||||||
};
|
|
||||||
|
|
||||||
static PyTypeObject pepy_relocation_type = {
|
static PyTypeObject pepy_relocation_type = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyObject_HEAD_INIT(NULL) 0, /* ob_size */
|
||||||
0, /* ob_size */
|
|
||||||
"pepy.relocation", /* tp_name */
|
"pepy.relocation", /* tp_name */
|
||||||
sizeof(pepy_relocation), /* tp_basicsize */
|
sizeof(pepy_relocation), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
@ -334,7 +328,8 @@ static PyTypeObject pepy_relocation_type = {
|
|||||||
pepy_relocation_new /* tp_new */
|
pepy_relocation_new /* tp_new */
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *pepy_section_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
static PyObject *
|
||||||
|
pepy_section_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||||
pepy_section *self;
|
pepy_section *self;
|
||||||
|
|
||||||
self = (pepy_section *) type->tp_alloc(type, 0);
|
self = (pepy_section *) type->tp_alloc(type, 0);
|
||||||
@ -342,8 +337,19 @@ static PyObject *pepy_section_new(PyTypeObject *type, PyObject *args, PyObject *
|
|||||||
return (PyObject *) self;
|
return (PyObject *) self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pepy_section_init(pepy_section *self, PyObject *args, PyObject *kwds) {
|
static int
|
||||||
if (!PyArg_ParseTuple(args, "OOOOOOOOO:pepy_section_init", &self->name, &self->base, &self->length, &self->virtaddr, &self->virtsize, &self->numrelocs, &self->numlinenums, &self->characteristics, &self->data))
|
pepy_section_init(pepy_section *self, PyObject *args, PyObject *kwds) {
|
||||||
|
if (!PyArg_ParseTuple(args,
|
||||||
|
"OOOOOOOOO:pepy_section_init",
|
||||||
|
&self->name,
|
||||||
|
&self->base,
|
||||||
|
&self->length,
|
||||||
|
&self->virtaddr,
|
||||||
|
&self->virtsize,
|
||||||
|
&self->numrelocs,
|
||||||
|
&self->numlinenums,
|
||||||
|
&self->characteristics,
|
||||||
|
&self->data))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -381,12 +387,10 @@ static PyGetSetDef pepy_section_getseters[] = {
|
|||||||
OBJECTGETTER(section, numlinenums, "Number of line numbers"),
|
OBJECTGETTER(section, numlinenums, "Number of line numbers"),
|
||||||
OBJECTGETTER(section, characteristics, "Characteristics"),
|
OBJECTGETTER(section, characteristics, "Characteristics"),
|
||||||
OBJECTGETTER(section, data, "Section data"),
|
OBJECTGETTER(section, data, "Section data"),
|
||||||
{ NULL }
|
{NULL}};
|
||||||
};
|
|
||||||
|
|
||||||
static PyTypeObject pepy_section_type = {
|
static PyTypeObject pepy_section_type = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyObject_HEAD_INIT(NULL) 0, /* ob_size */
|
||||||
0, /* ob_size */
|
|
||||||
"pepy.section", /* tp_name */
|
"pepy.section", /* tp_name */
|
||||||
sizeof(pepy_section), /* tp_basicsize */
|
sizeof(pepy_section), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
@ -426,7 +430,8 @@ static PyTypeObject pepy_section_type = {
|
|||||||
pepy_section_new /* tp_new */
|
pepy_section_new /* tp_new */
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *pepy_resource_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
static PyObject *
|
||||||
|
pepy_resource_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||||
pepy_resource *self;
|
pepy_resource *self;
|
||||||
|
|
||||||
self = (pepy_resource *) type->tp_alloc(type, 0);
|
self = (pepy_resource *) type->tp_alloc(type, 0);
|
||||||
@ -434,8 +439,20 @@ static PyObject *pepy_resource_new(PyTypeObject *type, PyObject *args, PyObject
|
|||||||
return (PyObject *) self;
|
return (PyObject *) self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pepy_resource_init(pepy_resource *self, PyObject *args, PyObject *kwds) {
|
static int
|
||||||
if (!PyArg_ParseTuple(args, "OOOOOOOOOO:pepy_resource_init", &self->type_str, &self->name_str, &self->lang_str, &self->type, &self->name, &self->lang, &self->codepage, &self->RVA, &self->size, &self->data))
|
pepy_resource_init(pepy_resource *self, PyObject *args, PyObject *kwds) {
|
||||||
|
if (!PyArg_ParseTuple(args,
|
||||||
|
"OOOOOOOOOO:pepy_resource_init",
|
||||||
|
&self->type_str,
|
||||||
|
&self->name_str,
|
||||||
|
&self->lang_str,
|
||||||
|
&self->type,
|
||||||
|
&self->name,
|
||||||
|
&self->lang,
|
||||||
|
&self->codepage,
|
||||||
|
&self->RVA,
|
||||||
|
&self->size,
|
||||||
|
&self->data))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -479,67 +496,67 @@ static PyObject *pepy_resource_type_as_str(PyObject *self, PyObject *args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch ((resource_type) type) {
|
switch ((resource_type) type) {
|
||||||
case(RT_CURSOR):
|
case (RT_CURSOR):
|
||||||
str = (char *) "CURSOR";
|
str = (char *) "CURSOR";
|
||||||
break;
|
break;
|
||||||
case(RT_BITMAP):
|
case (RT_BITMAP):
|
||||||
str = (char *) "BITMAP";
|
str = (char *) "BITMAP";
|
||||||
break;
|
break;
|
||||||
case(RT_ICON):
|
case (RT_ICON):
|
||||||
str = (char *) "ICON";
|
str = (char *) "ICON";
|
||||||
break;
|
break;
|
||||||
case(RT_MENU):
|
case (RT_MENU):
|
||||||
str = (char *) "MENU";
|
str = (char *) "MENU";
|
||||||
break;
|
break;
|
||||||
case(RT_DIALOG):
|
case (RT_DIALOG):
|
||||||
str = (char *) "DIALOG";
|
str = (char *) "DIALOG";
|
||||||
break;
|
break;
|
||||||
case(RT_STRING):
|
case (RT_STRING):
|
||||||
str = (char *) "STRING";
|
str = (char *) "STRING";
|
||||||
break;
|
break;
|
||||||
case(RT_FONTDIR):
|
case (RT_FONTDIR):
|
||||||
str = (char *) "FONTDIR";
|
str = (char *) "FONTDIR";
|
||||||
break;
|
break;
|
||||||
case(RT_FONT):
|
case (RT_FONT):
|
||||||
str = (char *) "FONT";
|
str = (char *) "FONT";
|
||||||
break;
|
break;
|
||||||
case(RT_ACCELERATOR):
|
case (RT_ACCELERATOR):
|
||||||
str = (char *) "ACCELERATOR";
|
str = (char *) "ACCELERATOR";
|
||||||
break;
|
break;
|
||||||
case(RT_RCDATA):
|
case (RT_RCDATA):
|
||||||
str = (char *) "RCDATA";
|
str = (char *) "RCDATA";
|
||||||
break;
|
break;
|
||||||
case(RT_MESSAGETABLE):
|
case (RT_MESSAGETABLE):
|
||||||
str = (char *) "MESSAGETABLE";
|
str = (char *) "MESSAGETABLE";
|
||||||
break;
|
break;
|
||||||
case(RT_GROUP_CURSOR):
|
case (RT_GROUP_CURSOR):
|
||||||
str = (char *) "GROUP_CURSOR";
|
str = (char *) "GROUP_CURSOR";
|
||||||
break;
|
break;
|
||||||
case(RT_GROUP_ICON):
|
case (RT_GROUP_ICON):
|
||||||
str = (char *) "GROUP_ICON";
|
str = (char *) "GROUP_ICON";
|
||||||
break;
|
break;
|
||||||
case(RT_VERSION):
|
case (RT_VERSION):
|
||||||
str = (char *) "VERSION";
|
str = (char *) "VERSION";
|
||||||
break;
|
break;
|
||||||
case(RT_DLGINCLUDE):
|
case (RT_DLGINCLUDE):
|
||||||
str = (char *) "DLGINCLUDE";
|
str = (char *) "DLGINCLUDE";
|
||||||
break;
|
break;
|
||||||
case(RT_PLUGPLAY):
|
case (RT_PLUGPLAY):
|
||||||
str = (char *) "PLUGPLAY";
|
str = (char *) "PLUGPLAY";
|
||||||
break;
|
break;
|
||||||
case(RT_VXD):
|
case (RT_VXD):
|
||||||
str = (char *) "VXD";
|
str = (char *) "VXD";
|
||||||
break;
|
break;
|
||||||
case(RT_ANICURSOR):
|
case (RT_ANICURSOR):
|
||||||
str = (char *) "ANICURSOR";
|
str = (char *) "ANICURSOR";
|
||||||
break;
|
break;
|
||||||
case(RT_ANIICON):
|
case (RT_ANIICON):
|
||||||
str = (char *) "ANIICON";
|
str = (char *) "ANIICON";
|
||||||
break;
|
break;
|
||||||
case(RT_HTML):
|
case (RT_HTML):
|
||||||
str = (char *) "HTML";
|
str = (char *) "HTML";
|
||||||
break;
|
break;
|
||||||
case(RT_MANIFEST):
|
case (RT_MANIFEST):
|
||||||
str = (char *) "MANIFEST";
|
str = (char *) "MANIFEST";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -557,10 +574,11 @@ static PyObject *pepy_resource_type_as_str(PyObject *self, PyObject *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef pepy_resource_methods[] = {
|
static PyMethodDef pepy_resource_methods[] = {
|
||||||
{ "type_as_str", pepy_resource_type_as_str, METH_NOARGS,
|
{"type_as_str",
|
||||||
"Return the resource type as a string." },
|
pepy_resource_type_as_str,
|
||||||
{ NULL }
|
METH_NOARGS,
|
||||||
};
|
"Return the resource type as a string."},
|
||||||
|
{NULL}};
|
||||||
|
|
||||||
static PyGetSetDef pepy_resource_getseters[] = {
|
static PyGetSetDef pepy_resource_getseters[] = {
|
||||||
OBJECTGETTER(resource, type_str, "Type string"),
|
OBJECTGETTER(resource, type_str, "Type string"),
|
||||||
@ -573,12 +591,10 @@ static PyGetSetDef pepy_resource_getseters[] = {
|
|||||||
OBJECTGETTER(resource, RVA, "RVA"),
|
OBJECTGETTER(resource, RVA, "RVA"),
|
||||||
OBJECTGETTER(resource, size, "Size (specified in RDAT)"),
|
OBJECTGETTER(resource, size, "Size (specified in RDAT)"),
|
||||||
OBJECTGETTER(resource, data, "Resource data"),
|
OBJECTGETTER(resource, data, "Resource data"),
|
||||||
{ NULL }
|
{NULL}};
|
||||||
};
|
|
||||||
|
|
||||||
static PyTypeObject pepy_resource_type = {
|
static PyTypeObject pepy_resource_type = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyObject_HEAD_INIT(NULL) 0, /* ob_size */
|
||||||
0, /* ob_size */
|
|
||||||
"pepy.resource", /* tp_name */
|
"pepy.resource", /* tp_name */
|
||||||
sizeof(pepy_resource), /* tp_basicsize */
|
sizeof(pepy_resource), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
@ -618,7 +634,8 @@ static PyTypeObject pepy_resource_type = {
|
|||||||
pepy_resource_new /* tp_new */
|
pepy_resource_new /* tp_new */
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject *pepy_parsed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
static PyObject *
|
||||||
|
pepy_parsed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
||||||
pepy_parsed *self;
|
pepy_parsed *self;
|
||||||
|
|
||||||
self = (pepy_parsed *) type->tp_alloc(type, 0);
|
self = (pepy_parsed *) type->tp_alloc(type, 0);
|
||||||
@ -724,15 +741,14 @@ static PyObject *pepy_parsed_get_bytes(PyObject *self, PyObject *args) {
|
|||||||
* In case the buffer is NULL, return an empty bytearray.
|
* In case the buffer is NULL, return an empty bytearray.
|
||||||
*/
|
*/
|
||||||
static PyObject *pepy_data_converter(bounded_buffer *data) {
|
static PyObject *pepy_data_converter(bounded_buffer *data) {
|
||||||
PyObject* ret;
|
PyObject *ret;
|
||||||
const char *str;
|
const char *str;
|
||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
|
|
||||||
if (!data || !data->buf) {
|
if (!data || !data->buf) {
|
||||||
str = "";
|
str = "";
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
str = (const char *) data->buf;
|
str = (const char *) data->buf;
|
||||||
len = data->bufLen;
|
len = data->bufLen;
|
||||||
}
|
}
|
||||||
@ -746,7 +762,11 @@ static PyObject *pepy_data_converter(bounded_buffer *data) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int section_callback(void *cbd, VA base, std::string &name, image_section_header s, bounded_buffer *data) {
|
int section_callback(void *cbd,
|
||||||
|
VA base,
|
||||||
|
std::string &name,
|
||||||
|
image_section_header s,
|
||||||
|
bounded_buffer *data) {
|
||||||
uint32_t buflen;
|
uint32_t buflen;
|
||||||
PyObject *sect;
|
PyObject *sect;
|
||||||
PyObject *tuple;
|
PyObject *tuple;
|
||||||
@ -771,10 +791,17 @@ int section_callback(void *cbd, VA base, std::string &name, image_section_header
|
|||||||
* The tuple item order is important here. It is passed into the
|
* The tuple item order is important here. It is passed into the
|
||||||
* section type initialization and parsed there.
|
* section type initialization and parsed there.
|
||||||
*/
|
*/
|
||||||
tuple = Py_BuildValue("sKKIIHHIO&", name.c_str(), base, buflen,
|
tuple = Py_BuildValue("sKKIIHHIO&",
|
||||||
s.VirtualAddress, s.Misc.VirtualSize,
|
name.c_str(),
|
||||||
s.NumberOfRelocations, s.NumberOfLinenumbers,
|
base,
|
||||||
s.Characteristics, pepy_data_converter, data);
|
buflen,
|
||||||
|
s.VirtualAddress,
|
||||||
|
s.Misc.VirtualSize,
|
||||||
|
s.NumberOfRelocations,
|
||||||
|
s.NumberOfLinenumbers,
|
||||||
|
s.Characteristics,
|
||||||
|
pepy_data_converter,
|
||||||
|
data);
|
||||||
if (!tuple)
|
if (!tuple)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -819,7 +846,21 @@ int resource_callback(void *cbd, resource r) {
|
|||||||
* The tuple item order is important here. It is passed into the
|
* The tuple item order is important here. It is passed into the
|
||||||
* section type initialization and parsed there.
|
* section type initialization and parsed there.
|
||||||
*/
|
*/
|
||||||
tuple = Py_BuildValue("s#s#s#IIIIIIO&", r.type_str.c_str(), r.type_str.length(), r.name_str.c_str(), r.name_str.length(), r.lang_str.c_str(), r.lang_str.length(), r.type, r.name, r.lang, r.codepage, r.RVA, r.size, pepy_data_converter, r.buf);
|
tuple = Py_BuildValue("s#s#s#IIIIIIO&",
|
||||||
|
r.type_str.c_str(),
|
||||||
|
r.type_str.length(),
|
||||||
|
r.name_str.c_str(),
|
||||||
|
r.name_str.length(),
|
||||||
|
r.lang_str.c_str(),
|
||||||
|
r.lang_str.length(),
|
||||||
|
r.type,
|
||||||
|
r.name,
|
||||||
|
r.lang,
|
||||||
|
r.codepage,
|
||||||
|
r.RVA,
|
||||||
|
r.size,
|
||||||
|
pepy_data_converter,
|
||||||
|
r.buf);
|
||||||
if (!tuple)
|
if (!tuple)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -995,12 +1036,13 @@ static PyObject *pepy_parsed_get_relocations(PyObject *self, PyObject *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define PEPY_PARSED_GET(ATTR, VAL) \
|
#define PEPY_PARSED_GET(ATTR, VAL) \
|
||||||
static PyObject *pepy_parsed_get_##ATTR(PyObject *self, void *closure) { \
|
static PyObject *pepy_parsed_get_##ATTR(PyObject *self, void *closure) { \
|
||||||
PyObject *ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.VAL); \
|
PyObject *ret = \
|
||||||
|
PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.VAL); \
|
||||||
if (!ret) \
|
if (!ret) \
|
||||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
PEPY_PARSED_GET(signature, Signature)
|
PEPY_PARSED_GET(signature, Signature)
|
||||||
PEPY_PARSED_GET(machine, FileHeader.Machine)
|
PEPY_PARSED_GET(machine, FileHeader.Machine)
|
||||||
@ -1018,21 +1060,26 @@ PEPY_PARSED_GET(magic, OptionalMagic)
|
|||||||
* This is why "magic" is handled above, and not here.
|
* This is why "magic" is handled above, and not here.
|
||||||
*/
|
*/
|
||||||
#define PEPY_PARSED_GET_OPTIONAL(ATTR, VAL) \
|
#define PEPY_PARSED_GET_OPTIONAL(ATTR, VAL) \
|
||||||
static PyObject *pepy_parsed_get_optional_##ATTR(PyObject *self, void *closure) { \
|
static PyObject *pepy_parsed_get_optional_##ATTR(PyObject *self, \
|
||||||
|
void *closure) { \
|
||||||
PyObject *ret = NULL; \
|
PyObject *ret = NULL; \
|
||||||
if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) { \
|
if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == \
|
||||||
ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader.VAL); \
|
NT_OPTIONAL_32_MAGIC) { \
|
||||||
|
ret = PyInt_FromLong( \
|
||||||
|
((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader.VAL); \
|
||||||
if (!ret) \
|
if (!ret) \
|
||||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
||||||
} else if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) { \
|
} else if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == \
|
||||||
ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader64.VAL); \
|
NT_OPTIONAL_64_MAGIC) { \
|
||||||
|
ret = PyInt_FromLong( \
|
||||||
|
((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader64.VAL); \
|
||||||
if (!ret) \
|
if (!ret) \
|
||||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
|
||||||
} else { \
|
} else { \
|
||||||
PyErr_SetString(pepy_error, "Bad magic value."); \
|
PyErr_SetString(pepy_error, "Bad magic value."); \
|
||||||
} \
|
} \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
PEPY_PARSED_GET_OPTIONAL(majorlinkerver, MajorLinkerVersion)
|
PEPY_PARSED_GET_OPTIONAL(majorlinkerver, MajorLinkerVersion)
|
||||||
PEPY_PARSED_GET_OPTIONAL(minorlinkerver, MinorLinkerVersion)
|
PEPY_PARSED_GET_OPTIONAL(minorlinkerver, MinorLinkerVersion)
|
||||||
@ -1063,13 +1110,17 @@ PEPY_PARSED_GET_OPTIONAL(rvasandsize, NumberOfRvaAndSizes);
|
|||||||
* BaseOfData is only in PE32, not PE32+. Thus, it uses a non-standard
|
* BaseOfData is only in PE32, not PE32+. Thus, it uses a non-standard
|
||||||
* getter function compared to the other shared fields.
|
* getter function compared to the other shared fields.
|
||||||
*/
|
*/
|
||||||
static PyObject *pepy_parsed_get_optional_baseofdata(PyObject *self, void *closure) {
|
static PyObject *pepy_parsed_get_optional_baseofdata(PyObject *self,
|
||||||
|
void *closure) {
|
||||||
PyObject *ret = NULL;
|
PyObject *ret = NULL;
|
||||||
if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic ==
|
||||||
ret = PyInt_FromLong(((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader.BaseOfData);
|
NT_OPTIONAL_32_MAGIC) {
|
||||||
|
ret = PyInt_FromLong(
|
||||||
|
((pepy_parsed *) self)->pe->peHeader.nt.OptionalHeader.BaseOfData);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
PyErr_SetString(PyExc_AttributeError, "Error getting attribute.");
|
PyErr_SetString(PyExc_AttributeError, "Error getting attribute.");
|
||||||
} else if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
|
} else if (((pepy_parsed *) self)->pe->peHeader.nt.OptionalMagic ==
|
||||||
|
NT_OPTIONAL_64_MAGIC) {
|
||||||
PyErr_SetString(PyExc_AttributeError, "Not available on PE32+.");
|
PyErr_SetString(PyExc_AttributeError, "Not available on PE32+.");
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString(pepy_error, "Bad magic value.");
|
PyErr_SetString(pepy_error, "Bad magic value.");
|
||||||
@ -1110,33 +1161,46 @@ static PyGetSetDef pepy_parsed_getseters[] = {
|
|||||||
OBJECTGETTER_OPTIONAL(loaderflags, "Loader flags"),
|
OBJECTGETTER_OPTIONAL(loaderflags, "Loader flags"),
|
||||||
OBJECTGETTER_OPTIONAL(rvasandsize, "Number of RVA and sizes"),
|
OBJECTGETTER_OPTIONAL(rvasandsize, "Number of RVA and sizes"),
|
||||||
/* Base of data is only available in PE32, not PE32+. */
|
/* Base of data is only available in PE32, not PE32+. */
|
||||||
{ (char *) "baseofdata", (getter) pepy_parsed_get_optional_baseofdata,
|
{(char *) "baseofdata",
|
||||||
|
(getter) pepy_parsed_get_optional_baseofdata,
|
||||||
(setter) pepy_attr_not_writable,
|
(setter) pepy_attr_not_writable,
|
||||||
(char *) "Base address of data", NULL },
|
(char *) "Base address of data",
|
||||||
{ NULL }
|
NULL},
|
||||||
};
|
{NULL}};
|
||||||
|
|
||||||
static PyMethodDef pepy_parsed_methods[] = {
|
static PyMethodDef pepy_parsed_methods[] = {
|
||||||
{ "get_entry_point", pepy_parsed_get_entry_point, METH_NOARGS,
|
{"get_entry_point",
|
||||||
"Return the entry point address." },
|
pepy_parsed_get_entry_point,
|
||||||
{ "get_bytes", pepy_parsed_get_bytes, METH_VARARGS,
|
METH_NOARGS,
|
||||||
"Return the first N bytes at a given address." },
|
"Return the entry point address."},
|
||||||
{ "get_sections", pepy_parsed_get_sections, METH_NOARGS,
|
{"get_bytes",
|
||||||
"Return a list of section objects." },
|
pepy_parsed_get_bytes,
|
||||||
{ "get_imports", pepy_parsed_get_imports, METH_NOARGS,
|
METH_VARARGS,
|
||||||
"Return a list of import objects." },
|
"Return the first N bytes at a given address."},
|
||||||
{ "get_exports", pepy_parsed_get_exports, METH_NOARGS,
|
{"get_sections",
|
||||||
"Return a list of export objects." },
|
pepy_parsed_get_sections,
|
||||||
{ "get_relocations", pepy_parsed_get_relocations, METH_NOARGS,
|
METH_NOARGS,
|
||||||
"Return a list of relocation objects." },
|
"Return a list of section objects."},
|
||||||
{ "get_resources", pepy_parsed_get_resources, METH_NOARGS,
|
{"get_imports",
|
||||||
"Return a list of resource objects." },
|
pepy_parsed_get_imports,
|
||||||
{ NULL }
|
METH_NOARGS,
|
||||||
};
|
"Return a list of import objects."},
|
||||||
|
{"get_exports",
|
||||||
|
pepy_parsed_get_exports,
|
||||||
|
METH_NOARGS,
|
||||||
|
"Return a list of export objects."},
|
||||||
|
{"get_relocations",
|
||||||
|
pepy_parsed_get_relocations,
|
||||||
|
METH_NOARGS,
|
||||||
|
"Return a list of relocation objects."},
|
||||||
|
{"get_resources",
|
||||||
|
pepy_parsed_get_resources,
|
||||||
|
METH_NOARGS,
|
||||||
|
"Return a list of resource objects."},
|
||||||
|
{NULL}};
|
||||||
|
|
||||||
static PyTypeObject pepy_parsed_type = {
|
static PyTypeObject pepy_parsed_type = {
|
||||||
PyObject_HEAD_INIT(NULL)
|
PyObject_HEAD_INIT(NULL) 0, /* ob_size */
|
||||||
0, /* ob_size */
|
|
||||||
"pepy.parsed", /* tp_name */
|
"pepy.parsed", /* tp_name */
|
||||||
sizeof(pepy_parsed), /* tp_basicsize */
|
sizeof(pepy_parsed), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
@ -1195,10 +1259,13 @@ static PyObject *pepy_parse(PyObject *self, PyObject *args) {
|
|||||||
err_str = (char *) malloc(len);
|
err_str = (char *) malloc(len);
|
||||||
if (!err_str)
|
if (!err_str)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
snprintf(err_str, len, "%s (%s)", GetPEErrString().c_str(), GetPEErrLoc().c_str());
|
snprintf(err_str,
|
||||||
|
len,
|
||||||
|
"%s (%s)",
|
||||||
|
GetPEErrString().c_str(),
|
||||||
|
GetPEErrLoc().c_str());
|
||||||
PyErr_SetString(pepy_error, err_str);
|
PyErr_SetString(pepy_error, err_str);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
PyErr_SetString(pepy_error, "Unable to init new parsed object.");
|
PyErr_SetString(pepy_error, "Unable to init new parsed object.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1207,9 +1274,7 @@ static PyObject *pepy_parse(PyObject *self, PyObject *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef pepy_methods[] = {
|
static PyMethodDef pepy_methods[] = {
|
||||||
{ "parse", pepy_parse, METH_VARARGS, "Parse PE from file." },
|
{"parse", pepy_parse, METH_VARARGS, "Parse PE from file."}, {NULL}};
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
PyMODINIT_FUNC initpepy(void) {
|
PyMODINIT_FUNC initpepy(void) {
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user