diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml deleted file mode 100644 index 40b1fb4..0000000 --- a/.github/workflows/mdbook.yml +++ /dev/null @@ -1,60 +0,0 @@ -# Sample workflow for building and deploying a mdBook site to GitHub Pages -# -# To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html -# -name: Deploy mdBook site to Pages - -on: - # Runs on pushes targeting the default branch - push: - branches: ["main"] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - # Build job - build: - runs-on: ubuntu-latest - env: - MDBOOK_VERSION: 0.4.36 - steps: - - uses: actions/checkout@v4 - - name: Install mdBook - run: | - curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh - rustup update - cargo install --version ${MDBOOK_VERSION} mdbook - - name: Setup Pages - id: pages - uses: actions/configure-pages@v4 - - name: Build with mdBook - run: mdbook build - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: ./book - - # Deployment job - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 40ed649..66a4c3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ docs/book +target +openat \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 95e5afd..5283022 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,5 +3,14 @@ version = 3 [[package]] -name = "okrust" +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "nosey_syscall_auditor" version = "0.1.0" +dependencies = [ + "libc", +] diff --git a/Cargo.toml b/Cargo.toml index d9ddd40..152f1e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,11 @@ [package] -name = "okrust" +name = "nosey_syscall_auditor" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "nsa" +crate-type = ["cdylib"] [dependencies] +libc = "0.2.153" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ff3c8c1 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ + +all: test_openat + +test_openat: test_openat.c + $(CC) $(CFLAGS) -o openat test_openat.c + +clean veryclean: + $(RM) Hello \ No newline at end of file diff --git a/README.md b/README.md index b6bd625..96392d6 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ -okRust logo +Nosey Syscall Auditor -# okRust +# Nosey Syscall Auditor -okrust is the template for new rust projects within oknotok.computer. +NSA, a tortured backronym for Nosey Syscall Auditor, is a simple tool to audit system calls made by a process. -It has some opinionated defaults, like using: -- mdBook for documentation -- release please for releases -- github actions for CI/CD +I'm sorry. I couldn't resist. + +## Usage + +```bash +LD_PRELOAD=./nsa.so make all +``` diff --git a/book.toml b/book.toml deleted file mode 100644 index d3127f0..0000000 --- a/book.toml +++ /dev/null @@ -1,5 +0,0 @@ -[book] -authors = ["sevki"] -language = "en" -multilingual = false -src = "docs/src" diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md deleted file mode 100644 index ae04977..0000000 --- a/docs/src/SUMMARY.md +++ /dev/null @@ -1,3 +0,0 @@ -# Summary - -- [Intro](intro.md) diff --git a/docs/src/intro.md b/docs/src/intro.md deleted file mode 100644 index ee14a9d..0000000 --- a/docs/src/intro.md +++ /dev/null @@ -1,10 +0,0 @@ -# okRust - -okRust logo - -okrust is the template for new rust projects within oknotok.computer. - -It has some opinionated defaults, like using: -- mdBook for documentation -- release please for releases -- github actions for CI/CD diff --git a/docs/src/okRust.png b/docs/src/okRust.png deleted file mode 100644 index 938b3cd..0000000 Binary files a/docs/src/okRust.png and /dev/null differ diff --git a/nsa.png b/nsa.png new file mode 100644 index 0000000..dd3d232 Binary files /dev/null and b/nsa.png differ diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..828fd8a --- /dev/null +++ b/rust-toolchain @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.76" +components = [ "rustfmt", "rust-src", "cargo", "clippy" ] diff --git a/src/lib.rs b/src/lib.rs index 7d12d9a..1fcd79b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,91 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right +//! ![NSA](https://raw.githubusercontent.com/sevki/nsa/master/nsa.png) +//! +//! # NSA: Nosey Syscall Abstractions +//! +//! NSA is a library that allows you to intercept and log system calls. +//! It uses the `dlsym` function to get the address of the original function and then calls it. This is a simple way to intercept and log system calls. +//! +//! ## Usage +//! +//! ```shell +//! cargo build --release +//! LD_PRELOAD=./target/release/nsa.so make +//! ``` + +// set docs rs logo and favicon +#![doc(html_logo_url = "https://raw.githubusercontent.com/sevki/nsa/master/nsa.png")] +#![doc(html_favicon_url = "https://raw.githubusercontent.com/sevki/nsa/master/nsa.png")] + +use libc::c_char; +use std::ffi::CStr; + +macro_rules! wrap_syscall { + ($func_name:ident, $($arg_name:ident: $arg_type:ty),*) => { + /// # Safety + /// + /// These functinos are inherently unsafe as they are calling system calls. + /// + #[no_mangle] + pub unsafe extern "C" fn $func_name($($arg_name: $arg_type),*) -> i32 { + let orig_func: unsafe extern "C" fn($($arg_type),*) -> i32 = + unsafe { std::mem::transmute(libc::dlsym(libc::RTLD_NEXT, concat!(stringify!($func_name), "\0").as_ptr() as *const i8)) }; + + println!("Intercepted {}", stringify!($func_name)); + println!("Arguments: "); + $( + println!(" {} {}: {}", stringify!($func_name), stringify!($arg_name), { + // check argtype is *const c_char + if stringify!($arg_type) == "*const c_char" { + if let Some(s) = unsafe { ($arg_name as *const c_char).as_ref() } { + let string = unsafe { CStr::from_ptr(s).to_string_lossy() }; + format!("{:?}", string) + } else { + format!("{:?}", $arg_name) + } + } else { + format!("{:?}", $arg_name) + } + }); + )* + + let result = orig_func($($arg_name),*); + println!("Original {} returned {}", stringify!($func_name), result); + + result + } + }; + + ($func_name:ident) => { + #[no_mangle] + pub unsafe extern "C" fn $func_name() -> i32 { + let orig_func: unsafe extern "C" fn() -> i32 = + unsafe { std::mem::transmute(libc::dlsym(libc::RTLD_NEXT, concat!(stringify!($func_name), "\0").as_ptr() as *const i8)) }; + + println!("Intercepted {}", stringify!($func_name)); + + let result = orig_func(); + println!("Original {} returned {}", stringify!($func_name), result); + + result + } + }; } -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +// open +wrap_syscall!(open, path: *const c_char, flags: i32, mode: i32); +// openat +wrap_syscall!(openat, dirfd: i32, path: *const c_char, flags: i32, mode: i32); +// execve +wrap_syscall!(execve, path: *const c_char, argv: *const *const c_char, envp: *const *const c_char); +// access +wrap_syscall!(access, pathname: *const c_char, mode: i32); +// uname +wrap_syscall!(uname, buf: *mut libc::utsname); +// getuid +wrap_syscall!(getuid); +// getpid +wrap_syscall!(getpid); +// getppid +wrap_syscall!(getppid); +// fork +wrap_syscall!(fork); diff --git a/test_openat.c b/test_openat.c new file mode 100644 index 0000000..b8ede8a --- /dev/null +++ b/test_openat.c @@ -0,0 +1,13 @@ +#include +#include +#include + +int main() { + int fd = openat(AT_FDCWD, "Cargo.toml", O_RDONLY); + if (fd == -1) { + perror("openat"); + return 1; + } + close(fd); + return 0; +} \ No newline at end of file