Frida Cmplog improvements for aarch64 (#363)

* add support for cbz/tbz

* remove unecessary print

* implemented support for tbz

* add support for tbnz

* fix an error in the emitted code for both tbz/tbnz

* add support for cbnz

* fix error in logic

* add special handling to "subs"

* add restoration for X5 for tbz/tbnz

* add "adds" support

* add special handling for different opcodes

* add support for cbz/tbz

* remove unecessary print

* implemented support for tbz

* add support for tbnz

* fix an error in the emitted code for both tbz/tbnz

* add support for cbnz

* fix error in logic

* add special handling to "subs"

* add restoration for X5 for tbz/tbnz

* add "adds" support

* add special handling for different opcodes

* add adcs to cmplog commands

* get rid of irrelevant allocations
This commit is contained in:
OB 2021-11-07 16:39:34 +02:00 committed by GitHub
parent dd0b5fa74f
commit 3ffcfde9a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 8 deletions

View File

@ -77,22 +77,27 @@ impl CmpLogRuntime {
);}; );};
} }
// ldp/stp is more efficient than str/ldr so we use them instead.
macro_rules! tbz_masking { macro_rules! tbz_masking {
($ops:ident) => {dynasm!($ops ($ops:ident) => {dynasm!($ops
; .arch aarch64 ; .arch aarch64
; stp x5, x5, [sp, #-0x10]!
; mov x5, #1 ; mov x5, #1
; lsl x5, x5, x1 ; lsl x5, x5, x1
; eor x5, x5, #255 ; eor x5, x5, #255
; orr x1, x0, x5 ; orr x1, x0, x5
; ldp x5, x5, [sp], #0x10
);}; );};
} }
macro_rules! tbnz_masking { macro_rules! tbnz_masking {
($ops:ident) => {dynasm!($ops ($ops:ident) => {dynasm!($ops
; .arch aarch64 ; .arch aarch64
; stp x5, x5, [sp, #-0x10]!
; mov x5, #1 ; mov x5, #1
; lsl x5, x5, x1 ; lsl x5, x5, x1
; orr x1, x0, x5 ; orr x1, x0, x5
; ldp x5, x5, [sp], #0x10
);}; );};
} }

View File

@ -62,13 +62,12 @@ enum CmplogOperandType {
Mem(capstone::RegId, capstone::RegId, i32, u32), Mem(capstone::RegId, capstone::RegId, i32, u32),
} }
#[cfg(all(feature = "cmplog", target_arch = "aarch64"))]
enum SpecialCmpLogCase { enum SpecialCmpLogCase {
Tbz, Tbz,
Tbnz, Tbnz,
} }
#[cfg(target_vendor = "apple")] #[cfg(any(target_vendor = "apple"))]
const ANONYMOUS_FLAG: MapFlags = MapFlags::MAP_ANON; const ANONYMOUS_FLAG: MapFlags = MapFlags::MAP_ANON;
#[cfg(not(any(target_vendor = "apple", target_os = "windows")))] #[cfg(not(any(target_vendor = "apple", target_os = "windows")))]
const ANONYMOUS_FLAG: MapFlags = MapFlags::MAP_ANONYMOUS; const ANONYMOUS_FLAG: MapFlags = MapFlags::MAP_ANONYMOUS;
@ -1400,11 +1399,11 @@ impl<'a> FridaInstrumentationHelper<'a> {
> { > {
// We only care for compare instrunctions - aka instructions which set the flags // We only care for compare instrunctions - aka instructions which set the flags
match instr.mnemonic().unwrap() { match instr.mnemonic().unwrap() {
"cmp" | "ands" | "subs" | "adds" | "negs" | "ngcs" | "sbcs" | "bics" | "cls" "cmp" | "ands" | "subs" | "adds" | "negs" | "ngcs" | "sbcs" | "bics" | "cbz"
| "cbz" | "tbz" | "tbnz" => (), | "cbnz" | "tbz" | "tbnz" | "adcs" => (),
_ => return Err(()), _ => return Err(()),
} }
let operands = self let mut operands = self
.capstone .capstone
.insn_detail(instr) .insn_detail(instr)
.unwrap() .unwrap()
@ -1412,12 +1411,25 @@ impl<'a> FridaInstrumentationHelper<'a> {
.operands(); .operands();
// cbz - 1 operand, tbz - 3 operands // cbz - 1 operand, tbz - 3 operands
let special_case = ["cbz", "tbz", "tbnz"].contains(&instr.mnemonic().unwrap()); let special_case = [
if operands.len() != 2 || !special_case { "cbz", "cbnz", "tbz", "tbnz", "subs", "adds", "ands", "sbcs", "bics", "adcs",
]
.contains(&instr.mnemonic().unwrap());
if operands.len() != 2 && !special_case {
return Err(()); return Err(());
} }
// 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()) {
//remove the dest operand from the list
operands.remove(0);
}
// cbz marked as special since there is only 1 operand // cbz marked as special since there is only 1 operand
let special_case = instr.mnemonic().unwrap() == "cbz"; let special_case = match instr.mnemonic().unwrap() {
"cbz" | "cbnz" => true,
_ => false,
};
let operand1 = if let Arm64Operand(arm64operand) = operands.first().unwrap() { let operand1 = if let Arm64Operand(arm64operand) = operands.first().unwrap() {
match arm64operand.op_type { match arm64operand.op_type {