LD_PRELOAD Method to Overload Linux Date Functions

LD_PRELOAD Method to Overload Linux Date Functions


On Linux, LD_PRELOAD is an environment variable that allows a user to specify a library that should be loaded BEFORE any other library. This allows standard functions to be overriden by different and custom versions. By doing this, these custom functions will be used by the dynamic linker instead of the standard versions.

Checkout the source code below for a very simple shared object, *.so, ( library ) that overrides functions called by the linux ‘/bin/date’ command.

To test it out, you would compile and run the command like this:

LD_PRELOAD=./datehack.so date -u

Compile the following example library like this:

$($(C_)PROJECT_TOP_DIR)/toolchain/$($(C_)PROJECT_ARM_TOOLCHAIN_NAME)/bin/arm-linux-gnueabi-gcc -Wall -fPIC -DPIC -c hackdate.c

cd $(@D)/src && $($(C_)PROJECT_TOP_DIR)/toolchain/$($(C_)PROJECT_ARM_TOOLCHAIN_NAME)/bin/arm-linux-gnueabi-ld -shared -ohackdate.c.so hackdate.c.o -ldl

And here is the source code:

#define _GNU_SOURCE

#include <dlfcn.h>

#include <stdio.h>

#include <time.h>

#include <sys/time.h>

#include <stdlib.h>

#include <sys/timeb.h>


struct tm *(*orig_localtime)(const time_t *timep, struct tm *result);


static long get_time() {

fprintf(stdout,"Callin get_time()...\n");

FILE * input_values;

input_values = fopen("/tmp/ntp.txt","r");

if (input_values == NULL) {

fprintf(stderr, "Error! Could not open file.\n");

}


int retValue;

fscanf(input_values, "%ld", &retValue);

fclose(input_values);

fprintf(stdout,"Function get_time() returned: %d\n",retValue);


return retValue;


}


int gettimeofday(struct timeval *tv, struct timezone *tz) {

fprintf(stdout,"Overriding gettimeofday...\n");

if(tv == NULL)

return -1;

tv->tv_sec = get_time();

return 0;

}


int clock_gettime(clockid_t clk_id, struct timespec *tp) {

fprintf(stdout,"Calling clock_gettime...\n");

if(tp == NULL)

return -1;

tp->tv_sec = get_time();

return 0;

}


time_t time(time_t *t) {

fprintf(stdout,"Overriding time...\n");

int t_ = get_time();

if(t)

*t = t_;

return t_;

}


int ftime(struct timeb *tp) {

fprintf(stdout,"Overriding ftime...\n");

tp->time = get_time();

return 0;

}


struct tm *localtime_r(const time_t *timep, struct tm *result)

{

fprintf(stdout,"Overriding localtime...\n");

time_t t = (time_t)get_time();

fprintf(stdout,"Time is: %d\n",(int)t);

return orig_localtime(&t,result);

}


void

_init(void)

{

fprintf(stdout,"Loading hack.\n");

orig_localtime = dlsym(RTLD_NEXT, "localtime_r");


/*

orig_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");

orig_get_time = dlsym(RTLD_NEXT, "get_time");

orig_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");

orig_time = dlsym(RTLD_NEXT, "time");

orig_ftime = dlsym(RTLD_NEXT, "ftime");

*/


}

Hope this helps someone, Happy Coding!!


ClassyBits 2016