Merge remote-tracking branch 'rem/master'

This commit is contained in:
a.yankovich 2019-12-23 18:37:16 +03:00
commit d7fa0b2d4b
20 changed files with 1003 additions and 475 deletions

View File

@ -2,7 +2,6 @@ AlignEscapedNewlinesLeft: true
AllowShortFunctionsOnASingleLine: false
BinPackArguments: false
BinPackParameters: false
BreakBeforeBraces: Attach
ColumnLimit: 80
IndentCaseLabels: true
IndentWidth: 2

49
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,49 @@
name: CI
on:
push:
branches:
- master
pull_request:
schedule:
# run CI every day even if no PRs/merges occur
- cron: '0 12 * * *'
jobs:
test:
strategy:
matrix:
platform: ["ubuntu-latest", "macos-latest"]
compiler:
- { CC: "clang", CXX: "clang++" }
- { CC: "gcc", CXX: "g++" }
exclude:
- platform: macos-latest
compiler: { CC: "gcc", CXX: "g++" }
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Build C
env:
CC: ${{ matrix.compiler.CC }}
CXX: ${{ matrix.compiler.CXX }}
run: |
mkdir build
cd build
cmake ..
make
- name: Build Python
run: |
cd python
python2 setup.py build
python3 setup.py build
test-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Build C
run: |
mkdir build
cd build
cmake -G "Visual Studio 16 2019" -A x64 ..
cmake --build .

View File

@ -1,32 +1,63 @@
language: cpp
__build_stage_script: &__build_stage_script
stage: build
language: cpp
script:
- mkdir build && cd build
- cmake ..
- make
- cd ../python
- python2 setup.py build
- python3 setup.py build
addons:
apt:
packages:
- cmake
- python2.7
- python-dev
- build-essential
- realpath
- libicu-dev
homebrew:
packages:
- cmake
coverity_scan:
project:
name: "trailofbits/pe-parse"
description: "Principled, lightweight C/C++ PE parser"
notification_email: dan@trailofbits.com
build_command_prepend: mkdir cov_build && cd cov_build && cmake ..
build_command: make
branch_pattern: master
os:
- linux
- osx
compiler:
- clang
- gcc
before_install:
- ./travis.sh "$TRAVIS_OS_NAME" initialize
script:
- ./travis.sh "$TRAVIS_OS_NAME" build
matrix:
exclude:
- compiler: gcc
os: osx
jobs:
include:
- stage: lint
language: minimal
dist: bionic
addons:
apt:
packages:
- clang-format-8
script:
- find . \( -name '*.h' \) -or \( -name '*.cpp' \) | xargs clang-format -i -style=file
- git diff --exit-code
- <<: *__build_stage_script
os: linux
compiler: clang
- <<: *__build_stage_script
os: linux
compiler: gcc
- <<: *__build_stage_script
os: osx
compiler: clang
- stage: build
os: windows
language: cpp
script:
- mkdir build && cd build
- cmake -G "Visual Studio 15 2017 Win64" ..
- cmake --build .
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: "./travis.sh linux build"
branch_pattern: master

