Skip to content
Snippets Groups Projects
zax_driver.cpp 12 KiB
Newer Older
// @HEADER_LANG C++ 
// @HEADER_COMPONENT zafl
// @HEADER_BEGIN
/*
* Copyright (c) 2018-2019 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/
*
* This software was developed with SBIR funding and is subject to SBIR Data Rights, 
* as detailed below.
*
* SBIR DATA RIGHTS
*
* Contract No. __FA8750-17-C-0295___________________________.
* Contractor Name __Zephyr Software LLC_____________________.
* Address __4826 Stony Point Rd, Barboursville, VA 22923____.
*
*/

// @HEADER_END
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
#include <stdlib.h>
#include <getopt.h>
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
#include <unistd.h>
#include "zax.hpp"
#include "critical_edge_breaker.hpp"
#include "loop_count.hpp"
#include "zuntracer.hpp"

using namespace std;
Jason Hiser's avatar
Jason Hiser committed
using namespace IRDB_SDK;
using namespace Zafl;

Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
static void usage(char* name)
{
	cerr<<"Usage: "<<name<<" <variant_id>\n";
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	cerr<<"\t[--verbose | -v]                               Verbose mode                  "<<endl;
	cerr<<"\t[--help,--usage,-?,-h]                         Display this message          "<<endl;
	cerr<<"\t[--entrypoint|-e {<funcName>|<hex_address>}]   Specify where to insert fork server (defaults to main if found)"<<endl;
	cerr<<"\t[--exitpoint|-E {<funcName>|<hex_address>}]    Specify where to insert exit"<<endl;
	cerr<<"\t[--whitelist|-w whitelistFile]                 Specify list of functions/addresses to instrument"<<endl;
	cerr<<"\t[--blacklist|-b blacklistFile]                 Specify list of functions/addresses to omit"<<endl;
	cerr<<"\t[--fixed-map-address <addr>]                   Enable fixed-mapping addressing and Specify the address to use for the map [Default 0x10000]"<<endl;
	cerr<<"\t[--no-fixed-map]                               Disablw fixed-mapping addressing"<<endl;
	cerr<<"\t[--stars|-s]                                   Enable STARS optimizations    "<<endl;
	cerr<<"\t[--enable-bb-graph-optimization|-g]            Elide instrumentation if basic block has 1 successor"<<endl;
	cerr<<"\t[--disable-bb-graph-optimization|-G]           Elide instrumentation if basic block has 1 successor"<<endl;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	cerr<<"\t[--autozafl|-a]                                Auto-initialize fork server (incompatible with --entrypoint)"<<endl;
	cerr<<"\t[--untracer|-u]                                Untracer-style block-coverage instrumentation"<<endl;
	cerr<<"\t[--break-critical-edge-style|-c]               Breakup critical edges"<<endl;
	cerr<<"\t[--enable-loop-count-instr|-j]                 Insert instrumentation to do afl-style loop counting for zuntracer."<<endl;
	cerr<<"\t[--disable-loop-count-instr|-J]                Do not do -j (default)"<<endl;
	cerr<<"\t[--enable-floating-instrumentation|-i]         Select best instrumentation within basic block"<<endl;
	cerr<<"\t[--disable-floating-instrumentation|-I]        Instrument first instruction in basic blocks"<<endl;
	cerr<<"\t[--enable-context-sensitivity <style>]         Use calling context sensitivity, style={callsite,function}"<<endl;
	cerr<<"\t[--disable-context-sensitivity]                Disable calling context sensitivity"<<endl;
	cerr<<"\t[--random-seed|r <value>]                      Specify random seed"<<endl;
}

