ArrowIO is a cross-platform tool designed to audit EDR telemetry. By utilizing raw assembly syscalls and bypassing CRT/glibc, this script assists in confirming evasion via naked Rust binaries through user-mode API hooking and IAT-based static analysis.
Modern security solutions monitor high-level function calls (e.g., CreateFile or write). ArrowIO bypasses these by communicating directly with the OS Kernel.
- Zero Dependencies: No linking to
libc,ntdll.dll, orkernel32.dll. - Minimalist Footprint: Linux binaries at ~13KB, Windows binaries at 2.5KB.
- Import Stealth: Empty IAT, making the binary invisible to static API monitors.
Building binary on a Linux environment (or WSL2).
Ensure you have Rust toolchain and musl targets installed. This allows the file to link without a dynamic C library.
# install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# add the static 64-bit target
rustup target add x86_64-unknown-linux-musl
# install musl tools
sudo apt update && sudo apt install musl-tools -yChange to the Linux directory. Copy this build command to override the standard entry point and strip all runtime metadata.
cd Linux
RUSTFLAGS="-C panic=abort -C link-arg=-nostartfiles -C link-self-contained=no" cargo build --release --target x86_64-unknown-linux-muslOnce the build is complete, verify that the binary has no dependencies and is talking directly to the kernel.
A. Dependency Check: Check if the binary is statically linked.
ldd ./target/x86_64-unknown-linux-musl/release/arrowio-linux- Success Result:
not a dynamic executable,statically linked
B. Syscall Audit:
Use strace to see the direct kernel transitions.
strace ./target/x86_64-unknown-linux-musl/release/arrowio-linux- Observation: Look for
writeandexitcalls occurring without the usualglibcinitialization noise (likemmap,open, orbrkcalls that standard binaries make before reaching your code).
C. Size Audit: Verify the minimalist footprint.
ls -lh ./target/x86_64-unknown-linux-musl/release/arrowio-linux- Result: Should be ~13KB.
This script bypasses the standard Win32 subsystem (kernel32.dll and ntdll.dll) by using direct syscalls and a custom entry point.
To build this, you need the Rust toolchain and the C++ Build Tools (Linker and SDK).
- Install Rust: Download and run
rustup-init.exefrom rustup.rs. - Install Build Tools: Complete the installation via the Visual Studio installer.
- Terminal: To access Linker tools, open Developer PowerShell for VS 2022 instead of regular PowerShell.
Navigate to the Windows directory within the repo. To strip CRT from the binary, pass these flags:
cd Windows
# set environment flags
$env:RUSTFLAGS="-C target-feature=+crt-static -C link-arg=/NODEFAULTLIB -C link-arg=/SUBSYSTEM:CONSOLE"
# compile
cargo build --releaseSince the binary has no console output, verify its integrity by auditing its structure.
A. IAT Audit: Verify that the binary does not import any functions from Windows DLLs.
dumpbin /IMPORTS .\target\release\arrowio-win.exe- Expected Result: The output should only show a summary (e.g.,
.text,.rdata). There should be no list of DLLs likeKERNEL32.dll. This confirms the binary slipped unrecognized to API hookers.
B. Exit Code Verification:
Run the binary and check the process exit code. This confirms the direct syscall reached the kernel successfully.
.\target\release\arrowio-win.exe
echo $LASTEXITCODE- Expected Result:
0(This confirmsNtTerminateProcesswas executed via raw assembly).
C. Footprint Audit: Verify the binary size.
(Get-Item .\target\release\arrowio-win.exe).length- Expected Result:
~2.5 KB
| Detection Layer | Standard Binary Behavior | ArrowIO Stealth Behavior |
|---|---|---|
| Static IAT Analysis | Lists all used functions (e.g., CreateFile) in the Import Address Table. |
Bypassed. IAT is empty. Scanners see no suspicious API dependencies. |
| User-Mode Hooking | Calls functions in ntdll.dll or libc where EDRs have placed hooks. |
Bypassed. Assembly syscall instructions jump directly to the kernel skipping the hooked libraries. |
| Standard Telemetry | Generates noisy logs via CRT initialization. | Minimized. No runtime overhead, no thread initialization noise, sub-3KB footprint. |
| API Monitoring | Security tools monitor kernel32!CreateFile or libc!write. |
Bypassed. Execution flow never enters these monitored function addresses. |
This script demonstrates MITRE ATT&CK T1059 (Command and Scripting Interpreter) and T1106 (Native API).
With ❤️ by Arusha