26
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,26 @@
Contributing to pe-parse
========================
Hello, and welcome to the contributing guidelines for pe-parse!
For general building instructions, see the [README](README.md).
For licensing information, see the [LICENSE](LICENSE.txt) file. pe-parse includes a CLA; you will be
automatically prompted to sign it during your first PR.
## General contribution guidelines
* Your changes should be valid C++11
* Your changes should work across all major compiler vendors (GCC, Clang, MSVC) and all
major operating systems (Linux, macOS, Windows)
* Your changes should be auto-formatted with `clang-format -style=file`
* Your changes should not introduce *mandatory* third-party dependencies
## Adding features
Feature additions to either the parsing library or `dump-pe` are welcome!
Check out the following issue labels for some contribution ideas:
* [Enhancements](https://github.com/trailofbits/pe-parse/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
* [Hacktoberfest](https://github.com/trailofbits/pe-parse/issues?q=is%3Aissue+is%3Aopen+label%3Ahacktoberfest)

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
FROM alpine:latest
ARG BUILD_TYPE=Release
LABEL name "pe-parse"
LABEL src "https://github.com/trailofbits/pe-parse"
LABEL creator "Trail of Bits"
LABEL dockerfile_maintenance "William Woodruff <william@trailofbits>"
LABEL desc "Principled, lightweight C/C++ PE parser"
RUN apk add --no-cache cmake icu-dev build-base
COPY . /app/pe-parse
WORKDIR /app/pe-parse
RUN mkdir build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" .. && \
cmake --build . --config "${BUILD_TYPE}" && \
cmake --build . --config "${BUILD_TYPE}" --target install
ENTRYPOINT [ "/usr/bin/dump-pe" ]
CMD ["--help"]

View File

@ -1,10 +1,10 @@
pe-parse
=========================================
[![Build Status](https://travis-ci.org/trailofbits/pe-parse.svg?branch=master)](https://travis-ci.org/trailofbits/pe-parse)
[![Build Status](https://img.shields.io/github/workflow/status/trailofbits/pe-parse/CI/master)](https://github.com/trailofbits/pe-parse/actions?query=workflow%3ACI)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/3671/badge.svg)](https://scan.coverity.com/projects/3671)
pe-parse is a principled, lightweight parser for windows portable executable files. It was created to assist in compiled program analysis, potentially of programs of unknown origins. This means that it should be resistant to malformed or maliciously crafted PE files, and it should support questions that analysis software would ask of an executable program container. For example, listing relocations, describing imports and exports, and supporting byte reads from virtual addresses as well as file offsets.
pe-parse is a principled, lightweight parser for windows portable executable files. It was created to assist in compiled program analysis, potentially of programs of unknown origins. This means that it should be resistant to malformed or maliciously crafted PE files, and it should support questions that analysis software would ask of an executable program container. For example, listing relocations, describing imports and exports, and supporting byte reads from virtual addresses as well as file offsets.
pe-parse supports these use cases via a minimal API that provides methods for
* Opening and closing a PE file
@ -16,7 +16,7 @@ pe-parse supports these use cases via a minimal API that provides methods for
* Reading bytes from specified virtual addresses
* Retrieving the program entry point
The interface is defined in `parser-library/parse.h`. The program in `dump-prog/dump.cpp` is an example of using the parser-library API to dump information about a PE file.
The interface is defined in `parser-library/parse.h`. The program in `dump-prog/dump.cpp` is an example of using the parser-library API to dump information about a PE file.
Internally, the parser-library uses a bounded buffer abstraction to access information stored in the PE file. This should help in constructing a sane parser that allows for detection of the use of bogus values in the PE that would result in out of bounds accesses of the input buffer. Once data is read from the file it is sanitized and placed in C++ STL containers of internal types.

View File

@ -22,10 +22,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <parser-library/parse.h>
@ -64,28 +64,28 @@ int printRelocs(void *N, VA relocAddr, reloc_type type) {
std::cout << "TYPE: ";
switch (type) {
case ABSOLUTE:
case RELOC_ABSOLUTE:
std::cout << "ABSOLUTE";
break;
case HIGH:
case RELOC_HIGH:
std::cout << "HIGH";
break;
case LOW:
case RELOC_LOW:
std::cout << "LOW";
break;
case HIGHLOW:
case RELOC_HIGHLOW:
std::cout << "HIGHLOW";
break;
case HIGHADJ:
case RELOC_HIGHADJ:
std::cout << "HIGHADJ";
break;
case MIPS_JMPADDR:
case RELOC_MIPS_JMPADDR:
std::cout << "MIPS_JMPADDR";
break;
case MIPS_JMPADDR16:
case RELOC_MIPS_JMPADDR16:
std::cout << "MIPS_JMPADD16";
break;
case DIR64:
case RELOC_DIR64:
std::cout << "DIR64";
break;
default:
@ -229,11 +229,12 @@ int printSymbols(void *N,
int printRich(void *N, rich_entry r) {
static_cast<void>(N);
std::cout << std::dec;
std::cout << std::setw(10) << "ProdId:" << std::setw(7) << r.ProductId;
std::cout << std::setw(10) << "Build:" << std::setw(7) << r.BuildNumber;
std::cout << std::setw(10) << "Name:"
<< std::setw(20) << GetRichProductName(r.ProductId, r.BuildNumber);
std::cout << std::setw(10) << "Name:" << std::setw(40)
<< GetRichProductName(r.BuildNumber) << " "
<< GetRichObjectType(r.ProductId);
std::cout << std::setw(10) << "Count:" << std::setw(7) << r.Count << "\n";
return 0;
}
@ -275,18 +276,20 @@ int printSecs(void *N,
if (data)
std::cout << "Sec Size: " << std::dec << data->bufLen << "\n";
else
std::cout << "Sec Size: 0" << "\n";
std::cout << "Sec Size: 0"
<< "\n";
return 0;
}
#define DUMP_FIELD(x) \
std::cout << "" #x << ": 0x"; \
std::cout << std::hex << static_cast<std::uint64_t>(p->peHeader.nt.x) \
<< "\n";
#define DUMP_DEC_FIELD(x) \
std::cout << "" #x << ": "; \
std::cout << std::dec << static_cast<std::uint64_t>(p->peHeader.nt.x) \
<< "\n";
#define DUMP_FIELD(x) \
std::cout << "" #x << ": 0x"; \
std::cout << std::hex << static_cast<std::uint64_t>(p->peHeader.x) << "\n";
#define DUMP_DEC_FIELD(x) \
std::cout << "" #x << ": "; \
std::cout << std::dec << static_cast<std::uint64_t>(p->peHeader.x) << "\n";
#define DUMP_BOOL_FIELD(x) \
std::cout << "" #x << ": "; \
std::cout << std::boolalpha << static_cast<bool>(p->peHeader.x) << "\n";
int main(int argc, char *argv[]) {
if (argc != 2 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
@ -297,99 +300,142 @@ int main(int argc, char *argv[]) {
}
parsed_pe *p = ParsePEFromFile(argv[1]);
if (p == nullptr) {
std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
<< "\n";
std::cout << "Location: " << GetPEErrLoc() << "\n";
return 1;
}
if (p != NULL) {
// Print DOS header
DUMP_FIELD(dos.e_magic);
DUMP_FIELD(dos.e_cp);
DUMP_FIELD(dos.e_crlc);
DUMP_FIELD(dos.e_cparhdr);
DUMP_FIELD(dos.e_minalloc);
DUMP_FIELD(dos.e_maxalloc);
DUMP_FIELD(dos.e_ss);
DUMP_FIELD(dos.e_sp);
DUMP_FIELD(dos.e_csum);
DUMP_FIELD(dos.e_ip);
DUMP_FIELD(dos.e_cs);
DUMP_FIELD(dos.e_lfarlc);
DUMP_FIELD(dos.e_ovno);
DUMP_FIELD(dos.e_res[0]);
DUMP_FIELD(dos.e_res[1]);
DUMP_FIELD(dos.e_res[2]);
DUMP_FIELD(dos.e_res[3]);
DUMP_FIELD(dos.e_oemid);
DUMP_FIELD(dos.e_oeminfo);
DUMP_FIELD(dos.e_res2[0]);
DUMP_FIELD(dos.e_res2[1]);
DUMP_FIELD(dos.e_res2[2]);
DUMP_FIELD(dos.e_res2[3]);
DUMP_FIELD(dos.e_res2[4]);
DUMP_FIELD(dos.e_res2[5]);
DUMP_FIELD(dos.e_res2[6]);
DUMP_FIELD(dos.e_res2[7]);
DUMP_FIELD(dos.e_res2[8]);
DUMP_FIELD(dos.e_res2[9]);
DUMP_FIELD(dos.e_lfanew);
// Print Rich header info
if(p->peHeader.rich.isPresent) {
std::cout << "Rich header: present\n";
DUMP_BOOL_FIELD(rich.isPresent);
if (p->peHeader.rich.isPresent) {
DUMP_FIELD(rich.DecryptionKey);
DUMP_FIELD(rich.Checksum);
DUMP_BOOL_FIELD(rich.isValid);
IterRich(p, printRich, NULL);
} else {
std::cout << "Rich header: not present\n";
}
// 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);
DUMP_FIELD(nt.Signature);
DUMP_FIELD(nt.FileHeader.Machine);
DUMP_FIELD(nt.FileHeader.NumberOfSections);
DUMP_DEC_FIELD(nt.FileHeader.TimeDateStamp);
DUMP_FIELD(nt.FileHeader.PointerToSymbolTable);
DUMP_DEC_FIELD(nt.FileHeader.NumberOfSymbols);
DUMP_FIELD(nt.FileHeader.SizeOfOptionalHeader);
DUMP_FIELD(nt.FileHeader.Characteristics);
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);
DUMP_FIELD(nt.OptionalHeader.Magic);
DUMP_DEC_FIELD(nt.OptionalHeader.MajorLinkerVersion);
DUMP_DEC_FIELD(nt.OptionalHeader.MinorLinkerVersion);
DUMP_FIELD(nt.OptionalHeader.SizeOfCode);
DUMP_FIELD(nt.OptionalHeader.SizeOfInitializedData);
DUMP_FIELD(nt.OptionalHeader.SizeOfUninitializedData);
DUMP_FIELD(nt.OptionalHeader.AddressOfEntryPoint);
DUMP_FIELD(nt.OptionalHeader.BaseOfCode);
DUMP_FIELD(nt.OptionalHeader.BaseOfData);
DUMP_FIELD(nt.OptionalHeader.ImageBase);
DUMP_FIELD(nt.OptionalHeader.SectionAlignment);
DUMP_FIELD(nt.OptionalHeader.FileAlignment);
DUMP_DEC_FIELD(nt.OptionalHeader.MajorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader.MinorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader.Win32VersionValue);
DUMP_FIELD(nt.OptionalHeader.SizeOfImage);
DUMP_FIELD(nt.OptionalHeader.SizeOfHeaders);
DUMP_FIELD(nt.OptionalHeader.CheckSum);
DUMP_FIELD(nt.OptionalHeader.Subsystem);
DUMP_FIELD(nt.OptionalHeader.DllCharacteristics);
DUMP_FIELD(nt.OptionalHeader.SizeOfStackReserve);
DUMP_FIELD(nt.OptionalHeader.SizeOfStackCommit);
DUMP_FIELD(nt.OptionalHeader.SizeOfHeapReserve);
DUMP_FIELD(nt.OptionalHeader.SizeOfHeapCommit);
DUMP_FIELD(nt.OptionalHeader.LoaderFlags);
DUMP_DEC_FIELD(nt.OptionalHeader.NumberOfRvaAndSizes);
} 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);
DUMP_FIELD(nt.OptionalHeader64.Magic);
DUMP_DEC_FIELD(nt.OptionalHeader64.MajorLinkerVersion);
DUMP_DEC_FIELD(nt.OptionalHeader64.MinorLinkerVersion);
DUMP_FIELD(nt.OptionalHeader64.SizeOfCode);
DUMP_FIELD(nt.OptionalHeader64.SizeOfInitializedData);
DUMP_FIELD(nt.OptionalHeader64.SizeOfUninitializedData);
DUMP_FIELD(nt.OptionalHeader64.AddressOfEntryPoint);
DUMP_FIELD(nt.OptionalHeader64.BaseOfCode);
DUMP_FIELD(nt.OptionalHeader64.ImageBase);
DUMP_FIELD(nt.OptionalHeader64.SectionAlignment);
DUMP_FIELD(nt.OptionalHeader64.FileAlignment);
DUMP_DEC_FIELD(nt.OptionalHeader64.MajorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader64.MinorOperatingSystemVersion);
DUMP_DEC_FIELD(nt.OptionalHeader64.Win32VersionValue);
DUMP_FIELD(nt.OptionalHeader64.SizeOfImage);
DUMP_FIELD(nt.OptionalHeader64.SizeOfHeaders);
DUMP_FIELD(nt.OptionalHeader64.CheckSum);
DUMP_FIELD(nt.OptionalHeader64.Subsystem);
DUMP_FIELD(nt.OptionalHeader64.DllCharacteristics);
DUMP_FIELD(nt.OptionalHeader64.SizeOfStackReserve);
DUMP_FIELD(nt.OptionalHeader64.SizeOfStackCommit);
DUMP_FIELD(nt.OptionalHeader64.SizeOfHeapReserve);
DUMP_FIELD(nt.OptionalHeader64.SizeOfHeapCommit);
DUMP_FIELD(nt.OptionalHeader64.LoaderFlags);
DUMP_DEC_FIELD(nt.OptionalHeader64.NumberOfRvaAndSizes);
}
#undef DUMP_FIELD
#undef DUMP_DEC_FIELD
std::cout << "Imports: " << "\n";
std::cout << "Imports: "
<< "\n";
IterImpVAString(p, printImports, NULL);
std::cout << "Relocations: " << "\n";
std::cout << "Relocations: "
<< "\n";
IterRelocs(p, printRelocs, NULL);
std::cout << "Symbols (symbol table): " << "\n";
std::cout << "Symbols (symbol table): "
<< "\n";
IterSymbols(p, printSymbols, NULL);
std::cout << "Sections: " << "\n";
std::cout << "Sections: "
<< "\n";
IterSec(p, printSecs, NULL);
std::cout << "Exports: " << "\n";
std::cout << "Exports: "
<< "\n";
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";
std::cout << std::hex << entryPoint << "):" << "\n";
std::cout << std::hex << entryPoint << "):"
<< "\n";
for (std::size_t i = 0; i < 8; i++) {
std::uint8_t b;
if (!ReadByteAtVA(p, i + entryPoint, b)) {
@ -402,14 +448,12 @@ int main(int argc, char *argv[]) {
std::cout << "\n";
}
std::cout << "Resources: " << "\n";
IterRsrc(p, printRsrc, NULL);
DestructParsedPE(p);
} else {
std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
std::cout << "Resources: "
<< "\n";
std::cout << "Location: " << GetPEErrLoc() << "\n";
}
IterRsrc(p, printRsrc, NULL);
return 0;
DestructParsedPE(p);
return 0;
}
}

View File

@ -1,7 +0,0 @@
dump_prog = executable(
'dump-prog',
'dump.cpp',
include_directories : [ incdirs ],
install : true,
install_dir : join_paths(get_option('datadir'), 'pe-parse/examples'),
link_with : pe_parser_library)

View File

@ -1,7 +1,7 @@
#include <algorithm>
#include <iostream>
#include <limits>
#include <memory>
#include <algorithm>
#include <climits>
#include <cstring>
@ -262,7 +262,8 @@ int main(int argc, char *argv[]) {
char *last_parsed_char = nullptr;
errno = 0;
std::uint64_t address = std::strtoull(address_as_string, &last_parsed_char, 16);
std::uint64_t 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;

View File

@ -1,8 +0,0 @@
project('pe-parse',
'cpp',
default_options : [ 'cpp_std=c++11' ],
license : [ 'MIT' ],
)
subdir('parser-library')
subdir('dump-prog')

View File

@ -1,11 +0,0 @@
incdirs = include_directories('.')
parser_source = [
'buffer.cpp',
'parse.cpp'
]
pe_parser_library = library('pe-parser-library',
sources : parser_source,
install : true
)
install_headers('parse.h', subdir : 'pe-parse')

View File

@ -1,4 +1,8 @@
find_path(PEPARSE_INCLUDE_DIR $<SHELL_PATH:"parser-library/parse.h">)
if(CMAKE_CROSSCOMPILING)
find_path(PEPARSE_INCLUDE_DIR "parser-library/parse.h")
else()
find_path(PEPARSE_INCLUDE_DIR $<SHELL_PATH:"parser-library/parse.h">)
endif()
find_library(PEPARSE_LIBRARIES NAMES "libpe-parser-library" "pe-parser-library")
include(FindPackageHandleStandardArgs)

View File

@ -47,22 +47,8 @@ constexpr std::uint16_t NT_OPTIONAL_32_MAGIC = 0x10B;
constexpr std::uint16_t NT_OPTIONAL_64_MAGIC = 0x20B;
constexpr std::uint16_t NT_SHORT_NAME_LEN = 8;
constexpr std::uint16_t SYMTAB_RECORD_LEN = 18;
constexpr std::uint16_t DIR_EXPORT = 0;
constexpr std::uint16_t DIR_IMPORT = 1;
constexpr std::uint16_t DIR_RESOURCE = 2;
constexpr std::uint16_t DIR_EXCEPTION = 3;
constexpr std::uint16_t DIR_SECURITY = 4;
constexpr std::uint16_t DIR_BASERELOC = 5;
constexpr std::uint16_t DIR_DEBUG = 6;
constexpr std::uint16_t DIR_ARCHITECTURE = 7;
constexpr std::uint16_t DIR_GLOBALPTR = 8;
constexpr std::uint16_t DIR_TLS = 9;
constexpr std::uint16_t DIR_LOAD_CONFIG = 10;
constexpr std::uint16_t DIR_BOUND_IMPORT = 11;
constexpr std::uint16_t DIR_IAT = 12;
constexpr std::uint16_t DIR_DELAY_IMPORT = 13;
constexpr std::uint16_t DIR_COM_DESCRIPTOR = 14;
#ifndef _PEPARSE_WINDOWS_CONFLICTS
// Machine Types
constexpr std::uint16_t IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
constexpr std::uint16_t IMAGE_FILE_MACHINE_ALPHA = 0x1d3; // Alpha_AXP
@ -224,6 +210,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;
#endif
// clang-format on
struct dos_header {
@ -263,6 +250,25 @@ struct data_directory {
std::uint32_t Size;
};
enum data_directory_kind {
DIR_EXPORT = 0,
DIR_IMPORT = 1,
DIR_RESOURCE = 2,
DIR_EXCEPTION = 3,
DIR_SECURITY = 4,
DIR_BASERELOC = 5,
DIR_DEBUG = 6,
DIR_ARCHITECTURE = 7,
DIR_GLOBALPTR = 8,
DIR_TLS = 9,
DIR_LOAD_CONFIG = 10,
DIR_BOUND_IMPORT = 11,
DIR_IAT = 12,
DIR_DELAY_IMPORT = 13,
DIR_COM_DESCRIPTOR = 14,
DIR_RESERVED = 15,
};
struct optional_header_32 {
std::uint16_t Magic;
std::uint8_t MajorLinkerVersion;
@ -353,7 +359,9 @@ struct rich_header {
std::vector<rich_entry> Entries;
std::uint32_t EndSignature;
std::uint32_t DecryptionKey;
std::uint32_t Checksum;
bool isPresent;
bool isValid;
};
/*
@ -436,19 +444,116 @@ struct export_dir_table {
};
enum reloc_type {
ABSOLUTE = 0,
HIGH = 1,
LOW = 2,
HIGHLOW = 3,
HIGHADJ = 4,
MIPS_JMPADDR = 5,
MIPS_JMPADDR16 = 9,
IA64_IMM64 = 9,
DIR64 = 10
RELOC_ABSOLUTE = 0,
RELOC_HIGH = 1,
RELOC_LOW = 2,
RELOC_HIGHLOW = 3,
RELOC_HIGHADJ = 4,
RELOC_MIPS_JMPADDR = 5,
RELOC_MIPS_JMPADDR16 = 9,
RELOC_IA64_IMM64 = 9,
RELOC_DIR64 = 10
};
struct reloc_block {
std::uint32_t PageRVA;
std::uint32_t BlockSize;
};
struct image_load_config_code_integrity {
std::uint16_t Flags;
std::uint16_t Catalog;
std::uint32_t CatalogOffset;
std::uint32_t Reserved;
};
struct image_load_config_32 {
std::uint32_t Size;
std::uint32_t TimeDateStamp;
std::uint16_t MajorVersion;
std::uint16_t MinorVersion;
std::uint32_t GlobalFlagsClear;
std::uint32_t GlobalFlagsSet;
std::uint32_t CriticalSectionDefaultTimeout;
std::uint32_t DeCommitFreeBlockThreshold;
std::uint32_t DeCommitTotalFreeThreshold;
std::uint32_t LockPrefixTable;
std::uint32_t MaximumAllocationSize;
std::uint32_t VirtualMemoryThreshold;
std::uint32_t ProcessHeapFlags;
std::uint32_t ProcessAffinityMask;
std::uint16_t CSDVersion;
std::uint16_t DependentLoadFlags;
std::uint32_t EditList;
std::uint32_t SecurityCookie;
std::uint32_t SEHandlerTable;
std::uint32_t SEHandlerCount;
std::uint32_t GuardCFCheckFunctionPointer;
std::uint32_t GuardCFDispatchFunctionPointer;
std::uint32_t GuardCFFunctionTable;
std::uint32_t GuardCFFunctionCount;
std::uint32_t GuardFlags;
image_load_config_code_integrity CodeIntegrity;
std::uint32_t GuardAddressTakenIatEntryTable;
std::uint32_t GuardAddressTakenIatEntryCount;
std::uint32_t GuardLongJumpTargetTable;
std::uint32_t GuardLongJumpTargetCount;
std::uint32_t DynamicValueRelocTable;
std::uint32_t CHPEMetadataPointer;
std::uint32_t GuardRFFailureRoutine;
std::uint32_t GuardRFFailureRoutineFunctionPointer;
std::uint32_t DynamicValueRelocTableOffset;
std::uint16_t DynamicValueRelocTableSection;
std::uint16_t Reserved2;
std::uint32_t GuardRFVerifyStackPointerFunctionPointer;
std::uint32_t HotPatchTableOffset;
std::uint32_t Reserved3;
std::uint32_t EnclaveConfigurationPointer;
std::uint32_t VolatileMetadataPointer;
};
struct image_load_config_64 {
std::uint32_t Size;
std::uint32_t TimeDateStamp;
std::uint16_t MajorVersion;
std::uint16_t MinorVersion;
std::uint32_t GlobalFlagsClear;
std::uint32_t GlobalFlagsSet;
std::uint32_t CriticalSectionDefaultTimeout;
std::uint64_t DeCommitFreeBlockThreshold;
std::uint64_t DeCommitTotalFreeThreshold;
std::uint64_t LockPrefixTable;
std::uint64_t MaximumAllocationSize;
std::uint64_t VirtualMemoryThreshold;
std::uint64_t ProcessAffinityMask;
std::uint32_t ProcessHeapFlags;
std::uint16_t CSDVersion;
std::uint16_t DependentLoadFlags;
std::uint64_t EditList;
std::uint64_t SecurityCookie;
std::uint64_t SEHandlerTable;
std::uint64_t SEHandlerCount;
std::uint64_t GuardCFCheckFunctionPointer;
std::uint64_t GuardCFDispatchFunctionPointer;
std::uint64_t GuardCFFunctionTable;
std::uint64_t GuardCFFunctionCount;
std::uint32_t GuardFlags;
image_load_config_code_integrity CodeIntegrity;
std::uint64_t GuardAddressTakenIatEntryTable;
std::uint64_t GuardAddressTakenIatEntryCount;
std::uint64_t GuardLongJumpTargetTable;
std::uint64_t GuardLongJumpTargetCount;
std::uint64_t DynamicValueRelocTable;
std::uint64_t CHPEMetadataPointer;
std::uint64_t GuardRFFailureRoutine;
std::uint64_t GuardRFFailureRoutineFunctionPointer;
std::uint32_t DynamicValueRelocTableOffset;
std::uint16_t DynamicValueRelocTableSection;
std::uint16_t Reserved2;
std::uint64_t GuardRFVerifyStackPointerFunctionPointer;
std::uint32_t HotPatchTableOffset;
std::uint32_t Reserved3;
std::uint64_t EnclaveConfigurationPointer;
std::uint64_t VolatileMetadataPointer;
};
} // namespace peparse

View File

@ -32,7 +32,7 @@ THE SOFTWARE.
#include "to_string.h"
#ifdef _MSC_VER
#define __typeof__(x) std::remove_reference < decltype(x) > ::type
#define __typeof__(x) std::remove_reference < decltype(x)> ::type
#endif
#define PE_ERR(x) \
@ -99,6 +99,7 @@ struct resource {
bounded_buffer *buf;
};
#ifndef _PEPARSE_WINDOWS_CONFLICTS
// http://msdn.microsoft.com/en-us/library/ms648009(v=vs.85).aspx
enum resource_type {
RT_CURSOR = 1,
@ -123,6 +124,7 @@ enum resource_type {
RT_HTML = 23,
RT_MANIFEST = 24
};
#endif
enum pe_err {
PEERR_NONE = 0,
@ -137,6 +139,7 @@ enum pe_err {
PEERR_MAGIC = 9,
PEERR_BUFFER = 10,
PEERR_ADDRESS = 11,
PEERR_SIZE = 12,
};
bool readByte(bounded_buffer *b, std::uint32_t offset, std::uint8_t &out);
@ -154,6 +157,7 @@ uint64_t bufLen(bounded_buffer *b);
struct parsed_pe_internal;
typedef struct _pe_header {
dos_header dos;
rich_header rich;
nt_header_32 nt;
} pe_header;
@ -167,7 +171,8 @@ typedef struct _parsed_pe {
// Resolve a Rich header product id / build number pair to a known
// product name
typedef std::pair<std::uint16_t, std::uint16_t> ProductKey;
const std::string& GetRichProductName(std::uint16_t prodId, std::uint16_t buildNum);
const std::string &GetRichObjectType(std::uint16_t prodId);
const std::string &GetRichProductName(std::uint16_t buildNum);
// get parser error status as integer
std::uint32_t GetPEErr();
@ -230,4 +235,9 @@ const char *GetMachineAsString(parsed_pe *pe);
// get subsystem as human readable string
const char *GetSubsystemAsString(parsed_pe *pe);
// get a table or string by its data directory entry
bool GetDataDirectoryEntry(parsed_pe *pe,
data_directory_kind dirnum,
std::vector<std::uint8_t> &raw_entry);
} // namespace peparse

View File

@ -1,7 +1,7 @@
#pragma once
#include <string>
#include <sstream>
#include <string>
#ifdef USE_ICU4C
#include <unicode/unistr.h>

View File

@ -23,10 +23,11 @@ THE SOFTWARE.
*/
#include <algorithm>
#include <array>
#include <cstring>
#include <iostream>
#include <vector>
#include <stdexcept>
#include <vector>
#include <parser-library/nt-headers.h>
#include <parser-library/parse.h>
@ -122,18 +123,347 @@ struct parsed_pe_internal {
std::vector<symbol> symbols;
};
// The mapping of Rich header product id / build number pairs
// to strings
static const std::map<ProductKey, const std::string> ProductMap = {
{std::make_pair(1, 0), "Imported Functions"}
// String representation of Rich header object types
static const std::string kProdId_C = "[ C ]";
static const std::string kProdId_CPP = "[C++]";
static const std::string kProdId_RES = "[RES]";
static const std::string kProdId_IMP = "[IMP]";
static const std::string kProdId_EXP = "[EXP]";
static const std::string kProdId_ASM = "[ASM]";
static const std::string kProdId_LNK = "[LNK]";
static const std::string kProdId_UNK = "[ ? ]";
// Mapping of Rich header Product ID to object type string
// Source: https://github.com/dishather/richprint/blob/master/comp_id.txt
static const std::map<std::uint16_t, std::string> ProductIdMap = {
{std::make_pair(static_cast<std::uint16_t>(0x0000), kProdId_UNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0002), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x0004), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0006), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x000A), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x000B), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x000F), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0015), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0016), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x0019), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x001C), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x001D), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x003D), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x003F), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x0040), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0045), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x005A), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x005C), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x005D), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x005E), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x005F), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0060), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x006D), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x006E), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x0078), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x007A), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x007B), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x007C), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x007D), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0083), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0084), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x0091), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0092), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x0093), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x0094), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x0095), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x009A), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x009B), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x009C), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x009D), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x009E), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x00AA), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x00AB), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x00C9), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x00CA), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x00CB), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x00CC), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x00CD), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x00CE), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x00CF), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x00DB), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x00DC), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x00DD), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x00DE), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x00DF), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x00E0), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x00E1), kProdId_CPP)},
{std::make_pair(static_cast<std::uint16_t>(0x00FF), kProdId_RES)},
{std::make_pair(static_cast<std::uint16_t>(0x0100), kProdId_EXP)},
{std::make_pair(static_cast<std::uint16_t>(0x0101), kProdId_IMP)},
{std::make_pair(static_cast<std::uint16_t>(0x0102), kProdId_LNK)},
{std::make_pair(static_cast<std::uint16_t>(0x0103), kProdId_ASM)},
{std::make_pair(static_cast<std::uint16_t>(0x0104), kProdId_C)},
{std::make_pair(static_cast<std::uint16_t>(0x0105), kProdId_CPP)}};
// Mapping of Rich header build number to version strings
static const std::map<std::uint16_t, const std::string> ProductMap = {
// Source: https://github.com/dishather/richprint/blob/master/comp_id.txt
{std::make_pair(static_cast<std::uint16_t>(0x0000), "Imported Functions")},
{std::make_pair(static_cast<std::uint16_t>(0x0684),
"VS97 v5.0 SP3 cvtres 5.00.1668")},
{std::make_pair(static_cast<std::uint16_t>(0x06B8),
"VS98 v6.0 cvtres build 1720")},
{std::make_pair(static_cast<std::uint16_t>(0x06C8),
"VS98 v6.0 SP6 cvtres build 1736")},
{std::make_pair(static_cast<std::uint16_t>(0x1C87),
"VS97 v5.0 SP3 link 5.10.7303")},
{std::make_pair(static_cast<std::uint16_t>(0x5E92),
"VS2015 v14.0 UPD3 build 24210")},
{std::make_pair(static_cast<std::uint16_t>(0x5E95),
"VS2015 UPD3 build 24213")},
// http://bytepointer.com/articles/the_microsoft_rich_header.htm
{std::make_pair(static_cast<std::uint16_t>(0x0BEC),
"VS2003 v7.1 Free Toolkit .NET build 3052")},
{std::make_pair(static_cast<std::uint16_t>(0x0C05),
"VS2003 v7.1 .NET build 3077")},
{std::make_pair(static_cast<std::uint16_t>(0x0FC3),
"VS2003 v7.1 | Windows Server 2003 SP1 DDK build 4035")},
{std::make_pair(static_cast<std::uint16_t>(0x1C83), "MASM 6.13.7299")},
{std::make_pair(static_cast<std::uint16_t>(0x178E),
"VS2003 v7.1 SP1 .NET build 6030")},
{std::make_pair(static_cast<std::uint16_t>(0x1FE8),
"VS98 v6.0 RTM/SP1/SP2 build 8168")},
{std::make_pair(static_cast<std::uint16_t>(0x1FE9),
"VB 6.0/SP1/SP2 build 8169")},
{std::make_pair(static_cast<std::uint16_t>(0x20FC), "MASM 6.14.8444")},
{std::make_pair(static_cast<std::uint16_t>(0x20FF),
"VC++ 6.0 SP3 build 8447")},
{std::make_pair(static_cast<std::uint16_t>(0x212F),
"VB 6.0 SP3 build 8495")},
{std::make_pair(static_cast<std::uint16_t>(0x225F),
"VS 6.0 SP4 build 8799")},
{std::make_pair(static_cast<std::uint16_t>(0x2263), "MASM 6.15.8803")},
{std::make_pair(static_cast<std::uint16_t>(0x22AD),
"VB 6.0 SP4 build 8877")},
{std::make_pair(static_cast<std::uint16_t>(0x2304),
"VB 6.0 SP5 build 8964")},
{std::make_pair(static_cast<std::uint16_t>(0x2306),
"VS 6.0 SP5 build 8966")},
// {std::make_pair(static_cast<std::uint16_t>(0x2346), "MASM 6.15.9030
// (VS.NET 7.0 BETA 1)")},
{std::make_pair(static_cast<std::uint16_t>(0x2346),
"VS 7.0 2000 Beta 1 build 9030")},
{std::make_pair(static_cast<std::uint16_t>(0x2354),
"VS 6.0 SP5 Processor Pack build 9044")},
{std::make_pair(static_cast<std::uint16_t>(0x2426),
"VS2001 v7.0 Beta 2 build 9254")},
{std::make_pair(static_cast<std::uint16_t>(0x24FA),
"VS2002 v7.0 .NET build 9466")},
{std::make_pair(static_cast<std::uint16_t>(0x2636),
"VB 6.0 SP6 / VC++ build 9782")},
{std::make_pair(static_cast<std::uint16_t>(0x26E3),
"VS2002 v7.0 SP1 build 9955")},
{std::make_pair(static_cast<std::uint16_t>(0x520D),
"VS2013 v12.[0,1] build 21005")},
{std::make_pair(static_cast<std::uint16_t>(0x521E),
"VS2008 v9.0 build 21022")},
{std::make_pair(static_cast<std::uint16_t>(0x56C7),
"VS2015 v14.0 build 22215")},
{std::make_pair(static_cast<std::uint16_t>(0x59F2),
"VS2015 v14.0 build 23026")},
{std::make_pair(static_cast<std::uint16_t>(0x5BD2),
"VS2015 v14.0 UPD1 build 23506")},
{std::make_pair(static_cast<std::uint16_t>(0x5D10),
"VS2015 v14.0 UPD2 build 23824")},
{std::make_pair(static_cast<std::uint16_t>(0x5E97),
"VS2015 v14.0 UPD3.1 build 24215")},
{std::make_pair(static_cast<std::uint16_t>(0x7725),
"VS2013 v12.0 UPD2 build 30501")},
{std::make_pair(static_cast<std::uint16_t>(0x766F),
"VS2010 v10.0 build 30319")},
{std::make_pair(static_cast<std::uint16_t>(0x7809),
"VS2008 v9.0 SP1 build 30729")},
{std::make_pair(static_cast<std::uint16_t>(0x797D),
"VS2013 v12.0 UPD4 build 31101")},
{std::make_pair(static_cast<std::uint16_t>(0x9D1B),
"VS2010 v10.0 SP1 build 40219")},
{std::make_pair(static_cast<std::uint16_t>(0x9EB5),
"VS2013 v12.0 UPD5 build 40629")},
{std::make_pair(static_cast<std::uint16_t>(0xC497),
"VS2005 v8.0 (Beta) build 50327")},
{std::make_pair(static_cast<std::uint16_t>(0xC627),
"VS2005 v8.0 | VS2012 v11.0 build 50727")},
{std::make_pair(static_cast<std::uint16_t>(0xC751),
"VS2012 v11.0 Nov CTP build 51025")},
{std::make_pair(static_cast<std::uint16_t>(0xC7A2),
"VS2012 v11.0 UPD1 build 51106")},
{std::make_pair(static_cast<std::uint16_t>(0xEB9B),
"VS2012 v11.0 UPD2 build 60315")},
{std::make_pair(static_cast<std::uint16_t>(0xECC2),
"VS2012 v11.0 UPD3 build 60610")},
{std::make_pair(static_cast<std::uint16_t>(0xEE66),
"VS2012 v11.0 UPD4 build 61030")},
{std::make_pair(static_cast<std::uint16_t>(0x5E9A),
"VS2015 v14.0 build 24218")},
{std::make_pair(static_cast<std::uint16_t>(0x61BB),
"VS2017 v14.1 build 25019")},
// https://dev.to/yumetodo/list-of-mscver-and-mscfullver-8nd
{std::make_pair(static_cast<std::uint16_t>(0x2264),
"VS 6 [SP5,SP6] build 8804")},
{std::make_pair(static_cast<std::uint16_t>(0x23D8), "Windows XP SP1 DDK")},
{std::make_pair(static_cast<std::uint16_t>(0x0883),
"Windows Server 2003 DDK")},
{std::make_pair(static_cast<std::uint16_t>(0x08F4),
"VS2003 v7.1 .NET Beta build 2292")},
{std::make_pair(static_cast<std::uint16_t>(0x9D76),
"Windows Server 2003 SP1 DDK (for AMD64)")},
{std::make_pair(static_cast<std::uint16_t>(0x9E9F),
"VS2005 v8.0 Beta 1 build 40607")},
{std::make_pair(static_cast<std::uint16_t>(0xC427),
"VS2005 v8.0 Beta 2 build 50215")},
{std::make_pair(static_cast<std::uint16_t>(0xC490),
"VS2005 v8.0 build 50320")},
{std::make_pair(static_cast<std::uint16_t>(0x50E2),
"VS2008 v9.0 Beta 2 build 20706")},
{std::make_pair(static_cast<std::uint16_t>(0x501A),
"VS2010 v10.0 Beta 1 build 20506")},
{std::make_pair(static_cast<std::uint16_t>(0x520B),
"VS2010 v10.0 Beta 2 build 21003")},
{std::make_pair(static_cast<std::uint16_t>(0x5089),
"VS2013 v12.0 Preview build 20617")},
{std::make_pair(static_cast<std::uint16_t>(0x515B),
"VS2013 v12.0 RC build 20827")},
{std::make_pair(static_cast<std::uint16_t>(0x527A),
"VS2013 v12.0 Nov CTP build 21114")},
{std::make_pair(static_cast<std::uint16_t>(0x63A3),
"VS2017 v15.3.3 build 25507")},
{std::make_pair(static_cast<std::uint16_t>(0x63C6),
"VS2017 v15.4.4 build 25542")},
{std::make_pair(static_cast<std::uint16_t>(0x63CB),
"VS2017 v15.4.5 build 25547")},
{std::make_pair(static_cast<std::uint16_t>(0x7674),
"VS2013 v12.0 UPD2 RC build 30324")},
// https://walbourn.github.io/visual-studio-2015-update-2/
{std::make_pair(static_cast<std::uint16_t>(0x5D6E),
"VS2015 v14.0 UPD2 build 23918")},
// https://walbourn.github.io/visual-studio-2017/
{std::make_pair(static_cast<std::uint16_t>(0x61B9),
"VS2017 v15.[0,1] build 25017")},
{std::make_pair(static_cast<std::uint16_t>(0x63A2),
"VS2017 v15.2 build 25019")},
// https://walbourn.github.io/vs-2017-15-5-update/
{std::make_pair(static_cast<std::uint16_t>(0x64E6),
"VS2017 v15 build 25830")},
{std::make_pair(static_cast<std::uint16_t>(0x64E7),
"VS2017 v15.5.2 build 25831")},
{std::make_pair(static_cast<std::uint16_t>(0x64EA),
"VS2017 v15.5.[3,4] build 25834")},
{std::make_pair(static_cast<std::uint16_t>(0x64EB),
"VS2017 v15.5.[5,6,7] build 25835")},
// https://walbourn.github.io/vs-2017-15-6-update/
{std::make_pair(static_cast<std::uint16_t>(0x6610),
"VS2017 v15.6.[0,1,2] build 26128")},
{std::make_pair(static_cast<std::uint16_t>(0x6611),
"VS2017 v15.6.[3,4] build 26129")},
{std::make_pair(static_cast<std::uint16_t>(0x6613),
"VS2017 v15.6.6 build 26131")},
{std::make_pair(static_cast<std::uint16_t>(0x6614),
"VS2017 v15.6.7 build 26132")},
// https://devblogs.microsoft.com/visualstudio/visual-studio-2017-update/
{std::make_pair(static_cast<std::uint16_t>(0x6723),
"VS2017 v15.1 build 26403")},
// https://walbourn.github.io/vs-2017-15-7-update/
{std::make_pair(static_cast<std::uint16_t>(0x673C),
"VS2017 v15.7.[0,1] build 26428")},
{std::make_pair(static_cast<std::uint16_t>(0x673D),
"VS2017 v15.7.2 build 26429")},
{std::make_pair(static_cast<std::uint16_t>(0x673E),
"VS2017 v15.7.3 build 26430")},
{std::make_pair(static_cast<std::uint16_t>(0x673F),
"VS2017 v15.7.4 build 26431")},
{std::make_pair(static_cast<std::uint16_t>(0x6741),
"VS2017 v15.7.5 build 26433")},
// https://walbourn.github.io/visual-studio-2019/
{std::make_pair(static_cast<std::uint16_t>(0x6B74),
"VS2019 v16.0.0 build 27508")},
// https://walbourn.github.io/vs-2017-15-8-update/
{std::make_pair(static_cast<std::uint16_t>(0x6866),
"VS2017 v15.8.0 build 26726")},
{std::make_pair(static_cast<std::uint16_t>(0x6869),
"VS2017 v15.8.4 build 26729")},
{std::make_pair(static_cast<std::uint16_t>(0x686A),
"VS2017 v15.8.9 build 26730")},
{std::make_pair(static_cast<std::uint16_t>(0x686C),
"VS2017 v15.8.5 build 26732")},
// https://walbourn.github.io/vs-2017-15-9-update/
{std::make_pair(static_cast<std::uint16_t>(0x698F),
"VS2017 v15.9.[0,1] build 27023")},
{std::make_pair(static_cast<std::uint16_t>(0x6990),
"VS2017 v15.9.2 build 27024")},
{std::make_pair(static_cast<std::uint16_t>(0x6991),
"VS2017 v15.9.4 build 27025")},
{std::make_pair(static_cast<std::uint16_t>(0x6992),
"VS2017 v15.9.5 build 27026")},
{std::make_pair(static_cast<std::uint16_t>(0x6993),
"VS2017 v15.9.7 build 27027")},
{std::make_pair(static_cast<std::uint16_t>(0x6996),
"VS2017 v15.9.11 build 27030")},
{std::make_pair(static_cast<std::uint16_t>(0x6997),
"VS2017 v15.9.12 build 27031")},
{std::make_pair(static_cast<std::uint16_t>(0x6998),
"VS2017 v15.9.14 build 27032")},
{std::make_pair(static_cast<std::uint16_t>(0x699A),
"VS2017 v15.9.16 build 27034")},
// https://walbourn.github.io/visual-studio-2019/
{std::make_pair(static_cast<std::uint16_t>(0x6B74),
"VS2019 v16.0.0 RTM build 27508")},
// https://walbourn.github.io/vs-2019-update-1/
{std::make_pair(static_cast<std::uint16_t>(0x6C36),
"VS2019 v16.1.2 UPD1 build 27702")},
// https://walbourn.github.io/vs-2019-update-2/
{std::make_pair(static_cast<std::uint16_t>(0x6D01),
"VS2019 v16.2.3 UPD2 build 27905")},
// https://walbourn.github.io/vs-2019-update-3/
{std::make_pair(static_cast<std::uint16_t>(0x6DC9),
"VS2019 v16.3.2 UPD3 build 28105")},
// https://walbourn.github.io/visual-studio-2013-update-3/
{std::make_pair(static_cast<std::uint16_t>(0x7803),
"VS2013 v12.0 UPD3 build 30723")},
// experimentation
{std::make_pair(static_cast<std::uint16_t>(0x685B),
"VS2017 v15.8.? build 26715")},
};
static const std::string kUnknownProduct = "<unknown>";
// Resolve a Rich header product id / build number pair to a known
// product name
const std::string& GetRichProductName(std::uint16_t prodId, std::uint16_t buildNum) {
auto it = ProductMap.find(std::make_pair(prodId, buildNum));
// Returns a stringified Rich header object type given a product id
const std::string &GetRichObjectType(std::uint16_t prodId) {
auto it = ProductIdMap.find(prodId);
if (it != ProductIdMap.end()) {
return it->second;
} else {
return kProdId_UNK;
}
}
// Returns a stringified Rich header product name given a build number
const std::string &GetRichProductName(std::uint16_t buildNum) {
auto it = ProductMap.find(buildNum);
if (it != ProductMap.end()) {
return it->second;
} else {
@ -144,18 +474,21 @@ const std::string& GetRichProductName(std::uint16_t prodId, std::uint16_t buildN
std::uint32_t err = 0;
std::string err_loc;
static const char *pe_err_str[] = {"None",
"Out of memory",
"Invalid header",
"Invalid section",
"Invalid resource",
"Unable to get section for VA",
"Unable to read data",
"Unable to open",
"Unable to stat",
"Bad magic",
"Invalid buffer",
"Invalid address",};
static const char *pe_err_str[] = {
"None",
"Out of memory",
"Invalid header",
"Invalid section",
"Invalid resource",
"Unable to get section for VA",
"Unable to read data",
"Unable to open",
"Unable to stat",
"Bad magic",
"Invalid buffer",
"Invalid address",
"Invalid size",
};
std::uint32_t GetPEErr() {
return err;
@ -230,8 +563,9 @@ const char *GetSymbolTableStorageClassName(std::uint8_t id) {
}
}
static bool
readCString(const bounded_buffer &buffer, std::uint32_t off, std::string &result) {
static bool readCString(const bounded_buffer &buffer,
std::uint32_t off,
std::string &result) {
if (off < buffer.bufLen) {
std::uint8_t *p = buffer.buf;
std::uint32_t n = buffer.bufLen;
@ -282,7 +616,9 @@ void IterRsrc(parsed_pe *pe, iterRsrc cb, void *cbd) {
return;
}
bool parse_resource_id(bounded_buffer *data, std::uint32_t id, std::string &result) {
bool parse_resource_id(bounded_buffer *data,
std::uint32_t id,
std::string &result) {
std::uint16_t len;
if (!readWord(data, id, len)) {
return false;
@ -388,9 +724,10 @@ bool parse_resource_table(bounded_buffer *sectionData,
}
}
} else {
/* .rsrc can accomodate up to 2**31 levels, but Windows only uses 3 by convention.
* As such, any depth above 3 indicates potentially unchecked recusion.
* See: https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-rsrc-section
/* .rsrc can accomodate up to 2**31 levels, but Windows only uses 3 by
* convention. As such, any depth above 3 indicates potentially unchecked
* recusion. See:
* https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-rsrc-section
*/
PE_ERR(PEERR_RESC);
@ -575,7 +912,8 @@ bool getSections(bounded_buffer *b,
// now we have the section header information, so fill in a section
// object appropriately
section thisSec;
for (std::uint32_t charIndex = 0; charIndex < NT_SHORT_NAME_LEN; charIndex++) {
for (std::uint32_t charIndex = 0; charIndex < NT_SHORT_NAME_LEN;
charIndex++) {
std::uint8_t c = curSec.Name[charIndex];
if (c == 0) {
break;
@ -825,7 +1163,44 @@ bool readNtHeader(bounded_buffer *b, nt_header_32 &header) {
return true;
}
bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &rich_hdr) {
// zero extends its first argument to 32 bits and then performs a rotate left
// operation equal to the second arguments value of the first arguments bits
static inline std::uint32_t rol(std::uint32_t val, std::uint32_t num) {
return ((val << num) & 0xffffffff) | (val >> (32 - num));
}
std::uint32_t calculateRichChecksum(const bounded_buffer *b, pe_header &p) {
// First, calculate the sum of the DOS header bytes each rotated left the
// number of times their position relative to the start of the DOS header e.g.
// second byte is rotated left 2x using rol operation
std::uint32_t checksum = 0;
for (uint8_t i = 0; i < RICH_OFFSET; i++) {
// skip over dos e_lfanew field at offset 0x3C
if (i >= 0x3C && i <= 0x3F) {
continue;
}
checksum += rol(b->buf[i], i);
}
// Next, take summation of each Rich header entry by combining its ProductId
// and BuildNumber into a single 32 bit number and rotating by its count.
for (rich_entry entry : p.rich.Entries) {
std::uint32_t num =
static_cast<std::uint32_t>((entry.ProductId << 16) | entry.BuildNumber);
checksum += rol(num, entry.Count & 0x1F);
}
checksum += RICH_OFFSET;
return checksum;
}
bool readRichHeader(bounded_buffer *rich_buf,
std::uint32_t key,
rich_header &rich_hdr) {
if (rich_buf == nullptr) {
return false;
}
@ -837,8 +1212,8 @@ bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &ri
// The first decrypted DWORD value of the rich header
// at offset 0 should be 0x536e6144 aka the "DanS" signature
if (!readDword(rich_buf, 0, encrypted_dword)) {
PE_ERR(PEERR_READ);
return false;
PE_ERR(PEERR_READ);
return false;
}
decrypted_dword = encrypted_dword ^ key;
@ -859,7 +1234,7 @@ bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &ri
// a DWORD is 4 bytes. Loop is incrementing 8 bytes, however
// we are reading two DWORDS at a time, which is the size
// of one rich header entry.
for (std::uint32_t i = 16; i < rich_buf->bufLen-8; i += 8) {
for (std::uint32_t i = 16; i < rich_buf->bufLen - 8; i += 8) {
rich_entry entry;
// Read first DWORD of entry and decrypt it
if (!readDword(rich_buf, i, encrypted_dword)) {
@ -873,7 +1248,7 @@ bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &ri
entry.BuildNumber = (decrypted_dword & 0xFFFF);
// The second DWORD represents the use count
if (!readDword(rich_buf, i+4, encrypted_dword)) {
if (!readDword(rich_buf, i + 4, encrypted_dword)) {
PE_ERR(PEERR_READ);
return false;
}
@ -883,13 +1258,12 @@ bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &ri
// Preserve the individual entry
rich_hdr.Entries.push_back(entry);
}
// Preserve the end signature aka "Rich" magic
if (!readDword(rich_buf, rich_buf->bufLen-4, rich_hdr.EndSignature)) {
PE_ERR(PEERR_READ);
return false;
if (!readDword(rich_buf, rich_buf->bufLen - 4, rich_hdr.EndSignature)) {
PE_ERR(PEERR_READ);
return false;
};
if (rich_hdr.EndSignature != RICH_MAGIC_END) {
PE_ERR(PEERR_MAGIC);
@ -897,7 +1271,47 @@ bool readRichHeader(bounded_buffer *rich_buf, std::uint32_t key, rich_header &ri
}
// Preserve the decryption key
rich_hdr.DecryptionKey = key;
rich_hdr.DecryptionKey = key;
return true;
}
bool readDosHeader(bounded_buffer *file, dos_header &dos_hdr) {
if (file == nullptr) {
return false;
}
READ_WORD(file, 0, dos_hdr, e_magic);
READ_WORD(file, 0, dos_hdr, e_cblp);
READ_WORD(file, 0, dos_hdr, e_cp);
READ_WORD(file, 0, dos_hdr, e_crlc);
READ_WORD(file, 0, dos_hdr, e_cparhdr);
READ_WORD(file, 0, dos_hdr, e_minalloc);
READ_WORD(file, 0, dos_hdr, e_maxalloc);
READ_WORD(file, 0, dos_hdr, e_ss);
READ_WORD(file, 0, dos_hdr, e_sp);
READ_WORD(file, 0, dos_hdr, e_csum);
READ_WORD(file, 0, dos_hdr, e_ip);
READ_WORD(file, 0, dos_hdr, e_cs);
READ_WORD(file, 0, dos_hdr, e_lfarlc);
READ_WORD(file, 0, dos_hdr, e_ovno);
READ_WORD(file, 0, dos_hdr, e_res[0]);
READ_WORD(file, 0, dos_hdr, e_res[1]);
READ_WORD(file, 0, dos_hdr, e_res[2]);
READ_WORD(file, 0, dos_hdr, e_res[3]);
READ_WORD(file, 0, dos_hdr, e_oemid);
READ_WORD(file, 0, dos_hdr, e_oeminfo);
READ_WORD(file, 0, dos_hdr, e_res2[0]);
READ_WORD(file, 0, dos_hdr, e_res2[1]);
READ_WORD(file, 0, dos_hdr, e_res2[2]);
READ_WORD(file, 0, dos_hdr, e_res2[3]);
READ_WORD(file, 0, dos_hdr, e_res2[4]);
READ_WORD(file, 0, dos_hdr, e_res2[5]);
READ_WORD(file, 0, dos_hdr, e_res2[6]);
READ_WORD(file, 0, dos_hdr, e_res2[7]);
READ_WORD(file, 0, dos_hdr, e_res2[8]);
READ_WORD(file, 0, dos_hdr, e_res2[9]);
READ_DWORD(file, 0, dos_hdr, e_lfanew);
return true;
}
@ -907,29 +1321,21 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
return false;
}
// start by reading MZ
std::uint16_t tmp = 0;
std::uint32_t curOffset = 0;
if (!readWord(file, curOffset, tmp)) {
PE_ERR(PEERR_READ);
return false;
}
if (tmp != MZ_MAGIC) {
// read the DOS header
readDosHeader(file, p.dos);
if (p.dos.e_magic != MZ_MAGIC) {
PE_ERR(PEERR_MAGIC);
return false;
}
// read the offset to the NT headers
std::uint32_t offset;
if (!readDword(file, _offset(dos_header, e_lfanew), offset)) {
PE_ERR(PEERR_READ);
return false;
}
curOffset += offset;
// get the offset to the NT headers
std::uint32_t offset = p.dos.e_lfanew;
std::uint32_t curOffset = offset;
// read rich header
std::uint32_t dword;
std::uint32_t rich_end_signature_offset;
std::uint32_t rich_end_signature_offset = 0;
std::uint32_t xor_key;
bool found_rich = false;
@ -960,7 +1366,8 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
}
// Split the Rich header out into its own buffer
bounded_buffer *richBuf = splitBuffer(file, 0x80, rich_end_signature_offset + 4);
bounded_buffer *richBuf =
splitBuffer(file, 0x80, rich_end_signature_offset + 4);
if (richBuf == nullptr) {
return false;
}
@ -970,6 +1377,24 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
deleteBuffer(richBuf);
}
// Split the DOS header into a separate buffer which
// starts at offset 0 and has length 0x80
bounded_buffer *dosBuf = splitBuffer(file, 0, RICH_OFFSET);
if (dosBuf == nullptr) {
return false;
}
// Calculate checksum
p.rich.Checksum = calculateRichChecksum(dosBuf, p);
if (p.rich.Checksum == p.rich.DecryptionKey) {
p.rich.isValid = true;
} else {
p.rich.isValid = false;
}
if (dosBuf != nullptr) {
deleteBuffer(dosBuf);
}
// Rich header not present
} else {
p.rich.isPresent = false;
}
@ -992,12 +1417,12 @@ bool getHeader(bounded_buffer *file, pe_header &p, bounded_buffer *&rem) {
std::uint32_t rem_size;
if (p.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
// signature + file_header + optional_header_32
rem_size =
sizeof(std::uint32_t) + sizeof(file_header) + sizeof(optional_header_32);
rem_size = sizeof(std::uint32_t) + sizeof(file_header) +
sizeof(optional_header_32);
} else if (p.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
// signature + file_header + optional_header_64
rem_size =
sizeof(std::uint32_t) + sizeof(file_header) + sizeof(optional_header_64);
rem_size = sizeof(std::uint32_t) + sizeof(file_header) +
sizeof(optional_header_64);
} else {
PE_ERR(PEERR_MAGIC);
deleteBuffer(ntBuf);
@ -1529,8 +1954,8 @@ bool getImports(parsed_pe *p) {
ent.moduleName = modName;
p->internal->imports.push_back(ent);
} else {
std::string symName =
"ORDINAL_" + modName + "_" + to_string<std::uint32_t>(oval, std::dec);
std::string symName = "ORDINAL_" + modName + "_" +
to_string<std::uint32_t>(oval, std::dec);
importent ent;
@ -1579,7 +2004,8 @@ bool getSymbolTable(parsed_pe *p) {
std::uint32_t offset = p->peHeader.nt.FileHeader.PointerToSymbolTable;
for (std::uint32_t i = 0; i < p->peHeader.nt.FileHeader.NumberOfSymbols; i++) {
for (std::uint32_t i = 0; i < p->peHeader.nt.FileHeader.NumberOfSymbols;
i++) {
symbol sym;
// Read name
@ -1607,7 +2033,8 @@ bool getSymbolTable(parsed_pe *p) {
strOffset += sizeof(std::uint8_t);
}
} else {
for (std::uint8_t n = 0; n < NT_SHORT_NAME_LEN && sym.name.shortName[n] != 0;
for (std::uint8_t n = 0;
n < NT_SHORT_NAME_LEN && sym.name.shortName[n] != 0;
n++) {
sym.strName.push_back(static_cast<char>(sym.name.shortName[n]));
}
@ -2192,4 +2619,50 @@ const char *GetSubsystemAsString(parsed_pe *pe) {
}
}
bool GetDataDirectoryEntry(parsed_pe *pe,
data_directory_kind dirnum,
std::vector<std::uint8_t> &raw_entry) {
raw_entry.clear();
if (pe == nullptr) {
PE_ERR(PEERR_NONE);
return false;
}
data_directory dir;
VA addr;
if (pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_32_MAGIC) {
dir = pe->peHeader.nt.OptionalHeader.DataDirectory[dirnum];
addr = dir.VirtualAddress + pe->peHeader.nt.OptionalHeader.ImageBase;
} else if (pe->peHeader.nt.OptionalMagic == NT_OPTIONAL_64_MAGIC) {
dir = pe->peHeader.nt.OptionalHeader64.DataDirectory[dirnum];
addr = dir.VirtualAddress + pe->peHeader.nt.OptionalHeader64.ImageBase;
} else {
PE_ERR(PEERR_MAGIC);
return false;
}
if (dir.Size <= 0) {
PE_ERR(PEERR_SIZE);
return false;
}
section sec;
if (!getSecForVA(pe->internal->secs, addr, sec)) {
PE_ERR(PEERR_SECTVA);
return false;
}
auto off = static_cast<std::uint32_t>(addr - sec.sectionBase);
if (off + dir.Size >= sec.sectionData->bufLen) {
PE_ERR(PEERR_SIZE);
return false;
}
raw_entry.assign(sec.sectionData->buf + off,
sec.sectionData->buf + off + dir.Size);
return true;
}
} // namespace peparse

View File

@ -22,17 +22,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <parser-library/to_string.h>
#include <locale>
#include <codecvt>
#include <locale>
#include <parser-library/to_string.h>
namespace peparse {
// See https://stackoverflow.com/questions/38688417/utf-conversion-functions-in-c11
std::string from_utf16(const UCharString &u)
{
// See
// https://stackoverflow.com/questions/38688417/utf-conversion-functions-in-c11
std::string from_utf16(const UCharString &u) {
#if defined(_MSC_VER)
// std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>convert; // Doesn't compile with Visual Studio.
// See https://stackoverflow.com/questions/32055357/visual-studio-c-2015-stdcodecvt-with-char16-t-or-char32-t
// std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>convert;
// // Doesn't compile with Visual Studio. See
// https://stackoverflow.com/questions/32055357/visual-studio-c-2015-stdcodecvt-with-char16-t-or-char32-t
std::wstring_convert<std::codecvt_utf8<std::int16_t>, std::int16_t> convert;
auto p = reinterpret_cast<const std::int16_t *>(u.data());
return convert.to_bytes(p, p + u.size());

View File

@ -26,8 +26,7 @@ THE SOFTWARE.
#include <unicode/unistr.h>
namespace peparse {
std::string from_utf16(const UCharString &u)
{
std::string from_utf16(const UCharString &u) {
icu::UnicodeString utf16_string = icu::UnicodeString(u.data(), u.length());
std::string result;
utf16_string.toUTF8String(result);

View File

@ -704,7 +704,8 @@ static PyObject *pepy_parsed_get_entry_point(PyObject *self, PyObject *args) {
return ret;
}
static PyObject *pepy_parsed_get_machine_as_str(PyObject *self, PyObject *args) {
static PyObject *pepy_parsed_get_machine_as_str(PyObject *self,
PyObject *args) {
PyObject *ret;
const char *str;
@ -721,7 +722,8 @@ static PyObject *pepy_parsed_get_machine_as_str(PyObject *self, PyObject *args)
return ret;
}
static PyObject *pepy_parsed_get_subsystem_as_str(PyObject *self, PyObject *args) {
static PyObject *pepy_parsed_get_subsystem_as_str(PyObject *self,
PyObject *args) {
PyObject *ret;
const char *str;
@ -1079,9 +1081,8 @@ static PyObject *pepy_parsed_get_relocations(PyObject *self, PyObject *args) {
#define PEPY_PARSED_GET(ATTR, VAL) \
static PyObject *pepy_parsed_get_##ATTR(PyObject *self, void *closure) { \
PyObject *ret = \
PyLong_FromUnsignedLongLong( \
((pepy_parsed *) self)->pe->peHeader.nt.VAL); \
PyObject *ret = PyLong_FromUnsignedLongLong( \
((pepy_parsed *) self)->pe->peHeader.nt.VAL); \
if (!ret) \
PyErr_SetString(PyExc_AttributeError, "Error getting attribute."); \
return ret; \

210
travis.sh
View File

@ -1,210 +0,0 @@
#!/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 libicu-dev > "${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; the 'install' step will be skipped\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
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 $?