int main(int argc, char **argv)
{
	if(argc < 2)
	{
		usage(argv[0]);
		exit(1);
	}

	string programName(argv[0]);
	auto entry_fork_server = string();
	auto variantID = atoi(argv[1]);
	auto verbose=false;
	auto use_stars=false;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	auto autozafl=false;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	auto whitelistFile=string();
	auto blacklistFile=string();
	auto bb_graph_optimize=false;
	auto domgraph_optimize=false;
	auto forkserver_enabled=true;
	auto untracer_mode=false;
	auto break_critical_edge_style=bceNone;
	auto do_loop_count_instr=false;
	auto do_keep_loop_headers_only=false;
	auto loop_count_buckets=string("1,2,3,4,8,16,32,128");
	auto floating_instrumentation=false;
	auto context_sensitivity=ContextSensitivity_None;
	auto random_seed = 0U;
	auto fixed_map_address=VirtualOffset_t(0x10000);
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	set<string> exitpoints;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	srand(getpid()+time(NULL));

	// Parse some options for the transform
	static struct option long_options[] = {
		{"verbose",                          no_argument,       0, 'v'},
		{"help",                             no_argument,       0, 'h'},
		{"usage",                            no_argument,       0, '?'},
		{"stars",                            no_argument,       0, 's'},
		{"entrypoint",                       required_argument, 0, 'e'},
		{"exitpoint",                        required_argument, 0, 'E'},
		{"whitelist",                        required_argument, 0, 'w'},
		{"blacklist",                        required_argument, 0, 'b'},
		{"fixed-map-address",                required_argument, 0, 'm'},
		{"no-fixed-map",                     no_argument,       0, 'M'},
		{"autozafl",                         no_argument,       0, 'a'},
		{"enable-bb-graph-optimization",     no_argument,       0, 'g'},
		{"disable-bb-graph-optimization",    no_argument,       0, 'G'},
		{"enable-domgraph-optimization",     no_argument,       0, 'd'},
		{"disable-domgraph-optimization",    no_argument,       0, 'D'},
		{"enable-forkserver",                no_argument,       0, 'f'},
		{"disable-forkserver",               no_argument,       0, 'F'},
		{"untracer",                         no_argument,       0, 'u'},
		{"break-critical-edge",     	     required_argument, 0, 'c'},
		{"enable-loop-count-instr",          no_argument,       0, 'j'},
		{"disable-loop-count-instr",         no_argument,       0, 'J'},
		{"keep-loop-headers-only",           no_argument,       0, 'k'},
		{"loop-count-buckets",               required_argument, 0, ':'},
		{"enable-floating-instrumentation",  no_argument,       0, 'i'},
		{"disable-floating-instrumentation", no_argument,       0, 'I'},
		{"enable-context-sensitivity",       required_argument, 0, 'z'},
		{"random-seed",                      required_argument, 0, 'r'},
		{0,0,0,0}
	};
	const char* short_opts="r:z:e:E:w:sv?hagGdDfFuc:jJkiIm:M";

	while(true)
	{
		int index = 0;
		int c = getopt_long(argc, argv, short_opts, long_options, &index);
		if(c == -1)
			break;
		switch(c)
		{
			case 'v':
				verbose=true;
				break;
			case '?':
			case 'h':
				usage(argv[0]);
				exit(1);
				break;
			case 's':
				use_stars=true;
				cout << "STARS optimization enabled" << endl;
				break;
			case 'e':
				entry_fork_server = optarg;
				break;
			case 'E':
				exitpoints.insert(optarg);
				break;
			case 'w':
				whitelistFile=optarg;
				break;
			case 'b':
				blacklistFile=optarg;
				break;
			case 'm':
				fixed_map_address = strtoul(optarg, nullptr, 0);
				break;
			case 'M':
				fixed_map_address = 0;
				break;
			case 'a':
				autozafl=true;
				break;
			case 'g':
				bb_graph_optimize=true;
				break;
			case 'G':
				bb_graph_optimize=false;
				break;
			case 'd':
				domgraph_optimize=true;
				break;
			case 'D':
				domgraph_optimize=false;
				break;
			case 'f':
				forkserver_enabled=true;
				break;
			case 'F':
				forkserver_enabled=false;
				break;
			case 'u':
				untracer_mode=true;
				break;
			case 'c':
				if(optarg)
				{
					if(string(optarg)=="all")
						break_critical_edge_style=bceAll;
					else if(string(optarg)=="none")
						break_critical_edge_style=bceNone;
					else if(string(optarg)=="targets")
						break_critical_edge_style=bceTargets;
					else if(string(optarg)=="target")
						break_critical_edge_style=bceTargets;
					else if(string(optarg)=="fallthroughs")
						break_critical_edge_style=bceFallthroughs;
					else if(string(optarg)=="fallthrough")
						break_critical_edge_style=bceFallthroughs;
					else
					{
						cout << "Cannot map " << optarg << "to {all,none,targets,fallthrough}" << endl;
						exit(2);
					}
				}
				else
					break_critical_edge_style=bceAll;
			case 'j':
				do_loop_count_instr=true;
				break;
			case 'J':
				do_loop_count_instr=false;
				break;
			case 'k':
				do_keep_loop_headers_only=true;
				break;
			case ':':
				loop_count_buckets = string(optarg);
				break;
			case 'i':
				floating_instrumentation=true;
				break;
			case 'I':
				floating_instrumentation=false;
				break;
			case 'z':
				if (optarg == string("callsite"))
					context_sensitivity=ContextSensitivity_Callsite; // Angora fuzzer style
				else if (optarg == string("function"))
					context_sensitivity=ContextSensitivity_Function;
				else
					context_sensitivity=ContextSensitivity_None;
				break;
			case 'r':
				random_seed = strtoul(optarg, NULL, 0);
				srand(random_seed);
				cout << "Setting random seed to: " << random_seed << endl;
				break;
			default:
				break;
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
	if (entry_fork_server.size() > 0 && autozafl)
	{
		cerr << "--entrypoint and --autozafl are incompatible options" << endl;
		usage(argv[0]);
		exit(1);
	}

	if (floating_instrumentation && !use_stars)
	{
		cerr << "STARS must be turned on when using floating instrumentation" << endl;
		usage(argv[0]);
		exit(1);
	}


	/* setup the interface to the sql server */
Jason Hiser's avatar
Jason Hiser committed
	auto pqxx_interface=pqxxDB_t::factory();
	BaseObj_t::setInterface(pqxx_interface.get());
Jason Hiser's avatar
Jason Hiser committed
	auto pidp=VariantID_t::factory(variantID);
	assert(pidp->isRegistered()==true);

	bool one_success = false;
Jason Hiser's avatar
Jason Hiser committed
	for(set<File_t*>::iterator it=pidp->getFiles().begin();
	        it!=pidp->getFiles().end();
	        ++it)
	{
		File_t* this_file = *it;
Jason Hiser's avatar
Jason Hiser committed
		auto firp = FileIR_t::factory(pidp.get(), this_file);
Jason Hiser's avatar
Jason Hiser committed
		cout<<"Transforming "<<this_file->getURL()<<endl;

		assert(firp && pidp);

		try
		{
				ZedgeNS::Zedge_t(firp.get(), loop_count_buckets).execute();
				firp->setBaseIDS();
				firp->assembleRegistry();
			}
			if (break_critical_edge_style != bceNone)
				CriticalEdgeBreaker_t ceb(firp.get(), {}, break_critical_edge_style, verbose);
				cout << "#ATTRIBUTE num_bb_extra_blocks=" << ceb.getNumberExtraNodes() << endl;
				firp->setBaseIDS();
				firp->assembleRegistry();
			}

			const auto zax = unique_ptr<ZaxBase_t>( 
					untracer_mode ? static_cast<ZaxBase_t*>(new ZUntracer_t(*pqxx_interface, firp.get(), entry_fork_server, exitpoints, use_stars, autozafl)) : 
					                static_cast<ZaxBase_t*>(new Zax_t      (*pqxx_interface, firp.get(), entry_fork_server, exitpoints, use_stars, autozafl))); 
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
			if (whitelistFile.size()>0)
				zax->setWhitelist(whitelistFile);
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
			if (blacklistFile.size()>0)
				zax->setBlacklist(blacklistFile);
Anh Nguyen-Tuong's avatar
Anh Nguyen-Tuong committed
			zax->setVerbose(verbose);
			zax->setBasicBlockOptimization(bb_graph_optimize);
			zax->setDomgraphOptimization(domgraph_optimize);
			zax->setBasicBlockFloatingInstrumentation(floating_instrumentation);
			zax->setEnableForkServer(forkserver_enabled);
//		 	zax->setBreakCriticalEdgeStyle(break_critical_edge_style);
			zax->setKeepLoopHeadersOnly(do_keep_loop_headers_only);
//			zax->setDoLoopCountInstrumentation(do_loop_count_instr);
//			zax->setLoopCountBuckets(loop_count_buckets);
			zax->setContextSensitivity(context_sensitivity); 
			zax->setFixedMapAddress(fixed_map_address);
			int success=zax->execute();

			if (success)
			{
Jason Hiser's avatar
Jason Hiser committed
				cout<<"Writing changes for "<<this_file->getURL()<<endl;
				one_success = true;
Jason Hiser's avatar
Jason Hiser committed
				firp->writeToDB();
Jason Hiser's avatar
Jason Hiser committed
				cout<<"Skipping (no changes) "<<this_file->getURL()<<endl;
Jason Hiser's avatar
Jason Hiser committed
		catch (const DatabaseError_t &pnide)
Jason Hiser's avatar
Jason Hiser committed
			cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->getURL() << endl;
			exit(1);
		}
		catch (const std::exception &e)
		{
			cerr << programName << ": Error: " << e.what() << endl;
			exit(1);
		}
		catch (...)
		{
Jason Hiser's avatar
Jason Hiser committed
			cerr << programName << ": Unexpected error file url: " << this_file->getURL() << endl;
			exit(1);
		}
	} // end file iterator

	// if any transforms for any files succeeded, we commit
	if (one_success)
	{
		cout<<"Commiting changes...\n";
Jason Hiser's avatar
Jason Hiser committed
		pqxx_interface->commit();