-
Notifications
You must be signed in to change notification settings - Fork 16
Loader and binary rewriter API
Cristian Cadar edited this page Apr 22, 2020
·
4 revisions
All API definitions are located in a single header file: https://github.com/parras/varan/blob/split-loader/includes/vx_api_defs.h
Examples of existing plugins can be found in https://github.com/parras/varan/tree/split-loader/plugins
The basic steps to create a minimal working plugin are as follows:
- Clone the split-loader branch:
git clone [email protected]:parras/varan.git
- Under
plugins/
create a new subdirnew_plugin
and add it to the rootCMakeLists.txt
:add_subdirectory("plugins/new_plugin")
- Implement a syscall handler function of type
vx_sc_handler_fn
. This function is responsible for actually issuing the real syscall. - Implement the
vx_init
function of typevx_init_fn
. It should at least set thevx_sc_handler_fn
function pointer argument to the function defined in 3, and adjustargv
andargc
to point to the client ELF path. - Write a
CMakeLists.txt
to build a shared object, see for instance https://github.com/parras/varan/blob/split-loader/plugins/vstrace/CMakeLists.txt - Build and run:
./loader/run plugins/new_plugin/libnew_plugin.so
Loader: executable that loads and rewrites the client application to redirect system calls to the plugin
Plugin: library implementing syscall handlers (e.g. varan
for MVE or vstrace
for tracing)
Client: executable whose system calls have to be intercepted
- the loader is passed the path of the plugin (which is an ELF shared object)
- the loader uses
dlopen()
to open the ELF anddlsym()
to findvx_init()
- the loader calls the
vx_init()
, providing the following arguments:
a) pointers toargc
andargv
—both of them will be modified by the plugin
b) pointer to interception callback registration function to be called by the plugin
c) pointer to vDSO callback function to be populated by the plugin
d) pointer to syscall handler function to be populated by the plugin
e) pointer to post-load function to be populated by the plugin, that will be called after rewriting just before jumping into the client
- the plugin parses arguments and leaves them in a state such that when
vx_init
returns,argv[0]
is the path to the client ELF to be executed and subsequent arguments are the client's actual arguments - the plugin populates
syscall_handler
with appropriate function - the plugin calls
fn_icept_reg
for each of the functions that need to be intercepted (optional) - the plugin populates
vdso_callback
with appropriate function (optional) - the plugin populates
post_load
with appropriate function (optional)
- the loader loads the ELF file
- the loader performs the interception of the functions registered:
a) each function is located and its first few instructions are relocated to make room for unconditional jump - pointer to the first function is saved and an unconditional jump is injected at the end to connect these instructions to the rest of the function
b) some static ASM code is injected to divert the flow of control through a pointer returned by the callback (that has to be called with the pointer of the start of the original function - the first relocated instruction)
c) the unconditional jump mentioned in a) now jumps to code in b) - the loader performs the interception of vDSO if
vdso_callback
was populated in a similar way to 10 - the loader performs the interception of all system calls in a similar way
- the loader transfers control to the entry point of the client ELF