Exemplo n.º 1
0
int main (int argc, char **argv)
{

    if(!parseOptions(argc,argv)) {
        return EXIT_FAILURE;
    }

    BPatch bpatch;

    BPatch_binaryEdit *appBin = bpatch.openBinary (originalBinary, !instrumentLibraries.empty());
    if (appBin == NULL) {
        cerr << "Failed to open binary" << endl;
        return EXIT_FAILURE;
    }

    if (!appBin->loadLibrary (instLibrary)) {
        cerr << "Failed to open instrumentation library." << endl;
        cerr << "It needs to be located in the current working directory." << endl;
        return EXIT_FAILURE;
    }

    BPatch_image *appImage = appBin->getImage ();

    /* Find code coverage functions in the instrumentation library */
    BPatch_function *initAflForkServer =
        findFuncByName (appImage, (char *) "initAflForkServer");
    BPatch_function *bbCallback =
        findFuncByName (appImage, (char *) "bbCallback");
    if (!initAflForkServer || !bbCallback ) {
        cerr << "Instrumentation library lacks callbacks!" << endl;
        return EXIT_FAILURE;
    }

    //get and iterate over all modules, instrumenting only the default and manualy specified ones
    vector < BPatch_module * >*modules = appImage->getModules ();
    vector < BPatch_module * >::iterator moduleIter;
    BPatch_module *defaultModule = NULL;
    string defaultModuleName;
    for (moduleIter = modules->begin (); moduleIter != modules->end (); ++moduleIter) {
    //find default module name
        char moduleName[1024];
        (*moduleIter)->getName (moduleName, 1024);    
        if (string (moduleName).find ("DEFAULT_MODULE") != string::npos) {
            defaultModuleName = "DEFAULT_MODULE";
        }
    }
    if(defaultModuleName.empty()) 
        defaultModuleName = string(originalBinary).substr(string(originalBinary).find_last_of("\\/")+1);
    int bbIndex = 0;
    for (moduleIter = modules->begin (); moduleIter != modules->end (); ++moduleIter) {
        char moduleName[1024];
        (*moduleIter)->getName (moduleName, 1024);

        if ((*moduleIter)->isSharedLib ()) {
            if (instrumentLibraries.find (moduleName) == instrumentLibraries.end ()) {
                cout << "Skipping library: " << moduleName << endl;
                continue;
            }
        }

        if (string (moduleName).find (defaultModuleName) != string::npos) {
            defaultModule = (*moduleIter);
            if(skipMainModule) continue;
        }
        cout << "Instrumenting module: " << moduleName << endl;
        vector < BPatch_function * >*allFunctions =
            (*moduleIter)->getProcedures ();
        vector < BPatch_function * >::iterator funcIter;

        // iterate over all functions in the module
        for (funcIter = allFunctions->begin (); funcIter != allFunctions->end ();
             ++funcIter) {
            BPatch_function *curFunc = *funcIter;
            char funcName[1024];
            curFunc->getName (funcName, 1024);
            if(string (funcName) == string("_start")) continue; // here's a bug on hlt
            insertBBCallback (appBin, curFunc, funcName, bbCallback, &bbIndex);
        }

    }

    //if entrypoint set ,find function  , else find _init
    BPatch_function *funcToPatch = NULL;
    if(!entryPoint) {
        BPatch_Vector<BPatch_function*> funcs;
        defaultModule->findFunction("_init", funcs);
        if(!funcs.size()) {
            cerr << "Couldn't locate _init, specify entry point manualy. "<< endl;
            return EXIT_FAILURE;
        }
        // there should really be only one
        funcToPatch = funcs[0];
    } else {
        funcToPatch = defaultModule->findFunctionByEntry(entryPoint);
    }
    if(!funcToPatch) {
        cerr << "Couldn't locate function at given entry point. "<< endl;
        return EXIT_FAILURE;
    }
    if(!insertCallToInit (appBin,  initAflForkServer,defaultModule,funcToPatch)){
        cerr << "Could not insert init callback at given entry point." << endl;
        return EXIT_FAILURE;
    }

    cout << "Saving the instrumented binary to " << instrumentedBinary << "..." << endl;
    // Output the instrumented binary
    if (!appBin->writeFile (instrumentedBinary)) {
        cerr << "Failed to write output file: " << instrumentedBinary << endl;
        return EXIT_FAILURE;
    }

    if(!runtimeLibraries.empty()) {
        cout << "Instrumenting runtime libraries." << endl;
        set<string>::iterator rtLibIter ;
        for(rtLibIter = runtimeLibraries.begin(); rtLibIter != runtimeLibraries.end(); rtLibIter++) {
            BPatch_binaryEdit *libBin = bpatch.openBinary ((*rtLibIter).c_str(), false);
            if (libBin == NULL) {
                cerr << "Failed to open binary "<< *rtLibIter << endl;
                return EXIT_FAILURE;
            }
            libBin->loadLibrary (instLibrary);
            BPatch_image *libImg = libBin->getImage ();
            vector < BPatch_module * >*modules = libImg->getModules ();
            moduleIter = modules->begin ();
            ++moduleIter;
            for ( ; moduleIter != modules->end (); ++moduleIter) {
                char moduleName[1024];
                (*moduleIter)->getName (moduleName, 1024);
                cout << "Instrumenting module: " << moduleName << endl;
                vector < BPatch_function * >*allFunctions =
                    (*moduleIter)->getProcedures ();
                vector < BPatch_function * >::iterator funcIter;
                // iterate over all functions in the module
                for (funcIter = allFunctions->begin (); funcIter != allFunctions->end ();
                     ++funcIter) {
                    BPatch_function *curFunc = *funcIter;
                    char funcName[1024];
                    curFunc->getName (funcName, 1024);
                    if(string (funcName) == string("_start")) continue;
                    insertBBCallback (libBin, curFunc, funcName, bbCallback, &bbIndex);
                }
            }
            if (!libBin->writeFile ((*rtLibIter + ".ins").c_str())) {
                cerr << "Failed to write output file: " <<(*rtLibIter + ".ins").c_str() << endl;
                return EXIT_FAILURE;
            } else {
                cout << "Saved the instrumented library to " << (*rtLibIter + ".ins").c_str() << "." << endl;
            }
        }
    }

    cout << "All done! Happy fuzzing!" << endl;
    return EXIT_SUCCESS;

}
Exemplo n.º 2
0
int main(int argc, char**argv)
{
  if(argc != 3) {
    printf("usage: %s orig_prog new_prog\n", argv[0]);
    return 1;
  }

  char* file = argv[1];
  char* newFile = argv[2];
  bool ret;


  eztrace_dyninst_register ("compute_", 1, 2);
  eztrace_dyninst_register ("dist_", 3, 4);
  eztrace_dyninst_register ("initialize_", 5, 6);
  eztrace_dyninst_register ("timestamp_", 7, 8);
  eztrace_dyninst_register ("update_", 9, 10);


  if(!eztrace_dyninst_nb_function_to_register()) {
    printf("0 functions instrumented\n");
    return 1;
  }


#ifdef CREATE_BINARY
  //Create the BPatch_addressSpace and BPatch_binaryEdit
  appBin = bpatch.openBinary(file, true);
  if(!appBin) {
    fprintf(stderr, "Cannot open %s\n", file);
    return -1;
  }
  app = static_cast<BPatch_addressSpace *>(appBin);


  if(! app->loadLibrary(LIB_EZTRACE_SO)) {
    printf("Cannot load %s\n", LIB_EZTRACE_SO);
    return 1;
  }

#else
  // run the program
  BPatch_process *appProc = bpatch.processCreate(file, NULL);
  if(!appProc) {
    printf("Cannot load program %s\n", file);
  }

  if(! appProc->loadLibrary(LIB_EZTRACE_SO, true)) {
    printf("Cannot load %s\n", LIB_EZTRACE_SO);
    return 1;
  }

  app = static_cast<BPatch_addressSpace *>(appProc);

#endif


  // Instrument all the specified functions
  int nb_inst = eztrace_dyninst_instrument(app);
  printf("%d functions instrumented\n", nb_inst);
  if(! nb_inst)
    return 1;

#ifdef CREATE_BINARY
  if (appBin != NULL) {
    //Write a new instrumented executable
    appBin->writeFile(newFile);
  } else {
    fprintf(stderr, "cannot write %s\n", newFile);
    return -1;
  }
#else

  appProc->continueExecution();
  while(!appProc->isTerminated()) {
    bpatch.waitForStatusChange();
  }
#endif
  return 0;
}
Exemplo n.º 3
0
int main(int argc, char* argv[])
{
	//open a file, output the mapping from id to addresses to it
	FILE * pFile;
	pFile=fopen(argv[3],"w");
	if(pFile==NULL)perror("Error opening file.\n");
	fprintf(pFile,"shortID\tfullID\tentryAddr\texitAddr\n");

	//open argv[1]
	BPatch bpatch;
	BPatch_binaryEdit *binedit=bpatch.openBinary(argv[1]);
	BPatch_image *appImage=binedit->getImage();	
	std::vector<BPatch_function *> *funcs_ptr;
	funcs_ptr=appImage->getProcedures();
	std::vector<BPatch_function *> funcs=*funcs_ptr;

	//open libc and find printf
	std::vector<BPatch_function *> printfFuncs;
	BPatch_binaryEdit *binedit_libc=bpatch.openBinary("/lib/libc.so.6");
	BPatch_image *appImage_libc=binedit_libc->getImage();
	appImage_libc->findFunction("printf",printfFuncs);

	//all points
	std::vector<BPatch_point *> * points=new std::vector<BPatch_point *>;
	//create a buf and a index
	BPatch_type *typeShort=appImage_libc->findType("unsigned short");
	BPatch_type *typeUL=appImage_libc->findType("unsigned long");
	//std::string bufname=std::string("buf");
	//BPatch_variableExpr *bufExpr=binedit->malloc(65536,bufname);
	//BPatch_snippet *basePtr=new BPatch_constExpr(bufExpr->getBaseAddr());
	BPatch_variableExpr *index=binedit->malloc(*typeShort);
	index=binedit->createVariable(std::string("index"),(Dyninst::Address)index->getBaseAddr(),typeShort);
	unsigned short indexIni=0;
	index->writeValue(&indexIni);
	BPatch_variableExpr *basePtr=binedit->malloc(*typeUL);
	index=binedit->createVariable(std::string("basePtr"),(Dyninst::Address)basePtr->getBaseAddr(),typeUL);
	BPatch_snippet* basePtrAddr=new BPatch_constExpr(basePtr->getBaseAddr());

	//open PtrDeref
	BPatch_binaryEdit *binedit_PtrDeref=bpatch.openBinary("/usr/lib/libPtrDeref.so");
	BPatch_image *appImage_PtrDeref=binedit_PtrDeref->getImage();
	std::vector<BPatch_function *> RegSig;
        appImage_PtrDeref->findFunction("shm_sig",RegSig);	
	std::vector<BPatch_snippet *> RegSigArgs;
	RegSigArgs.push_back(basePtrAddr);
	BPatch_funcCallExpr RegSigCall(*(RegSig[0]),RegSigArgs);
        std::vector<BPatch_function *> stoplogger;
        appImage_PtrDeref->findFunction("stoplogger",stoplogger);
        std::vector<BPatch_snippet *> stoploggerArgs;  
        BPatch_funcCallExpr stoploggerCall(*(stoplogger[0]),stoploggerArgs);


	printf("begin inserting to start...\n");
	//find _start function and insert
	std::vector<BPatch_function *> startFuncs;
	appImage->findFunction("_start",startFuncs);
	std::vector<BPatch_point *> *startPoints=new std::vector<BPatch_point *>;
	startPoints=startFuncs[0]->findPoint(BPatch_entry);
	binedit->insertSnippet(BPatch_arithExpr(BPatch_assign,*basePtr,RegSigCall),startPoints[0]);
	//find fini function and insert
        std::vector<BPatch_function *> finiFuncs;
        appImage->findFunction("_fini",finiFuncs);
        std::vector<BPatch_point *> *finiPoints=new std::vector<BPatch_point *>;
        finiPoints=finiFuncs[0]->findPoint(BPatch_exit);
        binedit->insertSnippet(stoploggerCall,finiPoints[0]);


	unsigned int mod=65535;
	unsigned int id=0; 

	for(std::vector<BPatch_function *>::iterator fi=funcs.begin();
		fi!=funcs.end();fi++)
	{
		BPatch_flowGraph *fg=(*fi)->getCFG();
	
		std::set<BPatch_basicBlock *> blocks;
		fg->getAllBasicBlocks(blocks);

		std::set<BPatch_basicBlock *>::iterator block_iter;
		for(block_iter=blocks.begin();block_iter!=blocks.end();++block_iter)
		{
			BPatch_basicBlock *block=*block_iter;
			BPatch_point *entry_point=NULL;
			unsigned long blockstart=0;
			unsigned long blockend=0;
			unsigned short partial_id=65534;
			if(block!=NULL)
			{
				entry_point=block->findEntryPoint();
				blockstart=block->getStartAddress();
                                blockend=block->getEndAddress();
				partial_id=id%mod+1;	
				fprintf(pFile,"%u\t%u\t%p\t%p\n",partial_id,id,blockstart,blockend);
				id++;
			}
			void *entryAddr=NULL;
			if(entry_point!=NULL)
			{
				entryAddr=entry_point->getAddress();
				points->push_back(entry_point);
				std::vector<BPatch_snippet *> printfArgs3;
				BPatch_snippet *fmt=new BPatch_constExpr("entrypoint first instruction address: %p\n");
				printfArgs3.push_back(fmt);
				BPatch_snippet *entryAddr=new BPatch_constExpr(blockstart);
				printfArgs3.push_back(entryAddr);
				BPatch_funcCallExpr printfCall3(*(printfFuncs[0]),printfArgs3);	
				//binedit->insertSnippet(printfCall3,*entry_point);
				std::string s=entry_point->getFunction()->getName();
				printf("entry point is in:%s\n",s.c_str());
				std::vector<BPatch_snippet *> printfArgs4;
				BPatch_snippet *fmt_m=new BPatch_constExpr("memory log entrypoint: %p\tid: %hu\t func: %s\n");
				printfArgs4.push_back(fmt_m);
				BPatch_snippet entryAddr_m=BPatch_arithExpr(BPatch_plus,*basePtr,/**index*/BPatch_constExpr(0));
				printfArgs4.push_back(&entryAddr_m);
				//block partial id
				BPatch_snippet *idsnippet=new BPatch_constExpr(partial_id);
				printfArgs4.push_back(idsnippet);
				BPatch_constExpr *funcname=new BPatch_constExpr(s.c_str());
				printfArgs4.push_back(funcname);

				BPatch_arithExpr log(BPatch_seq,
						BPatch_funcCallExpr(*(printfFuncs[0]),printfArgs4),						
						BPatch_arithExpr(BPatch_seq,
							BPatch_arithExpr(BPatch_assign,BPatch_arithExpr(BPatch_plus,*basePtr,/**index*/BPatch_constExpr(0)),*idsnippet),
							BPatch_arithExpr(BPatch_assign,*basePtr/**index*/,BPatch_arithExpr(BPatch_plus,*basePtr/**index*/,BPatch_constExpr(2)))
								)
							);
				BPatch_arithExpr log_s=BPatch_arithExpr(BPatch_seq,
							BPatch_arithExpr(BPatch_assign,BPatch_arithExpr(BPatch_plus,*basePtr,/**index*/BPatch_constExpr(0)),*idsnippet),
							BPatch_arithExpr(BPatch_assign,*basePtr/**index*/,BPatch_arithExpr(BPatch_plus,*basePtr/**index*/,BPatch_constExpr(2)))
								);
				binedit->insertSnippet(log_s,*entry_point);	
				//binedit->insertSnippet(printfCall3,*entry_point);		
			}
		}
	}
	//binedit->insertSnippet(printfCall, *points);
	binedit->writeFile(argv[2]);
	fclose(pFile);

}
Exemplo n.º 4
0
int main(int argc, const char *argv[]) {

  // Use BPatch_* classes to initialize
  BPatch bpatch;
  BPatch_binaryEdit* app = bpatch.openBinary("mutatee/c");
  BPatch_image* image = app->getImage();


  BPatch_Vector<BPatch_function *> found_funcs;
  app->loadLibrary("mutatee/liblib.so");

  found_funcs.clear();
  image->findFunction("foo3", found_funcs);
  Function* foo3_func = found_funcs[0]->getParseAPIFunc();

  // Here we go, create PatchAPI objects!
  vector<AddressSpace*> addrSpaces;
  app->getAS(addrSpaces);

  mapped_object* obj = addrSpaces[0]->getAOut();
  DynAddrSpacePtr as = DynAddrSpace::create(obj);
  PatchMgrPtr mgr = PatchMgr::create(as);

  mapped_object* lib_obj = addrSpaces[1]->getAOut();
  as->loadLibrary(lib_obj);

  // Find Points
  PatchFunction* foo3 = lib_obj->getFunc(foo3_func);
  const vector<PatchBlock*>& blks = foo3->getCallBlocks();
  for (int i = 0; i < blks.size(); i++) {
    vector<Point*> func_points;
    mgr->findPoints(blks[i], Point::PreInsn|Point::PostInsn, inserter(func_points, func_points.begin()));
    cerr << std::hex << blks[i]->start() << "--" << func_points.size() << " points found\n";
  }
  /*
  vector<Point*> pts;
  mgr->findPoints(foo3, Point::FuncExit, inserter(pts, pts.begin()));
  cerr << pts.size() << " exit points found\n";
  const vector<PatchBlock*>& blks2 = foo3->getExitBlocks();
  cerr << blks2.size() << " exit blocks\n";

  // Insert snippets
  BPatch_variableExpr *intCounter = app->malloc(*image->findType("int"));
  BPatch_arithExpr addOne(BPatch_assign, *intCounter,
                          BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(1)));
  BPatch_arithExpr addTwo(BPatch_assign, *intCounter,
                          BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(2)));
  BPatch_arithExpr addThree(BPatch_assign, *intCounter,
                            BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(3)));
  BPatch_arithExpr addFour(BPatch_assign, *intCounter,
                           BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(4)));

  SnippetRep<AstNodePtr> one(addOne.ast_wrapper);
  SnippetRep<AstNodePtr> two(addTwo.ast_wrapper);
  SnippetRep<AstNodePtr> three(addThree.ast_wrapper);
  SnippetRep<AstNodePtr> four(addFour.ast_wrapper);
  SnippetPtr snippet = Snippet::create(&one);
  SnippetPtr snippet1 = Snippet::create(&two);
  SnippetPtr snippet2 = Snippet::create(&three);
  SnippetPtr snippet3 = Snippet::create(&four);

  vector<InstancePtr> errorInstances;

  mgr->batchStart();
  func_points[0]->push_back(snippet);
  mgr->batchFinish(errorInstances);
  */
}
Exemplo n.º 5
0
int main(int argc, char **argv) {
  if (argc < 3 || strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--h", 3) == 0) {
    cout << "Usage: " << argv[0] << USAGE;
    return false;
  }

  if (!parseOptions(argc, argv)) {
    return EXIT_FAILURE;
  }
  
  if (do_bb == true) {
    if (DYNINST_MAJOR_VERSION < 9 || (DYNINST_MAJOR_VERSION == 9 && DYNINST_MINOR_VERSION < 3) || (DYNINST_MAJOR_VERSION == 9 && DYNINST_MINOR_VERSION == 3 && DYNINST_PATCH_VERSION <= 2)) {
      if (dynfix == false)
        fprintf(stderr, "Warning: your dyninst version does not include a critical fix, you should use the -f option!\n");
    } else {
      if (dynfix == true)
        fprintf(stderr, "Notice: your dyninst version is fixed, the -f option should not be necessary.\n");
    }
  }

  BPatch bpatch;
  BPatch_binaryEdit *appBin = bpatch.openBinary(originalBinary, instrumentLibraries.size() != 1);

  if (appBin == NULL) {
    cerr << "Failed to open binary" << endl;
    return EXIT_FAILURE;
  }

  BPatch_image *appImage = appBin->getImage();

  //get and iterate over all modules, instrumenting only the default and manually specified ones
  vector < BPatch_module * >*modules = appImage->getModules();
  vector < BPatch_module * >::iterator moduleIter;
  vector < BPatch_function * >*funcsInModule;
  BPatch_module *defaultModule = NULL;
  string defaultModuleName;

  // look for _init
  if (defaultModuleName.empty()) {
    for (moduleIter = modules->begin(); moduleIter != modules->end(); ++moduleIter) {
      funcsInModule = (*moduleIter)->getProcedures();
      vector < BPatch_function * >::iterator funcsIterator;
      for (funcsIterator = funcsInModule->begin(); funcsIterator != funcsInModule->end(); ++funcsIterator) {
        char funcName[1024];

        (*funcsIterator)->getName(funcName, 1024);
        if (string(funcName) == string("_init")) {
          char moduleName[1024];

          (*moduleIter)->getName(moduleName, 1024);
          defaultModuleName = string(moduleName);
          if (verbose) {
            cout << "Found _init in " << moduleName << endl;
          }
          break;
        }
      }
      if (!defaultModuleName.empty())
        break;
    }
  }
  // last resort, by name of the binary
  if (defaultModuleName.empty())
    defaultModuleName = string(originalBinary).substr(string(originalBinary).find_last_of("\\/") + 1);

  if (!appBin->loadLibrary(instLibrary)) {
    cerr << "Failed to open instrumentation library " << instLibrary << endl;
    cerr << "It needs to be located in the current working directory." << endl;
    return EXIT_FAILURE;
  }

  appImage = appBin->getImage();

  /* Find code coverage functions in the instrumentation library */
  BPatch_function *initAflForkServer;
  save_rdi = findFuncByName(appImage, (char *) "save_rdi");
  restore_rdi = findFuncByName(appImage, (char *) "restore_rdi");
  BPatch_function *bbCallback = findFuncByName(appImage, (char *) "bbCallback");
  BPatch_function *forceCleanExit = findFuncByName(appImage, (char *) "forceCleanExit");

  if (do_bb == true)
    initAflForkServer = findFuncByName(appImage, (char *) "initAflForkServer");
  else
    initAflForkServer = findFuncByName(appImage, (char *) "initOnlyAflForkServer");

  if (!initAflForkServer || !bbCallback || !save_rdi || !restore_rdi || !forceCleanExit) {
    cerr << "Instrumentation library lacks callbacks!" << endl;
    return EXIT_FAILURE;
  }

  int bbIndex = 0;

  // instrument all shared libraries:
  for (moduleIter = modules->begin(); moduleIter != modules->end(); ++moduleIter) {
    char moduleName[1024];

    (*moduleIter)->getName(moduleName, 1024);

    if ((*moduleIter)->isSharedLib()) {
      if (instrumentLibraries.find(moduleName) == instrumentLibraries.end()) {
        cout << "Skipping library: " << moduleName << endl;
        continue;
      }
    }

    if (string(moduleName).find(defaultModuleName) != string::npos) {
      defaultModule = (*moduleIter);
      if (skipMainModule)
        continue;
    }
    
    if (do_bb == true) {
      cout << "Instrumenting module: " << moduleName << endl;
      vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures();
      vector < BPatch_function * >::iterator funcIter;

      // iterate over all functions in the module
      for (funcIter = allFunctions->begin(); funcIter != allFunctions->end(); ++funcIter) {
        BPatch_function *curFunc = *funcIter;
        char funcName[1024];
        int do_patch = 1;

        curFunc->getName(funcName, 1024);
        if (string(funcName) == string("_start"))
          continue;               // here's a bug on hlt // XXX: check what happens if removed
        
        if (!skipAddresses.empty()) {
          set < string >::iterator saiter;
          for (saiter = skipAddresses.begin(); saiter != skipAddresses.end() && do_patch == 1; saiter++)
            if (*saiter == string(funcName))
              do_patch = 0;
          if (do_patch == 0) {
            cout << "Skipping instrumenting function " << funcName << endl;
            continue;
          }
        }
        insertBBCallback(appBin, curFunc, funcName, bbCallback, &bbIndex);
      }
    }
  }

  // if an entrypoint was set then find function, else find _init
  BPatch_function *funcToPatch = NULL;

  if (!entryPoint) {
    BPatch_Vector < BPatch_function * >funcs;
    defaultModule->findFunction("_init", funcs);
    if (!funcs.size()) {
      cerr << "Couldn't locate _init, specify entry point manually with -e 0xaddr" << endl;
      return EXIT_FAILURE;
    }
    // there should really be only one
    funcToPatch = funcs[0];
  } else {
    funcToPatch = defaultModule->findFunctionByEntry(entryPoint);
  }
  if (!funcToPatch) {
    cerr << "Couldn't locate function at given entry point. " << endl;
    return EXIT_FAILURE;
  }
  if (!insertCallToInit(appBin, initAflForkServer, defaultModule, funcToPatch)) {
    cerr << "Could not insert init callback at given entry point." << endl;
    return EXIT_FAILURE;
  }

  if (!exitAddresses.empty()) {
    cout << "Instrumenting forced exit addresses." << endl;
    set < unsigned long >::iterator uliter;
    for (uliter = exitAddresses.begin(); uliter != exitAddresses.end(); uliter++) {
      if (*uliter > 0 && (signed long)*uliter != -1) {
        funcToPatch = defaultModule->findFunctionByEntry(*uliter);
        if (!funcToPatch) {
          cerr << "Could not find enty point 0x" << hex << *uliter << " (continuing)" << endl;
        } else {
          if (!insertCallToInit(appBin, forceCleanExit, defaultModule, funcToPatch))
            cerr << "Could not insert force clean exit callback at 0x" << hex << *uliter << " (continuing)" << endl;
        }
      }
    }
  }

  cout << "Saving the instrumented binary to " << instrumentedBinary << " ..." << endl;
  // Output the instrumented binary
  if (!appBin->writeFile(instrumentedBinary)) {
    cerr << "Failed to write output file: " << instrumentedBinary << endl;
    return EXIT_FAILURE;
  }

  if (!runtimeLibraries.empty()) {
    cout << "Instrumenting runtime libraries." << endl;
    set < string >::iterator rtLibIter;
    for (rtLibIter = runtimeLibraries.begin(); rtLibIter != runtimeLibraries.end(); rtLibIter++) {
      BPatch_binaryEdit *libBin = bpatch.openBinary((*rtLibIter).c_str(), false);

      if (libBin == NULL) {
        cerr << "Failed to open binary " << *rtLibIter << endl;
        return EXIT_FAILURE;
      }
      BPatch_image *libImg = libBin->getImage();

      vector < BPatch_module * >*modules = libImg->getModules();
      moduleIter = modules->begin();

      for (; moduleIter != modules->end(); ++moduleIter) {
        char moduleName[1024];

        (*moduleIter)->getName(moduleName, 1024);
        cout << "Instrumenting module: " << moduleName << endl;
        vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures();
        vector < BPatch_function * >::iterator funcIter;
        // iterate over all functions in the module
        for (funcIter = allFunctions->begin(); funcIter != allFunctions->end(); ++funcIter) {
          BPatch_function *curFunc = *funcIter;
          char funcName[1024];

          curFunc->getName(funcName, 1024);
          if (string(funcName) == string("_start"))
            continue;
          insertBBCallback(libBin, curFunc, funcName, bbCallback, &bbIndex);
        }
      }
      if (!libBin->writeFile((*rtLibIter + ".ins").c_str())) {
        cerr << "Failed to write output file: " << (*rtLibIter + ".ins").c_str() << endl;
        return EXIT_FAILURE;
      } else {
        cout << "Saved the instrumented library to " << (*rtLibIter + ".ins").c_str() << "." << endl;
      }
    }
  }

  cout << "All done! Happy fuzzing!" << endl;
  return EXIT_SUCCESS;
}