frida-asan: Un-inline report funclet to reduce code bloat (#81)
* frida-asan: Outline report funclet to reduce code bloat * fmt
This commit is contained in:
parent
730df64712
commit
a78a4b73fa
@ -6,9 +6,8 @@ edition = "2018"
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "frida"]
|
default = ["std"]
|
||||||
std = []
|
std = []
|
||||||
frida = ["frida-gum", "frida-gum-sys"]
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
@ -22,10 +21,10 @@ num_cpus = "1.0"
|
|||||||
which = "4.1"
|
which = "4.1"
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libafl = { path = "../../libafl/", features = [ "std" ] } #, "llmp_small_maps", "llmp_debug"]}
|
libafl = { path = "../../libafl/", features = [ "std", "llmp_compression" ] } #, "llmp_small_maps", "llmp_debug"]}
|
||||||
capstone = "0.8.0"
|
capstone = "0.8.0"
|
||||||
frida-gum = { version = "0.4", optional = true, features = [ "auto-download", "event-sink", "invocation-listener"] }
|
frida-gum = { version = "0.4", git = "https://github.com/s1341/frida-rust", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||||
frida-gum-sys = { version = "0.2.4", optional = true, features = [ "auto-download", "event-sink", "invocation-listener"] }
|
#frida-gum = { version = "0.4", path = "../../../frida-rust/frida-gum", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||||
libafl_frida = { path = "../../libafl_frida", version = "0.1.0" }
|
libafl_frida = { path = "../../libafl_frida", version = "0.1.0" }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
@ -89,7 +89,8 @@ __attribute__((noinline))
|
|||||||
void func3( char * alloc) {
|
void func3( char * alloc) {
|
||||||
printf("func3\n");
|
printf("func3\n");
|
||||||
if (random() == 0) {
|
if (random() == 0) {
|
||||||
alloc[0xff] = 0xde;
|
alloc[0x1ff] = 0xde;
|
||||||
|
printf("alloc[0x200]: %d\n", alloc[0x200]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
|
@ -20,8 +20,10 @@ libc = "0.2.92"
|
|||||||
hashbrown = "0.11"
|
hashbrown = "0.11"
|
||||||
libloading = "0.7.0"
|
libloading = "0.7.0"
|
||||||
rangemap = "0.1.10"
|
rangemap = "0.1.10"
|
||||||
frida-gum = { version = "0.4.0", features = [ "auto-download", "backtrace", "event-sink", "invocation-listener"] }
|
frida-gum = { version = "0.4.0", git = "https://github.com/s1341/frida-rust", features = [ "auto-download", "backtrace", "event-sink", "invocation-listener"] }
|
||||||
frida-gum-sys = { version = "0.2.4", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
frida-gum-sys = { version = "0.2.4", git = "https://github.com/s1341/frida-rust", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||||
|
#frida-gum = { version = "0.4.0", path = "../../frida-rust/frida-gum", features = [ "auto-download", "backtrace", "event-sink", "invocation-listener"] }
|
||||||
|
#frida-gum-sys = { version = "0.2.4", path = "../../frida-rust/frida-gum-sys", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||||
regex = "1.4"
|
regex = "1.4"
|
||||||
dynasmrt = "1.0.1"
|
dynasmrt = "1.0.1"
|
||||||
capstone = "0.8.0"
|
capstone = "0.8.0"
|
||||||
|
@ -595,6 +595,7 @@ extern "C" {
|
|||||||
|
|
||||||
pub struct AsanRuntime {
|
pub struct AsanRuntime {
|
||||||
regs: [usize; 32],
|
regs: [usize; 32],
|
||||||
|
blob_report: Option<Box<[u8]>>,
|
||||||
blob_check_mem_byte: Option<Box<[u8]>>,
|
blob_check_mem_byte: Option<Box<[u8]>>,
|
||||||
blob_check_mem_halfword: Option<Box<[u8]>>,
|
blob_check_mem_halfword: Option<Box<[u8]>>,
|
||||||
blob_check_mem_dword: Option<Box<[u8]>>,
|
blob_check_mem_dword: Option<Box<[u8]>>,
|
||||||
@ -679,6 +680,7 @@ impl AsanRuntime {
|
|||||||
pub fn new(options: FridaOptions) -> Rc<RefCell<AsanRuntime>> {
|
pub fn new(options: FridaOptions) -> Rc<RefCell<AsanRuntime>> {
|
||||||
let res = Rc::new(RefCell::new(Self {
|
let res = Rc::new(RefCell::new(Self {
|
||||||
regs: [0; 32],
|
regs: [0; 32],
|
||||||
|
blob_report: None,
|
||||||
blob_check_mem_byte: None,
|
blob_check_mem_byte: None,
|
||||||
blob_check_mem_halfword: None,
|
blob_check_mem_halfword: None,
|
||||||
blob_check_mem_dword: None,
|
blob_check_mem_dword: None,
|
||||||
@ -1421,113 +1423,12 @@ impl AsanRuntime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate the instrumentation blobs for the current arch.
|
fn generate_shadow_check_blob(&mut self, bit: u32) -> Box<[u8]> {
|
||||||
#[allow(clippy::similar_names)] // We allow things like dword and qword
|
|
||||||
fn generate_instrumentation_blobs(&mut self) {
|
|
||||||
let shadow_bit = Allocator::get().shadow_bit as u32;
|
let shadow_bit = Allocator::get().shadow_bit as u32;
|
||||||
macro_rules! shadow_check {
|
macro_rules! shadow_check {
|
||||||
($ops:ident, $bit:expr) => {dynasm!($ops
|
($ops:ident, $bit:expr) => {dynasm!($ops
|
||||||
; .arch aarch64
|
; .arch aarch64
|
||||||
//; brk #5
|
|
||||||
; b >skip_report
|
|
||||||
|
|
||||||
; report:
|
|
||||||
; stp x29, x30, [sp, #-0x10]!
|
|
||||||
; mov x29, sp
|
|
||||||
|
|
||||||
; ldr x0, >self_regs_addr
|
|
||||||
; stp x2, x3, [x0, #0x10]
|
|
||||||
; stp x4, x5, [x0, #0x20]
|
|
||||||
; stp x6, x7, [x0, #0x30]
|
|
||||||
; stp x8, x9, [x0, #0x40]
|
|
||||||
; stp x10, x11, [x0, #0x50]
|
|
||||||
; stp x12, x13, [x0, #0x60]
|
|
||||||
; stp x14, x15, [x0, #0x70]
|
|
||||||
; stp x16, x17, [x0, #0x80]
|
|
||||||
; stp x18, x19, [x0, #0x90]
|
|
||||||
; stp x20, x21, [x0, #0xa0]
|
|
||||||
; stp x22, x23, [x0, #0xb0]
|
|
||||||
; stp x24, x25, [x0, #0xc0]
|
|
||||||
; stp x26, x27, [x0, #0xd0]
|
|
||||||
; stp x28, x29, [x0, #0xe0]
|
|
||||||
; stp x30, xzr, [x0, #0xf0]
|
|
||||||
; mov x28, x0
|
|
||||||
; .dword (0xd53b4218u32 as i32) // mrs x24, nzcv
|
|
||||||
//; ldp x0, x1, [sp], #144
|
|
||||||
; ldp x0, x1, [sp, 0x10]
|
|
||||||
; stp x0, x1, [x28]
|
|
||||||
|
|
||||||
; adr x25, >done
|
|
||||||
; str x25, [x28, 0xf8]
|
|
||||||
|
|
||||||
; adr x25, <report
|
|
||||||
; adr x0, >eh_frame_fde
|
|
||||||
; adr x27, >fde_address
|
|
||||||
; ldr w26, [x27]
|
|
||||||
; cmp w26, #0x0
|
|
||||||
; b.ne >skip_register
|
|
||||||
; sub x25, x25, x27
|
|
||||||
; str w25, [x27]
|
|
||||||
; ldr x1, >register_frame_func
|
|
||||||
//; brk #11
|
|
||||||
; blr x1
|
|
||||||
; skip_register:
|
|
||||||
; ldr x0, >self_addr
|
|
||||||
; ldr x1, >trap_func
|
|
||||||
; blr x1
|
|
||||||
|
|
||||||
; .dword (0xd51b4218u32 as i32) // msr nzcv, x24
|
|
||||||
; ldr x0, >self_regs_addr
|
|
||||||
; ldp x2, x3, [x0, #0x10]
|
|
||||||
; ldp x4, x5, [x0, #0x20]
|
|
||||||
; ldp x6, x7, [x0, #0x30]
|
|
||||||
; ldp x8, x9, [x0, #0x40]
|
|
||||||
; ldp x10, x11, [x0, #0x50]
|
|
||||||
; ldp x12, x13, [x0, #0x60]
|
|
||||||
; ldp x14, x15, [x0, #0x70]
|
|
||||||
; ldp x16, x17, [x0, #0x80]
|
|
||||||
; ldp x18, x19, [x0, #0x90]
|
|
||||||
; ldp x20, x21, [x0, #0xa0]
|
|
||||||
; ldp x22, x23, [x0, #0xb0]
|
|
||||||
; ldp x24, x25, [x0, #0xc0]
|
|
||||||
; ldp x26, x27, [x0, #0xd0]
|
|
||||||
; ldp x28, x29, [x0, #0xe0]
|
|
||||||
; ldp x30, xzr, [x0, #0xf0]
|
|
||||||
|
|
||||||
; ldp x29, x30, [sp], #0x10
|
|
||||||
; b >done
|
|
||||||
; self_addr:
|
|
||||||
; .qword self as *mut _ as *mut c_void as i64
|
|
||||||
; self_regs_addr:
|
|
||||||
; .qword &mut self.regs as *mut _ as *mut c_void as i64
|
|
||||||
; trap_func:
|
|
||||||
; .qword AsanRuntime::handle_trap as *mut c_void as i64
|
|
||||||
; register_frame_func:
|
|
||||||
; .qword __register_frame as *mut c_void as i64
|
|
||||||
; eh_frame_cie:
|
|
||||||
; .dword 0x14
|
|
||||||
; .dword 0x00
|
|
||||||
; .dword 0x00527a01
|
|
||||||
; .dword 0x011e7c01
|
|
||||||
; .dword 0x001f0c1b
|
|
||||||
; eh_frame_fde:
|
|
||||||
; .dword 0x14
|
|
||||||
; .dword 0x18
|
|
||||||
; fde_address:
|
|
||||||
; .dword 0x0 // <-- address offset goes here
|
|
||||||
; .dword 0x104
|
|
||||||
//advance_loc 12
|
|
||||||
//def_cfa r29 (x29) at offset 16
|
|
||||||
//offset r30 (x30) at cfa-8
|
|
||||||
//offset r29 (x29) at cfa-16
|
|
||||||
; .dword 0x1d0c4c00
|
|
||||||
; .dword (0x9d029e10 as u32 as i32)
|
|
||||||
; .dword 0x04
|
|
||||||
// empty next FDE:
|
|
||||||
; .dword 0x0
|
|
||||||
; .dword 0x0
|
|
||||||
|
|
||||||
; skip_report:
|
|
||||||
; mov x1, #1
|
; mov x1, #1
|
||||||
; add x1, xzr, x1, lsl #shadow_bit
|
; add x1, xzr, x1, lsl #shadow_bit
|
||||||
; add x1, x1, x0, lsr #3
|
; add x1, x1, x0, lsr #3
|
||||||
@ -1539,20 +1440,65 @@ impl AsanRuntime {
|
|||||||
; lsr x1, x1, #16
|
; lsr x1, x1, #16
|
||||||
; lsr x1, x1, x0
|
; lsr x1, x1, x0
|
||||||
; tbnz x1, #$bit, >done
|
; tbnz x1, #$bit, >done
|
||||||
; b <report
|
|
||||||
|
|
||||||
|
; adr x1, >done
|
||||||
|
; nop // will be replaced by b to report
|
||||||
; done:
|
; done:
|
||||||
);};
|
);};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut ops = dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
||||||
|
shadow_check!(ops, bit);
|
||||||
|
let ops_vec = ops.finalize().unwrap();
|
||||||
|
ops_vec[..ops_vec.len() - 4].to_vec().into_boxed_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_shadow_check_exact_blob(&mut self, val: u32) -> Box<[u8]> {
|
||||||
|
let shadow_bit = Allocator::get().shadow_bit as u32;
|
||||||
macro_rules! shadow_check_exact {
|
macro_rules! shadow_check_exact {
|
||||||
($ops:ident, $val:expr) => {dynasm!($ops
|
($ops:ident, $val:expr) => {dynasm!($ops
|
||||||
; .arch aarch64
|
; .arch aarch64
|
||||||
; b >skip_report
|
|
||||||
|
; mov x1, #1
|
||||||
|
; add x1, xzr, x1, lsl #shadow_bit
|
||||||
|
; add x1, x1, x0, lsr #3
|
||||||
|
; ubfx x1, x1, #0, #(shadow_bit + 2)
|
||||||
|
; ldrh w1, [x1, #0]
|
||||||
|
; and x0, x0, #7
|
||||||
|
; rev16 w1, w1
|
||||||
|
; rbit w1, w1
|
||||||
|
; lsr x1, x1, #16
|
||||||
|
; lsr x1, x1, x0
|
||||||
|
; .dword -717536768 // 0xd53b4200 //mrs x0, NZCV
|
||||||
|
; and x1, x1, #$val as u64
|
||||||
|
; cmp x1, #$val
|
||||||
|
; b.eq >done
|
||||||
|
|
||||||
|
; adr x1, >done
|
||||||
|
; nop // will be replaced by b to report
|
||||||
|
; done:
|
||||||
|
);};
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ops = dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
||||||
|
shadow_check_exact!(ops, val);
|
||||||
|
let ops_vec = ops.finalize().unwrap();
|
||||||
|
ops_vec[..ops_vec.len() - 4].to_vec().into_boxed_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Generate the instrumentation blobs for the current arch.
|
||||||
|
#[allow(clippy::similar_names)] // We allow things like dword and qword
|
||||||
|
fn generate_instrumentation_blobs(&mut self) {
|
||||||
|
let mut ops_report = dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
||||||
|
dynasm!(ops_report
|
||||||
|
; .arch aarch64
|
||||||
|
|
||||||
; report:
|
; report:
|
||||||
; stp x29, x30, [sp, #-0x10]!
|
; stp x29, x30, [sp, #-0x10]!
|
||||||
; mov x29, sp
|
; mov x29, sp
|
||||||
|
// save the nvcz and the 'return-address'/address of instrumented instruction
|
||||||
|
; stp x0, x1, [sp, #-0x10]!
|
||||||
|
|
||||||
; ldr x0, >self_regs_addr
|
; ldr x0, >self_regs_addr
|
||||||
; stp x2, x3, [x0, #0x10]
|
; stp x2, x3, [x0, #0x10]
|
||||||
@ -1571,14 +1517,14 @@ impl AsanRuntime {
|
|||||||
; stp x28, x29, [x0, #0xe0]
|
; stp x28, x29, [x0, #0xe0]
|
||||||
; stp x30, xzr, [x0, #0xf0]
|
; stp x30, xzr, [x0, #0xf0]
|
||||||
; mov x28, x0
|
; mov x28, x0
|
||||||
; .dword (0xd53b4218u32 as i32) // mrs x24, nzcv
|
|
||||||
; ldp x0, x1, [sp, 0x10]
|
|
||||||
; stp x0, x1, [x28]
|
|
||||||
|
|
||||||
; adr x25, >done
|
; mov x25, x1 // address of instrumented instruction.
|
||||||
; add x25, x25, 4
|
|
||||||
; str x25, [x28, 0xf8]
|
; str x25, [x28, 0xf8]
|
||||||
|
|
||||||
|
; .dword 0xd53b4218u32 as i32 // mrs x24, nzcv
|
||||||
|
; ldp x0, x1, [sp, 0x20]
|
||||||
|
; stp x0, x1, [x28]
|
||||||
|
|
||||||
; adr x25, <report
|
; adr x25, <report
|
||||||
; adr x0, >eh_frame_fde
|
; adr x0, >eh_frame_fde
|
||||||
; adr x27, >fde_address
|
; adr x27, >fde_address
|
||||||
@ -1595,7 +1541,7 @@ impl AsanRuntime {
|
|||||||
; ldr x1, >trap_func
|
; ldr x1, >trap_func
|
||||||
; blr x1
|
; blr x1
|
||||||
|
|
||||||
; .dword (0xd51b4218u32 as i32) // msr nzcv, x24
|
; .dword 0xd51b4218u32 as i32 // msr nzcv, x24
|
||||||
; ldr x0, >self_regs_addr
|
; ldr x0, >self_regs_addr
|
||||||
; ldp x2, x3, [x0, #0x10]
|
; ldp x2, x3, [x0, #0x10]
|
||||||
; ldp x4, x5, [x0, #0x20]
|
; ldp x4, x5, [x0, #0x20]
|
||||||
@ -1613,8 +1559,11 @@ impl AsanRuntime {
|
|||||||
; ldp x28, x29, [x0, #0xe0]
|
; ldp x28, x29, [x0, #0xe0]
|
||||||
; ldp x30, xzr, [x0, #0xf0]
|
; ldp x30, xzr, [x0, #0xf0]
|
||||||
|
|
||||||
|
// restore nzcv. and 'return address'
|
||||||
|
; ldp x0, x1, [sp], #0x10
|
||||||
; ldp x29, x30, [sp], #0x10
|
; ldp x29, x30, [sp], #0x10
|
||||||
; b >done
|
; br x1 // go back to the 'return address'
|
||||||
|
|
||||||
; self_addr:
|
; self_addr:
|
||||||
; .qword self as *mut _ as *mut c_void as i64
|
; .qword self as *mut _ as *mut c_void as i64
|
||||||
; self_regs_addr:
|
; self_regs_addr:
|
||||||
@ -1640,111 +1589,34 @@ impl AsanRuntime {
|
|||||||
//offset r30 (x30) at cfa-8
|
//offset r30 (x30) at cfa-8
|
||||||
//offset r29 (x29) at cfa-16
|
//offset r29 (x29) at cfa-16
|
||||||
; .dword 0x1d0c4c00
|
; .dword 0x1d0c4c00
|
||||||
; .dword (0x9d029e10 as u32 as i32)
|
; .dword 0x9d029e10 as u32 as i32
|
||||||
; .dword 0x04
|
; .dword 0x04
|
||||||
// empty next FDE:
|
// empty next FDE:
|
||||||
; .dword 0x0
|
; .dword 0x0
|
||||||
; .dword 0x0
|
; .dword 0x0
|
||||||
|
|
||||||
|
|
||||||
; skip_report:
|
|
||||||
; mov x1, #1
|
|
||||||
; add x1, xzr, x1, lsl #shadow_bit
|
|
||||||
; add x1, x1, x0, lsr #3
|
|
||||||
; ubfx x1, x1, #0, #(shadow_bit + 2)
|
|
||||||
; ldrh w1, [x1, #0]
|
|
||||||
; and x0, x0, #7
|
|
||||||
; rev16 w1, w1
|
|
||||||
; rbit w1, w1
|
|
||||||
; lsr x1, x1, #16
|
|
||||||
; lsr x1, x1, x0
|
|
||||||
; .dword -717536768 // 0xd53b4200 //mrs x0, NZCV
|
|
||||||
; and x1, x1, #$val
|
|
||||||
; cmp x1, #$val
|
|
||||||
; b.eq >done
|
|
||||||
; b <report
|
|
||||||
|
|
||||||
; done:
|
|
||||||
; .dword -719633920 //0xd51b4200 // msr nvcz, x0
|
|
||||||
);};
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ops_check_mem_byte =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check!(ops_check_mem_byte, 0);
|
|
||||||
self.blob_check_mem_byte = Some(ops_check_mem_byte.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_halfword =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check!(ops_check_mem_halfword, 1);
|
|
||||||
self.blob_check_mem_halfword = Some(
|
|
||||||
ops_check_mem_halfword
|
|
||||||
.finalize()
|
|
||||||
.unwrap()
|
|
||||||
.into_boxed_slice(),
|
|
||||||
);
|
);
|
||||||
|
self.blob_report = Some(ops_report.finalize().unwrap().into_boxed_slice());
|
||||||
|
|
||||||
let mut ops_check_mem_dword =
|
self.blob_check_mem_byte = Some(self.generate_shadow_check_blob(0));
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
self.blob_check_mem_halfword = Some(self.generate_shadow_check_blob(1));
|
||||||
shadow_check!(ops_check_mem_dword, 2);
|
self.blob_check_mem_dword = Some(self.generate_shadow_check_blob(2));
|
||||||
self.blob_check_mem_dword =
|
self.blob_check_mem_qword = Some(self.generate_shadow_check_blob(3));
|
||||||
Some(ops_check_mem_dword.finalize().unwrap().into_boxed_slice());
|
self.blob_check_mem_16bytes = Some(self.generate_shadow_check_blob(4));
|
||||||
|
|
||||||
let mut ops_check_mem_qword =
|
self.blob_check_mem_3bytes = Some(self.generate_shadow_check_exact_blob(3));
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
self.blob_check_mem_6bytes = Some(self.generate_shadow_check_exact_blob(6));
|
||||||
shadow_check!(ops_check_mem_qword, 3);
|
self.blob_check_mem_12bytes = Some(self.generate_shadow_check_exact_blob(12));
|
||||||
self.blob_check_mem_qword =
|
self.blob_check_mem_24bytes = Some(self.generate_shadow_check_exact_blob(24));
|
||||||
Some(ops_check_mem_qword.finalize().unwrap().into_boxed_slice());
|
self.blob_check_mem_32bytes = Some(self.generate_shadow_check_exact_blob(32));
|
||||||
|
self.blob_check_mem_48bytes = Some(self.generate_shadow_check_exact_blob(48));
|
||||||
let mut ops_check_mem_16bytes =
|
self.blob_check_mem_64bytes = Some(self.generate_shadow_check_exact_blob(64));
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check!(ops_check_mem_16bytes, 4);
|
|
||||||
self.blob_check_mem_16bytes =
|
|
||||||
Some(ops_check_mem_16bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_3bytes =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check_exact!(ops_check_mem_3bytes, 3);
|
|
||||||
self.blob_check_mem_3bytes =
|
|
||||||
Some(ops_check_mem_3bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_6bytes =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check_exact!(ops_check_mem_6bytes, 6);
|
|
||||||
self.blob_check_mem_6bytes =
|
|
||||||
Some(ops_check_mem_6bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_12bytes =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check_exact!(ops_check_mem_12bytes, 12);
|
|
||||||
self.blob_check_mem_12bytes =
|
|
||||||
Some(ops_check_mem_12bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_24bytes =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check_exact!(ops_check_mem_24bytes, 24);
|
|
||||||
self.blob_check_mem_24bytes =
|
|
||||||
Some(ops_check_mem_24bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_32bytes =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check_exact!(ops_check_mem_32bytes, 32);
|
|
||||||
self.blob_check_mem_32bytes =
|
|
||||||
Some(ops_check_mem_32bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_48bytes =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check_exact!(ops_check_mem_48bytes, 48);
|
|
||||||
self.blob_check_mem_48bytes =
|
|
||||||
Some(ops_check_mem_48bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
|
|
||||||
let mut ops_check_mem_64bytes =
|
|
||||||
dynasmrt::VecAssembler::<dynasmrt::aarch64::Aarch64Relocation>::new(0);
|
|
||||||
shadow_check_exact!(ops_check_mem_64bytes, 64);
|
|
||||||
self.blob_check_mem_64bytes =
|
|
||||||
Some(ops_check_mem_64bytes.finalize().unwrap().into_boxed_slice());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the blob which implements the report funclet
|
||||||
|
#[inline]
|
||||||
|
pub fn blob_report(&self) -> &[u8] {
|
||||||
|
self.blob_report.as_ref().unwrap()
|
||||||
|
}
|
||||||
/// Get the blob which checks a byte access
|
/// Get the blob which checks a byte access
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn blob_check_mem_byte(&self) -> &[u8] {
|
pub fn blob_check_mem_byte(&self) -> &[u8] {
|
||||||
|
@ -58,6 +58,7 @@ pub struct FridaInstrumentationHelper<'a> {
|
|||||||
map: [u8; MAP_SIZE],
|
map: [u8; MAP_SIZE],
|
||||||
previous_pc: [u64; 1],
|
previous_pc: [u64; 1],
|
||||||
current_log_impl: u64,
|
current_log_impl: u64,
|
||||||
|
current_report_impl: u64,
|
||||||
/// Transformer that has to be passed to FridaInProcessExecutor
|
/// Transformer that has to be passed to FridaInProcessExecutor
|
||||||
transformer: Option<Transformer<'a>>,
|
transformer: Option<Transformer<'a>>,
|
||||||
capstone: Capstone,
|
capstone: Capstone,
|
||||||
@ -205,6 +206,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
|||||||
map: [0u8; MAP_SIZE],
|
map: [0u8; MAP_SIZE],
|
||||||
previous_pc: [0u64; 1],
|
previous_pc: [0u64; 1],
|
||||||
current_log_impl: 0,
|
current_log_impl: 0,
|
||||||
|
current_report_impl: 0,
|
||||||
transformer: None,
|
transformer: None,
|
||||||
capstone: Capstone::new()
|
capstone: Capstone::new()
|
||||||
.arm64()
|
.arm64()
|
||||||
@ -315,7 +317,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn emit_shadow_check(
|
fn emit_shadow_check(
|
||||||
&self,
|
&mut self,
|
||||||
_address: u64,
|
_address: u64,
|
||||||
output: &StalkerOutput,
|
output: &StalkerOutput,
|
||||||
basereg: capstone::RegId,
|
basereg: capstone::RegId,
|
||||||
@ -334,6 +336,22 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.current_report_impl == 0
|
||||||
|
|| !writer.can_branch_directly_to(self.current_report_impl)
|
||||||
|
|| !writer.can_branch_directly_between(writer.pc() + 128, self.current_report_impl)
|
||||||
|
{
|
||||||
|
let after_report_impl = writer.code_offset() + 2;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
writer.put_jmp_near_label(after_report_impl);
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
writer.put_b_label(after_report_impl);
|
||||||
|
|
||||||
|
self.current_report_impl = writer.pc();
|
||||||
|
writer.put_bytes(self.asan_runtime.borrow().blob_report());
|
||||||
|
|
||||||
|
writer.put_label(after_report_impl);
|
||||||
|
}
|
||||||
//writer.put_brk_imm(1);
|
//writer.put_brk_imm(1);
|
||||||
|
|
||||||
// Preserve x0, x1:
|
// Preserve x0, x1:
|
||||||
@ -477,9 +495,23 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
|||||||
16 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_16bytes()),
|
16 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_16bytes()),
|
||||||
24 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_24bytes()),
|
24 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_24bytes()),
|
||||||
32 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_32bytes()),
|
32 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_32bytes()),
|
||||||
|
48 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_48bytes()),
|
||||||
|
64 => writer.put_bytes(&self.asan_runtime.borrow().blob_check_mem_64bytes()),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add the branch to report
|
||||||
|
//writer.put_brk_imm(0x12);
|
||||||
|
writer.put_branch_address(self.current_report_impl);
|
||||||
|
|
||||||
|
match width {
|
||||||
|
3 | 6 | 12 | 24 | 32 | 48 | 64 => {
|
||||||
|
let msr_nvcz_x0: u32 = 0xd51b4200;
|
||||||
|
writer.put_bytes(&msr_nvcz_x0.to_le_bytes());
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
// Restore x0, x1
|
// Restore x0, x1
|
||||||
assert!(writer.put_ldp_reg_reg_reg_offset(
|
assert!(writer.put_ldp_reg_reg_reg_offset(
|
||||||
Aarch64Register::X0,
|
Aarch64Register::X0,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user