mirror of
https://github.com/QuasarApp/pe-parse.git
synced 2025-04-26 04:14:32 +00:00
Directory entry retrieval (#90)
* pe-parser-library: Directory entry extraction Also runs clang-format on all library files. * dump-pe: Refactor, clang-format * pe-parser-library: Use enum for directory kinds * travis: Refactor * travis: Fixup stages * travis: Fix matrix * examples, pe-parser-library, pepy: clang-format * travis: Use minimal for lint * travis: Use find * clang-format: Remove old option * travis: More experimentation * travis: Move addons * travis: Remove coverity * travis: Hackery * travis: Move addons up * .travis: clang-format-8 * examples: clang-format * travis: Fix homebrew * CONTRIBUTING: Add contrib guidelines * travis: Build python ext, reenable coverity Remove old build files. * travis: Re-add coverity secret * travis: Build with coverity in a separate dir
This commit is contained in:
parent
1544c61c38
commit
2c775e5d6a
@ -2,7 +2,6 @@ AlignEscapedNewlinesLeft: true
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBraces: Attach
|
||||
ColumnLimit: 80
|
||||
IndentCaseLabels: true
|
||||
IndentWidth: 2
|
||||
|
78
.travis.yml
78
.travis.yml
@ -1,32 +1,56 @@
|
||||
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
|
||||
|
||||
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
26
CONTRIBUTING.md
Normal 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)
|
239
dump-pe/main.cpp
239
dump-pe/main.cpp
@ -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>
|
||||
|
||||
@ -232,8 +232,8 @@ int printRich(void *N, rich_entry r) {
|
||||
|
||||
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(20)
|
||||
<< GetRichProductName(r.ProductId, r.BuildNumber);
|
||||
std::cout << std::setw(10) << "Count:" << std::setw(7) << r.Count << "\n";
|
||||
return 0;
|
||||
}
|
||||
@ -275,18 +275,17 @@ 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.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";
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 2 || (argc == 2 && std::strcmp(argv[1], "--help") == 0)) {
|
||||
@ -297,119 +296,127 @@ 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 Rich header info
|
||||
if(p->peHeader.rich.isPresent) {
|
||||
std::cout << "Rich header: present\n";
|
||||
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);
|
||||
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);
|
||||
}
|
||||
// Print Rich header info
|
||||
if (p->peHeader.rich.isPresent) {
|
||||
std::cout << "Rich header: present\n";
|
||||
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);
|
||||
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: " << "\n";
|
||||
IterImpVAString(p, printImports, NULL);
|
||||
std::cout << "Relocations: " << "\n";
|
||||
IterRelocs(p, printRelocs, NULL);
|
||||
std::cout << "Symbols (symbol table): " << "\n";
|
||||
IterSymbols(p, printSymbols, NULL);
|
||||
std::cout << "Sections: " << "\n";
|
||||
IterSec(p, printSecs, NULL);
|
||||
std::cout << "Exports: " << "\n";
|
||||
IterExpVA(p, printExps, NULL);
|
||||
std::cout << "Imports: "
|
||||
<< "\n";
|
||||
IterImpVAString(p, printImports, NULL);
|
||||
std::cout << "Relocations: "
|
||||
<< "\n";
|
||||
IterRelocs(p, printRelocs, NULL);
|
||||
std::cout << "Symbols (symbol table): "
|
||||
<< "\n";
|
||||
IterSymbols(p, printSymbols, NULL);
|
||||
std::cout << "Sections: "
|
||||
<< "\n";
|
||||
IterSec(p, printSecs, NULL);
|
||||
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";
|
||||
// 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";
|
||||
for (std::size_t i = 0; i < 8; i++) {
|
||||
std::uint8_t b;
|
||||
if (!ReadByteAtVA(p, i + entryPoint, b)) {
|
||||
std::cout << " ERR";
|
||||
} else {
|
||||
std::cout << " 0x" << std::hex << static_cast<int>(b);
|
||||
}
|
||||
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)) {
|
||||
std::cout << " ERR";
|
||||
} else {
|
||||
std::cout << " 0x" << std::hex << static_cast<int>(b);
|
||||
}
|
||||
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
std::cout << "Resources: " << "\n";
|
||||
IterRsrc(p, printRsrc, NULL);
|
||||
DestructParsedPE(p);
|
||||
} else {
|
||||
std::cout << "Error: " << GetPEErr() << " (" << GetPEErrString() << ")"
|
||||
<< "\n";
|
||||
std::cout << "Location: " << GetPEErrLoc() << "\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
std::cout << "Resources: "
|
||||
<< "\n";
|
||||
IterRsrc(p, printRsrc, NULL);
|
||||
|
||||
DestructParsedPE(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -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)
|
@ -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;
|
||||
|
@ -1,8 +0,0 @@
|
||||
project('pe-parse',
|
||||
'cpp',
|
||||
default_options : [ 'cpp_std=c++11' ],
|
||||
license : [ 'MIT' ],
|
||||
)
|
||||
|
||||
subdir('parser-library')
|
||||
subdir('dump-prog')
|
@ -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')
|
@ -47,21 +47,6 @@ 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;
|
||||
|
||||
// Machine Types
|
||||
constexpr std::uint16_t IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
|
||||
@ -263,6 +248,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;
|
||||
@ -451,4 +455,101 @@ 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
|
||||
|
@ -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) \
|
||||
@ -137,6 +137,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);
|
||||
@ -167,7 +168,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 &GetRichProductName(std::uint16_t prodId,
|
||||
std::uint16_t buildNum);
|
||||
|
||||
// get parser error status as integer
|
||||
std::uint32_t GetPEErr();
|
||||
@ -230,4 +232,7 @@ 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
|
||||
const void *GetDataDirectoryEntry(parsed_pe *pe, data_directory_kind dirnum);
|
||||
} // namespace peparse
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#ifdef USE_ICU4C
|
||||
#include <unicode/unistr.h>
|
||||
|
@ -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>
|
||||
@ -125,14 +126,14 @@ struct parsed_pe_internal {
|
||||
// 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"}
|
||||
};
|
||||
{std::make_pair(1, 0), "Imported Functions"}};
|
||||
|
||||
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) {
|
||||
const std::string &GetRichProductName(std::uint16_t prodId,
|
||||
std::uint16_t buildNum) {
|
||||
auto it = ProductMap.find(std::make_pair(prodId, buildNum));
|
||||
if (it != ProductMap.end()) {
|
||||
return it->second;
|
||||
@ -144,18 +145,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 +234,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 +287,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 +395,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 +583,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 +834,9 @@ 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) {
|
||||
bool readRichHeader(bounded_buffer *rich_buf,
|
||||
std::uint32_t key,
|
||||
rich_header &rich_hdr) {
|
||||
if (rich_buf == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -837,8 +848,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 +870,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 +884,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 +894,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 +907,7 @@ 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;
|
||||
}
|
||||
@ -960,7 +970,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;
|
||||
}
|
||||
@ -992,12 +1003,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 +1540,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 +1590,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 +1619,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 +2205,48 @@ const char *GetSubsystemAsString(parsed_pe *pe) {
|
||||
}
|
||||
}
|
||||
|
||||
const void *GetDataDirectoryEntry(parsed_pe *pe, data_directory_kind dirnum) {
|
||||
if (pe == nullptr) {
|
||||
PE_ERR(PEERR_NONE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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 nullptr;
|
||||
}
|
||||
|
||||
if (dir.Size <= 0) {
|
||||
PE_ERR(PEERR_SIZE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
section sec;
|
||||
if (!getSecForVA(pe->internal->secs, addr, sec)) {
|
||||
PE_ERR(PEERR_SECTVA);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto off = static_cast<std::uint32_t>(addr - sec.sectionBase);
|
||||
if (off + dir.Size >= sec.sectionData->bufLen) {
|
||||
PE_ERR(PEERR_SIZE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::cerr << "off: 0x" << std::hex << off << std::endl;
|
||||
|
||||
std::vector<uint8_t> rawEntry(sec.sectionData->buf + off,
|
||||
sec.sectionData->buf + off + dir.Size);
|
||||
|
||||
return rawEntry.data();
|
||||
}
|
||||
|
||||
} // namespace peparse
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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
210
travis.sh
@ -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 $?
|
Loading…
x
Reference in New Issue
Block a user