Update frida (#1408)
* Update frida * fix build * aarch64 * fix aarch64 buid * Fix CI * move to git version of frida * fix * Frida frida frida
This commit is contained in:
parent
b0179b4498
commit
35fa881ff0
@ -29,7 +29,7 @@ reqwest = { version = "0.11.4", features = ["blocking"] }
|
||||
libafl = { path = "../../libafl/", features = [ "std", "llmp_compression", "llmp_bind_public", "frida_cli" ] } #, "llmp_small_maps", "llmp_debug"]}
|
||||
libafl_bolts = { path = "../../libafl_bolts/" }
|
||||
capstone = "0.11.0"
|
||||
frida-gum = { version = "0.8.1", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
frida-gum = { version = "0.13.2", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
libafl_frida = { path = "../../libafl_frida", features = ["cmplog"] }
|
||||
libafl_targets = { path = "../../libafl_targets", features = ["sancov_cmplog"] }
|
||||
libc = "0.2"
|
||||
|
@ -26,7 +26,7 @@ reqwest = { version = "0.11.4", features = ["blocking"] }
|
||||
[dependencies]
|
||||
libafl = { path = "../../libafl/", features = [ "std", "llmp_compression", "llmp_bind_public", "frida_cli" ] } #, "llmp_small_maps", "llmp_debug"]}
|
||||
libafl_bolts = { path = "../../libafl_bolts/" }
|
||||
frida-gum = { version = "0.8.1", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
frida-gum = { version = "0.13.2", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
libafl_frida = { path = "../../libafl_frida", features = ["cmplog"] }
|
||||
libafl_targets = { path = "../../libafl_targets", features = ["sancov_cmplog"] }
|
||||
libloading = "0.7"
|
||||
|
@ -28,7 +28,7 @@ reqwest = { version = "0.11.4", features = ["blocking"] }
|
||||
[dependencies]
|
||||
libafl = { path = "../../libafl/", features = [ "std", "llmp_compression", "llmp_bind_public", "frida_cli" ] } #, "llmp_small_maps", "llmp_debug"]}
|
||||
libafl_bolts = { path = "../../libafl_bolts/" }
|
||||
frida-gum = { version = "0.8.1", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
frida-gum = { version = "0.13.2", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
libafl_frida = { path = "../../libafl_frida", features = ["cmplog"] }
|
||||
libafl_targets = { path = "../../libafl_targets", features = ["sancov_cmplog"] }
|
||||
libloading = "0.7"
|
||||
|
@ -28,8 +28,8 @@ nix = "0.26"
|
||||
libc = "0.2"
|
||||
hashbrown = "0.14"
|
||||
rangemap = "1.3"
|
||||
frida-gum-sys = { version = "0.4.1", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
frida-gum = { version = "0.8.1", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
frida-gum-sys = { version = "0.8.1", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||
frida-gum = { version = "0.13.2", features = [ "auto-download", "event-sink", "invocation-listener", "module-names"] }
|
||||
dynasmrt = "2"
|
||||
capstone = "0.11.0"
|
||||
color-backtrace ={ version = "0.5", features = [ "resolve-modules" ] }
|
||||
|
@ -16,7 +16,7 @@ use backtrace::Backtrace;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use capstone::{
|
||||
arch::{self, x86::X86OperandType, ArchOperand::X86Operand, BuildsCapstone},
|
||||
Capstone, Insn, RegAccessType, RegId,
|
||||
Capstone, RegAccessType, RegId,
|
||||
};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use capstone::{
|
||||
@ -25,7 +25,7 @@ use capstone::{
|
||||
ArchOperand::Arm64Operand,
|
||||
BuildsCapstone,
|
||||
},
|
||||
Capstone, Insn,
|
||||
Capstone,
|
||||
};
|
||||
use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@ -36,6 +36,8 @@ use frida_gum::{
|
||||
instruction_writer::InstructionWriter, interceptor::Interceptor, stalker::StalkerOutput, Gum,
|
||||
Module, ModuleDetails, ModuleMap, NativePointer, RangeDetails,
|
||||
};
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
use frida_gum_sys::Insn;
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{cli::FuzzerOptions, AsSlice};
|
||||
#[cfg(unix)]
|
||||
@ -48,6 +50,8 @@ use libc::{getrlimit64, rlimit64};
|
||||
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
|
||||
use rangemap::RangeMap;
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
use crate::utils::frida_to_cs;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::utils::instruction_width;
|
||||
use crate::{
|
||||
@ -1094,7 +1098,7 @@ impl AsanRuntime {
|
||||
3,
|
||||
)
|
||||
.unwrap();
|
||||
let instructions = instructions.iter().collect::<Vec<&Insn>>();
|
||||
let instructions = instructions.iter().collect::<Vec<&capstone::Insn>>();
|
||||
let mut insn = instructions.first().unwrap();
|
||||
if insn.mnemonic().unwrap() == "msr" && insn.op_str().unwrap() == "nzcv, x0" {
|
||||
insn = instructions.get(2).unwrap();
|
||||
@ -2206,9 +2210,13 @@ impl AsanRuntime {
|
||||
Arm64Shift,
|
||||
Arm64Extender,
|
||||
)> {
|
||||
// We need to re-decode frida-internal capstone values to upstream capstone
|
||||
let cs_instr = frida_to_cs(capstone, instr);
|
||||
let cs_instr = cs_instr.first().unwrap();
|
||||
|
||||
// We have to ignore these instructions. Simulating them with their side effects is
|
||||
// complex, to say the least.
|
||||
match instr.mnemonic().unwrap() {
|
||||
match cs_instr.mnemonic().unwrap() {
|
||||
"ldaxr" | "stlxr" | "ldxr" | "stxr" | "ldar" | "stlr" | "ldarb" | "ldarh" | "ldaxp"
|
||||
| "ldaxrb" | "ldaxrh" | "stlrb" | "stlrh" | "stlxp" | "stlxrb" | "stlxrh" | "ldxrb"
|
||||
| "ldxrh" | "stxrb" | "stxrh" => return None,
|
||||
@ -2216,7 +2224,7 @@ impl AsanRuntime {
|
||||
}
|
||||
|
||||
let operands = capstone
|
||||
.insn_detail(instr)
|
||||
.insn_detail(cs_instr)
|
||||
.unwrap()
|
||||
.arch_detail()
|
||||
.operands();
|
||||
@ -2230,7 +2238,7 @@ impl AsanRuntime {
|
||||
opmem.base(),
|
||||
opmem.index(),
|
||||
opmem.disp(),
|
||||
instruction_width(instr, &operands),
|
||||
instruction_width(cs_instr, &operands),
|
||||
arm64operand.shift,
|
||||
arm64operand.ext,
|
||||
));
|
||||
@ -2250,15 +2258,18 @@ impl AsanRuntime {
|
||||
_address: u64,
|
||||
instr: &Insn,
|
||||
) -> Option<(RegId, u8, RegId, RegId, i32, i64)> {
|
||||
// We need to re-decode frida-internal capstone values to upstream capstone
|
||||
let cs_instr = frida_to_cs(capstone, instr);
|
||||
let cs_instr = cs_instr.first().unwrap();
|
||||
let operands = capstone
|
||||
.insn_detail(instr)
|
||||
.insn_detail(cs_instr)
|
||||
.unwrap()
|
||||
.arch_detail()
|
||||
.operands();
|
||||
// Ignore lea instruction
|
||||
// put nop into the white-list so that instructions like
|
||||
// like `nop dword [rax + rax]` does not get caught.
|
||||
match instr.mnemonic().unwrap() {
|
||||
match cs_instr.mnemonic().unwrap() {
|
||||
"lea" | "nop" => return None,
|
||||
|
||||
_ => (),
|
||||
@ -2266,7 +2277,7 @@ impl AsanRuntime {
|
||||
|
||||
// This is a TODO! In this case, both the src and the dst are mem operand
|
||||
// so we would need to return two operadns?
|
||||
if instr.mnemonic().unwrap().starts_with("rep") {
|
||||
if cs_instr.mnemonic().unwrap().starts_with("rep") {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -2317,9 +2328,9 @@ impl AsanRuntime {
|
||||
basereg: RegId,
|
||||
indexreg: RegId,
|
||||
scale: i32,
|
||||
disp: i64,
|
||||
disp: isize,
|
||||
) {
|
||||
let redzone_size = i64::from(frida_gum_sys::GUM_RED_ZONE_SIZE);
|
||||
let redzone_size = isize::try_from(frida_gum_sys::GUM_RED_ZONE_SIZE).unwrap();
|
||||
let writer = output.writer();
|
||||
let true_rip = address;
|
||||
|
||||
|
@ -24,9 +24,11 @@ use frida_gum::{
|
||||
instruction_writer::{Aarch64Register, IndexMode, InstructionWriter},
|
||||
stalker::StalkerOutput,
|
||||
};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use frida_gum_sys::Insn;
|
||||
|
||||
#[cfg(all(feature = "cmplog", target_arch = "aarch64"))]
|
||||
use crate::utils::{instruction_width, writer_register};
|
||||
use crate::utils::{frida_to_cs, instruction_width, writer_register};
|
||||
|
||||
#[cfg(all(feature = "cmplog", target_arch = "aarch64"))]
|
||||
/// Speciial `CmpLog` Cases for `aarch64`
|
||||
@ -41,7 +43,7 @@ pub enum SpecialCmpLogCase {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use capstone::{
|
||||
arch::{arm64::Arm64OperandType, ArchOperand::Arm64Operand},
|
||||
Capstone, Insn,
|
||||
Capstone,
|
||||
};
|
||||
|
||||
/// The [`frida_gum_sys::GUM_RED_ZONE_SIZE`] casted to [`i32`]
|
||||
@ -599,14 +601,18 @@ impl CmpLogRuntime {
|
||||
CmplogOperandType,
|
||||
Option<SpecialCmpLogCase>,
|
||||
)> {
|
||||
// We need to re-decode frida-internal capstone values to upstream capstone
|
||||
let cs_instr = frida_to_cs(capstone, instr);
|
||||
let cs_instr = cs_instr.first().unwrap();
|
||||
|
||||
// We only care for compare instructions - aka instructions which set the flags
|
||||
match instr.mnemonic().unwrap() {
|
||||
match cs_instr.mnemonic().unwrap() {
|
||||
"cmp" | "ands" | "subs" | "adds" | "negs" | "ngcs" | "sbcs" | "bics" | "cbz"
|
||||
| "cbnz" | "tbz" | "tbnz" | "adcs" => (),
|
||||
_ => return None,
|
||||
}
|
||||
let mut operands = capstone
|
||||
.insn_detail(instr)
|
||||
.insn_detail(cs_instr)
|
||||
.unwrap()
|
||||
.arch_detail()
|
||||
.operands();
|
||||
@ -615,20 +621,21 @@ impl CmpLogRuntime {
|
||||
let special_case = [
|
||||
"cbz", "cbnz", "tbz", "tbnz", "subs", "adds", "ands", "sbcs", "bics", "adcs",
|
||||
]
|
||||
.contains(&instr.mnemonic().unwrap());
|
||||
.contains(&cs_instr.mnemonic().unwrap());
|
||||
if operands.len() != 2 && !special_case {
|
||||
return None;
|
||||
}
|
||||
|
||||
// handle special opcodes case which have 3 operands, but the 1st(dest) is not important to us
|
||||
if ["subs", "adds", "ands", "sbcs", "bics", "adcs"].contains(&instr.mnemonic().unwrap()) {
|
||||
if ["subs", "adds", "ands", "sbcs", "bics", "adcs"].contains(&cs_instr.mnemonic().unwrap())
|
||||
{
|
||||
//remove the dest operand from the list
|
||||
operands.remove(0);
|
||||
}
|
||||
|
||||
// cbz marked as special since there is only 1 operand
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
let special_case = matches!(instr.mnemonic().unwrap(), "cbz" | "cbnz");
|
||||
let special_case = matches!(cs_instr.mnemonic().unwrap(), "cbz" | "cbnz");
|
||||
|
||||
#[allow(clippy::cast_sign_loss, clippy::similar_names)]
|
||||
let operand1 = if let Arm64Operand(arm64operand) = operands.first().unwrap() {
|
||||
@ -639,7 +646,7 @@ impl CmpLogRuntime {
|
||||
opmem.base(),
|
||||
opmem.index(),
|
||||
opmem.disp(),
|
||||
instruction_width(instr, &operands),
|
||||
instruction_width(cs_instr, &operands),
|
||||
)),
|
||||
Arm64OperandType::Cimm(val) => Some(CmplogOperandType::Cimm(val as u64)),
|
||||
_ => return None,
|
||||
@ -659,7 +666,7 @@ impl CmpLogRuntime {
|
||||
opmem.base(),
|
||||
opmem.index(),
|
||||
opmem.disp(),
|
||||
instruction_width(instr, &operands),
|
||||
instruction_width(cs_instr, &operands),
|
||||
)),
|
||||
Arm64OperandType::Cimm(val) => Some(CmplogOperandType::Cimm(val as u64)),
|
||||
_ => return None,
|
||||
@ -669,7 +676,7 @@ impl CmpLogRuntime {
|
||||
};
|
||||
|
||||
// tbz will need to have special handling at emit time(masking operand1 value with operand2)
|
||||
let special_case = match instr.mnemonic().unwrap() {
|
||||
let special_case = match cs_instr.mnemonic().unwrap() {
|
||||
"tbz" => Some(SpecialCmpLogCase::Tbz),
|
||||
"tbnz" => Some(SpecialCmpLogCase::Tbnz),
|
||||
_ => None,
|
||||
|
@ -298,8 +298,14 @@ where
|
||||
if let Some((segment, width, basereg, indexreg, scale, disp)) = res {
|
||||
if let Some(rt) = runtimes.match_first_type_mut::<AsanRuntime>() {
|
||||
rt.emit_shadow_check(
|
||||
address, &output, segment, width, basereg, indexreg, scale,
|
||||
disp,
|
||||
address,
|
||||
&output,
|
||||
segment,
|
||||
width,
|
||||
basereg,
|
||||
indexreg,
|
||||
scale,
|
||||
disp.try_into().unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -325,9 +331,7 @@ where
|
||||
if let Some(rt) = runtimes.match_first_type_mut::<CmpLogRuntime>() {
|
||||
if let Some((op1, op2, special_case)) =
|
||||
CmpLogRuntime::cmplog_is_interesting_instruction(
|
||||
&helper.capstone,
|
||||
address,
|
||||
instr,
|
||||
&capstone, address, instr,
|
||||
)
|
||||
{
|
||||
//emit code that saves the relevant data in runtime(passes it to x0, x1)
|
||||
|
@ -1,3 +1,5 @@
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
use capstone::Capstone;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use capstone::{
|
||||
arch::{self, arm64::Arm64OperandType, ArchOperand::Arm64Operand},
|
||||
@ -7,6 +9,8 @@ use capstone::{
|
||||
use frida_gum::instruction_writer::Aarch64Register;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use frida_gum::instruction_writer::X86Register;
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
use frida_gum_sys;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use num_traits::cast::FromPrimitive;
|
||||
|
||||
@ -132,3 +136,15 @@ pub fn writer_register(reg: capstone::RegId) -> X86Register {
|
||||
_ => X86Register::None, // Ignore Xax..Xip
|
||||
}
|
||||
}
|
||||
|
||||
/// Translates a frida instruction to a capstone instruction.
|
||||
/// Returns a [`capstone::Instructions`] with a single [`capstone::Insn`] inside.
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
pub(crate) fn frida_to_cs<'a>(
|
||||
capstone: &'a Capstone,
|
||||
frida_insn: &frida_gum_sys::Insn,
|
||||
) -> capstone::Instructions<'a> {
|
||||
capstone
|
||||
.disasm_count(frida_insn.bytes(), frida_insn.address(), 1)
|
||||
.unwrap()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user