Remove capstone from frida [x86_64] (#1720)

* init

* more

* just fixing stuff
This commit is contained in:
Dongjia "toka" Zhang 2023-12-16 02:39:11 +09:00 committed by GitHub
parent ee447468c6
commit a0a4dd60bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 328 additions and 269 deletions

View File

@ -20,7 +20,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -21,7 +21,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''
@ -34,7 +34,7 @@ windows_alias = "unsupported"
[tasks.lib_unix] [tasks.lib_unix]
script_runner="@shell" script_runner="@shell"
script=''' 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 .. cd ..
make -C libpng-1.6.37 make -C libpng-1.6.37
''' '''

View File

@ -38,7 +38,7 @@ You can also fuzz libpng-1.6.37 on windows with frida mode
### To build it with visual studio ### To build it with visual studio
1. Install clang for windows (make sure you add LLVM to the system path!) 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) [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 3. Build libpng1.6.37
- Open libpng-1.6.37/projects/vstudio/vstudio.sln - Open libpng-1.6.37/projects/vstudio/vstudio.sln

View File

@ -465,7 +465,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
.run_client(&mut run_client) .run_client(&mut run_client)
.cores(&options.cores) .cores(&options.cores)
.broker_port(options.broker_port) .broker_port(options.broker_port)
.stdout_file(Some(&options.stdout)) // .stdout_file(Some(&options.stdout))
.remote_broker_addr(options.remote_broker_addr) .remote_broker_addr(options.remote_broker_addr)
.build() .build()
.launch() .launch()

View File

@ -21,7 +21,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = [ "./libpng-1.6.37" ] } condition = { files_not_exist = [ "./libpng-1.6.37" ] }
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -21,7 +21,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = [ "./libpng-1.6.37" ] } condition = { files_not_exist = [ "./libpng-1.6.37" ] }
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -26,7 +26,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```

View File

@ -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: Then download libpng, and unpack the archive:
```bash ```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 tar -xvf libpng-1.6.37.tar.xz
``` ```
Run `patch libpng-1.6.37/png.c diff.patch` before compiling the libpng Run `patch libpng-1.6.37/png.c diff.patch` before compiling the libpng

View File

@ -25,7 +25,7 @@ windows_alias = "unsupported"
condition = { files_not_exist = ["./libpng-1.6.37"]} condition = { files_not_exist = ["./libpng-1.6.37"]}
script_runner="@shell" script_runner="@shell"
script=''' 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 tar -xvf libpng-1.6.37.tar.xz
''' '''

View File

@ -146,7 +146,7 @@ script_runner="@shell"
script=''' script='''
wget \ wget \
-O "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \ -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 \ tar \
-xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \ -xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \

View File

@ -146,7 +146,7 @@ script_runner="@shell"
script=''' script='''
wget \ wget \
-O "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \ -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 \ tar \
-xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \ -xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \

View File

@ -146,7 +146,7 @@ script_runner="@shell"
script=''' script='''
wget \ wget \
-O "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \ -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 \ tar \
-xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \ -xvf "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/deps/libpng-1.6.37.tar.xz" \

View File

@ -1,17 +1,19 @@
use std::error::Error; use std::error::Error;
#[rustversion::nightly] #[rustversion::nightly]
#[allow(clippy::unnecessary_wraps)]
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rustc-cfg=nightly"); println!("cargo:rustc-cfg=nightly");
#[cfg(feature = "unicode")] #[cfg(feature = "unicode")]
{ {
build_unicode_property_map()?; // build_unicode_property_map()?;
} }
Ok(()) Ok(())
} }
#[rustversion::not(nightly)] #[rustversion::not(nightly)]
#[allow(clippy::unnecessary_wraps)]
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
assert!( assert!(
@ -20,7 +22,7 @@ fn main() -> Result<(), Box<dyn Error>> {
); );
#[cfg(feature = "unicode")] #[cfg(feature = "unicode")]
{ {
build_unicode_property_map()?; // build_unicode_property_map()?;
} }
Ok(()) Ok(())
} }

