extern crate clap;
extern crate goblin;
extern crate owl;
use clap::{Arg, App};
use owl::*;
use std::fs::File;
use std::io::Read;
use std::path::Path;
fn do_elf(file: &[u8], elf: &goblin::elf::Elf, filter: Option<&str>) {
let gadget_finder: Box<GadgetFinder> = match elf.header.e_machine {
goblin::elf::header::EM_386 => Box::new(X86::new()),
goblin::elf::header::EM_X86_64 => Box::new(Amd64::new()),
goblin::elf::header::EM_MIPS => match elf.header.endianness().unwrap() {
goblin::container::Endian::Big => Box::new(Mips::new()),
goblin::container::Endian::Little => Box::new(Mipsel::new())
},
_ => panic!("Unsupported architecture")
};
let mut gadgets = Vec::new();
for program_header in &elf.program_headers {
if program_header.p_flags & goblin::elf::program_header::PF_X == 0 {
continue;
}
let vaddr = program_header.p_vaddr;
let offset = program_header.p_offset as usize;
let length = program_header.p_filesz as usize;
gadgets.append(
&mut gadget_finder.find(
vaddr,
file.get(offset..(offset + length)).expect("Failed to load from file"),
16)
.unwrap()
.into_iter()
.map(|mut gadget| {
let offset = gadget.offset();
gadget.set_offset(vaddr + offset);
gadget
})
.collect());
}
let gadgets = dedup(gadgets);
for gadget in gadgets {
let bytes =
gadget.bytes()
.iter()
.map(|byte| format!("{:02x}", byte))
.collect::<Vec<String>>()
.join(" ");
if let Some(filter) = filter {
if !gadget.instructions()
.iter()
.fold(false, |matches, instruction|
matches | instruction.contains(filter)) {
continue;
}
}
println!("{:0x}: {}", gadget.offset(), bytes);
for instruction in gadget.instructions() {
println!(" {}", instruction);
}
}
}
fn main () {
let matches = App::new("owl")
.author("Alex Eubanks <endeavor@rainbowsandpwnies.com>")
.about("ROP Gadget Finder")
.arg(Arg::with_name("filter")
.short("f")
.value_name("filter")
.help("Filter rop gadgets by substring"))
.arg(Arg::with_name("program")
.required(true)
.index(1))
.get_matches();
let filename = matches.value_of("program").unwrap();
let path = Path::new(&filename);
let mut fd = File::open(path).unwrap();
let mut data = Vec::new();
fd.read_to_end(&mut data).unwrap();
match goblin::Object::parse(&data).unwrap() {
goblin::Object::Elf(elf) => {
do_elf(&data, &elf, matches.value_of("filter"));
},
_ => println!("Unsupported file format")
}
}