ARM64 Linux Security Toolkit
Auris
Auris (Latin for "ear") is a security toolkit that intercepts every system call a process makes on ARM64 Linux. It uses the kernel's ptrace interface to attach to processes, monitor their behavior, and optionally modify their execution.
Version 2.0 introduces dual-purpose capabilities: defensive operations for behavioral analysis and policy enforcement, plus offensive operations for penetration testing and security research.
Defensive Operations
Trace syscalls, build behavioral profiles, detect anomalies, enforce security policies. Understand what normal looks like, then catch deviations.
Offensive Operations
Inject shellcode, find ROP gadgets, manipulate process memory. The same ptrace infrastructure that enables monitoring also enables exploitation.
How It Works
The ptrace System Call
Auris is built on ptrace(), a Linux system call that allows one process (the tracer) to observe and control another process (the tracee). This is the same mechanism used by debuggers like GDB. When Auris attaches to a process, the kernel stops the tracee before and after every system call, allowing Auris to inspect registers, read memory, and even modify the process state.
ARM64 Register Convention
On ARM64 (AArch64) Linux, system calls follow a specific register convention:
x8contains the syscall number (e.g., 221 for execve)x0-x5contain up to 6 argumentsx0contains the return value after the syscall completes
// Core tracing loop in Auris
while (1) {
// Wait for tracee to stop at syscall entry/exit
waitpid(pid, &status, 0);
// Read all registers using GETREGSET
struct iovec iov = { .iov_base = ®s, .iov_len = sizeof(regs) };
ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
// Extract syscall information
uint64_t syscall_nr = regs.regs[8]; // x8 = syscall number
uint64_t arg0 = regs.regs[0]; // x0 = first argument
uint64_t arg1 = regs.regs[1]; // x1 = second argument
// Record, analyze, block, or inject...
// Continue to next syscall
ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
}Capabilities Required
To use ptrace, you need appropriate permissions. The Linux kernel's Yama security module controls ptrace access through /proc/sys/kernel/yama/ptrace_scope:
- 0: Any process can ptrace any other process owned by the same user
- 1: Only parent processes can ptrace their children (default on most systems)
- 2: Only processes with CAP_SYS_PTRACE can use ptrace
- 3: No process can use ptrace
Auris typically requires running as root or with CAP_SYS_PTRACE capability. In Docker, use --cap-add=SYS_PTRACE.
Command: learn
The learn command traces a program's execution and records every system call it makes. This creates a trace file containing the complete syscall history, including syscall numbers, arguments, return values, and timing information.
Usage: auris learn [options] -- program [args...]
What it captures:
- Every syscall number and its human-readable name (e.g., openat, read, write, mmap)
- All syscall arguments, with special handling for file paths, flags, and pointers
- Return values and error codes
- Timestamps for performance analysis
- Process metadata: PID, binary path, SHA256 hash of the executable
Command: profile
The profile command analyzes a trace and builds a statistical behavioral profile. This profile captures the "fingerprint" of normal program behavior.
Usage: auris profile -t trace-id
Profile contents:
- Syscall histogram: Which syscalls were used and how often
- Shannon entropy: A measure of behavioral diversity (higher = more varied behavior)
- File access patterns: Which files were opened, read, or written
- Network behavior: Whether the program used sockets, connected to networks
- Process spawning: Whether the program created child processes
- Sensitive file access: Access to credentials, keys, or config files
Command: compare
The compare command runs a program while comparing its behavior against a baseline profile. It calculates a similarity score and flags any deviations.
Usage: auris compare -p profile-id -- program [args...]
What it detects:
- New syscalls: Syscalls that were never seen in the baseline
- Missing syscalls: Expected syscalls that did not occur
- Frequency anomalies: Syscalls occurring much more or less than expected
- New file access: Files accessed that were not in the baseline
- Network activity: Network operations when baseline had none
Commands: policy and enforce
The policy command generates a security policy from a behavioral profile. The enforce command then runs a program under that policy, blocking or alerting on violations.
Usage:
auris policy -p profile-id- Generate policy from profileauris enforce -P policy-id -m alert -- program- Log violationsauris enforce -P policy-id -m block -- program- Block and terminate on violation
Enforcement modes:
- alert: Log violations but allow the program to continue. Useful for testing policies before enforcement.
- block: When a violation occurs, the syscall is blocked (by setting x8 to -1) and the process is terminated with SIGKILL.
Process Injection Framework
Warning: For authorized security research and penetration testing only. Unauthorized use against systems you do not own or have explicit permission to test is illegal and may result in criminal prosecution.
The same ptrace mechanism that allows Auris to observe syscalls also enables it to modify process state. By writing to process memory and changing register values, Auris can inject and execute arbitrary code in a running process.
How injection works:
- Attach to the target process using PTRACE_ATTACH
- Wait for the process to stop (it receives SIGSTOP)
- Save the current register state using PTRACE_GETREGSET
- Save the original code at the injection point using PTRACE_PEEKDATA
- Write shellcode to executable memory using PTRACE_POKEDATA
- Set the program counter (PC) to point to the shellcode
- Continue execution with PTRACE_CONT
- Optionally restore original state after shellcode completes
Command: inject shellcode
The inject shellcode command injects pre-built ARM64 shellcode into a target process and executes it.
Usage: auris inject shellcode -p PID -t TYPE [options]
Available shellcode types:
exec_sh- Execute /bin/sh, spawning a shell in the target process contextreverse -i IP -P PORT- Connect back to attacker machine and spawn shellbind -P PORT- Listen on a port and spawn shell when connection receivedexec_cmd -c "command"- Execute an arbitrary command
Command: inject gadgets
The inject gadgets command scans ELF binaries to find ROP (Return-Oriented Programming) gadgets. ROP is a technique used when DEP/NX prevents direct code injection by chaining together existing code snippets that end in RET instructions.
Usage: auris inject gadgets -b /path/to/binary
Gadget types found:
- RET gadgets: Simple return instructions for chaining
- Load gadgets: Instructions that load registers from the stack (e.g., ldr x0, [sp, #8])
- Syscall gadgets: Instructions containing svc #0 for making system calls
- Stack pivot gadgets: Instructions that modify SP for stack manipulation
On ARM64, a typical ROP chain to call execve("/bin/sh", NULL, NULL) would: load x0 with pointer to "/bin/sh", set x1 and x2 to NULL, set x8 to 221 (execve syscall number), then execute svc #0.
Command: inject dump
The inject dump command reads memory from a target process and displays it in hexdump format.
Usage: auris inject dump -p PID -a ADDRESS -n LENGTH
Use cases:
- Analyze memory layout before injection to find suitable injection points
- Extract runtime data, secrets, or encryption keys from process memory
- Verify shellcode was written correctly
- Forensic analysis of running processes
- Debugging and reverse engineering
Installation and Setup
System Requirements
- Architecture: ARM64 (AArch64) only. Auris uses ARM64-specific register layouts and syscall conventions.
- Operating System: Linux kernel 4.8 or later (for PTRACE_GETREGSET support)
- Permissions: Root access or CAP_SYS_PTRACE capability
- Dependencies: libcurl, openssl, json-c (for AI integration features)
Option 1: Docker (Recommended)
Docker is the easiest way to run Auris, especially on machines that are not natively ARM64. Docker Desktop on Apple Silicon Macs or any ARM64 Linux host works out of the box.
# Clone the repository git clone https://github.com/kuladeepmantri/Auris.git cd Auris # Build the Docker image docker build --platform linux/arm64 -t auris . # Run with required capabilities docker run --platform linux/arm64 \ --cap-add=SYS_PTRACE \ --security-opt seccomp=unconfined \ -it auris # You are now inside the container ./build/auris version ./build/auris help
Important Docker flags explained:
--platform linux/arm64- Ensures ARM64 emulation if not on native ARM64--cap-add=SYS_PTRACE- Grants the ptrace capability required for tracing--security-opt seccomp=unconfined- Disables seccomp filtering that would block ptrace
Option 2: Native Build on ARM64 Linux
For native ARM64 Linux systems (Raspberry Pi 4/5, AWS Graviton, Apple Silicon with Linux VM, etc.):
# Install build dependencies (Debian/Ubuntu) sudo apt update sudo apt install -y build-essential cmake pkg-config \ libcurl4-openssl-dev libssl-dev libjson-c-dev # Clone and build git clone https://github.com/kuladeepmantri/Auris.git cd Auris mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. make -j$(nproc) # Verify the build ./auris version # Run with sudo (or set CAP_SYS_PTRACE) sudo ./auris learn -- /bin/ls -la
Data Directory
Auris stores traces, profiles, and policies in a data directory. By default, this is /data/auris in Docker or ~/.auris on native installs. You can override this with the -d flag:
# Use custom data directory auris -d /path/to/data learn -- /bin/ls # Directory structure /data/auris/ traces/ # JSON trace files profiles/ # Behavioral profiles policies/ # Security policies
Quick Start Examples
Example 1: Trace a program and build a profile
# Step 1: Learn the program's behavior auris learn -- /usr/bin/curl https://example.com # Output: Trace ID: abc123 # Step 2: Build a behavioral profile auris profile -t abc123 # Output: Profile ID: def456 # Step 3: Compare future executions auris compare -p def456 -- /usr/bin/curl https://example.com
Example 2: Create and enforce a security policy
# Generate policy from profile auris policy -p def456 # Output: Policy ID: ghi789 # Test policy in alert mode (logs violations but allows execution) auris enforce -P ghi789 -m alert -- ./my_program # Enforce policy in block mode (terminates on violation) auris enforce -P ghi789 -m block -- ./untrusted_program
Example 3: Offensive operations (authorized testing only)
# List injectable processes auris inject list # Get info about a specific process auris inject info -p 1234 # View process memory maps auris inject maps -p 1234 # Inject shellcode (spawns /bin/sh in target) auris inject shellcode -p 1234 -t exec_sh # Find ROP gadgets in libc auris inject gadgets -b /lib/aarch64-linux-gnu/libc.so.6 # Dump process memory auris inject dump -p 1234 -a 0x400000 -n 256
Command Reference
auris <command> [options] [-- program [args...]] Commands: learn Trace a program and record all syscalls profile Build behavioral profile from a trace compare Compare execution against baseline profile policy Generate security policy from profile enforce Run program under policy enforcement analyze Send profile to AI for analysis inject Process injection framework (offensive) help Show help message version Show version information Global Options: -h, --help Show help -V, --version Show version -v, --verbose Verbose output -q, --quiet Quiet mode -j, --json JSON output format -d, --data-dir DIR Data directory path -t, --trace-id ID Trace ID to use -p, --profile-id ID Profile ID to use -P, --policy-id ID Policy ID to use Inject Subcommands: inject list List injectable processes inject info -p PID Show process information inject maps -p PID Show memory maps inject shellcode Inject and execute shellcode inject gadgets Find ROP gadgets in binary inject dump Dump process memory