This is a draft of a control flow tracer based on source code instrumentation with a low overhead.
Instrument your software with instrumenter.py
. When running instrumented software, the trace is written into a file.
The format is basically one character (plus an optional number)
for each source code block on the trace.
For accurate retracing, retrace.py
uses symbolic execution.
Any software which is written in C/C++, with the source code available.
pip install libclang
)pip install angr
)make
pip install .
checksum.c
Optionally: Change configuration in include/src_tracer/constants.h
.
Load the environmental variables
source env.sh
First run the pre-processor
cd examples/
cpp -I${SRC_TRACER_INCL} checksum.c -o checksum.i
Instrument it (the pre-processed version)
instrumenter.py checksum.i -o checksum_inst.c
For a list of functions together with the num
generated by the instrumenter,
have a look at the newly created functions_database.db
.
Compile it with _TRACE_MODE
gcc -D_TRACE_MODE -L${SRC_TRACER_LIB} -I${SRC_TRACER_INCL} checksum_inst.c -o checksum_trace -lsrc_tracer
clang
instead of gcc
-O3
for recording/replayingTRACEFORK_ZSTD
in include/src_tracer/constants.h
, you would need -lzstd
hereRun it (replace 42
to get another trace)
./checksum_trace 42
The name of the recorded trace corresponds to the current time, e.g. 2023-04-28-143402-checksum.c.trace
.
Display the trace (replace the trace name with the correct one!)
print_trace.py 2023-04-28-143402-checksum.c.trace
TRACEFORK_ZSTD
in include/src_tracer/constants.h
, you would need to decompress the trace first using zstd -d
Compile it with _RETRACE_MODE
(you might also want different compiler optimizations for recording/replaying)
gcc -D_RETRACE_MODE -g -I${SRC_TRACER_INCL} -L${SRC_TRACER_LIB} checksum_inst.c -o checksum_retrace -lsrc_tracer
Retrace it (use python -i
to work with the traced state
in the interactive shell)
retrace.py checksum_retrace 2023-04-28-143402-checksum.c.trace
echo "C1 IIO" > sub.trace.txt
retrace.py checksum_retrace sub.trace.txt
The last one just retraces function checksum
.
An example to instrument and retrace busybox with musl-libc can be found in the wiki
You can do it manually as for the checksum.c
example.
For a more automatic way that works well with make scripts, make use of cc_wrapper/
for the gcc compiler.
source gcc_env.sh
This will set CC, CFLAGS and LIBS.
export SRC_TRACER=""
./configure
export SRC_TRACER="-D_TRACE_MODE"
make
, gcc
or similar. Example:
gcc $CFLAGS checksum.c -o checksum_trace2 $LIBS
~/.src_tracer
by default!./configure
your project again (e.g. with other options like CFLAGS
with -g
)
make sure to set SRC_TRACER=""
(as empty string) before you run ./configure
.export SRC_TRACER="-D_RETRACE_MODE"
make
, gcc
or similar. Example:
gcc $CFLAGS checksum.c -o checksum_retrace2 $LIBS
It can be a bit tricky to get the binary linking correctly, make sure that the record/replay executable includes the record/replay version of the app and its libraries.