In Amit Singh's book there's a chapter on interposing. You can tell the system to load a dylib you've created that will replace a given function with your own implementation.
I'm using interposing to alter the system time clock for a given application.
See below how cal shows date in February (system time) and date is a month back (because we've altered the gettimeofday call).
This is the part where we try and figure out which process makes the gettimeofday call. We are using a bash specific approach here, relying on the "_" environment variable that bash expands to the full name of the executed binary.
Out code parses through the environ array (this will be setup by execve when the system runs our executable).
Our replacement function.
It will set the date to somewhere in January 2007 if the caller is "/bin/date", otherwise just return the system time.
We are using "-undefined dynamic_lookup" because of the environ unsatisfied reference.
I'm using interposing to alter the system time clock for a given application.
Results
See below how cal shows date in February (system time) and date is a month back (because we've altered the gettimeofday call).
cristi:~/Programming/test diciu$ DYLD_INSERT_LIBRARIES=/tmp/libinterposers.dylib cal
February 2007
S M Tu W Th F S
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28
cristi:~/Programming/test diciu$ DYLD_INSERT_LIBRARIES=/tmp/libinterposers.dylib date
Fri Jan 26 15:19:21 CAT 2007
Code rundown
cristi:~/Programming/test diciu$ cat timeinterpose.c
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <strings.h>
typedef struct interpose_s
{
void * new_func;
void * orig_func;
} interpose_t;
int my_gettimeofday(struct timeval * tp, struct timezone * tzp);
static const interpose_t interposers[] __attribute__ ((section("__DATA, __interpose"))) = {
{ (void *) my_gettimeofday, (void *) gettimeofday },
};
This is the part where we try and figure out which process makes the gettimeofday call. We are using a bash specific approach here, relying on the "_" environment variable that bash expands to the full name of the executed binary.
Out code parses through the environ array (this will be setup by execve when the system runs our executable).
extern char **environ;
int lookup_process_name(char * process_name)
{
int i=0;
char * current;
do
{
current = environ[i];
if(current != NULL)
{
if(current[0] == '_' && current[1] == '=')
{
char * binary_full_file_name = NULL;
binary_full_file_name = index(current, '=');
if(binary_full_file_name != NULL)
{
if(!strcmp((char *)(binary_full_file_name + 1), process_name))
return 1;
else
return 0;
}
}
}
i++;
}
while(current != NULL);
return 0;
}
Our replacement function.
It will set the date to somewhere in January 2007 if the caller is "/bin/date", otherwise just return the system time.
int my_gettimeofday(struct timeval * tp, struct timezone * tzp)
{
int ret = gettimeofday(tp, tzp);
//printf("--> %d=gettimeofday(), tv sec is %d", ret, tp->tv_sec);
if(lookup_process_name("/bin/date"))
tp->tv_sec = 1169817561;
return ret;
}
Compiling the library
We are using "-undefined dynamic_lookup" because of the environ unsatisfied reference.
gcc -Wall -dynamiclib -undefined dynamic_lookup -o /tmp/libinterposers.dylib timeinterpose.c