DynamoRIO API
Deployment

Once the DynamoRIO distribution contents are unpacked (see Distribution Contents), configuration and execution of applications under DynamoRIO is handled by a set of libraries and tools. On Windows, the tools are drconfig.exe, drrun.exe, and drinject.exe. The corresponding libraries (whose APIs are exposed by the tools) are drconfiglib.dll and drinjectlib.dll with header files dr_config.h and dr_inject.h. On Linux, the tools are named drconfig, drrun, and drinject, and the libraries are libdrconfiglib.a and libdrinjectlib.a.

When using DynamoRIO as a third-party disassembly library (see IA-32/AMD64/ARM/AArch64 Disassembly Library), no deployment is needed, as DynamoRIO does not control a target application when used as a regular library.

Windows Deployment

There are two methods for running a process under DynamoRIO: the one-time configure-and-run, and the two-step separate configuration and execution. The drrun.exe tool supports the first, simpler model, while the drconfig.exe and drinject.exe tools support the second, more powerful model. The drconfig.exe tool, or the corresponding the drconfiglib.dll library, can also be used to nudge running processes.

Configuration information is stored in files in the current user's profile directory, which is obtained from the environment variable USERPROFILE. Thus, configurations are persistent across reboots and are private to each user. If the DYNAMORIO_CONFIGDIR environment variable is set, its value is used instead of USERPROFILE. If neither is set, a temp directory will be used when creating new configuration files for configure-and-run execution.

DynamoRIO also supports global configurations, which are stored in the "config" subdirectory of the directory specified by the DYNAMORIO_HOME registry value in the registry key \HKLM\SOFTWARE\DynamoRIO\DynamoRIO (or for 32-bit on 64-bit Windows (WOW64) \HKLM\SOFTWARE\Wow6432Node\DynamoRIO\DynamoRIO). Setting that DYNAMORIO_HOME value and creating the directory it points to must be done manually. The provided tools support reading and writing both local and global configuration files, and automatically creating the local directory. DynamoRIO gives local files precedence when both exist. Note that applications that do not have a USEPROFILE environment variable can be controlled using DYNAMORIO_CONFIGDIR or global configurations. Also note that by default USERPROFILE is not set over cygwin ssh and must be explicitly set in the shell startup files.

Configurations are per-process, with the basename of the process used for identification (e.g., notepad.exe). One-time configuration also uses the process id to specify that the configuration is for that process instance only.

As an example, assume you have unpacked the DynamoRIO distribution and your current directory is its base directory. Run notepad.exe with the bbsize sample client using the following configure-and-run command:

bin32/drrun.exe -c samples/bin32/bbsize.dll -- notepad

To use system-wide injection, allowing for an application to be run under DynamoRIO regardless of how it is invoked, configure the application first (-syswide_on requires administrative privileges):

bin32/drconfig.exe -reg notepad.exe -syswide_on -c samples/bin32/bbsize.dll

The next time notepad.exe is started by the current user, it will run under DynamoRIO with the bbsize client.

To unregister notepad.exe, issue the following command:

bin32/drconfig.exe -unreg notepad.exe

Invoke any of the drconfig.exe, drrun.exe, or drinject.exe tools with no arguments to see the full list of options available.

By default, DynamoRIO follows into all child processes, with the parent's settings inherited by the child if there is no configuration set up ahead of time for the child application. To instead only follow children that are configured (via drconfig.exe), use the -no_follow_children runtime option.

To ensure a client is loaded into a child process of a different bitwidth (i.e., a 32-bit child created by a 64-bit parent), use the -c32 and -c64 options to drconfig or drrun, with ending the first client's options:

bin32/drrun.exe -c32 samples/bin32/bbsize.dll – -c64 samples/bin64/bbsize.dll – notepad

The order matters: -c32 must come first.

To nudge all instances of notepad.exe running under DynamoRIO with argument "5", use:

bin32/drconfig.exe -nudge notepad.exe 0 5

