Another PE tool

February 4, 2018 · 3 minutes read    malware reverse-engineering

Analyzing PE files is a basic task in reverse engineering in order to understand their structure, look for anything interesting before going more in depth into the reverse engineering in itself. There are countless tools to do that, on Windows I use PeStudio, PEView and Resource Hacker. But most of the time I want to have a first view of the file before starting my Virtual Machine, so I was looking for a CLI tool on Linux. There is of course PEScanner published by Michael Ligh with the good Malware Analyst’s Cookbook but it is a bit outdated (python2 only) and I like to write my own tools to be sure I understand how they work and what are their limits.

So I wrote a CLI tool plainly called PE, it is written in python 3 and published on github under GPLv3. It is using the good pefile and has a plugin architecture so it is easy to write new commands.

Installation

The tool is not published under PyPI (yet?), but it is packaged for pip, so pretty easy to install :

git clone git@github.com:Te-k/pe.git
cd pe
pip install .

Plugins

For now, there are 7 different commands:

  • info : Extract info from the PE file
  • dump : Dump resource or section of the file
  • search : Search a string in a PE file
  • checksize : Check size of the PE file
  • check : Check for weird stuff in the PE file
  • shell : Launch ipython shell to analyze the PE file

Example

$ pe info playlib.exe
Metadata
================================================================================
MD5:           0963bee29e797ea7481be5f18f354029
SHA1:          2ab43fc90a1928684b8590375643da52285b8625
SHA256:        f5967a8f3db4f4f33e89976e39914fceff46401bd2243b29162e1ddeb61f8dd3
Imphash:       25c0914e1e7dc7c3bb957d88e787a155
Size:          6445256 bytes
Type:          PE32 executable (GUI) Intel 80386, for MS Windows
Compile Time:  2013-12-23 11:44:26 (UTC - 0x52B8221A)
Entry point:   0x40666e (section .text)
TLS Callback: 0x446bb0 (section .enigma2)

Sections
================================================================================
Name       VirtSize  VirtAddr  RawSize   RawAddr   Entropy  md5
.text      0x6d11    0x1000    0x400     0x6e00    6.0193   5eaee28e37a09d2102eb51e78b45b0c1
.rdata     0x8602    0x8000    0x7200    0x8800    5.5164   21bdbc2bf27fd551101d72b710e7f597
.data      0x8ac     0x11000   0xfa00    0x400     3.7505   9279c174353928a592cd4a7e75ed6b3b
.rsrc      0x1b4     0x12000   0xfe00    0x200     5.0920   81ed975a2d7b4836ff8515ef97ac2232
.reloc     0x1730    0x13000   0x10000   0x1800    6.2184   ce4be3ea2acc52c8fbefcde69e516b47
.enigma1   0x1000    0x15000   0x11800   0x5d4000  7.9314   a7a0284d8da4c85adbc23b8c600fe15f
.enigma2   0x40000   0x16000   0x5e5800  0x40000   6.0038   9314fd6d5c987f829f9f84d4acad0812


Imports
================================================================================
kernel32.dll
	0x44b168 DeleteCriticalSection
	0x44b16c LeaveCriticalSection
	0x44b170 EnterCriticalSection
	0x44b174 InitializeCriticalSection
	0x44b178 VirtualFree
	0x44b17c VirtualAlloc
	0x44b180 LocalFree
[SNIP]


Resources:
================================================================================
Id           Name    Size      Lang           Sublang           Type           MD5
24-1-1033    None    346 B     LANG_ENGLISH   SUBLANG_ENGLISH_US ASCII text, with CRLF line terminators 24d3b502e1846356b0263f945ddd5529
$ pe check playlib.exe
Running checks on playlib.exe:
[+] Abnormal section names: .enigma1 .enigma2
[+] Suspicious section's entropy: .enigma1 - 7.931
[+] Known malicious sections
	-.enigma1: Enigma Virtual Box protector
	-.enigma2: Enigma Virtual Box protector
[+] 200 extra bytes in the file
[+] TLS Callback: 0x446bb0
[+] PE header in sections .enigma2
[+] Known suspicious import hash: Enigma VirtualBox
$ pe checksize playlib.exe
Name       VirtSize  VirtAddr  RawSize   RawAddr   Entropy  md5
.text      0x6d11    0x1000    0x400     0x6e00    6.0193   5eaee28e37a09d2102eb51e78b45b0c1
.rdata     0x8602    0x8000    0x7200    0x8800    5.5164   21bdbc2bf27fd551101d72b710e7f597
.data      0x8ac     0x11000   0xfa00    0x400     3.7505   9279c174353928a592cd4a7e75ed6b3b
.rsrc      0x1b4     0x12000   0xfe00    0x200     5.0920   81ed975a2d7b4836ff8515ef97ac2232
.reloc     0x1730    0x13000   0x10000   0x1800    6.2184   ce4be3ea2acc52c8fbefcde69e516b47
.enigma1   0x1000    0x15000   0x11800   0x5d4000  7.9314   a7a0284d8da4c85adbc23b8c600fe15f
.enigma2   0x40000   0x16000   0x5e5800  0x40000   6.0038   9314fd6d5c987f829f9f84d4acad0812

200 bytes of extra data (6445256 while it should be 6445056)

Creating a new command

As it is based on a plugin model, it is pretty easy to extend with new commands. You need to create a new file in pe/plugin having the following model :

#! /usr/bin/env python
from pe.plugins.base import Plugin


class PluginLambda(Plugin):
    name = "lambda"
    description = "Description of the plugin here"

    def add_arguments(self, parser):
	# Add argparse arguments
	parser.add_argument('INFORMATION')

    def run(self, args, pe, data):
	# Code here

Feel free to open issues and propose Pull Requests.