Fix capsone mode in LibAFL QEMU (#1136)

* Use regex feature in libafl_qemu

* wip

* set mode for arm reading pc

* fixes
This commit is contained in:
Andrea Fioraldi 2023-03-12 23:29:55 +01:00 committed by GitHub
parent 786af9f6a9
commit e8d99b9975
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 8 deletions

@ -1 +1 @@
Subproject commit a42e95e754f7d8645957ab399d3eb346d2303b5a Subproject commit 5cccc33456c48ad83008eb618e7da5d005c72d89

View File

@ -1,3 +1,4 @@
use capstone::arch::BuildsCapstone;
use num_enum::{IntoPrimitive, TryFromPrimitive}; use num_enum::{IntoPrimitive, TryFromPrimitive};
#[cfg(feature = "python")] #[cfg(feature = "python")]
use pyo3::prelude::*; use pyo3::prelude::*;
@ -50,5 +51,14 @@ impl IntoPy<PyObject> for Regs {
/// Return an ARM ArchCapstoneBuilder /// Return an ARM ArchCapstoneBuilder
pub fn capstone() -> capstone::arch::arm::ArchCapstoneBuilder { pub fn capstone() -> capstone::arch::arm::ArchCapstoneBuilder {
capstone::Capstone::new().arm() capstone::Capstone::new()
.arm()
.mode(capstone::arch::arm::ArchMode::Arm)
}
/// Return an ARM Thumb ArchCapstoneBuilder
pub fn capstone_thumb() -> capstone::arch::arm::ArchCapstoneBuilder {
capstone::Capstone::new()
.arm()
.mode(capstone::arch::arm::ArchMode::Thumb)
} }

View File

@ -21,7 +21,11 @@ pub struct Instruction {
* - operand string * - operand string
* - instruction length * - instruction length
*/ */
pub fn pc2basicblock(pc: GuestAddr, emu: &Emulator) -> Result<Vec<Instruction>, String> { pub fn pc2basicblock(
pc: GuestAddr,
emu: &Emulator,
mode: Option<capstone::Mode>,
) -> Result<Vec<Instruction>, String> {
#[allow(unused_mut)] #[allow(unused_mut)]
let mut code = { let mut code = {
#[cfg(emulation_mode = "usermode")] #[cfg(emulation_mode = "usermode")]
@ -43,7 +47,10 @@ pub fn pc2basicblock(pc: GuestAddr, emu: &Emulator) -> Result<Vec<Instruction>,
let mut iaddr = pc; let mut iaddr = pc;
let mut block = Vec::<Instruction>::new(); let mut block = Vec::<Instruction>::new();
let cs = crate::capstone().detail(true).build().unwrap(); let mut cs = crate::capstone().detail(true).build().unwrap();
if let Some(m) = mode {
cs.set_mode(m).unwrap();
}
'disasm: while let Ok(insns) = cs.disasm_count(code, iaddr.into(), 1) { 'disasm: while let Ok(insns) = cs.disasm_count(code, iaddr.into(), 1) {
if insns.is_empty() { if insns.is_empty() {

View File

@ -301,12 +301,23 @@ where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
let emu = hooks.emulator(); if let Some(h) = hooks.helpers_mut().match_first_type_mut::<Self>() {
if let Some(h) = hooks.helpers().match_first_type::<Self>() {
if !h.must_instrument(pc) { if !h.must_instrument(pc) {
return None; return None;
} }
#[cfg(cpu_target = "arm")]
h.cs.set_mode(if pc & 1 == 1 {
arch::arm::ArchMode::Thumb.into()
} else {
arch::arm::ArchMode::Arm.into()
})
.unwrap();
}
let emu = hooks.emulator();
if let Some(h) = hooks.helpers().match_first_type::<Self>() {
#[allow(unused_mut)] #[allow(unused_mut)]
let mut code = { let mut code = {
#[cfg(emulation_mode = "usermode")] #[cfg(emulation_mode = "usermode")]

View File

@ -114,7 +114,16 @@ where
continue 'pcs_full; continue 'pcs_full;
} }
if *idm == *id { if *idm == *id {
match pc2basicblock(*pc, emulator) { #[cfg(cpu_target = "arm")]
let mode = if pc & 1 == 1 {
Some(capstone::arch::arm::ArchMode::Thumb.into())
} else {
Some(capstone::arch::arm::ArchMode::Arm.into())
};
#[cfg(not(cpu_target = "arm"))]
let mode = None;
match pc2basicblock(*pc, emulator, mode) {
Ok(block) => { Ok(block) => {
let mut block_len = 0; let mut block_len = 0;
for instr in &block { for instr in &block {
@ -153,7 +162,17 @@ where
if !module_found { if !module_found {
continue 'pcs; continue 'pcs;
} }
match pc2basicblock(*pc, emulator) {
#[cfg(cpu_target = "arm")]
let mode = if pc & 1 == 1 {
Some(capstone::arch::arm::ArchMode::Thumb.into())
} else {
Some(capstone::arch::arm::ArchMode::Arm.into())
};
#[cfg(not(cpu_target = "arm"))]
let mode = None;
match pc2basicblock(*pc, emulator, mode) {
Ok(block) => { Ok(block) => {
let mut block_len = 0; let mut block_len = 0;
for instr in &block { for instr in &block {