This will result in a nudge event with argument=5 delivered to the client callback registered with dr_register_nudge_event() in all notepad.exe processes running under DynamoRIO. The third argument, 0, is an ID supplied at registration which uniquely identifies the target client (see dr_deploy.h for details).

To view 32-bit or WOW64 processes running under DynamoRIO the drview.exe tool can be used. The bin64 version will display both 32-bit and 64-bit processes and will indicate which are 32-bit. The bin32 version will display 64-bit processes but is unable to determine whether DynamoRIO is present.

Attention
Note that on Windows NT a reboot is required after using -syswide_on or -syswide_off.

DynamoRIO uses the \HKLM\SOFTWARE\Microsoft\Windows\Windows NT\CurrentVersion\AppInit_DLLs key (for 32-bit on 64-bit Windows (WOW64), \HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs) for -syswide_on to inject into new processes without having to directly launch them drrun.exe or drinject.exe. For injection to work, the registered process must statically link to user32.dll (only a few small non-graphical windows applications don't link user32.dll). If a target application does not link to user32.dll, DynamoRIO can still inject if the process is launched with drinject.exe or if the parent process (usually cmd.exe or explorer.exe for user launched processes) is running under DynamoRIO. The drinject.exe tool uses the configuration information set by drconfig.exe for the target application.

Attention
The -syswide_on, -syswide_off, use of global configuration files, and nudging certain processes may require administrative privileges. On Windows Vista or higher, if UAC is enabled, use an elevated (runas admin) process. When using drconfig.exe and drrun.exe in these scenarios, be sure that the cmd shell being used was started with elevated permissions.

An alternative method to run an application under DynamoRIO is the app_start()/app_stop() interface, which requires modifying application source code.

Linux Deployment

Once DynamoRIO has been unpacked, the same set of helper binaries as on Windows provide flexibility in configuring and executing applications.

There are two methods for invoking an application under DynamoRIO:

  1. Configure and launch in one step via drrun
  2. Configure via drconfig and launch via drinject

As an example of the simpler method, the following command runs ls under DynamoRIO with the bbsize sample client:

% bin32/drrun -c samples/bin32/libbbsize.so -- ls

Run drrun with no options to get a list of the options and environment variable shortcuts it supports. To disable following across child execve calls, use the -no_follow_children runtime option.

Use the tools in bin32/ for 32-bit applications and the tools in bin64/ for 64-bit applications.

The two-step method allows for greater control over child processes. The drconfig tool writes a configuration file for a given application name. DynamoRIO reads its options from the configuration file at runtime. Once each process name is configured, the drinject tool can be used to invoke the parent process. The drrun tool can also be used but it creates a temporary configuration file that will override settings requested via drconfig. The configuration file for each application is stored in $DYNAMORIO_CONFIGDIR/.dynamorio/<appname>.config32 (or a config64 suffix for 64-bit). If DYNAMORIO_CONFIGDIR is not set, $HOME/.dynamorio/<appname>.config32 is used; if neither is set, a temp directory will be used when creating new configuration files for configure-and-run execution. On Android, if neither /data/local/tmp nor the current working directory are writable, you will need to specify a writable directory by setting the DYNAMORIO_CONFIGDIR environment variable.

DynamoRIO also supports global configuration files in /etc/dynamorio/<appname>.config32 when a local configuration file is not found. drconfig does not support directly writing a global config file but such files can be copied from or modeled on local files.

If a target application executes an execve that discards the HOME environment variable, the resulting process will still run under DynamoRIO control with the same settings as the parent process. Use DYNAMORIO_CONFIGDIR or global configuration files to specify separate options for such a child process.

When running scripts it is best to explicitly invoke the interpreter rather than invoking the script directly:

% bin64/drrun -- /bin/bash myscript.sh

To nudge a process with pid targetpid running under DynamoRIO and pass argument "5" to the nudge callback, use the nudgeunix tool:

bin32/nudgeunix -pid targetpid -client 0 5

This will result in a nudge event with argument=5 delivered to the client callback registered with dr_register_nudge_event() in the target process. The 0 argument is an ID supplied at registration which uniquely identifies the target client (see dr_deploy.h for details). If you used the -c argument to drrun or drconfig to register the client, the client's id defaults to 0.

An alternative method to run an application under DynamoRIO is the app_start()/app_stop() interface, which requires modifying application source code.

Android Deployment

Android deployment is generally the same as Linux Deployment except for the following differences.

For pure native applications, the default configuration file location (if DYNAMORIO_CONFIGDIR is not explicitly set) is usually (depending on whether $HOME happens to be writable) /data/local/tmp.

For Android applications on recent versions of Android, SELinux prevents writing to /data/local/tmp. The application's data directory should be pointed at in the TMPDIR or DYNAMORIO_CONFIGDIR environment variables, as shown below in the example wrapper script. We recommend using TMPDIR as its value will also be used by tools such as Dr. Memory for their log files.

To launch an Android application under DynamoRIO, use a wrapper script and point at the script via the logwrapper property set on your application's name prefixed by wrap.. For example, if your application's name is com.myco.appname, set the property for wrap.com.myco.appname, truncating to 31 characters:

setprop wrap.com.myco.appname "logwrapper /system/xbin/wrap.sh"

The wrapper shell script should contain the command line prefix you wish to use to launch your application under DynamoRIO:

#!/system/bin/sh
export TMPDIR=/data/data/com.myco.appname
exec /system/xbin/dynamorio/bin32/drrun -- $@

Be sure to place the DynamoRIO binaries and the wrapper script in an executable location, such as /system/xbin. Alternatively, disable SELinux via setenforce 0.

If you run into problems with configuration files being created due to SELinux denials (look in the logs for such denials), it may be simplest to disable SELinux via setenforce 0. We have attempted to get everything to work without this step, but we are not able to test on all versions or configurations of Android.

Passing Options to Clients

All of the earlier examples did not need to pass any arguments to the client. When using the -c argument to set the client, all arguments between the client path and the double dash are passed to the client. When using the -client argument to drrun, the third argument following -client is passed through to the client. For example, all these invocations of drrun pass '-op1 -op2 "value with spaces"' to the client:

bin32/drrun.exe -c libmyclient.dll -op1 -op2 \"value with spaces\" -- notepad
bin32/drrun.exe -client myclient.dll 0 '-op1 -op2 "value with spaces"' -- notepad

On Linux:

bin32/drrun -c libmyclient.so -op1 -op2 \"value with spaces\" -- ls
bin32/drrun -client libmyclient.so 0 '-op1 -op2 "value with spaces"' -- ls

When using a two-step model, the options are passed to drconfig:

bin32/drconfig.exe -reg notepad.exe -c myclient.dll -op1 -op2 \"value with spaces\"
bin32/drconfig.exe -reg notepad.exe -client myclient.dll 0 '-op1 -op2 "value with spaces"'

The client's options are passed directly to its dr_client_main() initialization routine, in the same manner as arguments are passed to a regular application's main() routine. To match standalone application conventions, argv[0] is set to the client library path, with the actual parameters starting at index 1. The client can also optionally call dr_get_option_array() to retrieve the options passed to it. C++ clients can use the convenience of the DynamoRIO Option Parser.

Client options are not allowed to contain semicolons. Additionally, the client option string combined with the path to the client library cannot contain all three quote characters (', ", `) simultaneously.

To ensure a client is loaded into a child process of a different bitwidth (i.e., a 32-bit child created by a 64-bit parent), use the -c32 and -c64 options to drconfig or drrun, with ending the first client's options:

bin32/drrun -c32 samples/bin32/bbsize.dll – -c64 samples/bin64/bbsize.dll – notepad

The order matters: -c32 must come first.

Multiple Clients

DynamoRIO does support multiple clients. It is each client's responsibility, however, to ensure compatibility with other clients. DynamoRIO makes no attempt to force cooperation among clients. For example, instruction stream modifcations made by one client are visible to other clients. Systems employing multiple clients must be aware of such interactions and design accordingly.

Client registration requires users to specify the priority of each client. DynamoRIO calls each client's dr_client_main() routine sequentially according to this priority. Clients with a numerically lower priority value are called first and therefore given the first opportunity to register callbacks (the client with priority 0 is called first). Since DynamoRIO delivers event callbacks sequentially, client priority and the order of event registration is important. For a given event, the first registered callback is called last. This scheme gives precedence to the first registered callback since that callback is given the final opportunity to modify the instruction stream or influence DynamoRIO's operation.

End-User Tools

A client can be packaged up with DynamoRIO to create an end-user tool. For many tools, a separate front-end executable is not necessary, and drrun is sufficient. Using drrun for a tool is made simpler by the -t option. To use the option, first create a file in the tools subdirectory of the root of the DynamoRIO installation called toolname.drrun32 or toolname.drrun64, depending on the target architecture. Here, toolname is the desired external name of the tool. This file should contain one of the following lines, or two if they are a pair of CLIENT32_* and CLIENT64_* specifiers:

CLIENT_ABS=/absolute/path/to/client
CLIENT32_ABS=/absolute/path/to/32-bit-client
CLIENT64_ABS=/absolute/path/to/64-bit-client

or

CLIENT_REL=relative/path/to/client/from/DynamoRIO/root
CLIENT32_REL=relative/path/to/32-bit-client/from/DynamoRIO/root
CLIENT64_REL=relative/path/to/64-bit-client/from/DynamoRIO/root

This enables drrun to locate the tool's client library. The 32 and 64 specifiers allow pointing at alternate-bitwidth paths for use if the target application creates a child process of a different bitwidth.

The file can also modify the default DynamoRIO runtime options (see Fine-Tuning DynamoRIO: Runtime Parameters) via DR_OP= lines. Each line contains only one option string token. For example:

DR_OP=-persist
DR_OP=-persist_dir
DR_OP=c:\\path with spaces\\subdir

Tool options can also be specified, but normally the defaults should be set up appropriately in the client itself:

TOOL_OP=-custom_op1
TOOL_OP=-custom_op2

Lines beginning with # are considered comments.

When drrun is passed the option string -t toolname, it looks for tools/toolname.drrun64 or tools/toolname.drrun32 and reads the file to determine the client library to use and the default DynamoRIO options. This makes for a simpler launching command, rather than the end user needing to name the exact location of the client library. For example, this command:

bin64/drrun -t mytool -tool_option1 -tool_option2 -- myapp

can be made to expand to this equivalent command:

bin64/drrun -mytool_dr_option1 -mytool_dr_option2 -c tools/mytool/libmytool.so -tool_option1 -tool_option2 -- myapp

For more extensive actions on launching the tool, a custom front-end executable can be created that replaces drrun by using drinjectlib, drconfiglib, and drfrontendlib. These three libraries facilitate creating cross-platform tools for configuring and launching applications under Dr. Memory. For more information about the interfaces they provide, see their header files: dr_inject.h, dr_config.h, dr_frontend.h.

A custom front-end executable can be invoked via a drrun -t configuration file using one of the following lines:

FRONTEND_ABS=/absolute/path/to/front-end

or

FRONTEND_REL=relative/path/to/front-end/from/DynamoRIO/root

This will cause drrun to transfer control to the specified front-end executable, passing any tool arguments (including client paths, if CLIENT{,32,64}_{ABS,REL} appears after the FRONTEND_* command) followed by "--" and the target application command line.

The path to the DynamoRIO install base can be included in the front-end options via this line

TOOL_OP_DR_PATH

The DynamoRIO runtime options can be included in a single token, preceded by a prefix, via this line, using "-dr_ops" as an example prefix:

TOOL_OP_DR_BUNDLE=-dr_ops

A warning message can be presented up front to the user with:

USER_NOTICE=This tool is currently experimental. Please report issues to mytool.com/issues.