mirror of
https://github.com/QuasarApp/pe-parse.git
synced 2025-04-25 20:04:31 +00:00
Install public headers, add Arch package, build pepy under Travis and more (#57)
* CMake: Added install directives * CMake: Added support for find_package(pe-parse) * Fixed a compilation error on Linux * CMake: Fix cmake module installation * Added ArchLinux package * Finished implementing the address converted example * peaddrconv: Print the image base address. * peaddrconv: Enable more warnings. * Update travis to also build the examples * Fix a compilation warning on Ubuntu 14.04 * Travis: Add macOS support. * Better output for Travis, fix a compilation error on macOS. * Travis: Do not build examples under macOS. * Travis: Also compile the python module (pepy) * Readme: Add a section to show how to use the library. * Windows: Fix a compilation error, enable /analyze (see details). The nt-headers.h include file is defining several constexpr values using reserved (by windows.h) names. These names (i.e.: IMAGE_FILE_MACHINE_UNKNOWN) are in fact macros defined inside the Windows header files, and causes the preprocessor to break definitions such as the following one: constexpr std::uint16_t IMAGE_FILE_MACHINE_UNKNOWN = 0x0; The fix (for now) consists in including the nt-headers.h file before windows.h, but we should probably choose whether to use different names or avoid defining those values (since they are inside the system header anyway).
This commit is contained in:
parent
e632a37290
commit
b60b908fa2
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,4 +8,5 @@ cmake-build-debug
|
||||
cmake-build-release
|
||||
build
|
||||
.vscode
|
||||
examples_build
|
||||
|
||||
|
15
.travis.yml
15
.travis.yml
@ -1,27 +1,32 @@
|
||||
language: cpp
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update ; fi
|
||||
script: cmake . && make
|
||||
- ./travis.sh "$TRAVIS_OS_NAME" initialize
|
||||
script:
|
||||
- ./travis.sh "$TRAVIS_OS_NAME" build
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- compiler: gcc
|
||||
os: osx
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "O+BGqz4ugoVIJbQTh0dJjKRrsSVzkCYSe0WpRzEWK3l8Mw7hqX300g81TxRwTzN2zfUsROMzaeGaXWfGzYakgW59K1WIioaczxtv2MzzUQTbqzJPa+qQoP9bk/b2wJ5jcOL965/rudRju4UiIwuIgzDAMN3nAfIEJgV/2zANLIg="
|
||||
|
||||
addons:
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "trailofbits/pe-parse"
|
||||
description: "Principled, lightweight C/C++ PE parser"
|
||||
notification_email: dan@trailofbits.com
|
||||
build_command_prepend: "cmake ."
|
||||
build_command: "make"
|
||||
build_command: "./travis.sh linux build"
|
||||
branch_pattern: master
|
||||
|
@ -1,6 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(pe-parse)
|
||||
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Default install directory" FORCE)
|
||||
endif ()
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE True)
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||
@ -9,5 +13,8 @@ endif ()
|
||||
include(cmake/compilation_flags.cmake)
|
||||
list(APPEND GLOBAL_CXXFLAGS ${DEFAULT_CXX_FLAGS})
|
||||
|
||||
add_subdirectory(parser-library)
|
||||
add_subdirectory(dump-prog)
|
||||
add_subdirectory(pe-parser-library)
|
||||
add_subdirectory(dump-pe)
|
||||
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
|
||||
|
13
README.md
13
README.md
@ -31,6 +31,19 @@ pe-parse is built using `cmake` and has no major dependencies.
|
||||
2. `cmake .`
|
||||
3. `make`
|
||||
|
||||
Using the library
|
||||
=======
|
||||
Once the library is installed, linking to it is easy! Add the following lines in your CMake project:
|
||||
|
||||
```
|
||||
find_package(peparse REQUIRED)
|
||||
|
||||
target_link_libraries(your_target_name ${PEPARSE_LIBRARIES})
|
||||
target_include_directories(your_target_name PRIVATE ${PEPARSE_INCLUDE_DIRS})
|
||||
```
|
||||
|
||||
You can see a full example in the examples/peaddrconv folder.
|
||||
|
||||
Authors
|
||||
=======
|
||||
pe-parse was designed and implemented by Andrew Ruef (andrew@trailofbits.com), with significant contributions from [Wesley Shields](https://github.com/wxsBSD).
|
||||
|
@ -1,5 +1,5 @@
|
||||
if (WIN32)
|
||||
list(APPEND DEFAULT_CXX_FLAGS /W4)
|
||||
list(APPEND DEFAULT_CXX_FLAGS /W4 /analyze)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
list(APPEND DEFAULT_CXX_FLAGS /Zi)
|
||||
@ -24,13 +24,13 @@ else ()
|
||||
)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
list(APPEND PROJECT_CXXFLAGS -gdwarf-2 -g3)
|
||||
list(APPEND DEFAULT_CXX_FLAGS -gdwarf-2 -g3)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(STATUS "This is a debug build; enabling -Weverything...")
|
||||
|
||||
list(APPEND PROJECT_CXXFLAGS
|
||||
list(APPEND DEFAULT_CXX_FLAGS
|
||||
-Weverything -Wno-c++98-compat -Wno-missing-prototypes
|
||||
-Wno-missing-variable-declarations -Wno-global-constructors
|
||||
-Wno-exit-time-destructors -Wno-padded -Wno-error
|
||||
|
@ -1,6 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(dump-prog)
|
||||
project(dump-pe)
|
||||
|
||||
add_executable(${PROJECT_NAME} dump.cpp)
|
||||
add_executable(${PROJECT_NAME} main.cpp)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE pe-parser-library)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${GLOBAL_CXXFLAGS})
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION "bin")
|
@ -22,9 +22,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "parse.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
#include <parser-library/parse.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace peparse;
|
||||
@ -273,112 +275,118 @@ int printSecs(void *N,
|
||||
<< endl;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc == 2) {
|
||||
parsed_pe *p = ParsePEFromFile(argv[1]);
|
||||
if (argc != 2 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
|
||||
std::cout << "dump-pe utility from Trail of Bits\n";
|
||||
std::cout << "Repository: https://github.com/trailofbits/pe-parse\n\n";
|
||||
std::cout << "Usage:\n\tdump-pe /path/to/executable.exe\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (p != NULL) {
|
||||
// print out some things
|
||||
DUMP_FIELD(Signature);
|
||||
DUMP_FIELD(FileHeader.Machine);
|
||||
DUMP_FIELD(FileHeader.NumberOfSections);
|
||||
DUMP_DEC_FIELD(FileHeader.TimeDateStamp);
|
||||
DUMP_FIELD(FileHeader.PointerToSymbolTable);
|
||||
DUMP_DEC_FIELD(FileHeader.NumberOfSymbols);
|
||||
DUMP_FIELD(FileHeader.SizeOfOptionalHeader);
|
||||
DUMP_FIELD(FileHeader.Characteristics);
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
DUMP_FIELD(OptionalHeader.Magic);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MajorLinkerVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MinorLinkerVersion);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfCode);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfInitializedData);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfUninitializedData);
|
||||
DUMP_FIELD(OptionalHeader.AddressOfEntryPoint);
|
||||
DUMP_FIELD(OptionalHeader.BaseOfCode);
|
||||
DUMP_FIELD(OptionalHeader.BaseOfData);
|
||||
DUMP_FIELD(OptionalHeader.ImageBase);
|
||||
DUMP_FIELD(OptionalHeader.SectionAlignment);
|
||||
DUMP_FIELD(OptionalHeader.FileAlignment);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MajorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MinorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.Win32VersionValue);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfImage);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeaders);
|
||||
DUMP_FIELD(OptionalHeader.CheckSum);
|
||||
DUMP_FIELD(OptionalHeader.Subsystem);
|
||||
DUMP_FIELD(OptionalHeader.DllCharacteristics);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfStackReserve);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfStackCommit);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeapReserve);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeapCommit);
|
||||
DUMP_FIELD(OptionalHeader.LoaderFlags);
|
||||
DUMP_DEC_FIELD(OptionalHeader.NumberOfRvaAndSizes);
|
||||
} else {
|
||||
DUMP_FIELD(OptionalHeader64.Magic);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MajorLinkerVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MinorLinkerVersion);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfCode);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfInitializedData);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfUninitializedData);
|
||||
DUMP_FIELD(OptionalHeader64.AddressOfEntryPoint);
|
||||
DUMP_FIELD(OptionalHeader64.BaseOfCode);
|
||||
DUMP_FIELD(OptionalHeader64.ImageBase);
|
||||
DUMP_FIELD(OptionalHeader64.SectionAlignment);
|
||||
DUMP_FIELD(OptionalHeader64.FileAlignment);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MajorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MinorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.Win32VersionValue);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfImage);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeaders);
|
||||
DUMP_FIELD(OptionalHeader64.CheckSum);
|
||||
DUMP_FIELD(OptionalHeader64.Subsystem);
|
||||
DUMP_FIELD(OptionalHeader64.DllCharacteristics);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfStackReserve);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfStackCommit);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeapReserve);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeapCommit);
|
||||
DUMP_FIELD(OptionalHeader64.LoaderFlags);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.NumberOfRvaAndSizes);
|
||||
}
|
||||
parsed_pe *p = ParsePEFromFile(argv[1]);
|
||||
|
||||
if (p != NULL) {
|
||||
// print out some things
|
||||
DUMP_FIELD(Signature);
|
||||
DUMP_FIELD(FileHeader.Machine);
|
||||
DUMP_FIELD(FileHeader.NumberOfSections);
|
||||
DUMP_DEC_FIELD(FileHeader.TimeDateStamp);
|
||||
DUMP_FIELD(FileHeader.PointerToSymbolTable);
|
||||
DUMP_DEC_FIELD(FileHeader.NumberOfSymbols);
|
||||
DUMP_FIELD(FileHeader.SizeOfOptionalHeader);
|
||||
DUMP_FIELD(FileHeader.Characteristics);
|
||||
if (p->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
|
||||
DUMP_FIELD(OptionalHeader.Magic);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MajorLinkerVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MinorLinkerVersion);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfCode);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfInitializedData);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfUninitializedData);
|
||||
DUMP_FIELD(OptionalHeader.AddressOfEntryPoint);
|
||||
DUMP_FIELD(OptionalHeader.BaseOfCode);
|
||||
DUMP_FIELD(OptionalHeader.BaseOfData);
|
||||
DUMP_FIELD(OptionalHeader.ImageBase);
|
||||
DUMP_FIELD(OptionalHeader.SectionAlignment);
|
||||
DUMP_FIELD(OptionalHeader.FileAlignment);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MajorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.MinorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader.Win32VersionValue);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfImage);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeaders);
|
||||
DUMP_FIELD(OptionalHeader.CheckSum);
|
||||
DUMP_FIELD(OptionalHeader.Subsystem);
|
||||
DUMP_FIELD(OptionalHeader.DllCharacteristics);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfStackReserve);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfStackCommit);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeapReserve);
|
||||
DUMP_FIELD(OptionalHeader.SizeOfHeapCommit);
|
||||
DUMP_FIELD(OptionalHeader.LoaderFlags);
|
||||
DUMP_DEC_FIELD(OptionalHeader.NumberOfRvaAndSizes);
|
||||
} else {
|
||||
DUMP_FIELD(OptionalHeader64.Magic);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MajorLinkerVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MinorLinkerVersion);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfCode);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfInitializedData);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfUninitializedData);
|
||||
DUMP_FIELD(OptionalHeader64.AddressOfEntryPoint);
|
||||
DUMP_FIELD(OptionalHeader64.BaseOfCode);
|
||||
DUMP_FIELD(OptionalHeader64.ImageBase);
|
||||
DUMP_FIELD(OptionalHeader64.SectionAlignment);
|
||||
DUMP_FIELD(OptionalHeader64.FileAlignment);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MajorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.MinorOperatingSystemVersion);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.Win32VersionValue);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfImage);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeaders);
|
||||
DUMP_FIELD(OptionalHeader64.CheckSum);
|
||||
DUMP_FIELD(OptionalHeader64.Subsystem);
|
||||
DUMP_FIELD(OptionalHeader64.DllCharacteristics);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfStackReserve);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfStackCommit);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeapReserve);
|
||||
DUMP_FIELD(OptionalHeader64.SizeOfHeapCommit);
|
||||
DUMP_FIELD(OptionalHeader64.LoaderFlags);
|
||||
DUMP_DEC_FIELD(OptionalHeader64.NumberOfRvaAndSizes);
|
||||
}
|
||||
|
||||
#undef DUMP_FIELD
|
||||
#undef DUMP_DEC_FIELD
|
||||
|
||||
std::cout << "Imports: " << endl;
|
||||
IterImpVAString(p, printImports, NULL);
|
||||
std::cout << "Relocations: " << endl;
|
||||
IterRelocs(p, printRelocs, NULL);
|
||||
std::cout << "Symbols (symbol table): " << endl;
|
||||
IterSymbols(p, printSymbols, NULL);
|
||||
std::cout << "Sections: " << endl;
|
||||
IterSec(p, printSecs, NULL);
|
||||
std::cout << "Exports: " << endl;
|
||||
IterExpVA(p, printExps, NULL);
|
||||
std::cout << "Imports: " << endl;
|
||||
IterImpVAString(p, printImports, NULL);
|
||||
std::cout << "Relocations: " << endl;
|
||||
IterRelocs(p, printRelocs, NULL);
|
||||
std::cout << "Symbols (symbol table): " << endl;
|
||||
IterSymbols(p, printSymbols, NULL);
|
||||
std::cout << "Sections: " << endl;
|
||||
IterSec(p, printSecs, NULL);
|
||||
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)) {
|
||||
std::cout << "First 8 bytes from entry point (0x";
|
||||
// read the first 8 bytes from the entry point and print them
|
||||
VA entryPoint;
|
||||
if (GetEntryPoint(p, entryPoint)) {
|
||||
std::cout << "First 8 bytes from entry point (0x";
|
||||
|
||||
std::cout << to_string<VA>(entryPoint, hex);
|
||||
std::cout << "):" << endl;
|
||||
for (std::size_t i = 0; i < 8; i++) {
|
||||
::uint8_t b;
|
||||
ReadByteAtVA(p, i + entryPoint, b);
|
||||
std::cout << " 0x" << to_string<uint32_t>(b, hex);
|
||||
}
|
||||
|
||||
std::cout << endl;
|
||||
std::cout << to_string<VA>(entryPoint, hex);
|
||||
std::cout << "):" << endl;
|
||||
for (std::size_t i = 0; i < 8; i++) {
|
||||
::uint8_t b;
|
||||
ReadByteAtVA(p, i + entryPoint, b);
|
||||
std::cout << " 0x" << to_string<uint32_t>(b, hex);
|
||||
}
|
||||
|
||||
std::cout << "Resources: " << endl;
|
||||
IterRsrc(p, printRsrc, NULL);
|
||||
DestructParsedPE(p);
|
||||
} else {
|
||||
std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
|
||||
<< endl;
|
||||
std::cout << "Location: " << GetPEErrLoc() << endl;
|
||||
std::cout << endl;
|
||||
}
|
||||
|
||||
std::cout << "Resources: " << endl;
|
||||
IterRsrc(p, printRsrc, NULL);
|
||||
DestructParsedPE(p);
|
||||
} else {
|
||||
std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
|
||||
<< endl;
|
||||
std::cout << "Location: " << GetPEErrLoc() << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
39
examples/peaddrconv/CMakeLists.txt
Normal file
39
examples/peaddrconv/CMakeLists.txt
Normal file
@ -0,0 +1,39 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(peaddrconv)
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND PEADDRCONV_CXXFLAGS /W4 /analyze)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
list(APPEND PEADDRCONV_CXXFLAGS /Zi)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
list(APPEND PEADDRCONV_CXXFLAGS /WX)
|
||||
endif ()
|
||||
|
||||
else ()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
list(APPEND PEADDRCONV_CXXFLAGS
|
||||
-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 PEADDRCONV_CXXFLAGS -gdwarf-2 -g3)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
find_package(peparse REQUIRED)
|
||||
|
||||
add_executable(${PROJECT_NAME} main.cpp)
|
||||
target_link_libraries(${PROJECT_NAME} ${PEPARSE_LIBRARIES})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${PEPARSE_INCLUDE_DIRS})
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${PEADDRCONV_CXXFLAGS})
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION "bin")
|
1
examples/peaddrconv/README.md
Normal file
1
examples/peaddrconv/README.md
Normal file
@ -0,0 +1 @@
|
||||
Note that you have to install the library before you can build this example!
|
374
examples/peaddrconv/main.cpp
Normal file
374
examples/peaddrconv/main.cpp
Normal file
@ -0,0 +1,374 @@
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
#include <parser-library/parse.h>
|
||||
|
||||
using ParsedPeRef =
|
||||
std::unique_ptr<peparse::parsed_pe, void (*)(peparse::parsed_pe *)>;
|
||||
|
||||
ParsedPeRef openExecutable(const std::string &path) noexcept {
|
||||
// The factory function does not throw exceptions!
|
||||
ParsedPeRef obj(peparse::ParsePEFromFile(path.data()),
|
||||
peparse::DestructParsedPE);
|
||||
if (!obj) {
|
||||
return ParsedPeRef(nullptr, peparse::DestructParsedPE);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
enum class AddressType {
|
||||
PhysicalOffset,
|
||||
RelativeVirtualAddress,
|
||||
VirtualAddress
|
||||
};
|
||||
|
||||
bool convertAddress(ParsedPeRef &pe,
|
||||
std::uintptr_t address,
|
||||
AddressType source_type,
|
||||
AddressType destination_type,
|
||||
std::uintptr_t &result) noexcept {
|
||||
if (source_type == destination_type) {
|
||||
result = address;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::uint64_t image_base_address = 0U;
|
||||
if (pe->peHeader.nt.FileHeader.Machine == peparse::IMAGE_FILE_MACHINE_AMD64) {
|
||||
image_base_address = pe->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
image_base_address = pe->peHeader.nt.OptionalHeader.ImageBase;
|
||||
}
|
||||
|
||||
struct SectionAddressLimits final {
|
||||
std::uintptr_t lowest_rva;
|
||||
std::uintptr_t lowest_offset;
|
||||
|
||||
std::uintptr_t highest_rva;
|
||||
std::uintptr_t highest_offset;
|
||||
};
|
||||
|
||||
auto L_getSectionAddressLimits = [](void *N,
|
||||
peparse::VA secBase,
|
||||
std::string &secName,
|
||||
peparse::image_section_header s,
|
||||
peparse::bounded_buffer *data) -> int {
|
||||
static_cast<void>(secBase);
|
||||
static_cast<void>(secName);
|
||||
static_cast<void>(data);
|
||||
|
||||
SectionAddressLimits *section_address_limits =
|
||||
static_cast<SectionAddressLimits *>(N);
|
||||
|
||||
section_address_limits->lowest_rva =
|
||||
std::min(section_address_limits->lowest_rva,
|
||||
static_cast<std::uintptr_t>(s.VirtualAddress));
|
||||
|
||||
section_address_limits->lowest_offset =
|
||||
std::min(section_address_limits->lowest_offset,
|
||||
static_cast<std::uintptr_t>(s.PointerToRawData));
|
||||
|
||||
std::uintptr_t sectionSize;
|
||||
if (s.SizeOfRawData != 0) {
|
||||
sectionSize = s.SizeOfRawData;
|
||||
} else {
|
||||
sectionSize = s.Misc.VirtualSize;
|
||||
}
|
||||
|
||||
section_address_limits->highest_rva =
|
||||
std::max(section_address_limits->highest_rva,
|
||||
static_cast<std::uintptr_t>(s.VirtualAddress + sectionSize));
|
||||
|
||||
section_address_limits->highest_offset =
|
||||
std::max(section_address_limits->highest_offset,
|
||||
static_cast<std::uintptr_t>(s.PointerToRawData + sectionSize));
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
SectionAddressLimits section_address_limits = {
|
||||
std::numeric_limits<std::uintptr_t>::max(),
|
||||
std::numeric_limits<std::uintptr_t>::max(),
|
||||
std::numeric_limits<std::uintptr_t>::min(),
|
||||
std::numeric_limits<std::uintptr_t>::min()};
|
||||
|
||||
IterSec(pe.get(), L_getSectionAddressLimits, §ion_address_limits);
|
||||
|
||||
switch (source_type) {
|
||||
case AddressType::PhysicalOffset: {
|
||||
if (address >= section_address_limits.highest_offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (destination_type == AddressType::RelativeVirtualAddress) {
|
||||
struct CallbackData final {
|
||||
bool found;
|
||||
std::uintptr_t address;
|
||||
std::uintptr_t result;
|
||||
};
|
||||
|
||||
auto L_inspectSection = [](void *N,
|
||||
peparse::VA secBase,
|
||||
std::string &secName,
|
||||
peparse::image_section_header s,
|
||||
peparse::bounded_buffer *data) -> int {
|
||||
static_cast<void>(secBase);
|
||||
static_cast<void>(secName);
|
||||
static_cast<void>(data);
|
||||
|
||||
std::uintptr_t sectionBaseOffset = s.PointerToRawData;
|
||||
|
||||
std::uintptr_t sectionEndOffset = sectionBaseOffset;
|
||||
if (s.SizeOfRawData != 0) {
|
||||
sectionEndOffset += s.SizeOfRawData;
|
||||
} else {
|
||||
sectionEndOffset += s.Misc.VirtualSize;
|
||||
}
|
||||
|
||||
auto callback_data = static_cast<CallbackData *>(N);
|
||||
if (callback_data->address >= sectionBaseOffset &&
|
||||
callback_data->address < sectionEndOffset) {
|
||||
callback_data->result = s.VirtualAddress + (callback_data->address -
|
||||
s.PointerToRawData);
|
||||
|
||||
callback_data->found = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
CallbackData callback_data = {false, address, 0U};
|
||||
IterSec(pe.get(), L_inspectSection, &callback_data);
|
||||
|
||||
if (!callback_data.found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = callback_data.result;
|
||||
return true;
|
||||
|
||||
} else if (destination_type == AddressType::VirtualAddress) {
|
||||
std::uintptr_t rva = 0U;
|
||||
if (!convertAddress(pe,
|
||||
address,
|
||||
source_type,
|
||||
AddressType::RelativeVirtualAddress,
|
||||
rva)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = image_base_address + rva;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
case AddressType::RelativeVirtualAddress: {
|
||||
if (address < section_address_limits.lowest_rva) {
|
||||
result = address;
|
||||
return true;
|
||||
} else if (address >= section_address_limits.highest_rva) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (destination_type == AddressType::PhysicalOffset) {
|
||||
struct CallbackData final {
|
||||
bool found;
|
||||
std::uintptr_t address;
|
||||
std::uintptr_t result;
|
||||
};
|
||||
|
||||
auto L_inspectSection = [](void *N,
|
||||
peparse::VA secBase,
|
||||
std::string &secName,
|
||||
peparse::image_section_header s,
|
||||
peparse::bounded_buffer *data) -> int {
|
||||
static_cast<void>(secBase);
|
||||
static_cast<void>(secName);
|
||||
static_cast<void>(data);
|
||||
|
||||
std::uintptr_t sectionBaseAddress = s.VirtualAddress;
|
||||
std::uintptr_t sectionEndAddress =
|
||||
sectionBaseAddress + s.Misc.VirtualSize;
|
||||
|
||||
auto callback_data = static_cast<CallbackData *>(N);
|
||||
if (callback_data->address >= sectionBaseAddress &&
|
||||
callback_data->address < sectionEndAddress) {
|
||||
callback_data->result =
|
||||
s.PointerToRawData +
|
||||
(callback_data->address - sectionBaseAddress);
|
||||
|
||||
callback_data->found = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
CallbackData callback_data = {false, address, 0U};
|
||||
IterSec(pe.get(), L_inspectSection, &callback_data);
|
||||
|
||||
if (!callback_data.found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = callback_data.result;
|
||||
return true;
|
||||
|
||||
} else if (destination_type == AddressType::VirtualAddress) {
|
||||
result = image_base_address + address;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
case AddressType::VirtualAddress: {
|
||||
if (address < image_base_address) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::uintptr_t rva = address - image_base_address;
|
||||
return convertAddress(pe,
|
||||
rva,
|
||||
AddressType::RelativeVirtualAddress,
|
||||
destination_type,
|
||||
result);
|
||||
}
|
||||
|
||||
default: { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 3 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
|
||||
std::cout << "PE address conversion utility from Trail of Bits\n";
|
||||
std::cout << "Usage:\n\tpeaddrconv /path/to/executable.exe address\n\n";
|
||||
std::cout << "The <address> parameter is always interpreted as hex!\n";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *executable_path = argv[1];
|
||||
const char *address_as_string = argv[2];
|
||||
|
||||
char *last_parsed_char = nullptr;
|
||||
errno = 0;
|
||||
|
||||
auto address = std::strtoull(address_as_string, &last_parsed_char, 16);
|
||||
if (address == 0U && *last_parsed_char != 0) {
|
||||
std::cout << "Invalid address specified\n";
|
||||
return 1;
|
||||
|
||||
} else if (address == ULLONG_MAX && errno == ERANGE) {
|
||||
std::cout << "The address you specified is too big\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto pe = openExecutable(executable_path);
|
||||
if (!pe) {
|
||||
std::cout << "Failed to open the executable\n\n";
|
||||
|
||||
std::cout << "Error: " << peparse::GetPEErr() << " ("
|
||||
<< peparse::GetPEErrString() << ")\n";
|
||||
|
||||
std::cout << "Location: " << peparse::GetPEErrLoc() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::uint64_t image_base_address = 0U;
|
||||
if (pe->peHeader.nt.FileHeader.Machine == peparse::IMAGE_FILE_MACHINE_AMD64) {
|
||||
image_base_address = pe->peHeader.nt.OptionalHeader64.ImageBase;
|
||||
} else {
|
||||
image_base_address = pe->peHeader.nt.OptionalHeader.ImageBase;
|
||||
}
|
||||
|
||||
std::cout << "Image base address: 0x" << std::hex << image_base_address
|
||||
<< "\n";
|
||||
std::cout << "Converting address 0x" << std::hex << address << "...\n\n";
|
||||
|
||||
std::uintptr_t result = 0U;
|
||||
|
||||
std::cout << "as Physical offset (off)\n";
|
||||
std::cout << " to rva:\t";
|
||||
if (convertAddress(pe,
|
||||
address,
|
||||
AddressType::PhysicalOffset,
|
||||
AddressType::RelativeVirtualAddress,
|
||||
result)) {
|
||||
std::cout << "0x" << std::hex << result;
|
||||
} else {
|
||||
std::cout << "-";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << " to va:\t";
|
||||
if (convertAddress(pe,
|
||||
address,
|
||||
AddressType::PhysicalOffset,
|
||||
AddressType::VirtualAddress,
|
||||
result)) {
|
||||
std::cout << "0x" << std::hex << result;
|
||||
} else {
|
||||
std::cout << "-";
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "as Relative virtual address (rva)\n";
|
||||
std::cout << " to off:\t";
|
||||
if (convertAddress(pe,
|
||||
address,
|
||||
AddressType::RelativeVirtualAddress,
|
||||
AddressType::PhysicalOffset,
|
||||
result)) {
|
||||
std::cout << "0x" << std::hex << result;
|
||||
} else {
|
||||
std::cout << "-";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << " to va:\t";
|
||||
if (convertAddress(pe,
|
||||
address,
|
||||
AddressType::RelativeVirtualAddress,
|
||||
AddressType::VirtualAddress,
|
||||
result)) {
|
||||
std::cout << "0x" << std::hex << result;
|
||||
} else {
|
||||
std::cout << "-";
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
|
||||
std::cout << "as Virtual address (va)\n";
|
||||
std::cout << " to off:\t";
|
||||
if (convertAddress(pe,
|
||||
address,
|
||||
AddressType::VirtualAddress,
|
||||
AddressType::PhysicalOffset,
|
||||
result)) {
|
||||
std::cout << "0x" << std::hex << result;
|
||||
} else {
|
||||
std::cout << "-";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << " to rva:\t";
|
||||
if (convertAddress(pe,
|
||||
address,
|
||||
AddressType::VirtualAddress,
|
||||
AddressType::RelativeVirtualAddress,
|
||||
result)) {
|
||||
std::cout << "0x" << std::hex << result;
|
||||
} else {
|
||||
std::cout << "-";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
5
packages/archlinux/.gitignore
vendored
Normal file
5
packages/archlinux/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
pkg
|
||||
src
|
||||
*.pkg.tar
|
||||
*.pkg.tar.xz
|
||||
|
18
packages/archlinux/PKGBUILD
Normal file
18
packages/archlinux/PKGBUILD
Normal file
@ -0,0 +1,18 @@
|
||||
pkgname=pe-parse
|
||||
pkgver=1.0
|
||||
pkgrel=1
|
||||
arch=("x86_64" "x86")
|
||||
pkgdesc="PE parsing library from Trail of Bits"
|
||||
url="https://github.com/trailofbits/pe-parse"
|
||||
license=('MIT')
|
||||
makedepends=("cmake")
|
||||
provides=("pe-parse")
|
||||
|
||||
build() {
|
||||
cmake ../../../
|
||||
make -j `nproc`
|
||||
}
|
||||
|
||||
package() {
|
||||
make DESTDIR="$pkgdir/" install
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
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})
|
20
pe-parser-library/CMakeLists.txt
Normal file
20
pe-parser-library/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(pe-parser-library)
|
||||
|
||||
# List all files explicitly; this will make IDEs happy (i.e. QtCreator, CLion, ...)
|
||||
list(APPEND PEPARSERLIB_SOURCEFILES
|
||||
include/parser-library/parse.h
|
||||
include/parser-library/nt-headers.h
|
||||
include/parser-library/to_string.h
|
||||
|
||||
src/buffer.cpp
|
||||
src/parse.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${PEPARSERLIB_SOURCEFILES})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${GLOBAL_CXXFLAGS})
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION "lib")
|
||||
install(FILES "cmake/peparse-config.cmake" DESTINATION "lib/cmake/peparse")
|
||||
install(DIRECTORY "include/parser-library" DESTINATION "include")
|
5
pe-parser-library/cmake/peparse-config.cmake
Normal file
5
pe-parser-library/cmake/peparse-config.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
find_path(PEPARSE_INCLUDE_DIR "parser-library/parse.h")
|
||||
find_library(PEPARSE_LIBRARIES NAMES "libpe-parser-library.a")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libproxy DEFAULT_MSG PEPARSE_INCLUDE_DIR PEPARSE_LIBRARIES)
|
@ -25,6 +25,7 @@ THE SOFTWARE.
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#define _offset(t, f) \
|
||||
static_cast<std::uint32_t>( \
|
@ -22,12 +22,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "parse.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
// keep this header above "windows.h" because it contains many types
|
||||
#include <parser-library/parse.h>
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define VC_EXTRALEAN
|
||||
|
||||
#include <intrin.h>
|
||||
#include <windows.h>
|
||||
#else
|
@ -22,15 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "parse.h"
|
||||
#include "nt-headers.h"
|
||||
#include "to_string.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <parser-library/nt-headers.h>
|
||||
#include <parser-library/parse.h>
|
||||
#include <parser-library/to_string.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace peparse {
|
@ -25,8 +25,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "parse.h"
|
||||
#include <Python.h>
|
||||
#include <parser-library/parse.h>
|
||||
#include <structmember.h>
|
||||
|
||||
using namespace peparse;
|
||||
@ -37,9 +37,9 @@ using namespace peparse;
|
||||
* Add some definition for compatibility between python2 and python3
|
||||
*/
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define PyInt_FromLong PyLong_FromLong
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyString_FromString PyUnicode_FromString
|
||||
#define PyInt_FromLong PyLong_FromLong
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyString_FromString PyUnicode_FromString
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -47,12 +47,11 @@ using namespace peparse;
|
||||
* Needed for compatibility with python3
|
||||
*/
|
||||
#ifndef PyVarObject_HEAD_INIT
|
||||
#define PyVarObject_HEAD_INIT(type, size) \
|
||||
PyObject_HEAD_INIT(type) size,
|
||||
#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
|
||||
#endif
|
||||
|
||||
#ifndef Py_TYPE
|
||||
#define Py_TYPE(_ob_) (((PyObject*)(_ob_))->ob_type)
|
||||
#define Py_TYPE(_ob_) (((PyObject *) (_ob_))->ob_type)
|
||||
#endif
|
||||
|
||||
/* These are used to across multiple objects. */
|
||||
@ -77,9 +76,13 @@ using namespace peparse;
|
||||
|
||||
static PyObject *pepy_error;
|
||||
|
||||
struct pepy { PyObject_HEAD };
|
||||
struct pepy {
|
||||
PyObject_HEAD
|
||||
};
|
||||
|
||||
struct pepy_parsed { PyObject_HEAD parsed_pe *pe; };
|
||||
struct pepy_parsed {
|
||||
PyObject_HEAD parsed_pe *pe;
|
||||
};
|
||||
|
||||
struct pepy_section {
|
||||
PyObject_HEAD PyObject *name;
|
||||
@ -164,7 +167,7 @@ static PyGetSetDef pepy_import_getseters[] = {
|
||||
{NULL}};
|
||||
|
||||
static PyTypeObject pepy_import_type = {
|
||||
PyVarObject_HEAD_INIT(NULL,0) /* ob_size */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) /* ob_size */
|
||||
"pepy.import", /* tp_name */
|
||||
sizeof(pepy_import), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
@ -238,7 +241,7 @@ static PyGetSetDef pepy_export_getseters[] = {
|
||||
{NULL}};
|
||||
|
||||
static PyTypeObject pepy_export_type = {
|
||||
PyVarObject_HEAD_INIT(NULL,0) /* ob_size */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) /* ob_size */
|
||||
"pepy.export", /* tp_name */
|
||||
sizeof(pepy_export), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
@ -310,7 +313,7 @@ static PyGetSetDef pepy_relocation_getseters[] = {
|
||||
{NULL}};
|
||||
|
||||
static PyTypeObject pepy_relocation_type = {
|
||||
PyVarObject_HEAD_INIT(NULL,0) /* ob_size */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) /* ob_size */
|
||||
"pepy.relocation", /* tp_name */
|
||||
sizeof(pepy_relocation), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
@ -412,7 +415,7 @@ static PyGetSetDef pepy_section_getseters[] = {
|
||||
{NULL}};
|
||||
|
||||
static PyTypeObject pepy_section_type = {
|
||||
PyVarObject_HEAD_INIT(NULL,0) /* ob_size */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) /* ob_size */
|
||||
"pepy.section", /* tp_name */
|
||||
sizeof(pepy_section), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
@ -616,7 +619,7 @@ static PyGetSetDef pepy_resource_getseters[] = {
|
||||
{NULL}};
|
||||
|
||||
static PyTypeObject pepy_resource_type = {
|
||||
PyVarObject_HEAD_INIT(NULL,0) /* ob_size */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) /* ob_size */
|
||||
"pepy.resource", /* tp_name */
|
||||
sizeof(pepy_resource), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
@ -716,20 +719,21 @@ static PyObject *pepy_parsed_get_bytes(PyObject *self, PyObject *args) {
|
||||
* PybyteArray_FromStringAndSize
|
||||
*/
|
||||
|
||||
uint8_t *buf = new(std::nothrow) uint8_t[len];
|
||||
uint8_t *buf = new (std::nothrow) uint8_t[len];
|
||||
if (!buf) {
|
||||
/* in case allocation failed */
|
||||
PyErr_SetString(pepy_error, "Unable to create initial buffer (allocation failure).");
|
||||
PyErr_SetString(pepy_error,
|
||||
"Unable to create initial buffer (allocation failure).");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (!ReadByteAtVA(((pepy_parsed *) self)->pe, start + idx, buf[idx]))
|
||||
break;
|
||||
}
|
||||
|
||||
/* use idx as content length, if we get less than asked for */
|
||||
ret = PyByteArray_FromStringAndSize(reinterpret_cast<char*>(buf), idx);
|
||||
ret = PyByteArray_FromStringAndSize(reinterpret_cast<char *>(buf), idx);
|
||||
if (!ret) {
|
||||
PyErr_SetString(pepy_error, "Unable to create new byte array.");
|
||||
return NULL;
|
||||
@ -1203,7 +1207,7 @@ static PyMethodDef pepy_parsed_methods[] = {
|
||||
{NULL}};
|
||||
|
||||
static PyTypeObject pepy_parsed_type = {
|
||||
PyVarObject_HEAD_INIT(NULL,0) /* ob_size */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) /* ob_size */
|
||||
"pepy.parsed", /* tp_name */
|
||||
sizeof(pepy_parsed), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
@ -1279,8 +1283,7 @@ static PyObject *pepy_parse(PyObject *self, PyObject *args) {
|
||||
static PyMethodDef pepy_methods[] = {
|
||||
{"parse", pepy_parse, METH_VARARGS, "Parse PE from file."}, {NULL}};
|
||||
|
||||
static
|
||||
PyObject* pepi_module_init(void) {
|
||||
static PyObject *pepi_module_init(void) {
|
||||
PyObject *m;
|
||||
|
||||
if (PyType_Ready(&pepy_parsed_type) < 0 ||
|
||||
@ -1293,15 +1296,15 @@ PyObject* pepi_module_init(void) {
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"pepy",
|
||||
"Python interface to pe-parse.",
|
||||
-1,
|
||||
pepy_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"pepy",
|
||||
"Python interface to pe-parse.",
|
||||
-1,
|
||||
pepy_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -1401,13 +1404,11 @@ PyObject* pepi_module_init(void) {
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyMODINIT_FUNC PyInit_pepy(void)
|
||||
{
|
||||
PyMODINIT_FUNC PyInit_pepy(void) {
|
||||
return pepi_module_init();
|
||||
}
|
||||
#else
|
||||
PyMODINIT_FUNC initpepy(void)
|
||||
{
|
||||
PyMODINIT_FUNC initpepy(void) {
|
||||
pepi_module_init();
|
||||
}
|
||||
#endif
|
||||
|
@ -28,15 +28,15 @@ from distutils.core import setup, Extension
|
||||
INCLUDE_DIRS = ['/usr/local/include',
|
||||
'/opt/local/include',
|
||||
'/usr/include',
|
||||
'../parser-library']
|
||||
'../pe-parser-library/include']
|
||||
LIBRARY_DIRS = ['/usr/lib',
|
||||
'/usr/local/lib']
|
||||
|
||||
extension_mod = Extension('pepy',
|
||||
sources = ['pepy.cpp',
|
||||
'../parser-library/parse.cpp',
|
||||
'../parser-library/buffer.cpp'],
|
||||
extra_compile_args = ["-g", "-O0"], # Debug only
|
||||
'../pe-parser-library/src/parse.cpp',
|
||||
'../pe-parser-library/src/buffer.cpp'],
|
||||
extra_compile_args = ["-std=c++11", "-g", "-O0"], # Debug only
|
||||
include_dirs = INCLUDE_DIRS,
|
||||
library_dirs = LIBRARY_DIRS)
|
||||
|
||||
|
239
travis.sh
Executable file
239
travis.sh
Executable file
@ -0,0 +1,239 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
main() {
|
||||
if [ $# -ne 2 ] ; then
|
||||
printf "Usage:\n\ttravis.sh <linux|osx> <initialize|build>\n"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local platform_name="$1"
|
||||
local operation_type="$2"
|
||||
|
||||
if [[ "${platform_name}" != "osx" && "${platform_name}" != "linux" ]] ; then
|
||||
printf "Invalid platform: ${platform_name}\n"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "${operation_type}" == "initialize" ]] ; then
|
||||
"${platform_name}_initialize"
|
||||
return $?
|
||||
|
||||
elif [[ "$operation_type" == "build" ]] ; then
|
||||
"${platform_name}_build"
|
||||
return $?
|
||||
|
||||
else
|
||||
printf "Invalid operation\n"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_processor_count() {
|
||||
which nproc > /dev/null
|
||||
if [ $? -eq 0 ] ; then
|
||||
nproc
|
||||
return 0
|
||||
fi
|
||||
|
||||
which sysctl > /dev/null
|
||||
if [ $? -eq 0 ] ; then
|
||||
sysctl -n hw.ncpu
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
linux_initialize() {
|
||||
printf "Initializing platform: linux\n"
|
||||
local log_file=`mktemp`
|
||||
|
||||
printf " > Updating the package database..\n"
|
||||
sudo apt-get -qq update > "${log_file}" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x The package database could not be updated\n\n\n"
|
||||
cat "${log_file}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf " > Installing the required packages...\n"
|
||||
sudo apt-get install -qqy cmake python2.7 python-dev build-essential realpath > "${log_file}" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Could not install the required dependencies\n\n\n"
|
||||
cat "${log_file}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf " > The system has been successfully initialized\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
osx_initialize() {
|
||||
printf "Initializing platform: macOS\n"
|
||||
local log_file=`mktemp`
|
||||
|
||||
printf " > Updating the package database..\n"
|
||||
brew update > "${log_file}" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x The package database could not be updated\n\n\n"
|
||||
cat "${log_file}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf " > Installing CMake...\n"
|
||||
brew install cmake > "${log_file}" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Failed to install CMake\n\n\n"
|
||||
cat "${log_file}"
|
||||
fi
|
||||
|
||||
printf " > The system has been successfully initialized\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
common_build() {
|
||||
printf "Gathering system information...\n"
|
||||
|
||||
which cmake > /dev/null
|
||||
printf " > CMake version: "
|
||||
if [ $? -eq 0 ] ; then
|
||||
cmake --version | head -n 1
|
||||
else
|
||||
printf "not found\n"
|
||||
fi
|
||||
|
||||
which gcc > /dev/null
|
||||
printf " > GCC version: "
|
||||
if [ $? -eq 0 ] ; then
|
||||
gcc --version | head -n 1
|
||||
else
|
||||
printf "not found\n"
|
||||
fi
|
||||
|
||||
which clang > /dev/null
|
||||
printf " > Clang version: "
|
||||
if [ $? -eq 0 ] ; then
|
||||
clang --version | head -n 1
|
||||
else
|
||||
printf "not found\n"
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
|
||||
printf "Library\n"
|
||||
if [ ! -d "build" ] ; then
|
||||
printf " > Creating the build directory...\n"
|
||||
mkdir "build"
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Failed to create the build directory\n"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
local log_file=`mktemp`
|
||||
local processor_count=`get_processor_count`
|
||||
|
||||
printf " > Configuring...\n"
|
||||
( cd "build" && cmake .. ) > "$log_file" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Configure failed; CMake returned an error.\n\n\n"
|
||||
cat "$log_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf " > Building...\n"
|
||||
( cd "build" && make -j "${processor_count}" ) > "$log_file" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x The build has failed.\n\n\n"
|
||||
cat "$log_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf " > Installing...\n"
|
||||
sudo touch /usr/lib/test_file > /dev/null 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Access denied to /usr/lib; examples will not be built\n"
|
||||
|
||||
else
|
||||
( cd "build" && sudo make install ) > "$log_file" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Failed to install the library.\n\n\n"
|
||||
cat "$log_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
|
||||
printf "Examples\n"
|
||||
if [ ! -d "examples_build" ] ; then
|
||||
printf " > Creating the build directory...\n"
|
||||
mkdir "examples_build"
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Failed to create the build directory\n\n\n"
|
||||
cat "$log_file"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
printf " > Configuring...\n"
|
||||
( cd "examples_build" && cmake "../examples/peaddrconv" ) > "$log_file" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Configure failed; CMake returned an error.\n\n\n"
|
||||
cat "$log_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf " > Building...\n"
|
||||
( cd "examples_build" && make -j "${processor_count}" ) > "$log_file" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x The build has failed.\n\n\n"
|
||||
cat "$log_file"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
|
||||
printf "pepy\n"
|
||||
|
||||
printf " > Building...\n"
|
||||
( cd python && python2 ./setup.py build ) > "$log_file" 2>&1
|
||||
if [ $? -ne 0 ] ; then
|
||||
printf " x Build failed.\n\n\n"
|
||||
cat "$log_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
linux_build() {
|
||||
printf "Building platform: linux\n"
|
||||
|
||||
source /etc/*-release
|
||||
printf "Distribution: ${DISTRIB_DESCRIPTION}\n\n"
|
||||
|
||||
common_build
|
||||
if [ $? -ne 0 ] ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
osx_build() {
|
||||
printf "Building platform: macOS\n\n"
|
||||
|
||||
printf "macOS version: "
|
||||
sw_vers -productVersion
|
||||
|
||||
common_build
|
||||
if [ $? -ne 0 ] ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
main $@
|
||||
exit $?
|
Loading…
x
Reference in New Issue
Block a user