Skip to content
Snippets Groups Projects
libzafl.c 3.86 KiB
Newer Older
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
/*
 * Copyright (c) 2018 - Zephyr Software LLC
 *
 * This file may be used and modified for non-commercial purposes as long as
 * all copyright, permission, and nonwarranty notices are preserved.
 * Redistribution is prohibited without prior written consent from Zephyr
 * Software.
 *
 * Please contact the authors for restrictions applying to commercial use.
 *
 * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Author: Zephyr Software
 * e-mail: jwd@zephyr-software.com
 * URL   : http://www.zephyr-software.com/
 *
 */


#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>

Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
#include "config.h"
// externally visible so that Zipr transformations can access directly
u8* zafl_trace_map = NULL;
unsigned short zafl_prev_id = 0;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
static int __afl_temp_data;
static pid_t __afl_fork_pid;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
static int debug = 0;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
#define PRINT_ERROR(string) if (debug) {int x=write(2, string, strlen(string));}
#define PRINT_DEBUG(string) if (debug) {int x=write(1, string, strlen(string));}
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed

static void zafl_setupSharedMemory();
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
static int shared_memory_is_setup = 0;
#ifdef ZAFL_AUTO_INIT_FORK_SERVER
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
void __attribute__((constructor)) zafl_initAflForkServer();
#else
void __attribute__((constructor)) zafl_setupSharedMemory();
#endif
void __attribute__((destructor)) zafl_dumpTracemap();

Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
// always setup a trace map so that an instrumented applicatin will run
// even if not running under AFL
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
static void zafl_setupSharedMemory()
{
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	if (getenv("ZAFL_DEBUG")) debug = 1;

	if (shared_memory_is_setup)
		return;

Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	zafl_prev_id = 0;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	zafl_trace_map = NULL;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed

	char *shm_env_var = getenv(SHM_ENV_VAR);
	if(!shm_env_var) {
		PRINT_ERROR("Error getting shm environment variable - fake allocate AFL trace map\n");

		// fake allocate until someone calls zafl_initAflForkServer()
		zafl_trace_map = (u8*)malloc(MAP_SIZE); 
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		return;
	}
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed

Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	shm_id = atoi(shm_env_var);
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	zafl_trace_map = (u8*)shmat(shm_id, NULL, 0);
	if(zafl_trace_map == (u8*)-1) {
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		PRINT_ERROR("shmat");
		return;
	}
	PRINT_DEBUG("libzafl: shared memory segment is setup\n");
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	shared_memory_is_setup = 1;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
}

void zafl_initAflForkServer()
{
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	static int fork_server_initialized = 0;

	if (fork_server_initialized) return;

Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	if (getenv("ZAFL_DEBUG")) debug = 1;
	zafl_setupSharedMemory();
	if (debug)
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		printf("libzafl: map is at 0x%p\n", zafl_trace_map);
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	if (!zafl_trace_map) {
		zafl_trace_map = (u8*)malloc(MAP_SIZE);
		if (debug)
			printf("no shmem detected: fake it: zafl_trace_map = %p, malloc_size(%d)\n", zafl_trace_map, MAP_SIZE);
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	int n = write(FORKSRV_FD+1, &__afl_temp_data,4);
	if( n!=4 ) {
		if (debug)
			perror("zafl_initAflForkServer()");
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	fork_server_initialized = 1;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	while(1) {
		n = read(FORKSRV_FD,&__afl_temp_data,4);
		if(n != 4) {
		    perror("Error reading fork server\n");
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		    return;
		}

		__afl_fork_pid = fork();
		if(__afl_fork_pid < 0) {
		    perror("Error on fork()\n");
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		    return;
		}
		if(__afl_fork_pid == 0) {
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		    // child
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		    close(FORKSRV_FD);
		    close(FORKSRV_FD+1);
		    break;
		} else {
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		    // parent
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
		    n = write(FORKSRV_FD+1,&__afl_fork_pid, 4);
		    pid_t temp_pid = waitpid(__afl_fork_pid,&__afl_temp_data,2);
		    if(temp_pid == 0) {
			return;
		    }
		    n = write(FORKSRV_FD+1,&__afl_temp_data,4);
		}
	}
}

// for efficiency, basic block instrumentation is inlined via a Zipr transformation
// this code is used for debugging purposes only
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
void zafl_bbInstrument(unsigned short id) {
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	zafl_trace_map[zafl_prev_id ^ id]++;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	zafl_prev_id = id >> 1;
}

void zafl_dumpTracemap()
{
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	int i;
	if (!debug) return;
	if (!zafl_trace_map) return;

Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	for (i = 0; i < 0xFFFF; ++i)
	{
		if (zafl_trace_map[i]!=0)
			printf("%x:%d\n",i, zafl_trace_map[i]); 
	}
}