|
![]() |
/*****************************************************************************
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