diff --git a/.gitignore b/.gitignore index 7296ad4..53b0920 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,9 @@ cmake_install.cmake dump-prog/dump-prog *.swp python/build +.idea +cmake-build-debug +cmake-build-release +build +.vscode + diff --git a/CMakeLists.txt b/CMakeLists.txt index bb5f1a9..fc7f267 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,13 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required(VERSION 3.1) +project(pe-parse) -project (pe-parse) +set(CMAKE_VERBOSE_MAKEFILE True) +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo") +endif () -if(UNIX) - set(CMAKE_CXX_FLAGS "-std=c++0x") -endif(UNIX) +include(cmake/compilation_flags.cmake) +list(APPEND GLOBAL_CXXFLAGS ${DEFAULT_CXX_FLAGS}) add_subdirectory(parser-library) add_subdirectory(dump-prog) diff --git a/cmake/compilation_flags.cmake b/cmake/compilation_flags.cmake new file mode 100644 index 0000000..d22807c --- /dev/null +++ b/cmake/compilation_flags.cmake @@ -0,0 +1,39 @@ +if (WIN32) + list(APPEND DEFAULT_CXX_FLAGS /W4) + + if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + list(APPEND DEFAULT_CXX_FLAGS /Zi) + endif () + + if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + list(APPEND DEFAULT_CXX_FLAGS /WX) + endif () + +else () + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_EXTENSIONS OFF) + + list(APPEND DEFAULT_CXX_FLAGS + -fPIC + + -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization + -Wformat=2 -Winit-self -Wlong-long -Wmissing-declarations -Wmissing-include-dirs -Wcomment + -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion + -Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wunused -Wuninitialized + -Wno-missing-declarations + ) + + if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + list(APPEND PROJECT_CXXFLAGS -gdwarf-2 -g3) + endif () + + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "This is a debug build; enabling -Weverything...") + + list(APPEND PROJECT_CXXFLAGS + -Weverything -Wno-c++98-compat -Wno-missing-prototypes + -Wno-missing-variable-declarations -Wno-global-constructors + -Wno-exit-time-destructors -Wno-padded -Wno-error + ) + endif () +endif () diff --git a/dump-prog/CMakeLists.txt b/dump-prog/CMakeLists.txt index f7fb4d0..5ecd67b 100644 --- a/dump-prog/CMakeLists.txt +++ b/dump-prog/CMakeLists.txt @@ -1,7 +1,6 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../parser-library) - -add_executable( dump-prog - dump.cpp ) - -target_link_libraries( dump-prog - pe-parser-library ) +cmake_minimum_required(VERSION 3.1) +project(dump-prog) + +add_executable(${PROJECT_NAME} dump.cpp) +target_link_libraries(${PROJECT_NAME} PRIVATE pe-parser-library) +target_compile_options(${PROJECT_NAME} PRIVATE ${GLOBAL_CXXFLAGS}) diff --git a/dump-prog/dump.cpp b/dump-prog/dump.cpp index d402e21..5897fd5 100644 --- a/dump-prog/dump.cpp +++ b/dump-prog/dump.cpp @@ -30,53 +30,66 @@ using namespace std; using namespace peparse; int printExps(void *N, VA funcAddr, std::string &mod, std::string &func) { - cout << "EXP: "; - cout << mod; - cout << "!"; - cout << func; - cout << ": 0x"; - cout << to_string(funcAddr, hex); - cout << endl; + static_cast(N); + + auto address = static_cast(funcAddr); + + std::cout << "EXP: "; + std::cout << mod; + std::cout << "!"; + std::cout << func; + std::cout << ": 0x"; + std::cout << to_string(address, hex); + std::cout << endl; return 0; } int printImports(void *N, VA impAddr, string &modName, string &symName) { - cout << "0x" << to_string(impAddr, hex); - cout << " " << modName << "!" << symName; - cout << endl; + static_cast(N); + + auto address = static_cast(impAddr); + + std::cout << "0x" << to_string(address, hex); + std::cout << " " << modName << "!" << symName; + std::cout << endl; return 0; } int printRelocs(void *N, VA relocAddr, reloc_type type) { - cout << "TYPE: "; + static_cast(N); + + std::cout << "TYPE: "; switch (type) { case ABSOLUTE: - cout << "ABSOLUTE"; + std::cout << "ABSOLUTE"; break; case HIGH: - cout << "HIGH"; + std::cout << "HIGH"; break; case LOW: - cout << "LOW"; + std::cout << "LOW"; break; case HIGHLOW: - cout << "HIGHLOW"; + std::cout << "HIGHLOW"; break; case HIGHADJ: - cout << "HIGHADJ"; + std::cout << "HIGHADJ"; break; case MIPS_JMPADDR: - cout << "MIPS_JMPADDR"; + std::cout << "MIPS_JMPADDR"; break; case MIPS_JMPADDR16: - cout << "MIPS_JMPADD16"; + std::cout << "MIPS_JMPADD16"; break; case DIR64: - cout << "DIR64"; + std::cout << "DIR64"; + break; + default: + std::cout << "UNKNOWN"; break; } - cout << " VA: 0x" << to_string(relocAddr, hex) << endl; + std::cout << " VA: 0x" << to_string(relocAddr, hex) << endl; return 0; } @@ -88,136 +101,146 @@ int printSymbols(void *N, uint16_t &type, uint8_t &storageClass, uint8_t &numberOfAuxSymbols) { - cout << "Symbol Name: " << strName << endl; - cout << "Symbol Value: 0x" << to_string(value, hex) << endl; + static_cast(N); - cout << "Symbol Section Number: "; + std::cout << "Symbol Name: " << strName << endl; + std::cout << "Symbol Value: 0x" << to_string(value, hex) << endl; + + std::cout << "Symbol Section Number: "; switch (sectionNumber) { case IMAGE_SYM_UNDEFINED: - cout << "UNDEFINED"; + std::cout << "UNDEFINED"; break; case IMAGE_SYM_ABSOLUTE: - cout << "ABSOLUTE"; + std::cout << "ABSOLUTE"; break; case IMAGE_SYM_DEBUG: - cout << "DEBUG"; + std::cout << "DEBUG"; break; default: - cout << sectionNumber; + std::cout << sectionNumber; break; } - cout << endl; + std::cout << endl; - cout << "Symbol Type: "; + std::cout << "Symbol Type: "; switch (type) { case IMAGE_SYM_TYPE_NULL: - cout << "NULL"; + std::cout << "NULL"; break; case IMAGE_SYM_TYPE_VOID: - cout << "VOID"; + std::cout << "VOID"; break; case IMAGE_SYM_TYPE_CHAR: - cout << "CHAR"; + std::cout << "CHAR"; break; case IMAGE_SYM_TYPE_SHORT: - cout << "SHORT"; + std::cout << "SHORT"; break; case IMAGE_SYM_TYPE_INT: - cout << "INT"; + std::cout << "INT"; break; case IMAGE_SYM_TYPE_LONG: - cout << "LONG"; + std::cout << "LONG"; break; case IMAGE_SYM_TYPE_FLOAT: - cout << "FLOAT"; + std::cout << "FLOAT"; break; case IMAGE_SYM_TYPE_DOUBLE: - cout << "DOUBLE"; + std::cout << "DOUBLE"; break; case IMAGE_SYM_TYPE_STRUCT: - cout << "STRUCT"; + std::cout << "STRUCT"; break; case IMAGE_SYM_TYPE_UNION: - cout << "UNION"; + std::cout << "UNION"; break; case IMAGE_SYM_TYPE_ENUM: - cout << "ENUM"; + std::cout << "ENUM"; break; case IMAGE_SYM_TYPE_MOE: - cout << "IMAGE_SYM_TYPE_MOE"; + std::cout << "IMAGE_SYM_TYPE_MOE"; break; case IMAGE_SYM_TYPE_BYTE: - cout << "BYTE"; + std::cout << "BYTE"; break; case IMAGE_SYM_TYPE_WORD: - cout << "WORD"; + std::cout << "WORD"; break; case IMAGE_SYM_TYPE_UINT: - cout << "UINT"; + std::cout << "UINT"; break; case IMAGE_SYM_TYPE_DWORD: - cout << "DWORD"; + std::cout << "DWORD"; + break; + default: + std::cout << "UNKNOWN"; break; } - cout << endl; + std::cout << endl; - cout << "Symbol Storage Class: "; + std::cout << "Symbol Storage Class: "; switch (storageClass) { case IMAGE_SYM_CLASS_END_OF_FUNCTION: - cout << "FUNCTION"; + std::cout << "FUNCTION"; break; case IMAGE_SYM_CLASS_NULL: - cout << "NULL"; + std::cout << "NULL"; break; case IMAGE_SYM_CLASS_AUTOMATIC: - cout << "AUTOMATIC"; + std::cout << "AUTOMATIC"; break; case IMAGE_SYM_CLASS_EXTERNAL: - cout << "EXTERNAL"; + std::cout << "EXTERNAL"; break; case IMAGE_SYM_CLASS_STATIC: - cout << "STATIC"; + std::cout << "STATIC"; break; case IMAGE_SYM_CLASS_REGISTER: - cout << "REGISTER"; + std::cout << "REGISTER"; break; case IMAGE_SYM_CLASS_EXTERNAL_DEF: - cout << "EXTERNAL DEF"; + std::cout << "EXTERNAL DEF"; break; case IMAGE_SYM_CLASS_LABEL: - cout << "LABEL"; + std::cout << "LABEL"; break; case IMAGE_SYM_CLASS_UNDEFINED_LABEL: - cout << "UNDEFINED LABEL"; + std::cout << "UNDEFINED LABEL"; break; case IMAGE_SYM_CLASS_MEMBER_OF_STRUCT: - cout << "MEMBER OF STRUCT"; + std::cout << "MEMBER OF STRUCT"; + break; + default: + std::cout << "UNKNOWN"; break; } - cout << endl; + std::cout << endl; - cout << "Symbol Number of Aux Symbols: " << (uint32_t) numberOfAuxSymbols - << endl; + std::cout << "Symbol Number of Aux Symbols: " + << static_cast(numberOfAuxSymbols) << endl; return 0; } int printRsrc(void *N, resource r) { + static_cast(N); + if (r.type_str.length()) - cout << "Type (string): " << r.type_str << endl; + std::cout << "Type (string): " << r.type_str << endl; else - cout << "Type: 0x" << to_string(r.type, hex) << endl; + std::cout << "Type: 0x" << to_string(r.type, hex) << endl; if (r.name_str.length()) - cout << "Name (string): " << r.name_str << endl; + std::cout << "Name (string): " << r.name_str << endl; else - cout << "Name: 0x" << to_string(r.name, hex) << endl; + std::cout << "Name: 0x" << to_string(r.name, hex) << endl; if (r.lang_str.length()) - cout << "Lang (string): " << r.lang_str << endl; + std::cout << "Lang (string): " << r.lang_str << endl; else - cout << "Lang: 0x" << to_string(r.lang, hex) << endl; - cout << "Codepage: 0x" << to_string(r.codepage, hex) << endl; - cout << "RVA: " << to_string(r.RVA, dec) << endl; - cout << "Size: " << to_string(r.size, dec) << endl; + std::cout << "Lang: 0x" << to_string(r.lang, hex) << endl; + std::cout << "Codepage: 0x" << to_string(r.codepage, hex) << endl; + std::cout << "RVA: " << to_string(r.RVA, dec) << endl; + std::cout << "Size: " << to_string(r.size, dec) << endl; return 0; } @@ -226,28 +249,35 @@ int printSecs(void *N, string &secName, image_section_header s, bounded_buffer *data) { - cout << "Sec Name: " << secName << endl; - cout << "Sec Base: 0x" << to_string(secBase, hex) << endl; + static_cast(N); + static_cast(s); + + std::cout << "Sec Name: " << secName << endl; + std::cout << "Sec Base: 0x" << to_string(secBase, hex) << endl; if (data) - cout << "Sec Size: " << to_string(data->bufLen, dec) << endl; + std::cout << "Sec Size: " << to_string(data->bufLen, dec) << endl; else - cout << "Sec Size: 0" << endl; + std::cout << "Sec Size: 0" << endl; return 0; } +#define DUMP_FIELD(x) \ + std::cout << "" #x << ": 0x"; \ + std::cout << to_string( \ + static_cast(p->peHeader.nt.x), std::hex) \ + << endl; +#define DUMP_DEC_FIELD(x) \ + std::cout << "" #x << ": "; \ + std::cout << to_string( \ + static_cast(p->peHeader.nt.x), std::dec) \ + << endl; + int main(int argc, char *argv[]) { if (argc == 2) { parsed_pe *p = ParsePEFromFile(argv[1]); if (p != NULL) { -// print out some things -#define DUMP_FIELD(x) \ - cout << "" #x << ": 0x"; \ - cout << to_string(p->peHeader.nt.x, hex) << endl; -#define DUMP_DEC_FIELD(x) \ - cout << "" #x << ": "; \ - cout << to_string(p->peHeader.nt.x, dec) << endl; - + // print out some things DUMP_FIELD(Signature); DUMP_FIELD(FileHeader.Machine); DUMP_FIELD(FileHeader.NumberOfSections); @@ -314,40 +344,40 @@ int main(int argc, char *argv[]) { #undef DUMP_FIELD #undef DUMP_DEC_FIELD - cout << "Imports: " << endl; + std::cout << "Imports: " << endl; IterImpVAString(p, printImports, NULL); - cout << "Relocations: " << endl; + std::cout << "Relocations: " << endl; IterRelocs(p, printRelocs, NULL); - cout << "Symbols (symbol table): " << endl; + std::cout << "Symbols (symbol table): " << endl; IterSymbols(p, printSymbols, NULL); - cout << "Sections: " << endl; + std::cout << "Sections: " << endl; IterSec(p, printSecs, NULL); - cout << "Exports: " << endl; + std::cout << "Exports: " << endl; IterExpVA(p, printExps, NULL); // read the first 8 bytes from the entry point and print them VA entryPoint; if (GetEntryPoint(p, entryPoint)) { - cout << "First 8 bytes from entry point (0x"; + std::cout << "First 8 bytes from entry point (0x"; - cout << to_string(entryPoint, hex); - cout << "):" << endl; - for (int i = 0; i < 8; i++) { + std::cout << to_string(entryPoint, hex); + std::cout << "):" << endl; + for (std::size_t i = 0; i < 8; i++) { ::uint8_t b; ReadByteAtVA(p, i + entryPoint, b); - cout << " 0x" << to_string(b, hex); + std::cout << " 0x" << to_string(b, hex); } - cout << endl; + std::cout << endl; } - cout << "Resources: " << endl; + std::cout << "Resources: " << endl; IterRsrc(p, printRsrc, NULL); DestructParsedPE(p); } else { - cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")" - << endl; - cout << "Location: " << GetPEErrLoc() << endl; + std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")" + << endl; + std::cout << "Location: " << GetPEErrLoc() << endl; } } return 0; diff --git a/parser-library/CMakeLists.txt b/parser-library/CMakeLists.txt index e0701eb..24ec07d 100644 --- a/parser-library/CMakeLists.txt +++ b/parser-library/CMakeLists.txt @@ -1,3 +1,6 @@ -add_library(pe-parser-library - buffer.cpp - parse.cpp) +cmake_minimum_required(VERSION 3.1) +project(pe-parser-library) + +add_library(${PROJECT_NAME} buffer.cpp parse.cpp) +target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_options(${PROJECT_NAME} PRIVATE ${GLOBAL_CXXFLAGS}) diff --git a/parser-library/buffer.cpp b/parser-library/buffer.cpp index 90fb98f..1c0f477 100644 --- a/parser-library/buffer.cpp +++ b/parser-library/buffer.cpp @@ -23,47 +23,52 @@ THE SOFTWARE. */ #include "parse.h" + +#include #include -#include #ifdef WIN32 +#include #include #else #include #include #include -#include #include #endif namespace { -inline uint16_t byteSwapUint16(uint16_t val) { - uint16_t a = (val >> 8) & 0x00FFU; - uint16_t b = (val << 8) & 0xFF00U; - return a | b; +inline std::uint16_t byteSwapUint16(std::uint16_t val) { +#if defined(_MSC_VER) || defined(_MSC_FULL_VER) + return _byteswap_ushort(val); +#else + return __builtin_bswap16(val); +#endif } -inline uint32_t byteSwapUint32(uint32_t val) { - uint32_t a = byteSwapUint16(val >> 16) & 0x0000FFFFU; - uint32_t b = ((static_cast(byteSwapUint16(val))) << 16) & 0xFFFF0000U; - return a | b; +inline std::uint32_t byteSwapUint32(std::uint32_t val) { +#if defined(_MSC_VER) || defined(_MSC_FULL_VER) + return _byteswap_ulong(val); +#else + return __builtin_bswap32(val); +#endif } -inline uint64_t byteSwapUint64(uint64_t val) { - uint64_t a = byteSwapUint32(val >> 32) & 0x00000000FFFFFFFFUL; - uint64_t b = ((static_cast(byteSwapUint32(val))) << 32) & 0xFFFFFFFF00000000UL; - return a | b; +inline uint64_t byteSwapUint64(std::uint64_t val) { +#if defined(_MSC_VER) || defined(_MSC_FULL_VER) + return _byteswap_uint64(val); +#else + return __builtin_bswap64(val); +#endif } } // anonymous namespace -using namespace std; - namespace peparse { -extern ::uint32_t err; -extern ::string err_loc; +extern std::uint32_t err; +extern std::string err_loc; struct buffer_detail { #ifdef WIN32 @@ -74,7 +79,7 @@ struct buffer_detail { #endif }; -bool readByte(bounded_buffer *b, ::uint32_t offset, ::uint8_t &out) { +bool readByte(bounded_buffer *b, std::uint32_t offset, std::uint8_t &out) { if (b == nullptr) { return false; } @@ -83,13 +88,13 @@ bool readByte(bounded_buffer *b, ::uint32_t offset, ::uint8_t &out) { return false; } - ::uint8_t *tmp = (b->buf + offset); + std::uint8_t *tmp = (b->buf + offset); out = *tmp; return true; } -bool readWord(bounded_buffer *b, ::uint32_t offset, ::uint16_t &out) { +bool readWord(bounded_buffer *b, std::uint32_t offset, std::uint16_t &out) { if (b == nullptr) { return false; } @@ -98,7 +103,7 @@ bool readWord(bounded_buffer *b, ::uint32_t offset, ::uint16_t &out) { return false; } - ::uint16_t *tmp = reinterpret_cast(b->buf + offset); + std::uint16_t *tmp = reinterpret_cast(b->buf + offset); if (b->swapBytes) { out = byteSwapUint16(*tmp); } else { @@ -108,7 +113,7 @@ bool readWord(bounded_buffer *b, ::uint32_t offset, ::uint16_t &out) { return true; } -bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) { +bool readDword(bounded_buffer *b, std::uint32_t offset, std::uint32_t &out) { if (b == nullptr) { return false; } @@ -117,7 +122,7 @@ bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) { return false; } - ::uint32_t *tmp = reinterpret_cast(b->buf + offset); + std::uint32_t *tmp = reinterpret_cast(b->buf + offset); if (b->swapBytes) { out = byteSwapUint32(*tmp); } else { @@ -127,7 +132,7 @@ bool readDword(bounded_buffer *b, ::uint32_t offset, ::uint32_t &out) { return true; } -bool readQword(bounded_buffer *b, ::uint32_t offset, ::uint64_t &out) { +bool readQword(bounded_buffer *b, std::uint32_t offset, std::uint64_t &out) { if (b == nullptr) { return false; } @@ -136,7 +141,7 @@ bool readQword(bounded_buffer *b, ::uint32_t offset, ::uint64_t &out) { return false; } - ::uint64_t *tmp = reinterpret_cast(b->buf + offset); + std::uint64_t *tmp = reinterpret_cast(b->buf + offset); if (b->swapBytes) { out = byteSwapUint64(*tmp); } else { @@ -178,7 +183,6 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) { // make a buffer object bounded_buffer *p = new (std::nothrow) bounded_buffer(); - if (p == nullptr) { PE_ERR(PEERR_MEM); return nullptr; @@ -221,7 +225,8 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) { #else p->detail->fd = fd; - struct stat s = {0}; + struct stat s; + memset(&s, 0, sizeof(struct stat)); if (fstat(fd, &s) != 0) { close(fd); @@ -231,7 +236,12 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) { return nullptr; } - void *maddr = mmap(nullptr, s.st_size, PROT_READ, MAP_SHARED, fd, 0); + void *maddr = mmap(nullptr, + static_cast(s.st_size), + PROT_READ, + MAP_SHARED, + fd, + 0); if (maddr == MAP_FAILED) { close(fd); @@ -241,8 +251,8 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) { return nullptr; } - p->buf = reinterpret_cast(maddr); - p->bufLen = s.st_size; + p->buf = reinterpret_cast(maddr); + p->bufLen = static_cast(s.st_size); #endif p->copy = false; p->swapBytes = false; @@ -251,7 +261,8 @@ bounded_buffer *readFileToFileBuffer(const char *filePath) { } // 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, std::uint32_t from, std::uint32_t to) { if (b == nullptr) { return nullptr; } @@ -262,8 +273,7 @@ bounded_buffer *splitBuffer(bounded_buffer *b, ::uint32_t from, ::uint32_t to) { } // make a new buffer - bounded_buffer *newBuff = new (std::nothrow) bounded_buffer(); - + auto newBuff = new (std::nothrow) bounded_buffer(); if (newBuff == nullptr) { return nullptr; } @@ -291,16 +301,11 @@ void deleteBuffer(bounded_buffer *b) { #endif } - if (b->detail != nullptr) { - delete b->detail; - } - + delete b->detail; delete b; - - return; } -uint64_t bufLen(bounded_buffer *b) { +std::uint64_t bufLen(bounded_buffer *b) { return b->bufLen; } } // namespace peparse diff --git a/parser-library/nt-headers.h b/parser-library/nt-headers.h index 47fa48e..5ce8d64 100644 --- a/parser-library/nt-headers.h +++ b/parser-library/nt-headers.h @@ -22,15 +22,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _NT_HEADERS -#define _NT_HEADERS +#pragma once + #include -#define _offset(t, f) ((std::uint32_t)(ptrdiff_t) & (((t *) 0)->f)) +#define _offset(t, f) \ + static_cast( \ + reinterpret_cast(&static_cast(nullptr)->f)) // need to pack these structure definitions // some constant definitions +// clang-format off namespace peparse { constexpr std::uint16_t MZ_MAGIC = 0x5A4D; constexpr std::uint32_t NT_MAGIC = 0x00004550; @@ -165,7 +168,7 @@ constexpr std::uint16_t IMAGE_SYM_DTYPE_FUNCTION = 2; constexpr std::uint16_t IMAGE_SYM_DTYPE_ARRAY = 3; // Symbol table storage classes -constexpr std::uint8_t IMAGE_SYM_CLASS_END_OF_FUNCTION = -1; +constexpr std::uint8_t IMAGE_SYM_CLASS_END_OF_FUNCTION = static_cast(-1); constexpr std::uint8_t IMAGE_SYM_CLASS_NULL = 0; constexpr std::uint8_t IMAGE_SYM_CLASS_AUTOMATIC = 1; constexpr std::uint8_t IMAGE_SYM_CLASS_EXTERNAL = 2; @@ -192,6 +195,7 @@ constexpr std::uint8_t IMAGE_SYM_CLASS_FILE = 103; constexpr std::uint8_t IMAGE_SYM_CLASS_SECTION = 104; constexpr std::uint8_t IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105; constexpr std::uint8_t IMAGE_SYM_CLASS_CLR_TOKEN = 107; +// clang-format on struct dos_header { std::uint16_t e_magic; @@ -405,5 +409,3 @@ struct reloc_block { std::uint32_t BlockSize; }; } // namespace peparse - -#endif diff --git a/parser-library/parse.cpp b/parser-library/parse.cpp index 348fc24..80343d9 100644 --- a/parser-library/parse.cpp +++ b/parser-library/parse.cpp @@ -25,10 +25,11 @@ THE SOFTWARE. #include "parse.h" #include "nt-headers.h" #include "to_string.h" + #include +#include #include #include -#include using namespace std; @@ -36,7 +37,7 @@ namespace peparse { struct section { string sectionName; - ::uint64_t sectionBase; + std::uint64_t sectionBase; bounded_buffer *sectionData; image_section_header sec; }; @@ -58,7 +59,7 @@ struct reloc { reloc_type type; }; -#define SYMBOL_NAME_OFFSET(sn) ((uint32_t)(sn.data >> 32)) +#define SYMBOL_NAME_OFFSET(sn) (static_cast(sn.data >> 32)) #define SYMBOL_TYPE_HI(x) (x.type >> 8) union symbol_name { @@ -122,7 +123,7 @@ struct parsed_pe_internal { list symbols; }; -::uint32_t err = 0; +std::uint32_t err = 0; std::string err_loc; static const char *pe_err_str[] = {"None", @@ -136,7 +137,7 @@ static const char *pe_err_str[] = {"None", "Unable to stat", "Bad magic"}; -int GetPEErr() { +std::uint32_t GetPEErr() { return err; } @@ -149,15 +150,17 @@ string GetPEErrLoc() { } static bool -readCString(const bounded_buffer &buffer, ::uint32_t off, string &result) { +readCString(const bounded_buffer &buffer, std::uint32_t off, string &result) { if (off < buffer.bufLen) { - ::uint8_t *p = buffer.buf; - ::uint32_t n = buffer.bufLen; - ::uint8_t *b = p + off; - ::uint8_t *x = std::find(b, p + n, 0); + std::uint8_t *p = buffer.buf; + std::uint32_t n = buffer.bufLen; + std::uint8_t *b = p + off; + std::uint8_t *x = std::find(b, p + n, 0); + if (x == p + n) { return false; } + result.insert(result.end(), b, x); return true; } @@ -190,30 +193,29 @@ void IterRsrc(parsed_pe *pe, iterRsrc cb, void *cbd) { return; } -bool parse_resource_id(bounded_buffer *data, ::uint32_t id, string &result) { - ::uint8_t c; - ::uint16_t len; +bool parse_resource_id(bounded_buffer *data, std::uint32_t id, string &result) { + std::uint8_t c; + std::uint16_t len; if (!readWord(data, id, len)) { return false; } id += 2; - for (::uint32_t i = 0; i < len * 2; i++) { + for (std::uint32_t i = 0; i < len * 2U; i++) { if (!readByte(data, id + i, c)) { return false; } - result.push_back((char) c); + result.push_back(static_cast(c)); } return true; } bool parse_resource_table(bounded_buffer *sectionData, - ::uint32_t o, - ::uint32_t virtaddr, - ::uint32_t depth, + std::uint32_t o, + std::uint32_t virtaddr, + std::uint32_t depth, resource_dir_entry *dirent, list &rsrcs) { - ::uint32_t i = 0; resource_dir_table rdt; if (sectionData == nullptr) { @@ -233,7 +235,9 @@ bool parse_resource_table(bounded_buffer *sectionData, return true; // This is not a hard error. It does happen. } - for (i = 0; i < rdt.NameEntries + rdt.IDEntries; i++) { + for (std::uint32_t i = 0; + i < static_cast(rdt.NameEntries + rdt.IDEntries); + i++) { resource_dir_entry *rde = dirent; if (dirent == nullptr) { rde = new resource_dir_entry; @@ -358,7 +362,8 @@ bool parse_resource_table(bounded_buffer *sectionData, return false; } - resource rsrc = {}; + resource rsrc; + memset(&rsrc, 0, sizeof(resource)); rsrc.type_str = rde->type_str; rsrc.name_str = rde->name_str; @@ -418,6 +423,7 @@ bool getResources(bounded_buffer *b, bounded_buffer *fileBegin, list
secs, list &rsrcs) { + static_cast(fileBegin); if (b == nullptr) return false; @@ -470,13 +476,13 @@ bool getSections(bounded_buffer *b, // now we have the section header information, so fill in a section // object appropriately section thisSec; - for (::uint32_t i = 0; i < NT_SHORT_NAME_LEN; i++) { - ::uint8_t c = curSec.Name[i]; + for (::uint32_t charIndex = 0; charIndex < NT_SHORT_NAME_LEN; charIndex++) { + ::uint8_t c = curSec.Name[charIndex]; if (c == 0) { break; } - thisSec.sectionName.push_back((char) c); + thisSec.sectionName.push_back(static_cast(c)); } if (nthdr.OptionalMagic == NT_OPTIONAL_32_MAGIC) { @@ -649,33 +655,24 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) { return false; } - if (TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_AMD64, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_ARM, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_ARM64, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_ARMNT, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_I386, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_M32R, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_POWERPC, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_R4000, - IMAGE_FILE_BYTES_REVERSED_HI) || - TEST_MACHINE_CHARACTERISTICS(header, - IMAGE_FILE_MACHINE_WCEMIPSV2, - IMAGE_FILE_BYTES_REVERSED_HI)) { + if (TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_ARM, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_ARM64, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_ARMNT, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_I386, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_M32R, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_POWERPC, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_R4000, IMAGE_FILE_BYTES_REVERSED_HI) || + TEST_MACHINE_CHARACTERISTICS( + header, IMAGE_FILE_MACHINE_WCEMIPSV2, IMAGE_FILE_BYTES_REVERSED_HI)) { b->swapBytes = true; } @@ -817,10 +814,10 @@ bool getExports(parsed_pe *p) { return false; } - ::uint32_t rvaofft = addr - s.sectionBase; + auto rvaofft = static_cast(addr - s.sectionBase); // get the name of this module - ::uint32_t nameRva; + std::uint32_t nameRva; if (!readDword(s.sectionData, rvaofft + _offset(export_dir_table, NameRVA), nameRva)) { @@ -841,14 +838,14 @@ bool getExports(parsed_pe *p) { return false; } - ::uint32_t nameOff = nameVA - nameSec.sectionBase; + auto nameOff = static_cast(nameVA - nameSec.sectionBase); string modName; if (!readCString(*nameSec.sectionData, nameOff, modName)) { return false; } // now, get all the named export symbols - ::uint32_t numNames; + std::uint32_t numNames; if (!readDword(s.sectionData, rvaofft + _offset(export_dir_table, NumberOfNamePointers), numNames)) { @@ -878,7 +875,8 @@ bool getExports(parsed_pe *p) { return false; } - ::uint32_t namesOff = namesVA - namesSec.sectionBase; + auto namesOff = + static_cast(namesVA - namesSec.sectionBase); // get the EAT section ::uint32_t eatRVA; @@ -902,7 +900,7 @@ bool getExports(parsed_pe *p) { return false; } - ::uint32_t eatOff = eatVA - eatSec.sectionBase; + auto eatOff = static_cast(eatVA - eatSec.sectionBase); // get the ordinal base ::uint32_t ordinalBase; @@ -913,7 +911,7 @@ bool getExports(parsed_pe *p) { } // get the ordinal table - ::uint32_t ordinalTableRVA; + std::uint32_t ordinalTableRVA; if (!readDword(s.sectionData, rvaofft + _offset(export_dir_table, OrdinalTableRVA), ordinalTableRVA)) { @@ -936,7 +934,8 @@ bool getExports(parsed_pe *p) { return false; } - ::uint32_t ordinalOff = ordinalTableVA - ordinalTableSec.sectionBase; + auto ordinalOff = static_cast(ordinalTableVA - + ordinalTableSec.sectionBase); for (::uint32_t i = 0; i < numNames; i++) { ::uint32_t curNameRVA; @@ -961,9 +960,10 @@ bool getExports(parsed_pe *p) { return false; } - ::uint32_t curNameOff = curNameVA - curNameSec.sectionBase; + auto curNameOff = + static_cast(curNameVA - curNameSec.sectionBase); string symName; - ::uint8_t d; + std::uint8_t d; do { if (!readByte(curNameSec.sectionData, curNameOff, d)) { @@ -974,7 +974,7 @@ bool getExports(parsed_pe *p) { break; } - symName.push_back(d); + symName.push_back(static_cast(d)); curNameOff++; } while (true); @@ -999,7 +999,7 @@ bool getExports(parsed_pe *p) { (symRVA < exportDir.VirtualAddress + exportDir.Size)); if (!isForwarded) { - ::uint32_t symVA; + VA symVA; if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) { symVA = symRVA + p->peHeader.nt.OptionalHeader.ImageBase; } else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) { @@ -1049,11 +1049,11 @@ bool getRelocations(parsed_pe *p) { return false; } - ::uint32_t rvaofft = vaAddr - d.sectionBase; + auto rvaofft = static_cast(vaAddr - d.sectionBase); while (rvaofft < relocDir.Size) { - ::uint32_t pageRva; - ::uint32_t blockSize; + std::uint32_t pageRva; + std::uint32_t blockSize; if (!readDword(d.sectionData, rvaofft + _offset(reloc_block, PageRVA), @@ -1071,7 +1071,7 @@ bool getRelocations(parsed_pe *p) { // including the Page RVA and Block Size fields and the Type/Offset fields // that follow. Therefore we should subtract 8 bytes from BlockSize to // exclude the Page RVA and Block Size fields. - ::uint32_t entryCount = (blockSize - 8) / sizeof(::uint16_t); + std::uint32_t entryCount = (blockSize - 8) / sizeof(std::uint16_t); // Skip the Page RVA and Block Size fields rvaofft += sizeof(reloc_block); @@ -1092,7 +1092,7 @@ bool getRelocations(parsed_pe *p) { offset = entry & ~0xf000; // Produce the VA of the relocation - ::uint32_t relocVA; + VA relocVA; if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) { relocVA = pageRva + offset + p->peHeader.nt.OptionalHeader.ImageBase; } else if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) { @@ -1106,7 +1106,7 @@ bool getRelocations(parsed_pe *p) { reloc r; r.shiftedAddr = relocVA; - r.type = (reloc_type) type; + r.type = static_cast(type); p->internal->relocs.push_back(r); entryCount--; @@ -1146,10 +1146,14 @@ bool getImports(parsed_pe *p) { } // get import directory from this section - ::uint32_t offt = addr - c.sectionBase; + auto offt = static_cast(addr - c.sectionBase); + + import_dir_entry emptyEnt; + memset(&emptyEnt, 0, sizeof(import_dir_entry)); + do { // read each directory entry out - import_dir_entry curEnt; + import_dir_entry curEnt = emptyEnt; READ_DWORD(c.sectionData, offt, curEnt, LookupTableRVA); READ_DWORD(c.sectionData, offt, curEnt, TimeStamp); @@ -1178,7 +1182,7 @@ bool getImports(parsed_pe *p) { return false; } - ::uint32_t nameOff = name - nameSec.sectionBase; + auto nameOff = static_cast(name - nameSec.sectionBase); string modName; if (!readCString(*nameSec.sectionData, nameOff, modName)) { return false; @@ -1216,7 +1220,8 @@ bool getImports(parsed_pe *p) { return false; } - ::uint64_t lookupOff = lookupVA - lookupSec.sectionBase; + auto lookupOff = + static_cast(lookupVA - lookupSec.sectionBase); ::uint32_t offInTable = 0; do { VA valVA = 0; @@ -1257,21 +1262,21 @@ bool getImports(parsed_pe *p) { return false; } - ::uint32_t nameOff = valVA - symNameSec.sectionBase; - nameOff += sizeof(::uint16_t); + std::uint32_t nameOffset = + static_cast(valVA - symNameSec.sectionBase) + + sizeof(::uint16_t); do { - ::uint8_t d; - - if (!readByte(symNameSec.sectionData, nameOff, d)) { + std::uint8_t chr; + if (!readByte(symNameSec.sectionData, nameOffset, chr)) { return false; } - if (d == 0) { + if (chr == 0) { break; } - symName.push_back(d); - nameOff++; + symName.push_back(static_cast(chr)); + nameOffset++; } while (true); // okay now we know the pair... add it @@ -1365,12 +1370,12 @@ bool getSymbolTable(parsed_pe *p) { if (ch == 0u) { break; } - sym.strName.push_back((char) ch); + sym.strName.push_back(static_cast(ch)); strOffset += sizeof(uint8_t); } } else { for (uint8_t n = 0; n < NT_SHORT_NAME_LEN; n++) { - sym.strName.push_back((char) (sym.name.shortName[n])); + sym.strName.push_back(static_cast(sym.name.shortName[n])); } } @@ -1390,7 +1395,7 @@ bool getSymbolTable(parsed_pe *p) { PE_ERR(PEERR_MAGIC); return false; } - sym.sectionNumber = (int16_t) secNum; + sym.sectionNumber = static_cast(secNum); offset += sizeof(uint16_t); @@ -1537,7 +1542,7 @@ bool getSymbolTable(parsed_pe *p) { PE_ERR(PEERR_MAGIC); return false; } - asym.strFilename.push_back((char) asym.filename[j]); + asym.strFilename.push_back(static_cast(asym.filename[j])); } // Save the record @@ -1805,8 +1810,7 @@ bool ReadByteAtVA(parsed_pe *pe, VA v, ::uint8_t &b) { return false; } - ::uint32_t off = v - s.sectionBase; - + auto off = static_cast(v - s.sectionBase); return readByte(s.sectionData, off, b); } diff --git a/parser-library/parse.h b/parser-library/parse.h index 842fcf0..2e7f662 100644 --- a/parser-library/parse.h +++ b/parser-library/parse.h @@ -22,8 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _PARSE_H -#define _PARSE_H +#pragma once + #include #include @@ -34,10 +34,10 @@ THE SOFTWARE. #define __typeof__(x) std::remove_reference < decltype(x) > ::type #endif -#define PE_ERR(x) \ - err = (pe_err) x; \ - err_loc.assign(__func__); \ - err_loc += ":" + to_string(__LINE__, dec); +#define PE_ERR(x) \ + err = static_cast(x); \ + err_loc.assign(__func__); \ + err_loc += ":" + to_string(__LINE__, std::dec); #define READ_WORD(b, o, inst, member) \ if (!readWord(b, o + _offset(__typeof__(inst), member), inst.member)) { \ @@ -57,25 +57,12 @@ THE SOFTWARE. return false; \ } -#define READ_DWORD_PTR(b, o, inst, member) \ - if (!readDword(b, o + _offset(__typeof__(*inst), member), inst->member)) { \ - PE_ERR(PEERR_READ); \ - return false; \ - } - #define READ_BYTE(b, o, inst, member) \ if (!readByte(b, o + _offset(__typeof__(inst), member), inst.member)) { \ PE_ERR(PEERR_READ); \ return false; \ } -/* This variant returns NULL instead of false. */ -#define READ_DWORD_NULL(b, o, inst, member) \ - if (!readDword(b, o + _offset(__typeof__(inst), member), inst.member)) { \ - PE_ERR(PEERR_READ); \ - return NULL; \ - } - #define TEST_MACHINE_CHARACTERISTICS(h, m, ch) \ ((h.FileHeader.Machine == m) && (h.FileHeader.Characteristics & ch)) @@ -158,7 +145,9 @@ uint64_t bufLen(bounded_buffer *b); struct parsed_pe_internal; -typedef struct _pe_header { nt_header_32 nt; } pe_header; +typedef struct _pe_header { + nt_header_32 nt; +} pe_header; typedef struct _parsed_pe { bounded_buffer *fileBuffer; @@ -167,7 +156,7 @@ typedef struct _parsed_pe { } parsed_pe; // get parser error status as integer -int GetPEErr(); +std::uint32_t GetPEErr(); // get parser error status as string std::string GetPEErrString(); @@ -196,11 +185,11 @@ void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd); // 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 &); + std::uint32_t &, + std::int16_t &, + std::uint16_t &, + std::uint8_t &, + std::uint8_t &); void IterSymbols(parsed_pe *pe, iterSymbol cb, void *cbd); // iterate over the exports @@ -218,5 +207,3 @@ bool ReadByteAtVA(parsed_pe *pe, VA v, std::uint8_t &b); // get entry point into PE bool GetEntryPoint(parsed_pe *pe, VA &v); } // namespace peparse - -#endif diff --git a/parser-library/to_string.h b/parser-library/to_string.h index cb0f240..e4a6b75 100644 --- a/parser-library/to_string.h +++ b/parser-library/to_string.h @@ -1,5 +1,5 @@ -#ifndef _TO_STRING_H -#define _TO_STRING_H +#pragma once + #include namespace peparse { @@ -9,5 +9,4 @@ static std::string to_string(T t, std::ios_base &(*f)(std::ios_base &) ) { oss << f << t; return oss.str(); } -} -#endif +} // namespace peparse