-
Notifications
You must be signed in to change notification settings - Fork 132
Usage
readpe
is the right tool for parsing PE files without infer anything regarding its fields and values. Using readpe
you can see all basic PE file information. For example, in order to see the Optional Header, you could run:
$ readpe --header optional putty.exe
Optional/Image header
Magic number: 0x10b (PE32)
Linker major version: 7
Linker minor version: 10
Size of .text section: 0x5c000
Size of .data section: 0x27000
Size of .bss section: 0
Entrypoint: 0x54eb0
Address of .text section: 0x1000
Address of .data section: 0x5d000
ImageBase: 0x400000
Alignment of sections: 0x1000
Alignment factor: 0x1000
Major version of required OS: 4
Minor version of required OS: 0
Major version of image: 0
Minor version of image: 0
Major version of subsystem: 4
Minor version of subsystem: 0
Size of image: 0x84000
Size of headers: 0x1000
Checksum: 0
Subsystem required: 0x2 (IMAGE_SUBSYSTEM_WINDOWS_GUI)
DLL characteristics: 0
DLL characteristics names
Size of stack to reserve: 0x100000
Size of stack to commit: 0x1000
Size of heap space to reserve: 0x100000
Size of heap space to commit: 0x1000
Hint: The Magic Number is 0x10b for PE32 files and 0x20b for PE32+ files.
In order to parse pev tools output you can use the -f
or --format
option. The following example will output the DOS Header in HTML:
$ readpe --format html --header dos putty.exe
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>src/build/readpe --format html --header dos /home/user/PUTTY.EXE</title>
</head>
<body>
<div class="object">
<h2>DOS Header</h2>
<p><span class="key"><b>Magic number</b></span>: <span class="value">0x5a4d (MZ)</span></p>
<p><span class="key"><b>Bytes in last page</b></span>: <span class="value">144</span></p>
<p><span class="key"><b>Pages in file</b></span>: <span class="value">3</span></p>
<p><span class="key"><b>Relocations</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>Size of header in paragraphs</b></span>: <span class="value">4</span></p>
<p><span class="key"><b>Minimum extra paragraphs</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>Maximum extra paragraphs</b></span>: <span class="value">65535</span></p>
<p><span class="key"><b>Initial (relative) SS value</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>Initial SP value</b></span>: <span class="value">0xb8</span></p>
<p><span class="key"><b>Initial IP value</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>Initial (relative) CS value</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>Address of relocation table</b></span>: <span class="value">0x40</span></p>
<p><span class="key"><b>Overlay number</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>OEM identifier</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>OEM information</b></span>: <span class="value">0</span></p>
<p><span class="key"><b>PE header offset</b></span>: <span class="value">0xf8</span></p>
</div>
</body>
</html>
By combining readpe
output with grep you could easily get the PE file entrypoint in CSV format by filtering the readpe output:
$ readpe --format csv --header optional putty.exe | grep ^Entry
Entrypoint,0x4f125
With readpe
you can inspect the PE sections as well. Use -S
option to see information about all PE sections, just like this:
$ readpe -S putty.exe
Sections
Section
Name: .text
Virtual Address: 0x1000
Physical Address: 0x5bd41
Size: 0x5c000 (376832 bytes)
Pointer To Data: 0x1000
Relocations: 0
Characteristics: 0x60000020
Characteristic Names
IMAGE_SCN_CNT_CODE
IMAGE_SCN_MEM_EXECUTE
IMAGE_SCN_MEM_READ
Section
Name: .rdata
Virtual Address: 0x5d000
Physical Address: 0x1ceda
Size: 0x1d000 (118784 bytes)
Pointer To Data: 0x5d000
Relocations: 0
Characteristics: 0x40000040
Characteristic Names
IMAGE_SCN_CNT_INITIALIZED_DATA
IMAGE_SCN_MEM_READ
Section
Name: .data
Virtual Address: 0x7a000
Physical Address: 0x5924
Size: 0x2000 (8192 bytes)
Pointer To Data: 0x7a000
Relocations: 0
Characteristics: 0xc0000040
Characteristic Names
IMAGE_SCN_CNT_INITIALIZED_DATA
IMAGE_SCN_MEM_READ
IMAGE_SCN_MEM_WRITE
Section
Name: .rsrc
Virtual Address: 0x80000
Physical Address: 0x3b90
Size: 0x4000 (16384 bytes)
Pointer To Data: 0x7c000
Relocations: 0
Characteristics: 0x40000040
Characteristic Names
IMAGE_SCN_CNT_INITIALIZED_DATA
IMAGE_SCN_MEM_READ
To list all data directories in a PE file, you can use -d
option:
$ readpe -d putty.exe
Data directories
Directory
IMAGE_DIRECTORY_ENTRY_IMPORT: 0x78378 (240 bytes)
Directory
IMAGE_DIRECTORY_ENTRY_RESOURCE: 0x80000 (15248 bytes)
Directory
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG: 0x78318 (72 bytes)
Directory
IMAGE_DIRECTORY_ENTRY_IAT: 0x5d000 (1292 bytes)
If the executable has an import directory you may want to see a list of imported functions using the -i
or --imports
option:
$ readpe -i putty.exe
Imported functions
Library
Name: ADVAPI32.dll
Functions
Function
Name: RegCloseKey
Function
Name: RegQueryValueExA
Function
Name: RegOpenKeyA
Function
Name: GetUserNameA
Function
Name: EqualSid
Function
Name: CopySid
Library
Name: COMCTL32.dll
Functions
Function
Ordinal: 14
Function
Ordinal: 15
Function
Ordinal: 17
Function
Ordinal: 13
Library
Name: comdlg32.dll
Functions
Function
Name: ChooseColorA
Function
Name: ChooseFontA
You can also see the exported functions by using -e
or --exports
option if that's applicable to your target binary.
With pehash
you can calculate checksums of PE pieces and not only whole PE files. You can for example compare two malwares by similarity using ssdeep. Have a look:
$ pehash -s CODE ComentarioDeVoz_.cpl
sections
section
section_name: CODE
md5: 67b498c232dfbe4f5cc0cabc5e78ac42
sha1: 32b5df9aaa201bc8cbfed37344aaa77bf842c1d4
sha256: 8f5b794da7fdbbc13f1abaae0949b4eb98935c99e7387c7e0dfef5d4f01ea298
ssdeep: 6144:2QrIKt9jjmVG0xcpcZTcLexXqS1XGtbNwI/4p3RLjD0OVG:2QrD3mVG0xcpcZTEexvXENv/e3RD0W
$ pehash -s CODE comentario.cpl
sections
section
section_name: CODE
md5: 973d11759194c14071aa6963de8f55c7
sha1: 1934e0085c8776e3243bf658e95b8943d4f91bc9
sha256: e68349bfcb04b20c11973ce27770570ebb22c8c7750133d073f15f7ec9eeda38
ssdeep: 6144:FQrIKt9jjmVG0xcpcZTcLexXqS1XGtbNwI/4p3Zv60G4:FQrD3mVG0xcpcZTEexvXENv/e3J6V
Although the CODE section hashes of each files are different, their ssdeep checksum matches. So, you could probably infer that these are variants.
You can also get the hash value for each PE supported part using pehash
with no arguments:
$ pehash -a putty.exe
file
filepath: /home/user/putty.exe
md5: 33c9d1e56152e212367e9c5b01671e45
sha1: 9ded3ce2ae09c37ca173bbd3dcb57258b72cdbd5
sha256: b10922648f6ad71f3f20b9acdfacf9aeff706cad6c52737cdc426307ccfa51d9
ssdeep: 12288:ApoNd4D7aVwSn8nW+nGQZZcLYX4RXwWLJQ6LU:UoNde7aVT8WvQ3O+4NzLu6w
imphash: dae4485dd029c5e0256f477eda4797a4
headers
header
header_name: IMAGE_DOS_HEADER
md5: 5084c5d5cfe99932e67450023c068941
sha1: 856558429bb575486a46a92ba2684eaab8578cef
sha256: 52ea4dd296abe995cc1052a3a29325a8306fc888b3d6fea352d2cebdd83e6eaa
ssdeep: 3:WlWUqt/vllPln:idqH
header
header_name: IMAGE_COFF_HEADER
md5: c29db8cff4c151279ea0f3e1e122bb92
sha1: 5df76c71b2fcb937b98d566dad7d353f23f23418
sha256: 4dc37a0d8a47d3c713b891a86b92acb28126729da2b7a6a5f3656d23fd8c1a9c
ssdeep: 3:OHwkn:wwk
header
header_name: IMAGE_OPTIONAL_HEADER
md5: 0de919344c187babea80d66adc2b0d9e
sha1: 4bdec527003b46348d8f9a1594f39f064e9dd680
sha256: 97e834e37ee922bca8a9388b2b1663491ddf0d3b20c6d37782aa4f2d1d9ebf64
ssdeep: 3:2H2l0lvl9gXH9lhtllrll3lll/ldt1l9tllH:NGlvA3
sections
section
section_name: .text
md5: 67b498c232dfbe4f5cc0cabc5e78ac42
sha1: 32b5df9aaa201bc8cbfed37344aaa77bf842c1d4
sha256: 8f5b794da7fdbbc13f1abaae0949b4eb98935c99e7387c7e0dfef5d4f01ea298
ssdeep: 6144:6poNd4D7aeaNqZs+iDpnRKnWDX/ZcnGs9BDT7JjZnZZGN+FAFtt6Xa//lrXwW:6poNd4D7aVwSn8nW+nGQZZcLYX4RXwW
section
section_name: .rdata
md5: 6087c2ffc1a7d69f82696a4f2d3aca75
sha1: d69529b6402c520bdbee855c34ce4455112bd1eb
sha256: 30b49d20acb96827857ca125ce0d49838fafafe9d7e49523982b2ff1afe54283
ssdeep: 3072:mDBKmaes7rlYhoAw/Jt8Lr6hx3bO6ta/4gRul:mS+oAw/Jt836L3bA/
section
section_name: .data
md5: 5578c6fd3e5a0b764a7f2bcde00f9a16
sha1: b71d5142594f56e896e79e12abf729e94512b9e0
sha256: edd88e6b2ccf3dd5624ebd07b8911e2fa51f4ddc7912d4699ed111d28a2a53e5
ssdeep: 96:j/1HpvU2Ro26mTfOkf14dBPBgtbAgUhoSkb/:9o26sN2dJ9rIb/
section
section_name: .rsrc
md5: 24b45ea2b1620870730382fb7308a074
sha1: bca5bc464c261f05751c24dce49d70458647e75c
sha256: 695707a6f3385838f6e5b58ab45584acb716bec2a2a953327dcb40314f0c0908
ssdeep: 192:Icgh8G2PnHGaAnkTjVDBY5disWxDgPWDSL73oqEnngLg:I5SG2vHi4jVDBKjPfL730ng0
The OpenSSL library used by pev supports a wider range of hashing algorithms and you can extend pehash to use them by recompiling its source code.
Suspicious files are nice. We could probably think about lots of suspicious characteristics that PE files may have and all we know is on pescan
:
$ pescan -v Nota.cpl
file entropy: 7.986840 (probably packed)
cpl analysis: malware
fpu anti-disassembly: no
imagebase: normal - 0x400000
entrypoint: normal - va: 0x15c330 - raw: 0x65530
DOS stub: suspicious - raw: 0x40
TLS directory: not found
section count: 3
.text: self-modifying
.rsrc: self-modifying
.reloc: small length
timestamp: normal - Wed, 26 Jun 2013 12:22:16 UTC
pescan
is the PE scanner program intented to find any suspicious characteristic on it. It's good for an initial analysis. Further you can analyze things deeply with readpe
, pedis
, peres
and so on.
Strings are also good indicators in general PE file analysis. To avoid the problem with Unicode and ASCII strings, we've developed our own strings dumper for PE files. With pestr
you know exactly where the string is inside the file and you don't need to specify wether you are looking for ASCII or Unicode strings. pestr
catches both.
$ pestr --so dotnet.exe
0x2a69c .text Button4
0x2a6a9 .text TextBox1
0x2a6b6 .text 3System.Resources.Tools.StronglyTypedResourceBuilder
0x2a6eb .text 4.0.0.0
0x2a6f7 .text KMicrosoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator
0x2a744 .text 12.0.0.0
0x2a752 .text My.Settings
0x2a972 .text _CorExeMain
0x2a97e .text mscoree.dll
0x2be7c .rsrc IHDR
0x2be95 .rsrc pHYs
0x2beaa .rsrc IDATx
0x2c1bb .rsrc IEND
0x2d742 .rsrc VS_VERSION_INFO
0x2d79e .rsrc VarFileInfo
0x2d7be .rsrc Translation
0x2d7e2 .rsrc StringFileInfo
pedis
is a full disassembler that can be used for different purposes. Let's say you find the following output from pescan first:
$ pescan -v malware.exe
file entropy: 7.868122 (probably packed)
fpu anti-disassembly: yes
imagebase: normal - 0x400000
entrypoint: fake - va: 0x2ddb40 - raw: 0xe0f40
DOS stub: suspicious - raw: 0x40
TLS callback function: 0x6ddd10
TLS directory: found - 1 function(s)
section count: 3
UPX0: suspicious name, zero length, self-modifying
UPX1: suspicious name, self-modifying
.rsrc: normal
timestamp: normal - Mon, 18 Nov 2013 16:34:20 UTC
You may want to see why DOS stub was marked as suspicious. You can use pedis for that. As DOS stub starts on offset 0x40 and it's a 16-bit assembly code, you can ask pedis
to disassemble 16 bytes for example, starting at offset 0x40. Look:
$ pedis -m 16 -o 0x40 -n 16 malware.exe
40: ba 10 00 mov dx, 0x10
43: 0e push cs
44: 1f pop ds
45: b4 09 mov ah, 0x9
47: cd 21 int 0x21
49: b8 01 4c mov ax, 0x4c01
4c: cd 21 int 0x21
4e: 90 nop
All tools are provided with manpages. Check it out and discover what you can do with pev. 😉