Skip to content

Commit 0c42ca4

Browse files
committed
intel_pt_command_ex: get binary addrs from file
Instead of hardcoding the addresses (that are compiler dependent), read them from the binary.
1 parent fe41244 commit 0c42ca4

File tree

3 files changed

+87
-19
lines changed

3 files changed

+87
-19
lines changed

fuzzers/binary_only/intel_pt_command_executor/Cargo.lock

Lines changed: 47 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fuzzers/binary_only/intel_pt_command_executor/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ libafl = { path = "../../../crates/libafl", default-features = false, features =
1212
libafl_bolts = { path = "../../../crates/libafl_bolts" }
1313
libafl_intelpt = { path = "../../../crates/libafl_intelpt" }
1414
log = { version = "0.4.22", features = ["release_max_level_info"] }
15+
object = "0.37.1"

fuzzers/binary_only/intel_pt_command_executor/src/main.rs

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::{
2-
env, ffi::CString, num::NonZero, os::unix::ffi::OsStrExt, path::PathBuf, time::Duration,
2+
env, ffi::CString, fs, num::NonZero, os::unix::ffi::OsStrExt, path::PathBuf, time::Duration,
33
};
44

55
use libafl::{
@@ -19,8 +19,9 @@ use libafl::{
1919
stages::mutational::StdMutationalStage,
2020
state::StdState,
2121
};
22-
use libafl_bolts::{core_affinity, rands::StdRand, tuples::tuple_list};
22+
use libafl_bolts::{core_affinity, rands::StdRand, tuples::tuple_list, Error};
2323
use libafl_intelpt::{AddrFilter, AddrFilterType, AddrFilters, IntelPT, PAGE_SIZE};
24+
use object::{elf::PF_X, Object, ObjectSegment, SegmentFlags};
2425

2526
// Coverage map
2627
const MAP_SIZE: usize = 4096;
@@ -29,7 +30,7 @@ static mut MAP: [u8; MAP_SIZE] = [0; MAP_SIZE];
2930
#[allow(static_mut_refs)] // only a problem in nightly
3031
static mut MAP_PTR: *mut u8 = unsafe { MAP.as_mut_ptr() };
3132

32-
pub fn main() {
33+
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
3334
// Let's set the default logging level to `warn`
3435
if env::var("RUST_LOG").is_err() {
3536
env::set_var("RUST_LOG", "warn")
@@ -44,9 +45,31 @@ pub fn main() {
4445
.parent()
4546
.unwrap()
4647
.join("target_program");
48+
let target_binary = fs::read(&target_path)?;
49+
let target_parsed = object::File::parse(&*target_binary)?;
50+
51+
// Get the executable segment from the target program.
52+
//
53+
// Note: this simple example target has just one range of executable memory, in real world binaries
54+
// there are likely multiple ranges.
55+
let executable_segments = target_parsed.segments().filter(|s| match s.flags() {
56+
SegmentFlags::Elf { p_flags } => (p_flags & PF_X) > 0,
57+
_ => panic!("target binary is not an ELF file."),
58+
});
59+
let executable_segment =
60+
executable_segments
61+
.into_iter()
62+
.next()
63+
.ok_or(Error::illegal_argument(
64+
"No executable segment found in target program",
65+
))?;
66+
log::debug!(
67+
"Executable segment: {executable_segment:x?} at binary file offset {:x?}",
68+
executable_segment.file_range()
69+
);
4770

4871
// We'll run the target on cpu (aka core) 0
49-
let cpu = core_affinity::get_core_ids().unwrap()[0];
72+
let cpu = core_affinity::get_core_ids()?[0];
5073
log::debug!("Using core {} for fuzzing", cpu.0);
5174

5275
// Create an observation channel using the map
@@ -72,8 +95,7 @@ pub fn main() {
7295
&mut feedback,
7396
// Same for objective feedbacks
7497
&mut objective,
75-
)
76-
.unwrap();
98+
)?;
7799

78100
// The Monitor trait define how the fuzzer stats are displayed to the user
79101
let mon = SimpleMonitor::new(|s| println!("{s}"));
@@ -94,27 +116,24 @@ pub fn main() {
94116
const ELF_ET_DYN_BASE: u64 = (DEFAULT_MAP_WINDOW / 3 * 2) & !(PAGE_SIZE as u64 - 1);
95117

96118
// Set the instruction pointer (IP) filter and memory image of our target.
97-
// These information can be retrieved from `readelf -l` (for example)
98-
let (code_memory_start, code_memory_end) =
99-
(ELF_ET_DYN_BASE + 0x6000, ELF_ET_DYN_BASE + 0x6000 + 0x3dfd9);
119+
let actual_virtual_address = executable_segment.address() + ELF_ET_DYN_BASE;
100120
let filters = AddrFilters::new(&[AddrFilter::new(
101-
code_memory_start,
102-
code_memory_end,
121+
actual_virtual_address,
122+
actual_virtual_address + executable_segment.size(),
103123
AddrFilterType::FILTER,
104-
)])
105-
.unwrap();
124+
)])?;
125+
106126
let intel_pt = IntelPT::builder()
107127
.cpu(cpu.0)
108128
.inherit(true)
109129
.ip_filters(&filters)
110-
.build()
111-
.unwrap();
130+
.build()?;
112131

113132
let sections = [SectionInfo {
114133
filename: target_path.to_string_lossy().to_string(),
115-
offset: 0x6000,
116-
size: code_memory_end - code_memory_start,
117-
virtual_address: code_memory_start,
134+
offset: executable_segment.file_range().0,
135+
size: executable_segment.size(),
136+
virtual_address: actual_virtual_address,
118137
}];
119138

120139
let hook = unsafe { IntelPTHook::builder().map_ptr(MAP_PTR).map_len(MAP_SIZE) }
@@ -158,4 +177,6 @@ pub fn main() {
158177
fuzzer
159178
.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
160179
.expect("Error in the fuzzing loop");
180+
181+
Ok(())
161182
}

0 commit comments

Comments
 (0)