-
Notifications
You must be signed in to change notification settings - Fork 5
NoDrop Examples
This page provides several example use cases of NoDrop.
NoDrop can be used in multiple scenarios, including:
- Offline trace collection and analysis
- Streaming compression of system event buffers
- Security research tools that rely on system call tracing
- Binary fuzzing and vulnerability discovery
The following examples demonstrate how NoDrop can be used in practice.
NoDrop can compress captured event buffers while recording them to disk.
This reduces storage usage when capturing large numbers of system events.
The recorded buffers can later be parsed into human-readable logs using the nodrop parse command.
This example demonstrates a simple workflow:
- Enable compressed recording
- Capture events
- Stop monitoring
- Parse the recorded buffers into readable logs
First enable compressed recording:
nodrop record compressThis instructs NoDrop to compress recorded buffers using gzip.
Start NoDrop normally:
sudo nodrop startDuring execution, NoDrop will capture system events and write compressed buffers to disk.
You can now run any workload you want to observe.
Example:
./helloworldAfter running your workload, stop NoDrop:
sudo nodrop stopCompressed buffers are stored in the default directory:
- from the Source Code:
/tmp/nodrop/ - from Binary Packages:
/var/log/nodrop/
Files are saved using the following format: tid-timestamp.buf.gz
Example:
/tmp/nodrop/23145-17110211234123.buf.gz
Each file contains compressed NoDrop event buffers generated by the corresponding thread.
Before parsing, decompress the buffer file:
gunzip 23145-17110211234123.buf.gzThis produces:
23145-17110211234123.buf
Convert the binary buffer into a human-readable log:
nodrop parse 23145-17110211234123.bufIf no output file is specified, NoDrop automatically generates:
23145-17110211234123.log
You can also specify the output file explicitly:
nodrop parse 23145-17110211234123.buf output.logThe resulting .log file contains decoded events that can be inspected directly.
Example:
1776007891921034989 4086 (7): execve(filename=(NULL), res=0, exe=./scripts/tests/helloworld, args=, tid=4086, pid=4086, ptid=2844, cwd=, fdlimit=1024, pgft_maj=0, pgft_min=29, vm_size=340, vm_rss=4, vm_swap=0, comm=helloworld, cgroups=cpuset=/, env=CLUTTER_IM_MODULE=xim, tty=34816, pgid=4086, loginuid=1000, flags=0x1)
1776007891921304317 4086 (7): brk(addr=0x0, res=0x562ae8d24000, vm_size=4044, vm_rss=16, vm_swap=0)
1776007891921553910 4086 (7): access(mode=0x0, res=-2, name=/etc/ld.so.nohwcap)
1776007891921556557 4086 (7): access(mode=0x4, res=-2, name=/etc/ld.so.preload)
1776007891921560686 4086 (7): openat(fd=3, dirfd=-100, name=/etc/ld.so.cache, flags=0x1001, mode=00, dev=0x801)
1776007891921562893 4086 (7): fstat(fd=, res=3)
1776007891921564609 4086 (7): mmap(addr=0x0, length=77999, prot=0x1, flags=0x2, fd=3, offset=0, res=0x7f73fe70e000, vm_size=4124, vm_rss=1768, vm_swap=0)
1776007891921565513 4086 (7): close(fd=3, res=0)
1776007891921568942 4086 (7): access(mode=0x0, res=-2, name=/etc/ld.so.nohwcap)
1776007891921573728 4086 (7): openat(fd=3, dirfd=-100, name=/lib/x86_64-linux-gnu/libc.so.6, flags=0x1001, mode=00, dev=0x801)
1776007891921575209 4086 (7): read(fd=3, size=832, res=832, data=ELF)
1776007891921576494 4086 (7): fstat(fd=, res=3)
1776007891921577585 4086 (7): mmap(addr=0x0, length=8192, prot=0x3, flags=0xa, fd=4294967295, offset=0, res=0x7f73fe70c000, vm_size=4132, vm_rss=1768, vm_swap=0)
1776007891921582717 4086 (7): mmap(addr=0x0, length=4131552, prot=0x5, flags=0x402, fd=3, offset=0, res=0x7f73fe0a2000, vm_size=8168, vm_rss=1768, vm_swap=0)
1776007891921588809 4086 (7): mprotect(addr=0x7f73fe289000, length=2097152, prot=0x0, res=0)
1776007891921592101 4086 (7): mmap(addr=0x7f73fe489000, length=24576, prot=0x3, flags=0x406, fd=3, offset=1994752, res=0x7f73fe489000, vm_size=8168, vm_rss=1848, vm_swap=0)
1776007891921595306 4086 (7): mmap(addr=0x7f73fe48f000, length=15072, prot=0x3, flags=0xe, fd=4294967295, offset=0, res=0x7f73fe48f000, vm_size=8168, vm_rss=1852, vm_swap=0)
1776007891921599337 4086 (7): close(fd=3, res=0)
1776007891921607515 4086 (7): syscall(ID=158)
1776007891921648173 4086 (7): mprotect(addr=0x7f73fe489000, length=16384, prot=0x1, res=0)
1776007891921651186 4086 (7): mprotect(addr=0x562ae8944000, length=4096, prot=0x1, res=0)
1776007891921656721 4086 (7): mprotect(addr=0x7f73fe8be000, length=4096, prot=0x1, res=0)
1776007891921663053 4086 (7): munmap(addr=0x7f73fe70e000, length=77999, res=0, vm_size=8088, vm_rss=2432, vm_swap=0)
1776007891922044002 4086 (7): fstat(fd=, res=1)
1776007891922060800 4086 (7): brk(addr=0x0, res=0x562ae8d24000, vm_size=8088, vm_rss=2432, vm_swap=0)
1776007891922062028 4086 (7): brk(addr=0x562ae8d45000, res=0x562ae8d45000, vm_size=8220, vm_rss=2432, vm_swap=0)
1776007891922073479 4086 (7): write(fd=1, size=14, res=14, data=Hello, world!)
1776007891922078674 4086 (7): syscall(ID=231)
Typical offline analysis workflow:
nodrop record compress
nodrop start
(run workload)
nodrop stop
gunzip *.buf.gz
nodrop parse *.buf
NoDrop has also been used in security research tools such as SPFuzz and SPFuzz++, which are binary fuzzing frameworks designed for source-code-unavailable scenarios.
These tools leverage NoDrop to capture system call traces and use them as feedback signals during fuzzing.
SPFuzz and SPFuzz++ are binary fuzzing tools designed for environments where the source code of the target program is not available.
Instead of relying on traditional instrumentation-based techniques, SPFuzz collects system call traces generated during program execution and uses this information to approximate the program's internal execution behavior.
This information is then used to guide fuzzing input generation.
The design of SPFuzz allows it to perform efficient fuzzing while minimizing the overhead typically associated with binary instrumentation.
SPFuzz and SPFuzz++ support fuzz testing without requiring source code.
Unlike many binary fuzzers that rely on instrumentation, SPFuzz avoids modifying the target binary. This reduces runtime overhead and allows fuzzing of protected or closed-source software.
This capability is enabled by NoDrop, which captures system call traces without modifying the target binary.
The current prototype of SPFuzz runs on Linux systems.
However, the underlying approach is designed to be portable across different operating systems and environments.
By leveraging NoDrop's system call tracing capability, SPFuzz can analyze execution behavior in real environments while minimizing interference with the target program.
SPFuzz relies on NoDrop as its primary runtime information source.
During execution:
- NoDrop captures system call events generated by the target program
- SPFuzz analyzes these system call traces
- The traces are used as feedback signals to guide input mutation
This mechanism allows SPFuzz to approximate execution paths even without internal program instrumentation.
When SPFuzz was originally implemented, NoDrop was still in an early development stage. As a result, SPFuzz depends on specific Linux kernel versions compatible with that early NoDrop implementation.
Future improvements to NoDrop may allow SPFuzz-like systems to support additional platforms and kernel versions.
Example repository:
https://github.com/Nova-xiao/SPFuzz
SPFuzz depends on the NoDrop kernel module.
First obtain musl using the script provided in the NoDrop repository:
NoDrop/scripts/getmusl.sh
Then build and load NoDrop:
cd NoDrop/build
cmake ..
make load
Compile SPFuzz:
make
To enable debug mode:
make debug=1
Debug logs will be stored in:
SPFuzz/logs/logging
SPFuzz operates similarly to AFL-style fuzzers.
One important difference is that the path count displayed in SPFuzz corresponds to the number of system call paths, rather than traditional program execution paths.
These system call paths are derived from traces captured by NoDrop.