1
1
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 ,
3
3
} ;
4
4
5
5
use libafl:: {
@@ -19,8 +19,9 @@ use libafl::{
19
19
stages:: mutational:: StdMutationalStage ,
20
20
state:: StdState ,
21
21
} ;
22
- use libafl_bolts:: { core_affinity, rands:: StdRand , tuples:: tuple_list} ;
22
+ use libafl_bolts:: { core_affinity, rands:: StdRand , tuples:: tuple_list, Error } ;
23
23
use libafl_intelpt:: { AddrFilter , AddrFilterType , AddrFilters , IntelPT , PAGE_SIZE } ;
24
+ use object:: { elf:: PF_X , Object , ObjectSegment , SegmentFlags } ;
24
25
25
26
// Coverage map
26
27
const MAP_SIZE : usize = 4096 ;
@@ -29,7 +30,7 @@ static mut MAP: [u8; MAP_SIZE] = [0; MAP_SIZE];
29
30
#[ allow( static_mut_refs) ] // only a problem in nightly
30
31
static mut MAP_PTR : * mut u8 = unsafe { MAP . as_mut_ptr ( ) } ;
31
32
32
- pub fn main ( ) {
33
+ pub fn main ( ) -> Result < ( ) , Box < dyn std :: error :: Error > > {
33
34
// Let's set the default logging level to `warn`
34
35
if env:: var ( "RUST_LOG" ) . is_err ( ) {
35
36
env:: set_var ( "RUST_LOG" , "warn" )
@@ -44,9 +45,31 @@ pub fn main() {
44
45
. parent ( )
45
46
. unwrap ( )
46
47
. 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
+ ) ;
47
70
48
71
// 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 ] ;
50
73
log:: debug!( "Using core {} for fuzzing" , cpu. 0 ) ;
51
74
52
75
// Create an observation channel using the map
@@ -72,8 +95,7 @@ pub fn main() {
72
95
& mut feedback,
73
96
// Same for objective feedbacks
74
97
& mut objective,
75
- )
76
- . unwrap ( ) ;
98
+ ) ?;
77
99
78
100
// The Monitor trait define how the fuzzer stats are displayed to the user
79
101
let mon = SimpleMonitor :: new ( |s| println ! ( "{s}" ) ) ;
@@ -94,27 +116,24 @@ pub fn main() {
94
116
const ELF_ET_DYN_BASE : u64 = ( DEFAULT_MAP_WINDOW / 3 * 2 ) & !( PAGE_SIZE as u64 - 1 ) ;
95
117
96
118
// 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 ;
100
120
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 ( ) ,
103
123
AddrFilterType :: FILTER ,
104
- ) ] )
105
- . unwrap ( ) ;
124
+ ) ] ) ? ;
125
+
106
126
let intel_pt = IntelPT :: builder ( )
107
127
. cpu ( cpu. 0 )
108
128
. inherit ( true )
109
129
. ip_filters ( & filters)
110
- . build ( )
111
- . unwrap ( ) ;
130
+ . build ( ) ?;
112
131
113
132
let sections = [ SectionInfo {
114
133
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 ,
118
137
} ] ;
119
138
120
139
let hook = unsafe { IntelPTHook :: builder ( ) . map_ptr ( MAP_PTR ) . map_len ( MAP_SIZE ) }
@@ -158,4 +177,6 @@ pub fn main() {
158
177
fuzzer
159
178
. fuzz_loop ( & mut stages, & mut executor, & mut state, & mut mgr)
160
179
. expect ( "Error in the fuzzing loop" ) ;
180
+
181
+ Ok ( ( ) )
161
182
}
0 commit comments