--- title: "How to Run" layout: default permalink: /page_deploy.html ---
DynamoRIO
|
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 Disassembly Library), no deployment is needed, as DynamoRIO does not control a target application when used as a regular library.
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:
Alternatively, you can first run notepad.exe
, and then use drrun
to attach to it, but please note that attaching is an experimental feature and is not yet as well-supported as launching a new process:
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):
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:
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:
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.
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.
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.
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:
drrun
drconfig
and launch via drinject
As an example of the simpler method, the following command runs ls
under DynamoRIO with the bbsize sample client:
Alternatively, you can first run the target, and then use drrun
to attach to it, but please note that attaching is an experimental feature and is not yet as well-supported as launching a new process. In particular, if the application is in the middle of a blocking syscall, DynamoRIO will wait for that to finish. To instead force interruption of the syscall, additionally pass -skip_syscall.
This attach feature requires ptrace capabilities, which can be enabled with this command:
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:
To nudge a process with pid targetpid
running under DynamoRIO and pass argument "5" to the nudge callback, use the nudgeunix
tool:
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 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
. For example, if your application's name is wrap
.com.myco.appname
, set the property for wrap.com.myco.appname
, truncating to 31 characters:
The wrapper shell script should contain the command line prefix you wish to use to launch your application under DynamoRIO:
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.
To run DynamoRIO under QEMU, use the -xarch_root option to point at the base directory of the guest system libraries. This is the same path passed to QEMU's -L
option:
Be sure to install both the qemu-user
and qemu-user-binfmt
packages in order for QEMU to impose itself across an execve:
If using a custom build of QEMU, be sure to update the binfmt rule to ensure the proper build is used across execve: QEMU does not ensure that the same build is preserved and instead relies on the global binfmt rule. On an Ubuntu system, edit /usr/share/binfmts/qemu-arm
and replace the interpreter
path. Then run:
Confirm the change took effect:
On Fedora, edit /usr/lib/binfmt.d/qemu-arm-dynamic.conf
and then run:
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:
On Linux:
When using a two-step model, the options are passed to drconfig:
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.
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.
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:
or
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 DynamoRIO Runtime Options) via DR_OP=
lines. Each line contains only one option string token. For example:
Tool options can also be specified, but normally the defaults should be set up appropriately in the client itself:
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:
can be made to expand to this equivalent command:
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 DynamoRIO. 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:
or
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
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:
A warning message can be presented up front to the user with:
An alternative to running an entire application under DynamoRIO control is to use the Application Interface to specify a portion of the application to run. This interface consists of the following routines:
When building an executable that uses DynamoRIO's Application Interface, follow the steps for How to Build a Tool to include the header files and link with the DynamoRIO library, but omit the linker flags requesting no standard libraries or startup files. DynamoRIO's CMake support does this automatically, as the linker flags for shared libraries are separate from those for executables.
DynamoRIO's behavior can be fine-tuned using runtime parameters. Options are specified via drconfig
, drrun
, or dr_register_process(). See How to Run.
-no_follow_children: By default, DynamoRIO follows all child processes. When this option is disabled via -no_follow_children
, DynamoRIO follows only into child processes for which a configuration file exists (typically created by drconfig
; see How to Run). On Linux, forked children are always followed and this option only affects execve.
To follow all children in general but exclude certain children, leave -follow_children
on (the default) and create config files that exclude the desired applications by running drconfig
with the -norun
option.
-persist_dir
. See Persisting Code for more details.Options controlling notifications from DynamoRIO:
-msgbox_mask 0xN: Controls whether DynamoRIO uses pop-up message boxes on Windows, or waits for a key press on Linux, when presenting information. The mask takes the following bitfields:
dr_messagebox() is not affected by -msgbox_mask. For the provided Windows debug build -msgbox_mask defaults to 0xC. On Linux the default is 0, as this feature reads from standard input and might conflict with some applications. On Linux the pause can be changed to use an infinite loop rather than reading from standard input by passing the -pause_via_loop runtime option, which allows attaching a debugger.
cmd
console on Windows 7 or earlier or on any Windows version when running a graphical application in cmd
(even with dr_enable_console_printing(), as that only affects clients calling dr_printf() or dr_fprintf()) but the output can be viewed from cmd
by redirecting to a file. For the provided Linux debug builds, -stderr_mask defaults to 0xF; for the Linux release builds, its default is 0xE. The default on Windows is 0.Options aiding in debugging:
Options available only in the debug build of DynamoRIO:
drconfig
, or drrun
configuration for the target application. The runtime option -logdir can be used to override the default directory. There is one main log file per directory named app.0.TID.html, where TID is the thread identifier of the initial thread. There is also a log file per thread, named log.N.TID.html, where N is the thread's creation ordinal and TID is its thread identifier. The loglevel may be changed during program execution, but if it began at 0 then it cannot be raised later. The -logmask parameter can be used to control which DynamoRIO modules output data to the log files. dr_log() allows the client to write to the above logfiles.