View File

@ -28,6 +28,13 @@ serdeany_autoreg = ["libafl_bolts/serdeany_autoreg"]
[build-dependencies] [build-dependencies]
cc = { version = "1.0", features = ["parallel"] } 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] [dependencies]
libafl = { path = "../libafl", default-features = false, version = "0.11.1", features = [ libafl = { path = "../libafl", default-features = false, version = "0.11.1", features = [
"std", "std",
@ -60,7 +67,6 @@ frida-gum = { version = "0.13.2", features = [
"module-names", "module-names",
] } ] }
dynasmrt = "2" dynasmrt = "2"
capstone = "0.11.0"
color-backtrace = { version = "0.6", features = ["resolve-modules"] } color-backtrace = { version = "0.6", features = ["resolve-modules"] }
termcolor = "1.1.3" termcolor = "1.1.3"
serde = "1.0" serde = "1.0"

View File

@ -13,11 +13,6 @@ use core::{
use std::{ffi::c_void, num::NonZeroUsize, ptr::write_volatile, rc::Rc}; use std::{ffi::c_void, num::NonZeroUsize, ptr::write_volatile, rc::Rc};
use backtrace::Backtrace; use backtrace::Backtrace;
#[cfg(target_arch = "x86_64")]
use capstone::{
arch::{self, x86::X86OperandType, ArchOperand::X86Operand, BuildsCapstone},
Capstone, RegAccessType, RegId,
};
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use capstone::{ use capstone::{
arch::{ arch::{
@ -49,16 +44,20 @@ use libc::{getrlimit, rlimit};
use libc::{getrlimit64, rlimit64}; use libc::{getrlimit64, rlimit64};
use nix::sys::mman::{mmap, MapFlags, ProtFlags}; use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use rangemap::RangeMap; use rangemap::RangeMap;
#[cfg(target_arch = "x86_64")]
use yaxpeax_x86::amd64::{InstDecoder, Instruction, Opcode};
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
use crate::utils::frida_to_cs; use crate::utils::frida_to_cs;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use crate::utils::instruction_width; use crate::utils::instruction_width;
#[cfg(target_arch = "x86_64")]
use crate::utils::operand_details;
use crate::{ use crate::{
alloc::Allocator, alloc::Allocator,
asan::errors::{AsanError, AsanErrors, AsanReadWriteError, ASAN_ERRORS}, asan::errors::{AsanError, AsanErrors, AsanReadWriteError, ASAN_ERRORS},
helper::{FridaRuntime, SkipRange}, helper::{FridaRuntime, SkipRange},
utils::writer_register, utils::{disas_count, AccessType},
}; };
extern "C" { extern "C" {
@ -922,32 +921,30 @@ impl AsanRuntime {
let fault_address = self.regs[17]; let fault_address = self.regs[17];
let actual_pc = self.regs[18]; let actual_pc = self.regs[18];
let cs = Capstone::new() let decoder = InstDecoder::minimal();
.x86()
.mode(arch::x86::ArchMode::Mode64)
.detail(true)
.build()
.expect("Failed to create Capstone object");
let instructions = cs let instructions: Vec<Instruction> = disas_count(
.disasm_count( &decoder,
unsafe { std::slice::from_raw_parts(actual_pc as *mut u8, 24) }, unsafe { std::slice::from_raw_parts(actual_pc as *mut u8, 24) },
actual_pc as u64,
3, 3,
) );
.expect("Failed to disassmeble");
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:#?}"); 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 access_type: Option<AccessType> = None;
let mut regs: Option<(RegId, RegId, i64)> = None; let mut regs: Option<(X86Register, X86Register, i32)> = None;
for operand in operands { for operand_idx in 0..operand_count {
if let X86Operand(x86operand) = operand { let operand = insn.operand(operand_idx);
if let X86OperandType::Mem(mem) = x86operand.op_type { if operand.is_memory() {
access_type = x86operand.access; access_type = if operand_idx == 0 {
regs = Some((mem.base(), mem.index(), mem.disp())); 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(); let (stack_start, stack_end) = Self::current_stack();
if let Some(r) = regs { if let Some(r) = regs {
let (base_idx, size) = self.register_idx(r.0); // safe to unwrap let base = self.register_idx(r.0); // safe to unwrap
let (index_idx, _) = self.register_idx(r.1); let index = self.register_idx(r.1);
let disp = r.2; let disp = r.2;
// from capstone register id to self.regs's index let (base_idx, base_value) = match base {
let base_value = match base_idx { Some((idx, size)) => {
Some(base) => match size { let value = if size == 64 {
Some(sz) => { Some(self.regs[idx as usize])
if sz == 64 {
Some(self.regs[base as usize])
} else { } else {
Some(self.regs[base as usize] & 0xffffffff) Some(self.regs[idx as usize] & 0xffffffff)
};
(Some(idx), value)
} }
} _ => (None, None),
_ => None, };
},
let index_idx = match index {
Some((idx, _)) => Some(idx),
_ => None, _ => None,
}; };
@ -980,13 +979,13 @@ impl AsanRuntime {
let error = if fault_address >= stack_start && fault_address < stack_end { let error = if fault_address >= stack_start && fault_address < stack_end {
match access_type { match access_type {
Some(typ) => match typ { Some(typ) => match typ {
RegAccessType::ReadOnly => AsanError::StackOobRead(( AccessType::Read => AsanError::StackOobRead((
self.regs, self.regs,
actual_pc, actual_pc,
(base_idx, index_idx, disp as usize, fault_address), (base_idx, index_idx, disp as usize, fault_address),
backtrace, backtrace,
)), )),
_ => AsanError::StackOobWrite(( AccessType::Write => AsanError::StackOobWrite((
self.regs, self.regs,
actual_pc, actual_pc,
(base_idx, index_idx, disp as usize, fault_address), (base_idx, index_idx, disp as usize, fault_address),
@ -1015,14 +1014,14 @@ impl AsanRuntime {
backtrace, backtrace,
}; };
match typ { match typ {
RegAccessType::ReadOnly => { AccessType::Read => {
if metadata.freed { if metadata.freed {
AsanError::ReadAfterFree(asan_readwrite_error) AsanError::ReadAfterFree(asan_readwrite_error)
} else { } else {
AsanError::OobRead(asan_readwrite_error) AsanError::OobRead(asan_readwrite_error)
} }
} }
_ => { AccessType::Write => {
if metadata.freed { if metadata.freed {
AsanError::WriteAfterFree(asan_readwrite_error) AsanError::WriteAfterFree(asan_readwrite_error)
} else { } else {
@ -1245,43 +1244,43 @@ impl AsanRuntime {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
fn register_idx(&self, capid: RegId) -> (Option<u16>, Option<u16>) { fn register_idx(&self, reg: X86Register) -> Option<(u16, u16)> {
match capid.0 { match reg {
19 => (Some(0), Some(32)), X86Register::Eax => Some((0, 32)),
22 => (Some(2), Some(32)), X86Register::Ecx => Some((2, 32)),
24 => (Some(3), Some(32)), X86Register::Edx => Some((3, 32)),
21 => (Some(1), Some(32)), X86Register::Ebx => Some((1, 32)),
30 => (Some(5), Some(32)), X86Register::Esp => Some((5, 32)),
20 => (Some(4), Some(32)), X86Register::Ebp => Some((4, 32)),
29 => (Some(6), Some(32)), X86Register::Esi => Some((6, 32)),
23 => (Some(7), Some(32)), X86Register::Edi => Some((7, 32)),
226 => (Some(8), Some(32)), X86Register::R8d => Some((8, 32)),
227 => (Some(9), Some(32)), X86Register::R9d => Some((9, 32)),
228 => (Some(10), Some(32)), X86Register::R10d => Some((10, 32)),
229 => (Some(11), Some(32)), X86Register::R11d => Some((11, 32)),
230 => (Some(12), Some(32)), X86Register::R12d => Some((12, 32)),
231 => (Some(13), Some(32)), X86Register::R13d => Some((13, 32)),
232 => (Some(14), Some(32)), X86Register::R14d => Some((14, 32)),
233 => (Some(15), Some(32)), X86Register::R15d => Some((15, 32)),
26 => (Some(18), Some(32)), X86Register::Eip => Some((18, 32)),
35 => (Some(0), Some(64)), X86Register::Rax => Some((0, 4)),
38 => (Some(2), Some(64)), X86Register::Rcx => Some((2, 4)),
40 => (Some(3), Some(64)), X86Register::Rdx => Some((3, 4)),
37 => (Some(1), Some(64)), X86Register::Rbx => Some((1, 4)),
44 => (Some(5), Some(64)), X86Register::Rsp => Some((5, 4)),
36 => (Some(4), Some(64)), X86Register::Rbp => Some((4, 4)),
43 => (Some(6), Some(64)), X86Register::Rsi => Some((6, 4)),
39 => (Some(7), Some(64)), X86Register::Rdi => Some((7, 4)),
106 => (Some(8), Some(64)), X86Register::R8 => Some((8, 64)),
107 => (Some(9), Some(64)), X86Register::R9 => Some((9, 64)),
108 => (Some(10), Some(64)), X86Register::R10 => Some((10, 64)),
109 => (Some(11), Some(64)), X86Register::R11 => Some((11, 64)),
110 => (Some(12), Some(64)), X86Register::R12 => Some((12, 64)),
111 => (Some(13), Some(64)), X86Register::R13 => Some((13, 64)),
112 => (Some(14), Some(64)), X86Register::R14 => Some((14, 64)),
113 => (Some(15), Some(64)), X86Register::R15 => Some((15, 64)),
41 => (Some(18), Some(64)), X86Register::Rip => Some((18, 64)),
_ => (None, None), _ => None,
} }
} }
@ -2248,60 +2247,46 @@ impl AsanRuntime {
#[must_use] #[must_use]
#[allow(clippy::result_unit_err)] #[allow(clippy::result_unit_err)]
pub fn asan_is_interesting_instruction( pub fn asan_is_interesting_instruction(
capstone: &Capstone, decoder: InstDecoder,
_address: u64, _address: u64,
instr: &Insn, 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 // We need to re-decode frida-internal capstone values to upstream capstone
let cs_instr = frida_to_cs(capstone, instr); let cs_instr = frida_to_cs(decoder, instr);
let cs_instr = cs_instr.first().unwrap(); let mut operands = vec![];
let operands = capstone for operand_idx in 0..cs_instr.operand_count() {
.insn_detail(cs_instr) operands.push(cs_instr.operand(operand_idx));
.unwrap() }
.arch_detail()
.operands();
// Ignore lea instruction // Ignore lea instruction
// put nop into the white-list so that instructions like // put nop into the white-list so that instructions like
// like `nop dword [rax + rax]` does not get caught. // like `nop dword [rax + rax]` does not get caught.
match cs_instr.mnemonic().unwrap() { match cs_instr.opcode() {
"lea" | "nop" => return None, Opcode::LEA | Opcode::NOP => return None,
_ => (), _ => (),
} }
// This is a TODO! In this case, both the src and the dst are mem operand // This is a TODO! In this case, both the src and the dst are mem operand
// so we would need to return two operadns? // so we would need to return two operadns?
if cs_instr.mnemonic().unwrap().starts_with("rep") { if cs_instr.prefixes.rep_any() {
return None; return None;
} }
for operand in operands { for operand in operands {
if let X86Operand(x86operand) = operand { if operand.is_memory() {
if let X86OperandType::Mem(opmem) = x86operand.op_type { // log::trace!("{:#?}", operand)
/* // if we reach this point
log::trace!( // because in x64 there's no mem to mem inst, just return the first memory operand
"insn: {:#?} {:#?} width: {}, segment: {:#?}, base: {:#?}, index: {:#?}, scale: {}, disp: {}",
insn_id, if let Some((basereg, indexreg, scale, disp)) = operand_details(&operand) {
instr, let memsz = cs_instr.mem_size().unwrap().bytes_size().unwrap(); // this won't fail if it is mem access inst
x86operand.size,
opmem.segment(), // println!("{:#?} {:#?} {:#?}", cs_instr, cs_instr.to_string(), operand);
opmem.base(), // println!("{:#?}", (memsz, basereg, indexreg, scale, disp));
opmem.index(),
opmem.scale(), return Some((memsz, basereg, indexreg, scale, disp));
opmem.disp(), } // else {} // perhaps avx instructions?
);
*/
if opmem.segment() == RegId(0) {
return Some((
opmem.segment(),
x86operand.size,
opmem.base(),
opmem.index(),
opmem.scale(),
opmem.disp(),
));
}
}
} }
} }
@ -2317,29 +2302,26 @@ impl AsanRuntime {
&mut self, &mut self,
address: u64, address: u64,
output: &StalkerOutput, output: &StalkerOutput,
_segment: RegId,
width: u8, width: u8,
basereg: RegId, basereg: X86Register,
indexreg: RegId, indexreg: X86Register,
scale: i32, scale: u8,
disp: isize, disp: i32,
) { ) {
let redzone_size = isize::try_from(frida_gum_sys::GUM_RED_ZONE_SIZE).unwrap(); let redzone_size = isize::try_from(frida_gum_sys::GUM_RED_ZONE_SIZE).unwrap();
let writer = output.writer(); let writer = output.writer();
let true_rip = address; let true_rip = address;
let basereg = if basereg.0 == 0 { let basereg: Option<X86Register> = if basereg == X86Register::None {
None None
} else { } else {
let reg = writer_register(basereg); Some(basereg)
Some(reg)
}; };
let indexreg = if indexreg.0 == 0 { let indexreg = if indexreg == X86Register::None {
None None
} else { } else {
let reg = writer_register(indexreg); Some(indexreg)
Some(reg)
}; };
let scale = match scale { let scale = match scale {
@ -2447,7 +2429,7 @@ impl AsanRuntime {
// Finally set Rdi to base + index * scale + disp // Finally set Rdi to base + index * scale + disp
writer.put_add_reg_reg(X86Register::Rdi, X86Register::Rsi); 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_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 writer.put_push_reg(X86Register::Rsi); // save true_rip

View File

@ -2,7 +2,6 @@
use std::{fmt::Debug, io::Write, marker::PhantomData}; use std::{fmt::Debug, io::Write, marker::PhantomData};
use backtrace::Backtrace; use backtrace::Backtrace;
use capstone::{arch::BuildsCapstone, Capstone};
use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity}; use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity};
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use frida_gum::interceptor::Interceptor; use frida_gum::interceptor::Interceptor;
@ -20,10 +19,16 @@ use libafl::{
use libafl_bolts::{ownedref::OwnedPtr, Named, SerdeAny}; use libafl_bolts::{ownedref::OwnedPtr, Named, SerdeAny};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use termcolor::{Color, ColorSpec, WriteColor}; 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")] #[cfg(target_arch = "x86_64")]
use crate::asan::asan_rt::ASAN_SAVE_REGISTER_NAMES; 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)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct AsanReadWriteError { pub(crate) struct AsanReadWriteError {
@ -241,25 +246,18 @@ impl AsanErrors {
.unwrap(); .unwrap();
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
let mut cs = Capstone::new() let decoder = InstDecoder::minimal();
.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 start_pc = error.pc - 4 * 5; let start_pc = error.pc - 4 * 5;
for insn in &*cs let insts = disas_count(
.disasm_count( &decoder,
unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 4 * 11) }, unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 15 * 11) },
start_pc as u64,
11, 11,
) );
.expect("failed to disassemble instructions") let mut inst_address = start_pc;
{
if insn.address() as usize == error.pc { for insn in insts {
if inst_address == error.pc {
output output
.set_color(ColorSpec::new().set_fg(Some(Color::Red))) .set_color(ColorSpec::new().set_fg(Some(Color::Red)))
.unwrap(); .unwrap();
@ -268,6 +266,8 @@ impl AsanErrors {
} else { } else {
writeln!(output, "\t {insn}").unwrap(); writeln!(output, "\t {insn}").unwrap();
} }
inst_address += insn.len().to_const() as usize;
} }
backtrace_printer backtrace_printer
.print_trace(&error.backtrace, output) .print_trace(&error.backtrace, output)
@ -496,25 +496,18 @@ impl AsanErrors {
.unwrap(); .unwrap();
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
let mut cs = Capstone::new() let decoder = InstDecoder::minimal();
.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 start_pc = pc; let start_pc = pc;
for insn in &*cs let insts = disas_count(
.disasm_count( &decoder,
unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 4 * 11) }, unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 15 * 11) },
start_pc as u64,
11, 11,
) );
.expect("failed to disassemble instructions")
{ let mut inst_address = start_pc;
if insn.address() as usize == pc { for insn in insts {
if inst_address == pc {
output output
.set_color(ColorSpec::new().set_fg(Some(Color::Red))) .set_color(ColorSpec::new().set_fg(Some(Color::Red)))
.unwrap(); .unwrap();
@ -523,6 +516,8 @@ impl AsanErrors {
} else { } else {
writeln!(output, "\t {insn}").unwrap(); writeln!(output, "\t {insn}").unwrap();
} }
inst_address += insn.len().to_const() as usize;
} }
backtrace_printer.print_trace(&backtrace, output).unwrap(); backtrace_printer.print_trace(&backtrace, output).unwrap();
} }

View File

@ -6,7 +6,7 @@ use std::{
rc::Rc, rc::Rc,
}; };
#[cfg(any(target_arch = "aarch64", all(target_arch = "x86_64", unix)))] #[cfg(target_arch = "aarch64")]
use capstone::{ use capstone::{
arch::{self, BuildsCapstone}, arch::{self, BuildsCapstone},
Capstone, Capstone,
@ -27,6 +27,8 @@ use libafl_targets::drcov::DrCovBasicBlock;
#[cfg(unix)] #[cfg(unix)]
use nix::sys::mman::{mmap, MapFlags, ProtFlags}; use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use rangemap::RangeMap; use rangemap::RangeMap;
#[cfg(target_arch = "x86_64")]
use yaxpeax_x86::amd64::InstDecoder;
#[cfg(all(feature = "cmplog", target_arch = "aarch64"))] #[cfg(all(feature = "cmplog", target_arch = "aarch64"))]
use crate::cmplog_rt::CmpLogRuntime; use crate::cmplog_rt::CmpLogRuntime;
@ -450,13 +452,9 @@ where
.detail(true) .detail(true)
.build() .build()
.expect("Failed to create Capstone object"); .expect("Failed to create Capstone object");
#[cfg(all(target_arch = "x86_64", unix))]
let capstone = Capstone::new() #[cfg(target_arch = "x86_64")]
.x86() let decoder = InstDecoder::minimal();
.mode(arch::x86::ArchMode::Mode64)
.detail(true)
.build()
.expect("Failed to create Capstone object");
Transformer::from_callback(gum, move |basic_block, output| { Transformer::from_callback(gum, move |basic_block, output| {
Self::transform( Self::transform(
@ -464,8 +462,10 @@ where
&output, &output,
&ranges, &ranges,
&runtimes, &runtimes,
#[cfg(any(target_arch = "aarch64", all(target_arch = "x86_64", unix)))] #[cfg(target_arch = "aarch64")]
&capstone, &capstone,
#[cfg(target_arch = "x86_64")]
decoder,
); );
}) })
} }
@ -475,7 +475,7 @@ where
output: &StalkerOutput, output: &StalkerOutput,
ranges: &Rc<RefCell<RangeMap<usize, (u16, String)>>>, ranges: &Rc<RefCell<RangeMap<usize, (u16, String)>>>,
runtimes: &Rc<RefCell<RT>>, 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 first = true;
let mut basic_block_start = 0; let mut basic_block_start = 0;
@ -508,23 +508,16 @@ where
#[cfg(unix)] #[cfg(unix)]
let res = if let Some(_rt) = runtimes.match_first_type_mut::<AsanRuntime>() { 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 { } else {
None None
}; };
#[cfg(all(target_arch = "x86_64", unix))] #[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>() { if let Some(rt) = runtimes.match_first_type_mut::<AsanRuntime>() {
rt.emit_shadow_check( rt.emit_shadow_check(
address, address, output, details.0, details.1, details.2, details.3, details.4,
output,
segment,
width,
basereg,
indexreg,
scale,
disp.try_into().unwrap(),
); );
} }
} }

View File

@ -1,4 +1,4 @@
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] #[cfg(target_arch = "aarch64")]
use capstone::Capstone; use capstone::Capstone;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use capstone::{ use capstone::{
@ -13,6 +13,11 @@ use frida_gum::instruction_writer::X86Register;
use frida_gum_sys; use frida_gum_sys;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use num_traits::cast::FromPrimitive; 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 /// Determine the width of the specified instruction
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
@ -89,6 +94,44 @@ pub fn writer_register(reg: capstone::RegId) -> Aarch64Register {
Aarch64Register::from_u32(u32::from(regint)).unwrap() 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 /// The writer registers
/// frida registers: <https://docs.rs/frida-gum/0.4.0/frida_gum/instruction_writer/enum.X86Register.html> /// 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> /// 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] #[must_use]
#[inline] #[inline]
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
pub fn writer_register(reg: capstone::RegId) -> X86Register { pub fn writer_register(reg: RegSpec) -> X86Register {
let regint: u16 = reg.0; for (reg1, reg2) in &X86_64_REGS {
match regint { // println!("reg1:{:#?} reg2:{:#?}", reg1, reg);
19 => X86Register::Eax, if *reg1 == reg {
22 => X86Register::Ecx, return *reg2;
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
} }
} }
X86Register::None
}
/// Translates a frida instruction to a capstone instruction. /// Translates a frida instruction to a capstone instruction.
/// Returns a [`capstone::Instructions`] with a single [`capstone::Insn`] inside. /// Returns a [`capstone::Instructions`] with a single [`capstone::Insn`] inside.
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
pub(crate) fn frida_to_cs<'a>( pub(crate) fn frida_to_cs(decoder: InstDecoder, frida_insn: &frida_gum_sys::Insn) -> Instruction {
capstone: &'a Capstone, decoder.decode_slice(frida_insn.bytes()).unwrap()
frida_insn: &frida_gum_sys::Insn, }
) -> capstone::Instructions<'a> {
capstone #[cfg(target_arch = "x86_64")]
.disasm_count(frida_insn.bytes(), frida_insn.address(), 1) /// Get the base, idx, scale, disp for each operand
.unwrap() 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;
}
} }

View File

@ -46,7 +46,7 @@ fi
echo "[*] Checking QEMU-Nyx ..." echo "[*] Checking QEMU-Nyx ..."
if [ ! -f "QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64" ]; then if [ ! -f "QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64" ]; then
cd QEMU-Nyx/ || return cd QEMU-Nyx/ || return
./compile_qemu_nyx.sh static || exit 1 ./compile_qemu_nyx.sh lto || exit 1
cd .. cd ..
fi fi