use std::env;
use std::io::{self, Write};
use std::path::PathBuf;
use std::process;
use pelite::{FileMap, Wrap, PeFile};
const HELP_TEXT: &str = "
NAME:
pedump - Inspect PE binary files.
SYNOPSIS:
pedump FILEPATH
[-h | --help]
[-d | --dos]
[-n | --headers]
[-s | --sections]
[-i | --imports]
[-e | --exports]
[-r | --relocs]
[-x | --resources]
[-g | --debug-info]
DESCRIPTION:
Inspect and dump the contents of windows executable files.
OPTIONS:
-d, --dos
Print the DOS header and stub.
-n, --headers
Print the NT headers.
-s, --sections
Print the section headers.
-i, --imports
Print the imported symbols.
-e, --exports
Print the exported symbols.
-r, --relocs
Print the relocation table.
-l, --load-config
Prints the load config.
-t, --tls
Print the TLS directory.
-x, --resources
Print the embedded resource filesystem.
-g, --debug-info
Print debug information.
";
const SEPARATOR: &'static str = "----------------------------------------------------------------\n";
const NO_INPUT_VAL: &'static str = "missing path to input binary";
const INVALID_ARG: &'static str = "invalid argument was given";
#[derive(Debug)]
struct Parameters {
path: PathBuf,
_hex: bool,
dos: bool,
nt: bool,
sections: bool,
imports: bool,
exports: bool,
relocs: bool,
load_config: bool,
tls: bool,
resources: bool,
debug_info: bool,
}
impl Default for Parameters {
fn default() -> Parameters {
let mut vars = Parameters {
path: PathBuf::new(),
_hex: false,
dos: false,
nt: false,
sections: false,
imports: false,
exports: false,
relocs: false,
load_config: false,
tls: false,
resources: false,
debug_info: false,
};
let mut args = env::args_os();
let (_, mut args) = (args.next(), args.peekable());
if args.peek().is_none() {
print!("{}", HELP_TEXT);
process::exit(0);
}
vars.path = args.next()
.map(|path| PathBuf::from(path))
.map_or(None, |path| if path.starts_with("-") { None } else { Some(path) })
.unwrap_or_else(|| abort(NO_INPUT_VAL));
while let Some(arg) = args.next() {
let arg = arg.into_string().unwrap();
if arg.starts_with("--") {
match arg.as_str() {
"--dos" => vars.dos = true,
"--nt" => vars.nt = true,
"--sections" => vars.sections = true,
"--imports" => vars.imports = true,
"--exports" => vars.exports = true,
"--relocs" => vars.relocs = true,
"--load-config" => vars.load_config = true,
"--tls" => vars.tls = true,
"--resources" => vars.resources = true,
"--debug-info" => vars.debug_info = true,
_ => abort(INVALID_ARG),
}
}
else if arg.starts_with("-") {
let mut it = arg.chars(); it.next();
while let Some(opt) = it.next() {
match opt {
'd' => vars.dos = true,
'n' => vars.nt = true,
's' => vars.sections = true,
'i' => vars.imports = true,
'e' => vars.exports = true,
'r' => vars.relocs = true,
'l' => vars.load_config = true,
't' => vars.tls = true,
'x' => vars.resources = true,
'g' => vars.debug_info = true,
_ => abort(INVALID_ARG),
}
}
}
else {
abort(INVALID_ARG);
}
}
vars
}
}
fn abort(message: &str) -> ! {
{
let stderr = io::stderr();
let mut stderr = stderr.lock();
let _ = stderr.write(b"pedump: ");
let _ = stderr.write(message.as_bytes());
let _ = stderr.write(b".\n");
let _ = stderr.flush();
}
process::exit(1);
}
fn main() {
let args = Parameters::default();
let map = FileMap::open(&args.path).unwrap_or_else(|e| {
abort(&format!("{:?}", e));
});
match PeFile::from_bytes(&map) {
Ok(Wrap::T32(file)) => dump_pe32(&args, file),
Ok(Wrap::T64(file)) => dump_pe64(&args, file),
Err(err) => abort(&format!("{}", err)),
}
}
fn dump_pe64(args: &Parameters, file: pelite::pe64::PeFile) {
use pelite::pe64::Pe;
if args.dos {
let dos = file.dos_header();
print!("{}{:?}", SEPARATOR, dos);
}
if args.nt {
let nt = file.nt_headers();
print!("{}{:?}", SEPARATOR, nt);
}
if args.sections {
print!("{}", SEPARATOR);
for sec in file.section_headers() {
print!("{:?}", sec);
}
}
if args.exports {
print!("{}", SEPARATOR);
if let Ok(exports) = file.exports() {
print!("{:#?}", exports);
}
else {
println!("No Export Directory found.");
}
}
if args.imports {
print!("{}", SEPARATOR);
if let Ok(imports) = file.imports() {
print!("{:#?}", imports);
}
else {
println!("No Import Directory found.");
}
}
if args.resources {
print!("{}", SEPARATOR);
if let Ok(res) = file.resources() {
print!("{:#?}", res);
}
else {
println!("No Resources Directory found.");
}
}
if args.relocs {
print!("{}", SEPARATOR);
if let Ok(base_relocs) = file.base_relocs() {
print!("{:#?}", base_relocs);
}
else {
println!("No BaseRelocation Directory found.");
}
}
if args.load_config {
print!("{}", SEPARATOR);
if let Ok(load_config) = file.load_config() {
print!("{:#?}", load_config);
}
else {
println!("No Load Config Directory found.");
}
}
if args.tls {
print!("{}", SEPARATOR);
if let Ok(tls) = file.tls() {
print!("{:#?}", tls);
}
else {
println!("No TLS Directory found.");
}
}
if args.debug_info {
print!("{}", SEPARATOR);
if let Ok(debug) = file.debug() {
print!("{:?}", debug);
}
else {
println!("No Debug Directory found.");
}
}
}
fn dump_pe32(args: &Parameters, file: pelite::pe32::PeFile) {
use pelite::pe32::Pe;
if args.dos {
let dos = file.dos_header();
print!("{}{:?}", SEPARATOR, dos);
}
if args.nt {
let nt = file.nt_headers();
print!("{}{:?}", SEPARATOR, nt);
}
if args.sections {
print!("{}", SEPARATOR);
for sec in file.section_headers() {
print!("{:?}", sec);
}
}
if args.exports {
print!("{}", SEPARATOR);
if let Ok(exports) = file.exports() {
print!("{:#?}", exports);
}
else {
println!("No Export Directory found.");
}
}
if args.imports {
print!("{}", SEPARATOR);
if let Ok(imports) = file.imports() {
print!("{:#?}", imports);
}
else {
println!("No Import Directory found.");
}
}
if args.resources {
print!("{}", SEPARATOR);
if let Ok(res) = file.resources() {
print!("{:#?}", res);
}
else {
println!("No Resources Directory found.");
}
}
if args.relocs {
print!("{}", SEPARATOR);
if let Ok(base_relocs) = file.base_relocs() {
print!("{:#?}", base_relocs);
}
else {
println!("No BaseRelocation Directory found.");
}
}
if args.load_config {
print!("{}", SEPARATOR);
if let Ok(load_config) = file.load_config() {
print!("{:#?}", load_config);
}
else {
println!("No Load Config Directory found.");
}
}
if args.tls {
print!("{}", SEPARATOR);
if let Ok(tls) = file.tls() {
print!("{:#?}", tls);
}
else {
println!("No TLS Directory found.");
}
}
if args.debug_info {
print!("{}", SEPARATOR);
if let Ok(debug) = file.debug() {
print!("{:#?}", debug);
}
else {
println!("No Debug Directory found.");
}
}
}