* CMake: Added install directives
* CMake: Added support for find_package(pe-parse)
* Fixed a compilation error on Linux
* CMake: Fix cmake module installation
* Added ArchLinux package
* Finished implementing the address converted example
* peaddrconv: Print the image base address.
* peaddrconv: Enable more warnings.
* Update travis to also build the examples
* Fix a compilation warning on Ubuntu 14.04
* Travis: Add macOS support.
* Better output for Travis, fix a compilation error on macOS.
* Travis: Do not build examples under macOS.
* Travis: Also compile the python module (pepy)
* Readme: Add a section to show how to use the library.
* Windows: Fix a compilation error, enable /analyze (see details).
The nt-headers.h include file is defining several constexpr values
using reserved (by windows.h) names.
These names (i.e.: IMAGE_FILE_MACHINE_UNKNOWN) are in fact macros
defined inside the Windows header files, and causes the preprocessor
to break definitions such as the following one:
constexpr std::uint16_t IMAGE_FILE_MACHINE_UNKNOWN = 0x0;
The fix (for now) consists in including the nt-headers.h file before
windows.h, but we should probably choose whether to use different
names or avoid defining those values (since they are inside the
system header anyway).
* Adapt wrapper to support python3
This seems to work with either python3 and python2.
* converted test file
* Testing better get_byte implem
* Clean and working get_bytes wrapper
* Correct bytearray display method
* Documents macros for python 2/3 support
* Remove useless typedef
This is C++ code, typedefed struct is useless (and probably bad style
C++).
* Add some comments and C++ style cast.
* Replace new[] with nothrow version
* Update error message to indicate allocation failure
* Put all of peparse in the peparse namespace.
* Fixes dupicate symbol problems when using the library inside other applications, namely Python
* Closes#25
I've noticed this in one (otherwise valid) EFI image. What happens is
the section specifies an invalid PointerToRawData, which the bounded
buffer abstraction catches and returns NULL. However, the SizeOfRawData
is still in the structure (and probably invalid too).
I saw two ways to fix this. If sectionData ends up being NULL we can set
SizeOfRawData to 0, but that would be truncating what is otherwise
specified in the file.
The other option is to teach dump-prog and pepy about this and adjust
accordingly. This involves checking for a data being a NULL pointer in
dump-prog when printing sections. In pepy it required roughly the same
check.
I went with option 2.
Teach the parser to properly handle PE32+ binaries.
The major differences are:
- Fields in the OptionalHeader which are not relative are now 64 bits.
- Base addresses should all be 64 bits.
- The BaseOfData field is not available on PE32+
There is now a 16 bit field tacked on to the end of nt_header_32 called
OptionalMagic. This is a duplicate of the Magic field in optional_header_32
and optional_header_64, but is stored in nt_header_32 to make it easier
to determine which optional header is being used.
I also added support for better error reporting. Now when something fails
to parse you can use a couple of functions to find out what happened and
where it happened:
- GetPEErr(): Return the error as an integer.
- GetPEErrString(): Return the error as a string.
- GetPEErrLoc(): Return the function and line number of the error.
Made some changes to pepy to account for these changes. The interface
into pepy is identical. Only externally visible changes are that
pepy.parse() will now return the error string and location when parsing
fails and the baseofdata attribute will throw an exception if the binary
is PE32+.
to_string.h is now included from parse.h, so remove it from dump.cpp.
While here do a bunch of cleanups to make printing consistent. Use '0x'
where appropriate and ensure exceptions are punctuated correctly.
I have a UPX packed sample that corrupted the resource directory. These changes
allow the resources to be properly parsed.
They add an RVA and size to the resource struct. This is the address and size
of the resource as it is declared in the directory. If the address is invalid
create a zero-length buffer for the data. If the size is invalid (ie: it goes
off the end of the .rsrc section) create a zero-length buffer for the data.
Otherwise, return the actual data.
This allows consumers of the rsrc to figure out if the resource is corrupt
or not by comparing the length of the buffer to the size element. If the
size is greater than 0 but buffer is empty then it's invalid.
Also, it should never happen but just to be safe make pepy catch NULL
buffers (in pepy_data_converter) and return an empty bytearray.
If get_bytes does not fill the list, get a slice of what was filled and
use that to convert to a bytearray. I still want to find a way to just
use a bytearray from the start. Luckily with the rest of this commit I
don't have a need to call get_bytes() on sections anymore.
Sections now have a data attribute which is a bytearray of the data that
makes up that section. This way you can just use section.data attribute
to get the entire contents and operate on it as you wish.
Make test.py use section.data to generate an MD5 of the section. It now
also prints the first 10 bytes of each section (if there are bytes).
It probably isn't the best way to do it but I couldn't get anything to work
when trying to generate a bytearray object directly. As a workaround I first
put each byte into a list and then convert the list to a bytearray.
Instead of having 2 macros for each object simplify by having 1 set of
macros that can work across all objects except the parsed object. I could
make this work for the parsed object by making the parsed object store
PyObject pointers to the parsed values instead of creating them on the fly
while getting an attribute.
Might as well do some general cleanup too:
Rename the len attribute of a section to length.
The section, import and export callbacks return 0 on success and anything else
on failure.
Whitespace fixes.
Fix a bunch of copy/paste mistakes in the test script.
This means I don't have to store anything in the pepy_parsed object (PyObject
pointers or native C types). Use a macro to get things out of the parsed
structures and into python objects.
There was some weird memory corruption caused by how pepy_parsed_init()
was parsing arguments. The result was that accessing attributes or methods
which didn't exist would periodically cause segfaults. This code was leftover
from an earlier way of doing things and doesn't need to be done this way.
Just parse straight to a C style string instead of this crap.
Also implement support for signature, machine support.
Also, add Py_TPFLAGS_BASETYPE as you should.
Convert the PyObject pointers used inside pepy_parsed into their corresponding
native types and use those. Teach the members array to return them accordingly.
While here might as well add support for signature and machine values.
Also, convert test.py to have shorter output by not using pprint.