Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/target
/Cargo.lock
/build
build/
*.exe
/TinyInst
*.obj
Expand Down
11 changes: 9 additions & 2 deletions Makefile.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
[tasks.build_test]
command = "cl"
args = ["./test/test.c", "-o", "./test/test.exe"]
dependencies = ["build_configure"]
cwd = "./test"
command = "cmake"
args = ["--build", "build", "--config", "Debug"]

[tasks.build_configure]
cwd = "./test"
command = "cmake"
args = ["-S", ".", "-B", "build"]
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,29 @@

FFI to [TinyInst](https://github.com/googleprojectzero/TinyInst). Created for [LibAFL](https://github.com/AFLplusplus/LibAFL).

## Dependencies

* cxxbridge
* cargo-make
* python3
* git

## Running the test

1. Open up developer powershell so that you have access to cl (Windows Default Compiler)
1. Open a terminal and set up your build environment (e.g. On Windows, run Developer Powershell / Developer CMD/ vcvars64.bat / vcvars32.bat)
2. Run `cargo make build_test` to build the test binary
3. Run `cargo test` to run the test


## Optional ENV Variables

`CUSTOM_TINYINST_GENERATOR` = Generator used for cmake `-G` flag

`CUSTOM_TINYINST_PATH` = path to local Tinyinst repo

`CUSTOM_TINYINST_NO_BUILD` = if set, it won't build Tinyinst everytime. Useful when paired with `CUSTOM_TINYINST_PATH`


#### License

<sup>
Expand Down
46 changes: 37 additions & 9 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,36 @@ fn build_dep_check(tools: &[&str]) {
}
}
fn main() {
// First we generate .cc and .h files from ffi.rs
if !cfg!(windows) {
println!("cargo:warning=No MacOS support yet.");
if cfg!(linux) {
println!("cargo:warning=Tinyinst doesn't support linux");
exit(0);
}

build_dep_check(&["git", "python", "cxxbridge"]);
build_dep_check(&["git", "cxxbridge"]);

#[cfg(target_os = "windows")]
let cmake_generator = "Visual Studio 17 2022";
#[cfg(target_os = "macos")]
let cmake_generator = "Xcode";

let custom_tinyinst_generator =
env::var_os("CUSTOM_TINYINST_GENERATOR").map(|x| x.to_string_lossy().to_string());

env::set_var("CXXFLAGS", "-std=c++17");

let tinyinst_generator = if let Some(generator) = custom_tinyinst_generator.as_ref() {
generator
} else {
cmake_generator
};

let custum_tinyinst_dir =
env::var_os("CUSTOM_TINYINST_DIR").map(|x| x.to_string_lossy().to_string());
let custum_tinyinst_no_build = env::var("CUSTOM_TINYINST_NO_BUILD").is_ok();

println!("cargo:rerun-if-env-changed=CUSTOM_TINYINST_DIR");
println!("cargo:rerun-if-env-changed=CUSTOM_TINYINST_NO_BUILD");
println!("cargo:rerun-if-env-changed=CUSTOM_TINYINST_GENERATOR");

let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir_path = Path::new(&out_dir);
Expand Down Expand Up @@ -79,7 +95,7 @@ fn main() {

let mut submodules = tinyinst_repo.submodules().unwrap();

// do git submodule --init --recursive on Tinyinst
// do git submodule update --init --recursive on Tinyinst
for submodule in &mut submodules {
submodule.update(true, None).unwrap();
}
Expand All @@ -89,7 +105,6 @@ fn main() {
}
tinyinst_path
};

if !custum_tinyinst_no_build {
println!(
"cargo:warning=Generating Bridge files. and building for {}",
Expand All @@ -98,23 +113,36 @@ fn main() {
copy_tinyinst_files(&tinyinst_path);

let _ = Config::new(&tinyinst_path)
.generator("Visual Studio 17 2022") // make this configurable from env variable
.generator(tinyinst_generator)
.build_target("tinyinst")
.profile("Release") // without this, it goes into RelWithDbInfo folder??
.out_dir(&tinyinst_path)
.build();
}

// For m1 mac(?)
println!(
"cargo:rustc-link-search={}\\build\\Release",
"cargo:rustc-link-search={}/build/third_party/Release",
&tinyinst_path.to_string_lossy()
);

println!(
"cargo:rustc-link-search={}/build/Release",
&tinyinst_path.to_string_lossy()
);
println!(
"cargo:rustc-link-search={}\\build\\third_party\\obj\\wkit\\lib",
"cargo:rustc-link-search={}/build/third_party/obj/wkit/lib",
&tinyinst_path.to_string_lossy()
);
println!("cargo:rustc-link-lib=static=tinyinst");

#[cfg(target_arch = "x86_64")]
println!("cargo:rustc-link-lib=static=xed");

#[cfg(target_arch = "aarch64")]
println!("cargo:rustc-link-lib=static=reil");

#[cfg(target_os = "windows")]
println!("cargo:rustc-link-lib=dylib=dbghelp");

println!("cargo:rerun-if-changed=src/");
Expand Down
39 changes: 25 additions & 14 deletions src/tinyinst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,18 +228,33 @@ mod tests {
use std::{
fs::File,
io::{Seek, Write},
path::Path,
string::ToString,
};

#[cfg(target_os = "windows")]
const TEST_FILENAME: &str = "test.exe";
#[cfg(target_os = "macos")]
const TEST_FILENAME: &str = "test";

#[cfg(target_os = "macos")]
const TEST_PATH: &str = "test/build/";
#[cfg(target_os = "windows")]
const TEST_PATH: &str = "test/build/Debug/";

#[test]
fn tinyinst_ok() {
let tinyinst_args = vec!["-instrument_module".to_string(), "test.exe".to_string()];
let tinyinst_args = vec!["-instrument_module".to_string(), TEST_FILENAME.to_string()];
// Create file to test.
let mut file = File::create(".\\test\\test_file.txt").unwrap();
let mut file = File::create("./test/test_file.txt").unwrap();
file.write_all(b"test1").unwrap();

let program_args = vec![
".\\test\\test.exe".to_string(),
".\\test\\test_file.txt".to_string(),
Path::new(TEST_PATH)
.join(TEST_FILENAME)
.display()
.to_string(),
"./test/test_file.txt".to_string(),
];
let mut coverage = Vec::new();

Expand All @@ -259,29 +274,26 @@ mod tests {
tinyinst.vec_coverage(&mut coverage, true);
assert_eq!(result, super::litecov::RunResult::OK);

// Check if it contains address to if c == 'b' branch. Sometimes it gets address to memset function. Weird windows crap probably?
assert!(coverage.contains(&4151));

// Second test case for ba
_ = file.seek(std::io::SeekFrom::Start(0)).unwrap();
file.write_all(b"ba").unwrap();
let result = tinyinst.run();
tinyinst.vec_coverage(&mut coverage, true);
assert_eq!(result, super::litecov::RunResult::OK);

// Check if it contains address to if c == 'a' branch. Sometimes it gets address to memset function.
assert!(coverage.contains(&4174));
}
}
#[test]
fn tinyinst_crash() {
use alloc::{string::ToString, vec::Vec};

let tinyinst_args = vec!["-instrument_module".to_string(), "test.exe".to_string()];
let tinyinst_args = vec!["-instrument_module".to_string(), TEST_FILENAME.to_string()];

let program_args = vec![
".\\test\\test.exe".to_string(),
".\\test\\crash_input.txt".to_string(),
Path::new(TEST_PATH)
.join(TEST_FILENAME)
.display()
.to_string(),
"./test/crash_input.txt".to_string(),
];
let mut coverage = Vec::new();

Expand All @@ -290,7 +302,6 @@ mod tests {
let result = tinyinst.run();
tinyinst.vec_coverage(&mut coverage, true);
assert_eq!(result, super::litecov::RunResult::CRASH);
// assert_eq!(bitmap.iter().filter(|&x| *x == 1).count(), 1307);
}
}
}
9 changes: 9 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.10)
project("test")

# Disable implicit function declaration warning on macOS so it can compile vulnerable code
if(APPLE)
set(CMAKE_C_FLAGS "-Wno-error=implicit-function-declaration")
endif()

add_executable(test test.c)
40 changes: 25 additions & 15 deletions test/test.c
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
#include <stdio.h>

void pass1(char *buf, int buf_size) {
void pass1(char *buf, int buf_size)
{
char target[0x10];
if (buf[0] == 'b') {
if (buf[1] == 'a') {
if (buf[2] == 'd') {
if (buf[3] == '1') {
if (buf[4] == '2') {
printf("You got me\n");
if (buf[0] == 'b')
{
if (buf[1] == 'a')
{
if (buf[2] == 'd')
{
if (buf[3] == '1')
{
if (buf[4] == '2')
{
printf("Triggering buffer overflow\n");
memcpy(target, buf, 0x1000000);
printf("GG\n");
printf("Should never get to this point\n");
}
}
}
}
}
}
int main(int argc, char *argv[]) {
int main(int argc, char *argv[])
{
FILE *fp;
char buf[0x1000];
if (argc == 2) {
char buf[0x1000];
if (argc == 2)
{
fp = fopen(argv[1], "r");
if (fp == NULL) {
if (fp == NULL)
{
printf("File not found\n");
printf("Received filename %s\n", argv[1]);
return 1;
}
fscanf(fp, "%s", buf);

pass1(buf, sizeof(buf));

} else {
printf("there is nothing\n");
}
else
{
printf("Program requires input file\n");
}
}