Dr. Memory
|
Dr. Memory provides a fuzz testing mode that repeatedly executes one function in the target application, mutating the value of one argument before each iteration. Fuzz mode is configured using a set of runtime options that all share a -fuzz_
prefix. For example, -fuzz_function
specifies the function name for fuzzing. The aggregate runtime option -fuzz_target
can also be used to configure the fuzz target. An overview of each option and descriptor format is provided in the Dr. Memory Runtime Option Reference (and the command line help text). Many of these options require a more complete explanation, which is provided in the following sections.
Fuzzer Target
The fuzzer is capable of testing one target function on potentially multiple concurrent threads.
The fuzzer can locate the target function via either its symbol name or its offset from the start of the module with the following options:
-fuzz_module:
the module name that refers to a single binary image file such as a library (.so or .dll) or an application executable (.exe on Windows);-fuzz_function
or-fuzz_offset
-fuzz_function:
the target function name;-fuzz_offset:
the offset from the module base.
In addition, to repeatedly execute the target function, the fuzzer needs to know
-fuzz_num_args:
how many arguments are passed to the function;-fuzz_data_idx:
the ordinal number of the argument that should be fuzzed;-fuzz_size_idx:
the ordinal number of the argument that specifies the size of the fuzzed argument;-fuzz_num_iters:
how many iterations the function is to be repeated.
For example, to fuzz the following C function in the "a.out" executable:
void DrMemFuzzFunc(unsigned char *buffer, size_t size);
you would specify the following command-line option to drmemory:
-fuzz_module a.out -fuzz_function DrMemFuzzFunc -fuzz_num_args 2 -fuzz_data_idx 0 -fuzz_size_idx 1 -fuzz_num_iters 100
Alternatively, users can specify the target function on the Dr. Memory command line using the aggregate option -fuzz_target:
-fuzz_target 'a.out!DrMemFuzzFunc|2|0|1|100'
In bash, use single-quotes to avoid special behaviors of the '!' and '|' characters.
Users can skip an option if its value is the same as its default value. For the example above, the shortest command-line option is:
-fuzz
C++ Targets
Specifying C function targets is much simpler than C++ targets because the symbol name is the plain text name of the function, and the calling convention is almost always the default. For C++ functions, the mangled or de-mangled name is required. On Unix the fuzzer only accepts mangled names, while on Windows it accepts both the mangled and de-mangled names (for the former, use Windows-only option -fuzz_mangled_names
). To fuzz the following function on Unix (compiling the app as 32-bit with gcc):
void CryptoMagic::MungeBuffer(unsigned int *buffer, size_t size);
you would specify the following option to drmemory:
-fuzz_target 'crypto!_ZN11CryptoMagic11MungeBufferEPjj|2|0|1|0'
Calling Conventions
The fuzzer's default calling convention is cdecl
on 32-bit x86 platforms, AMD64
on 64-bit *nix, and Microsoft
x64
for Visual Studio 64-bit applications. Use the option -fuzz_call_convention
to specify a different calling convention for fuzz target functions. For example, to fuzz a C++ non-static member function, you would specify the following command-line option to drmemory:
-fuzz_call_convention \p thiscall
Possible -fuzz_call_convention value includes:
- amd64: AMD64
- arm32: ARM32
- fastcall: fastcall
- ms64: Microsoft x64 (Visual Studio)
- stdcall: cdecl or stdcall
- thiscall: thiscall
It is also possible to use the optional last field of option -fuzz_target
to specify a different calling convention. For example, to fuzz the following function on Windows (compiling the app with Visual Studio):
void CryptoMagic::MungeBuffer(unsigned int *buffer, size_t size);
you would specify:
-fuzz_target 'crypto.exe!?MungeBuffer-CryptoMagic--QAEXPAII-Z|3|1|2|0|6'
The value 6
at the last field specifies the calling convention 'thiscall'
(as defined by the enum drwrap_callconv_t
in the DynamoRIO header file drwrap.h
). Since the MungeBuffer()
method is a non-static class member, the first argument is reserved by the compiler for the this
pointer. Accordingly, the argument indexes in the descriptor (fields 3 and 4, "|1|2|"
) have been adjusted to account for the implicit first argument, along with the argument count (field 2, "|3|"
). Notice that the '@'
characters in the symbol have been escaped with '-'
for compatibility with the Dr. Memory command-line processor.
Mutator
The mutator is responsible for modifying the input to the target function on each iteration. A default mutator with a variety of options, including various random and sequential mutation strategies, is provided. Dr. Memory exposes all of the options for Dr. Fuzz's default mutator as front-end options. Please see the documentation under Dr. Fuzz Mutators as well as the -fuzz_mutator_*
options listed under Dr. Memory Runtime Option Reference. The option -fuzz_coverage
must be specified for any custom mutator that implements feedback guided mutation.
Dumping and Loading Fuzz Input Data
On reporting an error during fuzzing, Dr. Memory dumps the fuzz input data to a file in the log directory. The dumped file can be used for reproducing the error later with the option -fuzz_input_file
. For example, to load input.dat for reproducing an error, you would specify the following command-line option to drmemory:
-fuzz_input_file input.dat -fuzz_num_iters 0
Corpus-Based Fuzzing
Dr. Memory supports corpus-based fuzzing through the following options:
-fuzz_corpus:
the directory for loading and storing the corpus inputs-fuzz_corpus_out:
the directory for storing the minimized corpus inputs
Each input is stored by itself in a separate file in a specified directory, and that there should be nothing else in the directory.
For example, to fuzz the function DrMemFuzzFunc
with a set of inputs stored in /path/to/inputs/ and dump the minimized corpus inputs to /path/to/min_corpus/, you would specify the following command-line option to drmemory:
-fuzz_corpus /path/to/inputs -fuzz_corpus_out /path/to/min_corpus/