Remove capstone from frida [x86_64] (#1720)
* init * more * just fixing stuff
This commit is contained in:
parent
ee447468c6
commit
a0a4dd60bb
@ -20,7 +20,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -21,7 +21,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
@ -34,7 +34,7 @@ windows_alias = "unsupported"
|
||||
[tasks.lib_unix]
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes
|
||||
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes --disable-dependency-tracking
|
||||
cd ..
|
||||
make -C libpng-1.6.37
|
||||
'''
|
||||
|
@ -38,7 +38,7 @@ You can also fuzz libpng-1.6.37 on windows with frida mode
|
||||
### To build it with visual studio
|
||||
1. Install clang for windows (make sure you add LLVM to the system path!)
|
||||
[https://github.com/llvm/llvm-project/releases/tag/llvmorg-12.0.1](https://github.com/llvm/llvm-project/releases/tag/llvmorg-12.0.1)
|
||||
2. Download libpng-1.6.37[https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz] and zlib [https://zlib.net/fossils/zlib-1.2.11.tar.gz] into this directory, and rename `zlib-1.2.11` directory to `zlib`.
|
||||
2. Download libpng-1.6.37[https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz] and zlib [https://zlib.net/fossils/zlib-1.2.11.tar.gz] into this directory, and rename `zlib-1.2.11` directory to `zlib`.
|
||||
|
||||
3. Build libpng1.6.37
|
||||
- Open libpng-1.6.37/projects/vstudio/vstudio.sln
|
||||
|
@ -465,7 +465,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
||||
.run_client(&mut run_client)
|
||||
.cores(&options.cores)
|
||||
.broker_port(options.broker_port)
|
||||
.stdout_file(Some(&options.stdout))
|
||||
// .stdout_file(Some(&options.stdout))
|
||||
.remote_broker_addr(options.remote_broker_addr)
|
||||
.build()
|
||||
.launch()
|
||||
|
@ -21,7 +21,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = [ "./libpng-1.6.37" ] }
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -21,7 +21,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = [ "./libpng-1.6.37" ] }
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
curl https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz --output libpng-1.6.37.tar.xz
|
||||
curl https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz --output libpng-1.6.37.tar.xz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -26,7 +26,7 @@ The compiler wrappers, `libafl_cc` and `libafl_cxx`, will end up in `./target/re
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -19,7 +19,7 @@ In addition, it will also build two C and C++ compiler wrappers (bin/libafl_c(li
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
curl https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz --output libpng-1.6.37.tar.xz
|
||||
curl https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz --output libpng-1.6.37.tar.xz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -19,7 +19,7 @@ The compiler wrappers, `libafl_cc` and `libafl_cxx`, will end up in `./target/re
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -19,7 +19,7 @@ In addition, it will also build two C and C++ compiler wrappers (bin/libafl_c(li
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
curl https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz --output libpng-1.6.37.tar.xz
|
||||
curl https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz --output libpng-1.6.37.tar.xz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -26,7 +26,7 @@ The compiler wrappers, `libafl_cc` and libafl_cxx`, will end up in `./target/rel
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -19,7 +19,7 @@ In addition, it will also build two C and C++ compiler wrappers (bin/libafl_c(li
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -26,7 +26,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -19,7 +19,7 @@ In addition, it will also build two C and C++ compiler wrappers (bin/libafl_c(li
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -19,7 +19,7 @@ In addition, it will also build two C and C++ compiler wrappers (bin/libafl_c(li
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
curl https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz --output libpng-1.6.37.tar.xz
|
||||
curl https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz --output libpng-1.6.37.tar.xz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -26,7 +26,7 @@ The compiler wrappers, `libafl_cc` and `libafl_cxx`, will end up in `./target/re
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
|
||||
|
@ -25,7 +25,7 @@ The compiler wrappers, `libafl_cc` and `libafl_cxx`, will end up in `./target/re
|
||||
|
||||
Then download libpng, and unpack the archive:
|
||||
```bash
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
```
|
||||
Run `patch libpng-1.6.37/png.c diff.patch` before compiling the libpng
|
||||
|
@ -25,7 +25,7 @@ windows_alias = "unsupported"
|
||||
condition = { files_not_exist = ["./libpng-1.6.37"]}
|
||||
script_runner="@shell"
|
||||
script='''
|
||||
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
tar -xvf libpng-1.6.37.tar.xz
|
||||
'''
|
||||
|
||||
|
@ -146,7 +146,7 @@ script_runner="@shell"
|
||||
script='''
|
||||
wget \
|
||||
-O "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \
|
||||
https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
|
||||
tar \
|
||||
-xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \
|
||||
|
@ -146,7 +146,7 @@ script_runner="@shell"
|
||||
script='''
|
||||
wget \
|
||||
-O "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \
|
||||
https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
|
||||
tar \
|
||||
-xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \
|
||||
|
@ -146,7 +146,7 @@ script_runner="@shell"
|
||||
script='''
|
||||
wget \
|
||||
-O "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \
|
||||
https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
|
||||
https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
|
||||
|
||||
tar \
|
||||
-xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \
|
||||
|
@ -1,17 +1,19 @@
|
||||
use std::error::Error;
|
||||
|
||||
#[rustversion::nightly]
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rustc-cfg=nightly");
|
||||
#[cfg(feature = "unicode")]
|
||||
{
|
||||
build_unicode_property_map()?;
|
||||
// build_unicode_property_map()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[rustversion::not(nightly)]
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
assert!(
|
||||
@ -20,7 +22,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
);
|
||||
#[cfg(feature = "unicode")]
|
||||
{
|
||||
build_unicode_property_map()?;
|
||||
// build_unicode_property_map()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -28,6 +28,13 @@ serdeany_autoreg = ["libafl_bolts/serdeany_autoreg"]
|
||||
[build-dependencies]
|
||||
cc = { version = "1.0", features = ["parallel"] }
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||
capstone = "0.11.0"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
yaxpeax-x86 = { git = "https://github.com/tokatoka/yaxpeax-x86/" } # replace this with origin later
|
||||
yaxpeax-arch = "0.2.7"
|
||||
|
||||
[dependencies]
|
||||
libafl = { path = "../libafl", default-features = false, version = "0.11.1", features = [
|
||||
"std",
|
||||
@ -60,7 +67,6 @@ frida-gum = { version = "0.13.2", features = [
|
||||
"module-names",
|
||||
] }
|
||||
dynasmrt = "2"
|
||||
capstone = "0.11.0"
|
||||
color-backtrace = { version = "0.6", features = ["resolve-modules"] }
|
||||
termcolor = "1.1.3"
|
||||
serde = "1.0"
|
||||
|
@ -13,11 +13,6 @@ use core::{
|
||||
use std::{ffi::c_void, num::NonZeroUsize, ptr::write_volatile, rc::Rc};
|
||||
|
||||
use backtrace::Backtrace;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use capstone::{
|
||||
arch::{self, x86::X86OperandType, ArchOperand::X86Operand, BuildsCapstone},
|
||||
Capstone, RegAccessType, RegId,
|
||||
};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use capstone::{
|
||||
arch::{
|
||||
@ -49,16 +44,20 @@ use libc::{getrlimit, rlimit};
|
||||
use libc::{getrlimit64, rlimit64};
|
||||
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
|
||||
use rangemap::RangeMap;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use yaxpeax_x86::amd64::{InstDecoder, Instruction, Opcode};
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
use crate::utils::frida_to_cs;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::utils::instruction_width;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::utils::operand_details;
|
||||
use crate::{
|
||||
alloc::Allocator,
|
||||
asan::errors::{AsanError, AsanErrors, AsanReadWriteError, ASAN_ERRORS},
|
||||
helper::{FridaRuntime, SkipRange},
|
||||
utils::writer_register,
|
||||
utils::{disas_count, AccessType},
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
@ -922,32 +921,30 @@ impl AsanRuntime {
|
||||
let fault_address = self.regs[17];
|
||||
let actual_pc = self.regs[18];
|
||||
|
||||
let cs = Capstone::new()
|
||||
.x86()
|
||||
.mode(arch::x86::ArchMode::Mode64)
|
||||
.detail(true)
|
||||
.build()
|
||||
.expect("Failed to create Capstone object");
|
||||
let decoder = InstDecoder::minimal();
|
||||
|
||||
let instructions = cs
|
||||
.disasm_count(
|
||||
unsafe { std::slice::from_raw_parts(actual_pc as *mut u8, 24) },
|
||||
actual_pc as u64,
|
||||
3,
|
||||
)
|
||||
.expect("Failed to disassmeble");
|
||||
let instructions: Vec<Instruction> = disas_count(
|
||||
&decoder,
|
||||
unsafe { std::slice::from_raw_parts(actual_pc as *mut u8, 24) },
|
||||
3,
|
||||
);
|
||||
|
||||
let insn = instructions.as_ref().first().unwrap(); // This is the very instruction that has triggered fault
|
||||
let insn = instructions[0]; // This is the very instruction that has triggered fault
|
||||
log::info!("{insn:#?}");
|
||||
let operands = cs.insn_detail(insn).unwrap().arch_detail().operands();
|
||||
let operand_count = insn.operand_count();
|
||||
|
||||
let mut access_type: Option<RegAccessType> = None;
|
||||
let mut regs: Option<(RegId, RegId, i64)> = None;
|
||||
for operand in operands {
|
||||
if let X86Operand(x86operand) = operand {
|
||||
if let X86OperandType::Mem(mem) = x86operand.op_type {
|
||||
access_type = x86operand.access;
|
||||
regs = Some((mem.base(), mem.index(), mem.disp()));
|
||||
let mut access_type: Option<AccessType> = None;
|
||||
let mut regs: Option<(X86Register, X86Register, i32)> = None;
|
||||
for operand_idx in 0..operand_count {
|
||||
let operand = insn.operand(operand_idx);
|
||||
if operand.is_memory() {
|
||||
access_type = if operand_idx == 0 {
|
||||
Some(AccessType::Read)
|
||||
} else {
|
||||
Some(AccessType::Write)
|
||||
};
|
||||
if let Some((basereg, indexreg, _, disp)) = operand_details(&operand) {
|
||||
regs = Some((basereg, indexreg, disp));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -956,22 +953,24 @@ impl AsanRuntime {
|
||||
let (stack_start, stack_end) = Self::current_stack();
|
||||
|
||||
if let Some(r) = regs {
|
||||
let (base_idx, size) = self.register_idx(r.0); // safe to unwrap
|
||||
let (index_idx, _) = self.register_idx(r.1);
|
||||
let base = self.register_idx(r.0); // safe to unwrap
|
||||
let index = self.register_idx(r.1);
|
||||
let disp = r.2;
|
||||
|
||||
// from capstone register id to self.regs's index
|
||||
let base_value = match base_idx {
|
||||
Some(base) => match size {
|
||||
Some(sz) => {
|
||||
if sz == 64 {
|
||||
Some(self.regs[base as usize])
|
||||
} else {
|
||||
Some(self.regs[base as usize] & 0xffffffff)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
let (base_idx, base_value) = match base {
|
||||
Some((idx, size)) => {
|
||||
let value = if size == 64 {
|
||||
Some(self.regs[idx as usize])
|
||||
} else {
|
||||
Some(self.regs[idx as usize] & 0xffffffff)
|
||||
};
|
||||
(Some(idx), value)
|
||||
}
|
||||
_ => (None, None),
|
||||
};
|
||||
|
||||
let index_idx = match index {
|
||||
Some((idx, _)) => Some(idx),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -980,13 +979,13 @@ impl AsanRuntime {
|
||||
let error = if fault_address >= stack_start && fault_address < stack_end {
|
||||
match access_type {
|
||||
Some(typ) => match typ {
|
||||
RegAccessType::ReadOnly => AsanError::StackOobRead((
|
||||
AccessType::Read => AsanError::StackOobRead((
|
||||
self.regs,
|
||||
actual_pc,
|
||||
(base_idx, index_idx, disp as usize, fault_address),
|
||||
backtrace,
|
||||
)),
|
||||
_ => AsanError::StackOobWrite((
|
||||
AccessType::Write => AsanError::StackOobWrite((
|
||||
self.regs,
|
||||
actual_pc,
|
||||
(base_idx, index_idx, disp as usize, fault_address),
|
||||
@ -1015,14 +1014,14 @@ impl AsanRuntime {
|
||||
backtrace,
|
||||
};
|
||||
match typ {
|
||||
RegAccessType::ReadOnly => {
|
||||
AccessType::Read => {
|
||||
if metadata.freed {
|
||||
AsanError::ReadAfterFree(asan_readwrite_error)
|
||||
} else {
|
||||
AsanError::OobRead(asan_readwrite_error)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
AccessType::Write => {
|
||||
if metadata.freed {
|
||||
AsanError::WriteAfterFree(asan_readwrite_error)
|
||||
} else {
|
||||
@ -1245,43 +1244,43 @@ impl AsanRuntime {
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[allow(clippy::unused_self)]
|
||||
fn register_idx(&self, capid: RegId) -> (Option<u16>, Option<u16>) {
|
||||
match capid.0 {
|
||||
19 => (Some(0), Some(32)),
|
||||
22 => (Some(2), Some(32)),
|
||||
24 => (Some(3), Some(32)),
|
||||
21 => (Some(1), Some(32)),
|
||||
30 => (Some(5), Some(32)),
|
||||
20 => (Some(4), Some(32)),
|
||||
29 => (Some(6), Some(32)),
|
||||
23 => (Some(7), Some(32)),
|
||||
226 => (Some(8), Some(32)),
|
||||
227 => (Some(9), Some(32)),
|
||||
228 => (Some(10), Some(32)),
|
||||
229 => (Some(11), Some(32)),
|
||||
230 => (Some(12), Some(32)),
|
||||
231 => (Some(13), Some(32)),
|
||||
232 => (Some(14), Some(32)),
|
||||
233 => (Some(15), Some(32)),
|
||||
26 => (Some(18), Some(32)),
|
||||
35 => (Some(0), Some(64)),
|
||||
38 => (Some(2), Some(64)),
|
||||
40 => (Some(3), Some(64)),
|
||||
37 => (Some(1), Some(64)),
|
||||
44 => (Some(5), Some(64)),
|
||||
36 => (Some(4), Some(64)),
|
||||
43 => (Some(6), Some(64)),
|
||||
39 => (Some(7), Some(64)),
|
||||
106 => (Some(8), Some(64)),
|
||||
107 => (Some(9), Some(64)),
|
||||
108 => (Some(10), Some(64)),
|
||||
109 => (Some(11), Some(64)),
|
||||
110 => (Some(12), Some(64)),
|
||||
111 => (Some(13), Some(64)),
|
||||
112 => (Some(14), Some(64)),
|
||||
113 => (Some(15), Some(64)),
|
||||
41 => (Some(18), Some(64)),
|
||||
_ => (None, None),
|
||||
fn register_idx(&self, reg: X86Register) -> Option<(u16, u16)> {
|
||||
match reg {
|
||||
X86Register::Eax => Some((0, 32)),
|
||||
X86Register::Ecx => Some((2, 32)),
|
||||
X86Register::Edx => Some((3, 32)),
|
||||
X86Register::Ebx => Some((1, 32)),
|
||||
X86Register::Esp => Some((5, 32)),
|
||||
X86Register::Ebp => Some((4, 32)),
|
||||
X86Register::Esi => Some((6, 32)),
|
||||
X86Register::Edi => Some((7, 32)),
|
||||
X86Register::R8d => Some((8, 32)),
|
||||
X86Register::R9d => Some((9, 32)),
|
||||
X86Register::R10d => Some((10, 32)),
|
||||
X86Register::R11d => Some((11, 32)),
|
||||
X86Register::R12d => Some((12, 32)),
|
||||
X86Register::R13d => Some((13, 32)),
|
||||
X86Register::R14d => Some((14, 32)),
|
||||
X86Register::R15d => Some((15, 32)),
|
||||
X86Register::Eip => Some((18, 32)),
|
||||
X86Register::Rax => Some((0, 4)),
|
||||
X86Register::Rcx => Some((2, 4)),
|
||||
X86Register::Rdx => Some((3, 4)),
|
||||
X86Register::Rbx => Some((1, 4)),
|
||||
X86Register::Rsp => Some((5, 4)),
|
||||
X86Register::Rbp => Some((4, 4)),
|
||||
X86Register::Rsi => Some((6, 4)),
|
||||
X86Register::Rdi => Some((7, 4)),
|
||||
X86Register::R8 => Some((8, 64)),
|
||||
X86Register::R9 => Some((9, 64)),
|
||||
X86Register::R10 => Some((10, 64)),
|
||||
X86Register::R11 => Some((11, 64)),
|
||||
X86Register::R12 => Some((12, 64)),
|
||||
X86Register::R13 => Some((13, 64)),
|
||||
X86Register::R14 => Some((14, 64)),
|
||||
X86Register::R15 => Some((15, 64)),
|
||||
X86Register::Rip => Some((18, 64)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2248,60 +2247,46 @@ impl AsanRuntime {
|
||||
#[must_use]
|
||||
#[allow(clippy::result_unit_err)]
|
||||
pub fn asan_is_interesting_instruction(
|
||||
capstone: &Capstone,
|
||||
decoder: InstDecoder,
|
||||
_address: u64,
|
||||
instr: &Insn,
|
||||
) -> Option<(RegId, u8, RegId, RegId, i32, i64)> {
|
||||
) -> Option<(u8, X86Register, X86Register, u8, i32)> {
|
||||
// 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(cs_instr)
|
||||
.unwrap()
|
||||
.arch_detail()
|
||||
.operands();
|
||||
let cs_instr = frida_to_cs(decoder, instr);
|
||||
let mut operands = vec![];
|
||||
for operand_idx in 0..cs_instr.operand_count() {
|
||||
operands.push(cs_instr.operand(operand_idx));
|
||||
}
|
||||
|
||||
// Ignore lea instruction
|
||||
// put nop into the white-list so that instructions like
|
||||
// like `nop dword [rax + rax]` does not get caught.
|
||||
match cs_instr.mnemonic().unwrap() {
|
||||
"lea" | "nop" => return None,
|
||||
match cs_instr.opcode() {
|
||||
Opcode::LEA | Opcode::NOP => return None,
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// 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 cs_instr.mnemonic().unwrap().starts_with("rep") {
|
||||
if cs_instr.prefixes.rep_any() {
|
||||
return None;
|
||||
}
|
||||
|
||||
for operand in operands {
|
||||
if let X86Operand(x86operand) = operand {
|
||||
if let X86OperandType::Mem(opmem) = x86operand.op_type {
|
||||
/*
|
||||
log::trace!(
|
||||
"insn: {:#?} {:#?} width: {}, segment: {:#?}, base: {:#?}, index: {:#?}, scale: {}, disp: {}",
|
||||
insn_id,
|
||||
instr,
|
||||
x86operand.size,
|
||||
opmem.segment(),
|
||||
opmem.base(),
|
||||
opmem.index(),
|
||||
opmem.scale(),
|
||||
opmem.disp(),
|
||||
);
|
||||
*/
|
||||
if opmem.segment() == RegId(0) {
|
||||
return Some((
|
||||
opmem.segment(),
|
||||
x86operand.size,
|
||||
opmem.base(),
|
||||
opmem.index(),
|
||||
opmem.scale(),
|
||||
opmem.disp(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if operand.is_memory() {
|
||||
// log::trace!("{:#?}", operand)
|
||||
// if we reach this point
|
||||
// because in x64 there's no mem to mem inst, just return the first memory operand
|
||||
|
||||
if let Some((basereg, indexreg, scale, disp)) = operand_details(&operand) {
|
||||
let memsz = cs_instr.mem_size().unwrap().bytes_size().unwrap(); // this won't fail if it is mem access inst
|
||||
|
||||
// println!("{:#?} {:#?} {:#?}", cs_instr, cs_instr.to_string(), operand);
|
||||
// println!("{:#?}", (memsz, basereg, indexreg, scale, disp));
|
||||
|
||||
return Some((memsz, basereg, indexreg, scale, disp));
|
||||
} // else {} // perhaps avx instructions?
|
||||
}
|
||||
}
|
||||
|
||||
@ -2317,29 +2302,26 @@ impl AsanRuntime {
|
||||
&mut self,
|
||||
address: u64,
|
||||
output: &StalkerOutput,
|
||||
_segment: RegId,
|
||||
width: u8,
|
||||
basereg: RegId,
|
||||
indexreg: RegId,
|
||||
scale: i32,
|
||||
disp: isize,
|
||||
basereg: X86Register,
|
||||
indexreg: X86Register,
|
||||
scale: u8,
|
||||
disp: i32,
|
||||
) {
|
||||
let redzone_size = isize::try_from(frida_gum_sys::GUM_RED_ZONE_SIZE).unwrap();
|
||||
let writer = output.writer();
|
||||
let true_rip = address;
|
||||
|
||||
let basereg = if basereg.0 == 0 {
|
||||
let basereg: Option<X86Register> = if basereg == X86Register::None {
|
||||
None
|
||||
} else {
|
||||
let reg = writer_register(basereg);
|
||||
Some(reg)
|
||||
Some(basereg)
|
||||
};
|
||||
|
||||
let indexreg = if indexreg.0 == 0 {
|
||||
let indexreg = if indexreg == X86Register::None {
|
||||
None
|
||||
} else {
|
||||
let reg = writer_register(indexreg);
|
||||
Some(reg)
|
||||
Some(indexreg)
|
||||
};
|
||||
|
||||
let scale = match scale {
|
||||
@ -2447,7 +2429,7 @@ impl AsanRuntime {
|
||||
|
||||
// Finally set Rdi to base + index * scale + disp
|
||||
writer.put_add_reg_reg(X86Register::Rdi, X86Register::Rsi);
|
||||
writer.put_lea_reg_reg_offset(X86Register::Rdi, X86Register::Rdi, disp);
|
||||
writer.put_lea_reg_reg_offset(X86Register::Rdi, X86Register::Rdi, disp as isize);
|
||||
|
||||
writer.put_mov_reg_address(X86Register::Rsi, true_rip); // load true_rip into rsi in case we need them in handle_trap
|
||||
writer.put_push_reg(X86Register::Rsi); // save true_rip
|
||||
|
@ -2,7 +2,6 @@
|
||||
use std::{fmt::Debug, io::Write, marker::PhantomData};
|
||||
|
||||
use backtrace::Backtrace;
|
||||
use capstone::{arch::BuildsCapstone, Capstone};
|
||||
use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use frida_gum::interceptor::Interceptor;
|
||||
@ -20,10 +19,16 @@ use libafl::{
|
||||
use libafl_bolts::{ownedref::OwnedPtr, Named, SerdeAny};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use termcolor::{Color, ColorSpec, WriteColor};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use yaxpeax_arch::LengthedInstruction;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use yaxpeax_x86::amd64::InstDecoder;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::asan::asan_rt::ASAN_SAVE_REGISTER_NAMES;
|
||||
use crate::{alloc::AllocationMetadata, asan::asan_rt::ASAN_SAVE_REGISTER_COUNT};
|
||||
use crate::{
|
||||
alloc::AllocationMetadata, asan::asan_rt::ASAN_SAVE_REGISTER_COUNT, utils::disas_count,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct AsanReadWriteError {
|
||||
@ -241,25 +246,18 @@ impl AsanErrors {
|
||||
.unwrap();
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let mut cs = Capstone::new()
|
||||
.x86()
|
||||
.mode(capstone::arch::x86::ArchMode::Mode64)
|
||||
.detail(true)
|
||||
.build()
|
||||
.expect("Failed to create Capstone object");
|
||||
|
||||
cs.set_skipdata(true).expect("failed to set skipdata");
|
||||
let decoder = InstDecoder::minimal();
|
||||
|
||||
let start_pc = error.pc - 4 * 5;
|
||||
for insn in &*cs
|
||||
.disasm_count(
|
||||
unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 4 * 11) },
|
||||
start_pc as u64,
|
||||
11,
|
||||
)
|
||||
.expect("failed to disassemble instructions")
|
||||
{
|
||||
if insn.address() as usize == error.pc {
|
||||
let insts = disas_count(
|
||||
&decoder,
|
||||
unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 15 * 11) },
|
||||
11,
|
||||
);
|
||||
let mut inst_address = start_pc;
|
||||
|
||||
for insn in insts {
|
||||
if inst_address == error.pc {
|
||||
output
|
||||
.set_color(ColorSpec::new().set_fg(Some(Color::Red)))
|
||||
.unwrap();
|
||||
@ -268,6 +266,8 @@ impl AsanErrors {
|
||||
} else {
|
||||
writeln!(output, "\t {insn}").unwrap();
|
||||
}
|
||||
|
||||
inst_address += insn.len().to_const() as usize;
|
||||
}
|
||||
backtrace_printer
|
||||
.print_trace(&error.backtrace, output)
|
||||
@ -496,25 +496,18 @@ impl AsanErrors {
|
||||
.unwrap();
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let mut cs = Capstone::new()
|
||||
.x86()
|
||||
.mode(capstone::arch::x86::ArchMode::Mode64)
|
||||
.detail(true)
|
||||
.build()
|
||||
.expect("Failed to create Capstone object");
|
||||
|
||||
cs.set_skipdata(true).expect("failed to set skipdata");
|
||||
let decoder = InstDecoder::minimal();
|
||||
|
||||
let start_pc = pc;
|
||||
for insn in &*cs
|
||||
.disasm_count(
|
||||
unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 4 * 11) },
|
||||
start_pc as u64,
|
||||
11,
|
||||
)
|
||||
.expect("failed to disassemble instructions")
|
||||
{
|
||||
if insn.address() as usize == pc {
|
||||
let insts = disas_count(
|
||||
&decoder,
|
||||
unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 15 * 11) },
|
||||
11,
|
||||
);
|
||||
|
||||
let mut inst_address = start_pc;
|
||||
for insn in insts {
|
||||
if inst_address == pc {
|
||||
output
|
||||
.set_color(ColorSpec::new().set_fg(Some(Color::Red)))
|
||||
.unwrap();
|
||||
@ -523,6 +516,8 @@ impl AsanErrors {
|
||||
} else {
|
||||
writeln!(output, "\t {insn}").unwrap();
|
||||
}
|
||||
|
||||
inst_address += insn.len().to_const() as usize;
|
||||
}
|
||||
backtrace_printer.print_trace(&backtrace, output).unwrap();
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use std::{
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
#[cfg(any(target_arch = "aarch64", all(target_arch = "x86_64", unix)))]
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use capstone::{
|
||||
arch::{self, BuildsCapstone},
|
||||
Capstone,
|
||||
@ -27,6 +27,8 @@ use libafl_targets::drcov::DrCovBasicBlock;
|
||||
#[cfg(unix)]
|
||||
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
|
||||
use rangemap::RangeMap;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use yaxpeax_x86::amd64::InstDecoder;
|
||||
|
||||
#[cfg(all(feature = "cmplog", target_arch = "aarch64"))]
|
||||
use crate::cmplog_rt::CmpLogRuntime;
|
||||
@ -450,13 +452,9 @@ where
|
||||
.detail(true)
|
||||
.build()
|
||||
.expect("Failed to create Capstone object");
|
||||
#[cfg(all(target_arch = "x86_64", unix))]
|
||||
let capstone = Capstone::new()
|
||||
.x86()
|
||||
.mode(arch::x86::ArchMode::Mode64)
|
||||
.detail(true)
|
||||
.build()
|
||||
.expect("Failed to create Capstone object");
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let decoder = InstDecoder::minimal();
|
||||
|
||||
Transformer::from_callback(gum, move |basic_block, output| {
|
||||
Self::transform(
|
||||
@ -464,8 +462,10 @@ where
|
||||
&output,
|
||||
&ranges,
|
||||
&runtimes,
|
||||
#[cfg(any(target_arch = "aarch64", all(target_arch = "x86_64", unix)))]
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
&capstone,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
decoder,
|
||||
);
|
||||
})
|
||||
}
|
||||
@ -475,7 +475,7 @@ where
|
||||
output: &StalkerOutput,
|
||||
ranges: &Rc<RefCell<RangeMap<usize, (u16, String)>>>,
|
||||
runtimes: &Rc<RefCell<RT>>,
|
||||
#[cfg(any(target_arch = "aarch64", all(target_arch = "x86_64", unix)))] capstone: &Capstone,
|
||||
decoder: InstDecoder,
|
||||
) {
|
||||
let mut first = true;
|
||||
let mut basic_block_start = 0;
|
||||
@ -508,23 +508,16 @@ where
|
||||
|
||||
#[cfg(unix)]
|
||||
let res = if let Some(_rt) = runtimes.match_first_type_mut::<AsanRuntime>() {
|
||||
AsanRuntime::asan_is_interesting_instruction(capstone, address, instr)
|
||||
AsanRuntime::asan_is_interesting_instruction(decoder, address, instr)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", unix))]
|
||||
if let Some((segment, width, basereg, indexreg, scale, disp)) = res {
|
||||
if let Some(details) = res {
|
||||
if let Some(rt) = runtimes.match_first_type_mut::<AsanRuntime>() {
|
||||
rt.emit_shadow_check(
|
||||
address,
|
||||
output,
|
||||
segment,
|
||||
width,
|
||||
basereg,
|
||||
indexreg,
|
||||
scale,
|
||||
disp.try_into().unwrap(),
|
||||
address, output, details.0, details.1, details.2, details.3, details.4,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use capstone::Capstone;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use capstone::{
|
||||
@ -13,6 +13,11 @@ use frida_gum::instruction_writer::X86Register;
|
||||
use frida_gum_sys;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use num_traits::cast::FromPrimitive;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use yaxpeax_arch::LengthedInstruction;
|
||||
use yaxpeax_x86::amd64::Operand;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use yaxpeax_x86::amd64::{InstDecoder, Instruction, RegSpec};
|
||||
|
||||
/// Determine the width of the specified instruction
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@ -89,6 +94,44 @@ pub fn writer_register(reg: capstone::RegId) -> Aarch64Register {
|
||||
Aarch64Register::from_u32(u32::from(regint)).unwrap()
|
||||
}
|
||||
|
||||
/// Translate from `RegSpec` to `X86Register`
|
||||
const X86_64_REGS: [(RegSpec, X86Register); 34] = [
|
||||
(RegSpec::eax(), X86Register::Eax),
|
||||
(RegSpec::ecx(), X86Register::Ecx),
|
||||
(RegSpec::edx(), X86Register::Edx),
|
||||
(RegSpec::ebx(), X86Register::Ebx),
|
||||
(RegSpec::esp(), X86Register::Esp),
|
||||
(RegSpec::ebp(), X86Register::Ebp),
|
||||
(RegSpec::esi(), X86Register::Esi),
|
||||
(RegSpec::edi(), X86Register::Edi),
|
||||
(RegSpec::r8d(), X86Register::R8d),
|
||||
(RegSpec::r9d(), X86Register::R9d),
|
||||
(RegSpec::r10d(), X86Register::R10d),
|
||||
(RegSpec::r11d(), X86Register::R11d),
|
||||
(RegSpec::r12d(), X86Register::R12d),
|
||||
(RegSpec::r13d(), X86Register::R13d),
|
||||
(RegSpec::r14d(), X86Register::R14d),
|
||||
(RegSpec::r15d(), X86Register::R15d),
|
||||
(RegSpec::eip(), X86Register::Eip),
|
||||
(RegSpec::rax(), X86Register::Rax),
|
||||
(RegSpec::rcx(), X86Register::Rcx),
|
||||
(RegSpec::rdx(), X86Register::Rdx),
|
||||
(RegSpec::rbx(), X86Register::Rbx),
|
||||
(RegSpec::rsp(), X86Register::Rsp),
|
||||
(RegSpec::rbp(), X86Register::Rbp),
|
||||
(RegSpec::rsi(), X86Register::Rsi),
|
||||
(RegSpec::rdi(), X86Register::Rdi),
|
||||
(RegSpec::r8(), X86Register::R8),
|
||||
(RegSpec::r9(), X86Register::R9),
|
||||
(RegSpec::r10(), X86Register::R10),
|
||||
(RegSpec::r11(), X86Register::R11),
|
||||
(RegSpec::r12(), X86Register::R12),
|
||||
(RegSpec::r13(), X86Register::R13),
|
||||
(RegSpec::r14(), X86Register::R14),
|
||||
(RegSpec::r15(), X86Register::R15),
|
||||
(RegSpec::rip(), X86Register::Rip),
|
||||
];
|
||||
|
||||
/// The writer registers
|
||||
/// frida registers: <https://docs.rs/frida-gum/0.4.0/frida_gum/instruction_writer/enum.X86Register.html>
|
||||
/// capstone registers: <https://docs.rs/capstone-sys/0.14.0/capstone_sys/x86_reg/index.html>
|
||||
@ -96,55 +139,93 @@ pub fn writer_register(reg: capstone::RegId) -> Aarch64Register {
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[allow(clippy::unused_self)]
|
||||
pub fn writer_register(reg: capstone::RegId) -> X86Register {
|
||||
let regint: u16 = reg.0;
|
||||
match regint {
|
||||
19 => X86Register::Eax,
|
||||
22 => X86Register::Ecx,
|
||||
24 => X86Register::Edx,
|
||||
21 => X86Register::Ebx,
|
||||
30 => X86Register::Esp,
|
||||
20 => X86Register::Ebp,
|
||||
29 => X86Register::Esi,
|
||||
23 => X86Register::Edi,
|
||||
226 => X86Register::R8d,
|
||||
227 => X86Register::R9d,
|
||||
228 => X86Register::R10d,
|
||||
229 => X86Register::R11d,
|
||||
230 => X86Register::R12d,
|
||||
231 => X86Register::R13d,
|
||||
232 => X86Register::R14d,
|
||||
233 => X86Register::R15d,
|
||||
26 => X86Register::Eip,
|
||||
35 => X86Register::Rax,
|
||||
38 => X86Register::Rcx,
|
||||
40 => X86Register::Rdx,
|
||||
37 => X86Register::Rbx,
|
||||
44 => X86Register::Rsp,
|
||||
36 => X86Register::Rbp,
|
||||
43 => X86Register::Rsi,
|
||||
39 => X86Register::Rdi,
|
||||
106 => X86Register::R8,
|
||||
107 => X86Register::R9,
|
||||
108 => X86Register::R10,
|
||||
109 => X86Register::R11,
|
||||
110 => X86Register::R12,
|
||||
111 => X86Register::R13,
|
||||
112 => X86Register::R14,
|
||||
113 => X86Register::R15,
|
||||
41 => X86Register::Rip,
|
||||
_ => X86Register::None, // Ignore Xax..Xip
|
||||
pub fn writer_register(reg: RegSpec) -> X86Register {
|
||||
for (reg1, reg2) in &X86_64_REGS {
|
||||
// println!("reg1:{:#?} reg2:{:#?}", reg1, reg);
|
||||
if *reg1 == reg {
|
||||
return *reg2;
|
||||
}
|
||||
}
|
||||
X86Register::None
|
||||
}
|
||||
|
||||
/// 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()
|
||||
pub(crate) fn frida_to_cs(decoder: InstDecoder, frida_insn: &frida_gum_sys::Insn) -> Instruction {
|
||||
decoder.decode_slice(frida_insn.bytes()).unwrap()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// Get the base, idx, scale, disp for each operand
|
||||
pub fn operand_details(operand: &Operand) -> Option<(X86Register, X86Register, u8, i32)> {
|
||||
match operand {
|
||||
Operand::RegDeref(base) => {
|
||||
let base = writer_register(*base);
|
||||
Some((base, X86Register::None, 0, 0))
|
||||
}
|
||||
Operand::RegDisp(base, disp) => {
|
||||
let base = writer_register(*base);
|
||||
Some((base, X86Register::None, 0, *disp))
|
||||
}
|
||||
Operand::RegScale(base, scale) => {
|
||||
let base = writer_register(*base);
|
||||
Some((base, X86Register::None, *scale, 0))
|
||||
}
|
||||
Operand::RegIndexBase(base, index) => {
|
||||
let base = writer_register(*base);
|
||||
let index = writer_register(*index);
|
||||
Some((base, index, 0, 0))
|
||||
}
|
||||
Operand::RegIndexBaseDisp(base, index, disp) => {
|
||||
let base = writer_register(*base);
|
||||
let index = writer_register(*index);
|
||||
Some((base, index, 0, *disp))
|
||||
}
|
||||
Operand::RegScaleDisp(base, scale, disp) => {
|
||||
let base = writer_register(*base);
|
||||
Some((base, X86Register::None, *scale, *disp))
|
||||
}
|
||||
Operand::RegIndexBaseScale(base, index, scale) => {
|
||||
let base = writer_register(*base);
|
||||
let index = writer_register(*index);
|
||||
Some((base, index, *scale, 0))
|
||||
}
|
||||
Operand::RegIndexBaseScaleDisp(base, index, scale, disp) => {
|
||||
let base = writer_register(*base);
|
||||
let index = writer_register(*index);
|
||||
Some((base, index, *scale, *disp))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// What kind of memory access this instruction has
|
||||
pub enum AccessType {
|
||||
/// Read-access
|
||||
Read,
|
||||
/// Write-access
|
||||
Write,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// Disassemble "count" number of instructions
|
||||
pub fn disas_count(decoder: &InstDecoder, data: &[u8], count: usize) -> Vec<Instruction> {
|
||||
let mut counter = count;
|
||||
let mut ret = vec![];
|
||||
let mut start = 0;
|
||||
loop {
|
||||
if counter == 0 {
|
||||
break ret;
|
||||
}
|
||||
let Ok(inst) = decoder.decode_slice(&data[start..]) else {
|
||||
break ret;
|
||||
};
|
||||
start += inst.len().to_const() as usize;
|
||||
|
||||
ret.push(inst);
|
||||
counter -= 1;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ fi
|
||||
echo "[*] Checking QEMU-Nyx ..."
|
||||
if [ ! -f "QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64" ]; then
|
||||
cd QEMU-Nyx/ || return
|
||||
./compile_qemu_nyx.sh static || exit 1
|
||||
./compile_qemu_nyx.sh lto || exit 1
|
||||
cd ..
|
||||
fi
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user