PE Tree is a Python module for viewing Portable Executable (PE) files in a tree-view using pefile and PyQt5. It can also be used with IDA Pro, Ghidra, Volatility, Rekall and minidump to view and dump in-memory PE files, as well as perform import table reconstruction.
The PE Tree standalone application finds portable executables in files, folders and ZIP archives.
Install directly from GitHub using a fresh virtual environment and pip:
> virtualenv env
> env\Scripts\activate
> pip install --upgrade pip
> pip install git+https://github.com/blackberry/pe_tree.git
$ python3 -m venv env
$ source ./env/bin/activate
$ pip install --upgrade pip
$ pip install git+https://github.com/blackberry/pe_tree.git
Git clone the repository and setup for development:
> git clone https://github.com/blackberry/pe_tree.git
> cd pe_tree
> virtualenv env
> env\Scripts\activate
> pip install -e .
$ git clone https://github.com/blackberry/pe_tree.git
$ cd pe_tree
$ python3 -m venv env
$ source ./env/bin/activate
$ pip install -e .
Run PE Tree and scan for portable executables in files, folders and ZIP archives:
$ pe-tree -h
usage: pe-tree [-h] [filenames [filenames ...]]
PE-Tree
positional arguments:
filenames Path(s) to file/folder/zip
optional arguments:
-h, --help show this help message and exit
Run PE Tree and attempt to carve portable executable files from a binary file:
$ pe-tree-carve -h
usage: pe-tree-carve [-h] filename
PE-Tree (Carve)
positional arguments:
filename Path to file to carve
optional arguments:
-h, --help show this help message and exit
Dark-mode can be enabled by installing QDarkStyle:
$ pip install qdarkstyle
The PE Tree IDAPython plugin finds portable executables in IDA databases.
To install and run as an IDAPython plugin you can either use setuptools or install manually.
Download pe_tree and install for the global Python interpreter used by IDA:
$ git clone https://github.com/blackberry/pe_tree.git
$ cd pe_tree
$ python setup.py develop --ida
Download pe_tree and install requirements for the global Python interpreter used by IDA:
$ git clone https://github.com/blackberry/pe_tree.git
$ cd pe_tree
$ pip install -r requirements.txt
./pe_tree/
to your IDA plugins folderTo forgo installing as a plugin, and simply run as a script under IDA, first install the pe_tree package requirements for the global Python installation:
$ pip install -r requirements.txt
Then run pe_tree_ida.py under IDA:
File -> Script file... -> pe_tree_ida.py -> Open
OS | Plugins folder |
---|---|
Windows | %ProgramFiles%\IDA Pro 7.X\plugins |
Linux | /opt/ida-7.X/plugins |
Mac | ~/.idapro/plugins |
Load the PE Tree plugin:
Edit -> Plugins -> PE Tree
Below are the basic steps to dump a packed PE file (for example MPRESS or UPX) and reconstruct imports (assuming the image base/entry-point is fairly standard):
Launch IDA Pro and disassemble an MPRESS or UPX packed PE file (select Manual Load and Load Resources)
Select a debugger (Windows or Bochs) and run until OEP (usually 0x00401000, but not always!)
At this point you could take a memory snapshot (saving all segments) and save the IDB for later
Ensure IDA has found all code:
Options -> General -> Analysis -> Reanalyze program
Open the PE Tree IDAPython plugin, right-click in the right-hand pane and select:
Add PE -> Search IDB
This will scan the IDB for MZ/PE headers and display any modules it finds.
Right-click on HEADER-0x00400000 (or appropriate module name) and select Dump...
Specify the AddressOfEntryPoint (typically 0x1000, but again, not always!)
Ensure Rebuild IDT/IAT is selected
Dump!
A new executable will be created using the unpacked section data obtained from memory/IDB, whilst a new section named .pe_tree
and containing the rebuilt IAT, hint name table and IDT will be appended to the PE file (much like an .idata section).
If the entry-point memory segment has been marked writable during execution (via VirtualProtect for example) then the entry-point section's characteristics will also be marked writable.
Finally, the BASERELOC, BOUND_IMPORT and SECURITY data directories are marked null, and the OPTIONAL_HEADER checksum is recalculated (if specified).
Using the above approach it is possible to dump many in-memory PE files that have either been unpacked, injected, reflectively loaded or hollowed etc.
The PE Tree Rekall plugin finds portable executables in Windows memory dumps.
Run Rekall and view active processes, DLLs and drivers on a live system:
$ rekall --live Memory
[1] Live (Memory) 00:00:00> run -i pe_tree_rekall.py
Alternatively, run Rekall/PE Tree against an existing memory dump:
$rekall -f memory.vmem
[1] memory.vmem 00:00:00> run -i pe_tree_rekall.py
The PE Tree Volatility plugin finds portable executables in Windows memory dumps.
$ pe-tree-vol -h
usage: pe-tree-vol [-h] filename
PE-Tree (Volatility)
positional arguments:
filename Path to memory dump
optional arguments:
-h, --help show this help message and exit
The PE Tree Ghidra plugin finds portable executables in Ghidra databases.
$ pe-tree-ghidra -h
usage: pe-tree-ghidra [-h] [--server SERVER] [--port PORT]
PE-Tree (Ghidra)
optional arguments:
-h, --help show this help message and exit
--server SERVER Ghidra bridge server IP (default: 127.0.0.1)
--port PORT Ghidra bridge server port (default: 4768)
The PE Tree Minidump plugin finds portable executables in Windows Minidumps.
pip install minidump
)$ pe-tree-minidump -h
usage: pe-tree-minidump [-h] filename
PE-Tree (Minidump)
positional arguments:
filename Path to .dmp file
optional arguments:
-h, --help show this help message and exit
The configuration is stored in an INI file and defaults to the following values:
[config]
debug = False
fonts = Consolas,Monospace,Courier
passwords = ,infected
virustotal_url = https://www.virustotal.com/gui/search
cyberchef_url = https://gchq.github.io/CyberChef
Section | Option | Type | Description |
---|---|---|---|
config | debug | boolean | Print pefile.dump() to output |
config | fonts | string | Comma-separated list of font names for UI |
config | passwords | string | Comma-separated list of ZIP file passwords |
config | virustotal_url | string | VirusTotal search URL |
config | cyberchef_url | string | CyberChef URL |
Type | OS | Path |
---|---|---|
Application | Windows | %TEMP%\pe_tree.ini |
Application | Linux/Mac | /tmp/pe_tree.ini |
IDAPython | Windows | %APPDATA%\HexRays\IDA Pro\pe_tree.ini |
IDAPython | Linux/Mac | ~/.idapro/pe_tree.ini |
Rekall | Windows | %TEMP%\pe_tree_rekall.ini |
Rekall | Linux/Mac | /tmp/pe_tree_rekall.ini |
Volatility | Windows | %TEMP%\pe_tree_volatility.ini |
Volatility | Linux/Mac | /tmp/pe_tree_volatility.ini |
Ghidra | Windows | %TEMP%\pe_tree_ghidra.ini |
Ghidra | Linux/Mac | /tmp/pe_tree_ghidra.ini |
Minidump | Windows | %TEMP%\pe_tree_minidump.ini |
Minidump | Linux/Mac | /tmp/pe_tree_minidump.ini |
Carve | Windows | %TEMP%\pe_tree_carve.ini |
Carve | Linux/Mac | /tmp/pe_tree_carve.ini |
The following information will be shared with 3rd party web-applications (depending on configuration) under the following conditions:
If the VirusTotal URL is specified in the configuration then metadata such as file hashes, timestamps, etc will be sent to VirusTotal for processing when the user clicks on highlighted links or selects "VirusTotal search" from the right-click context menu.
If the CyberChef URL is present in the configuration then any file data will be base64 encoded and sent to CyberChef for processing when the user selects "CyberChef" from the right-click context menu.
or
Try to upgrade pip to version 20.0+:
$ pip install --upgrade pip
Try uninstalling and reinstalling PyQt5 as follows:
pip uninstall PyQt5
pip uninstall PyQt5-sip
pip install PyQt5 PyQt5-sip
Ensure IDA has found and disassembled all code:
Options -> General -> Analysis -> Reanalyze program
After this is completed try to dump/rebuild imports again.
Please feel free to contribute! Issues and pull requests are most welcome.
To build documentation from source using Sphinx:
$ pip install sphinx
$ sphinx-apidoc -o ./doc/source/ .
$ sphinx-build -b html ./doc/source ./doc/build -E
To view the documentation open ./doc/build/index.html
in a web-browser.
Tom Bonner - tombonner - @thomas_bonner
PE Tree is distributed under the Apache License. See LICENSE for more information.