int main (int argc, const char* argv[]) { BPatch bpatch; // argv[2] is muttee's file name, will be muttee's argv[0] BPatch_process *proc = bpatch.processCreate(argv[2], argv + 2); // Options to tune performance char *s; if ((s = getenv("SET_TRAMP_RECURSIVE")) && (strcmp(s, "true") == 0)) bpatch.setTrampRecursive(true); if ((s = getenv("SET_SAVE_FPR")) && (strcmp(s, "false") == 0)) bpatch.setSaveFPR(false); BPatch_object *ipa = proc->loadLibrary(argv[1]); BPatch_image *image = proc->getImage(); std::vector<BPatch_function *> tracepoints, probes; image->findFunction("do_stuff", tracepoints); BPatch_function *tracepoint = tracepoints[0]; image->findFunction("tpbench_no_arg", probes); BPatch_function *probe = probes[0]; std::vector<BPatch_snippet*> args; BPatch_funcCallExpr call_probe(*probe, args); proc->insertSnippet(call_probe, (tracepoint->findPoint(BPatch_exit))[0]); proc->detach(true); return 0; }
test_results_t test_fork_8_Mutator::executeTest() { // Initialize global variables parentDone = false; childDone = false; passedTest = true; parentThread = NULL; childThread = NULL; msgid = -1; // Register callbacks bpatch->registerPostForkCallback(postForkFunc); bpatch->registerExitCallback(exitFunc); bool passed = mutatorTest(bpatch, appThread); // Remove callbacks upon test completion bpatch->registerPostForkCallback(NULL); bpatch->registerExitCallback(NULL); showFinalResults(passed, 4); if ( passed ) return PASSED; else return FAILED; }
int main() { BPatch bpatch; BPatch_process* appProc = bpatch.processCreate("/bin/ls", NULL); BPatch_image* img = NULL; img = appProc->getImage(); vector<BPatch_module*> *mdl = img->getModules(); vector<BPatch_module*>::iterator moduleIter = mdl->begin(); void* addr = (*moduleIter)->getBaseAddr(); printf("0x%x\n",addr); return 0; }
test_results_t test4_1_Mutator::mutatorTest() { int n = 0; const char *child_argv[MAX_TEST+7]; dprintf("in mutatorTest1\n"); child_argv[n++] = pathname; if (debugPrint) child_argv[n++] = const_cast<char*>("-verbose"); child_argv[n++] = const_cast<char*>("-run"); child_argv[n++] = const_cast<char*>("test4_1"); child_argv[n] = NULL; // Start the mutatee logerror("Starting \"%s\"\n", pathname); appProc = bpatch->processCreate(pathname, child_argv,NULL); dprintf("Test 1: using thread %p\n", appProc); if (appProc == NULL) { logerror("Unable to run test program.\n"); return FAILED; } contAndWaitForAllProcs(bpatch, appProc, myprocs, &threadCount); if ( !passedTest ) { logerror("**Failed** test #1 (exit callback)\n"); logerror(" exit callback not executed\n"); return FAILED; } return PASSED; }
test_results_t test4_1_Mutator::executeTest() { // Register the proper callbacks for this test bpatch->registerPreForkCallback(forkFunc); bpatch->registerPostForkCallback(forkFunc); bpatch->registerExecCallback(execFunc); bpatch->registerExitCallback(exitFunc); test_results_t rv = mutatorTest(); // Remove callbacks upon test completion bpatch->registerPreForkCallback(NULL); bpatch->registerPostForkCallback(NULL); bpatch->registerExecCallback(NULL); bpatch->registerExitCallback(NULL); return rv; }
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) test_results_t test_stack_1_Mutator::executeTest() { appProc->continueExecution(); static const frameInfo_t correct_frame_info[] = { #if defined( os_linux_test ) && (defined( arch_x86_test ) || defined( arch_x86_64_test )) { true, true, BPatch_frameNormal, "_dl_sysinfo_int80" }, #endif #if !defined(rs6000_ibm_aix4_1_test) { false, false, BPatch_frameNormal, NULL }, #endif #if !defined(i386_unknown_nt4_0_test) { true, false, BPatch_frameNormal, "stop_process_" }, #endif { true, false, BPatch_frameNormal, "test_stack_1_func3" }, { true, false, BPatch_frameNormal, "test_stack_1_func2" }, { true, false, BPatch_frameNormal, "test_stack_1_func1" }, { true, false, BPatch_frameNormal, "test_stack_1_mutateeTest" }, { true, false, BPatch_frameNormal, "main" }, }; if (waitUntilStopped(bpatch, appProc, 1, "getCallStack") < 0) { appProc->terminateExecution(); return FAILED; } if (checkStack(appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 1, "getCallStack")) { logerror("Passed test #1 (getCallStack)\n"); } else { appProc->terminateExecution(); return FAILED; } appProc->continueExecution(); while (!appProc->isTerminated()) { bpatch->waitForStatusChange(); } return PASSED; }
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; }
// static int mutatorTest( BPatch_thread * appThread, BPatch_image * appImage ) { test_results_t test_stack_3_Mutator::executeTest() { bool passedTest; BPatch::bpatch->setInstrStackFrames(true); appProc->continueExecution(); static const frameInfo_t correct_frame_info[] = { #if defined( os_linux_test ) && (defined( arch_x86_test ) || defined( arch_x86_64_test )) { true, true, BPatch_frameNormal, "_dl_sysinfo_int80" }, #endif #if defined( os_aix_test ) && defined( arch_power_test ) /* AIX uses kill(), but the PC of a process in a syscall can not be correctly determined, and appears to be the address to which the syscall function will return. */ #elif defined( os_windows_test ) && (defined( arch_x86 ) || defined( arch_x86_64_test )) /* Windows/x86 does not use kill(), so its lowermost frame will be something unidentifiable in a system DLL. */ { false, false, BPatch_frameNormal, NULL }, #else { true, false, BPatch_frameNormal, "kill" }, #endif #if ! defined( os_windows_test ) /* Windows/x86's stop_process_() calls DebugBreak(); it's apparently normal to lose this frame. */ { true, false, BPatch_frameNormal, "stop_process_" }, #endif { true, false, BPatch_frameNormal, "test_stack_3_func3" }, { true, false, BPatch_frameTrampoline, NULL }, /* On AIX and x86 (and others), if our instrumentation fires before frame construction or after frame destruction, it's acceptable to not report the function (since, after all, it doesn't have a frame on the stack. */ { true, true, BPatch_frameNormal, "test_stack_3_func2" }, { true, false, BPatch_frameNormal, "test_stack_3_func1" }, { true, false, BPatch_frameNormal, "test_stack_3_mutateeTest" }, { true, false, BPatch_frameNormal, "main" } }; /* Wait for the mutatee to stop in test_stack_3_func1(). */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation") < 0) { appProc->terminateExecution(); return FAILED; } /* Instrument test_stack_3_func2() to call test_stack_3_func3(), which will trip another breakpoint. */ BPatch_Vector<BPatch_function *> instrumentedFunctions; const char *fName = "test_stack_3_func2"; appImage->findFunction(fName, instrumentedFunctions ); if (instrumentedFunctions.size() != 1) { // FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find function '%s'\n", fName); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_point *> * functionEntryPoints = instrumentedFunctions[0]->findPoint( BPatch_entry ); if (functionEntryPoints->size() != 1) { // FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find entry point to function '%s'\n", fName); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_function *> calledFunctions; const char *fName2 = "test_stack_3_func3"; appImage->findFunction(fName2, calledFunctions ); if (calledFunctions.size() != 1) { //FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find function '%s'\n", fName2); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_snippet *> functionArguments; BPatch_funcCallExpr functionCall( * calledFunctions[0], functionArguments ); appProc->insertSnippet( functionCall, functionEntryPoints[0] ); /* Repeat for all three types of instpoints. */ BPatch_Vector<BPatch_point *> * functionCallPoints = instrumentedFunctions[0]->findPoint( BPatch_subroutine ); if (functionCallPoints->size() != 1) { logerror("**Failed** test_stack_3\n"); logerror(" Unable to find subroutine call points in '%s'\n", fName); appProc->terminateExecution(); return FAILED; } appProc->insertSnippet( functionCall, functionCallPoints[0] ); BPatch_Vector<BPatch_point *> * functionExitPoints = instrumentedFunctions[0]->findPoint( BPatch_exit ); if (functionExitPoints->size() != 1) { logerror("**Failed** test_stack_3\n"); logerror(" Unable to find exit points in '%s'\n", fName); appProc->terminateExecution(); return FAILED; } appProc->insertSnippet( functionCall, functionExitPoints[0] ); #if defined( DEBUG ) for( int i = 0; i < 80; i++ ) { ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL ); } for( int i = 80; i < 120; i++ ) { ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL ); BPatch_Vector<BPatch_frame> stack; appThread->getCallStack( stack ); dprintf("single-step stack walk, %d instructions after stop for instrumentation.\n", i ); for( unsigned i = 0; i < stack.size(); i++ ) { char name[ 40 ]; BPatch_function * func = stack[i].findFunction(); if( func == NULL ) { strcpy( name, "[UNKNOWN]" ); } else { func->getName( name, 40 ); } dprintf(" %10p: %s, fp = %p\n", stack[i].getPC(), name, stack[i].getFP() ); } /* end stack walk dumper */ dprintf("end of stack walk.\n" ); } /* end single-step iterator */ #endif /* defined( DEBUG ) */ /* After inserting the instrumentation, let it be called. */ appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (entry)") < 0) { appProc->terminateExecution(); return FAILED; } passedTest = true; if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (entry)" ) ) { passedTest = false; } /* Repeat for other two types of instpoints. */ appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (call)") < 0) { appProc->terminateExecution(); return FAILED; } if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (call)" ) ) { passedTest = false; } appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (exit)") < 0) { appProc->terminateExecution(); return FAILED; } if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (exit)" ) ) { passedTest = false; } if (passedTest) logerror("Passed test #3 (unwind through base and mini tramps)\n"); /* Return the mutatee to its normal state. */ appProc->continueExecution(); while (!appProc->isTerminated()) { // Workaround for issue with pgCC_high mutatee bpatch->waitForStatusChange(); } if (passedTest) return PASSED; return FAILED; } /* end mutatorTest3() */
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; }
// static bool mutatorTest3and4(int testno, const char *testname) test_results_t test_thread_3_Mutator::executeTest() { test3_threadCreateCounter = 0; callback_tids.clear(); unsigned int timeout = 0; // in ms int err = 0; BPatchAsyncThreadEventCallback createcb = threadCreateCB; if (!bpatch->registerThreadEventCallback(BPatch_threadCreateEvent, createcb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to register thread callback\n", __FILE__, __LINE__); appThread->getProcess()->terminateExecution(); return FAILED; } #if 0 // unset mutateeIde to trigger thread (10) spawn. int zero = 0; // FIXME Check the return value of setVar() setVar("mutateeIdle", (void *) &zero, TESTNO, TESTDESC); dprintf("%s[%d]: continue execution for test %d\n", __FILE__, __LINE__, TESTNO); appThread->continueExecution(); #endif // wait until we have received the desired number of events // (or timeout happens) BPatch_Vector<BPatch_thread *> threads; BPatch_process *appProc = appThread->getProcess(); assert(appProc); appProc->getThreads(threads); int active_threads = 11; // FIXME Magic number threads.clear(); while (((test3_threadCreateCounter < TEST3_THREADS) || (active_threads > 1)) && (timeout < TIMEOUT)) { dprintf("%s[%d]: waiting for completion for test %d, num active threads = %d\n", __FILE__, __LINE__, TESTNO, active_threads); sleep_ms(SLEEP_INTERVAL/*ms*/); timeout += SLEEP_INTERVAL; if (appProc->isTerminated()) { dprintf("%s[%d]: BAD NEWS: somehow the process died\n", __FILE__, __LINE__); err = 1; break; } bpatch->pollForStatusChange(); if (appProc->isStopped()) { appProc->continueExecution(); } appProc->getThreads(threads); active_threads = threads.size(); threads.clear(); } if (timeout >= TIMEOUT) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: test timed out. got %d/10 events\n", __FILE__, __LINE__, test3_threadCreateCounter); logerror("test3_createCounter is %d, expected %d; active threads %d, expected %d\n", test3_threadCreateCounter, TEST3_THREADS, active_threads, 1); err = 1; } dprintf("%s[%d]: ending test %d, num active threads = %d\n", __FILE__, __LINE__, TESTNO, active_threads); dprintf("%s[%d]: stop execution for test %d\n", __FILE__, __LINE__, TESTNO); appProc->stopExecution(); // read all tids from the mutatee and verify that we got them all unsigned long mutatee_tids[TEST3_THREADS]; const char *threads_varname = "test4_threads"; getVar(threads_varname, (void *) mutatee_tids, (sizeof(unsigned long) * TEST3_THREADS), TESTNO, TESTDESC); if (debugPrint()) { dprintf("%s[%d]: read following tids for test%d from mutatee\n", __FILE__, __LINE__, TESTNO); for (unsigned int i = 0; i < TEST3_THREADS; ++i) { dprintf("\t%lu\n", mutatee_tids[i]); } } for (unsigned int i = 0; i < TEST3_THREADS; ++i) { bool found = false; for (unsigned int j = 0; j < callback_tids.size(); ++j) { if (callback_tids[j] == mutatee_tids[i]) { found = true; break; } } if (!found) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: could not find record for tid %lu: have these:\n", __FILE__, __LINE__, mutatee_tids[i]); for (unsigned int j = 0; j < callback_tids.size(); ++j) { logerror("%lu\n", callback_tids[j]); } err = true; break; } } dprintf("%s[%d]: removing thread callback\n", __FILE__, __LINE__); if (!bpatch->removeThreadEventCallback(BPatch_threadCreateEvent, createcb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to remove thread callback\n", __FILE__, __LINE__); err = true; } if (!err) { PASS_MES(TESTNAME, TESTDESC); appProc->terminateExecution(); return PASSED; } appProc->terminateExecution(); return FAILED; }
// static int mutatorTest(char *pathname, BPatch *bpatch) test_results_t test1_41_Mutator::executeTest() { unsigned int n=0; const char *child_argv[5]; child_argv[n++] = pathname; if (debugPrint) child_argv[n++] = const_cast<char*>("-verbose"); child_argv[n++] = const_cast<char*>("-run"); child_argv[n++] = const_cast<char*>("test1_41"); // run test41 in mutatee child_argv[n++] = NULL; int counts[iterations]; // Run the mutatee twice, querying line info each time & store the info for (n = 0; n < iterations; n++) { dprintf("Starting \"%s\"\n", pathname); BPatch_process *proc = bpatch->processCreate(pathname, child_argv, NULL); if (!proc) { logerror("*ERROR*: unable to create handle for executable\n", n); logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } dprintf("Mutatee started, pid=%d\n", n, proc->getPid()); BPatch_image *image = proc->getImage(); if (!image) { logerror("*ERROR*: unable to get image from thread\n"); logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } if (isMutateeFortran(image)) { // This shouldn't happen.. proc->terminateExecution(); logerror("Skipped test #41 (repeated line information)\n"); return SKIPPED; } BPatch_module *module = image->findModule("test1_41_mutatee.c", true); if (!module) { module = image->findModule("solo_mutatee_boilerplate.c", true); if (true) { logerror("*ERROR*: unable to get module from image\n"); logerror("Looking for \"test1_41_solo_me.c\" or \"solo_mutatee_boilerplate.c\". Available modules:\n"); BPatch_Vector<BPatch_module *> *mods = image->getModules(); char buffer[512]; for (unsigned i = 0; i < mods->size(); i++) { BPatch_module *mod = (*mods)[i]; char name[512]; mod->getName(name, 512); sprintf(buffer, "\t%s\n", name); logerror(buffer); } } } if (!module) { fprintf(stderr, "%s[%d]: could not find module solo_mutatee_boilerplate.c\n", FILE__, __LINE__); // First try again for 'test1_41_solo_me.c' module = image->findModule("test1_41_solo_me.c", true); if (!module) { logerror("*ERROR*: unable to get module from image\n"); logerror("Looking for \"test1_41_solo_me.c\" or \"solo_mutatee_boilerplate.c\". Available modules:\n"); BPatch_Vector<BPatch_module *> *mods = image->getModules(); char buffer[512]; for (unsigned i = 0; i < mods->size(); i++) { BPatch_module *mod = (*mods)[i]; char name[512]; mod->getName(name, 512); sprintf(buffer, "\t%s\n", name); logerror(buffer); } logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } } char buffer[16384]; // FIXME ugly magic number; No module name should be that long.. module->getName(buffer, sizeof(buffer)); BPatch_Vector<BPatch_statement> statements; bool res = module->getStatements(statements); if (!res) { fprintf(stderr, "%s[%d]: getStatements()\n", __FILE__, __LINE__); return FAILED; } counts[n] = statements.size(); dprintf("Trial %d: found %d statements\n", n, statements.size()); proc->terminateExecution(); } // Make sure we got the same info each time we ran the mutatee int last_count = -1; for (int i = 0; i < iterations; i++) { if ((last_count >= 0) && (last_count != counts[i])) { logerror("*ERROR*: statement counts didn't match: %d vs. %d\n", last_count, counts[i]); logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } last_count = counts[i]; } logerror("Passed test #41 (repeated line information)\n"); return PASSED; }
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); */ }
int main(int argc, char *argv[], char* envp[]) { if (argc < 2) { fprintf(stderr, "Usage: %s prog_filename prog_aruments\n", argv[0]); return 3; } #if 0 if (strcmp(argv[1], "prog") != 0 && strcmp(argv[1], "all")) { fprintf(stderr, "Options for patch selection are 'progonly' or 'all'\n"); return 3; } #endif int patchall = 0; //strcmp(argv[1], "all") != 0; // Create process BPatch_process *appProc = bpatch.processCreate(argv[1], (const char**) &(argv[1])); // Load pthread into the process... appProc->loadLibrary("libpthread.so.0"); // Get the process image BPatch_image *appImage = appProc->getImage(); // Find all the instrumentable procedures BPatch_Vector<BPatch_function*> *functions = appImage->getProcedures(); /************************************************************************* * General function search * *************************************************************************/ // Find the printf function BPatch_Vector<BPatch_function*> printfFuncs; appImage->findFunction("printf", printfFuncs); if (printfFuncs.size() == 0) appImage->findFunction("_printf", printfFuncs); if (printfFuncs.size() == 0) appImage->findFunction("__printf", printfFuncs); if(printfFuncs.size() == 0) { fprintf(stderr, "Could not find printf() function"); return 2; } // Find the exit function BPatch_Vector<BPatch_function*> exitFuncs; appImage->findFunction("exit", exitFuncs); if (exitFuncs.size() == 0) appImage->findFunction("_exit", exitFuncs); if (exitFuncs.size() == 0) appImage->findFunction("__exit", exitFuncs); if(exitFuncs.size() == 0) { fprintf(stderr, "Could not find exit() function"); return 2; } // Find the perror function BPatch_Vector<BPatch_function*> perrorFuncs; appImage->findFunction("perror", perrorFuncs); if (perrorFuncs.size() == 0) appImage->findFunction("_perror", perrorFuncs); if (perrorFuncs.size() == 0) appImage->findFunction("__perror", perrorFuncs); if(perrorFuncs.size() == 0) { fprintf(stderr, "Could not find perror() function"); return 2; } BPatch_Vector<BPatch_snippet*> mainEntryBlock; /************************************************************************ * Error exit call * ************************************************************************/ BPatch_Vector<BPatch_snippet*> exitArgs; BPatch_constExpr exitCode(-2); exitArgs.push_back(&exitCode); // Open call BPatch_funcCallExpr exitOnErrorCall(*exitFuncs[0], exitArgs); /************************************************************************ * Open imitate device patch * * **********************************************************************/ // Find main() BPatch_Vector<BPatch_function*> mainFunctions; appImage->findFunction("main", mainFunctions); if (mainFunctions.size() == 0) appImage->findFunction("_main", mainFunctions); if (mainFunctions.size() == 0) appImage->findFunction("__main", mainFunctions); if(mainFunctions.size() == 0) { fprintf(stderr, "Could not find main() function"); return 2; } // find open() BPatch_Vector<BPatch_function*> openFunctions; appImage->findFunction("open64", openFunctions); if (openFunctions.size() == 0) appImage->findFunction("open", openFunctions); if (openFunctions.size() == 0) appImage->findFunction("_open", openFunctions); if (openFunctions.size() == 0) appImage->findFunction("__open", openFunctions); if(openFunctions.size() == 0) { fprintf(stderr, "Could not find open() function"); return 2; } // Get main() entry point BPatch_Vector<BPatch_point*> *mainPoints = mainFunctions[0]->findPoint(BPatch_entry); // Open call arguments BPatch_Vector<BPatch_snippet*> openArgs; BPatch_constExpr fileName("/dev/imitate0"); BPatch_constExpr fileFlags(O_RDWR); openArgs.push_back(&fileName); openArgs.push_back(&fileFlags); // Open call BPatch_funcCallExpr openDevCall(*openFunctions[0], openArgs); // Allocate file descriptor BPatch_variableExpr *devFd = appProc->malloc(*appImage->findType("int")); // Assign fd with result of open call BPatch_arithExpr openDevice(BPatch_assign, *devFd, openDevCall); // defFd check BPatch_boolExpr devFdCheck(BPatch_lt, *devFd, BPatch_constExpr(0)); // perror message BPatch_Vector<BPatch_snippet*> devFdErrorArgs; BPatch_constExpr devFdErrorMsg("Opening imitate kernel device"); devFdErrorArgs.push_back(&devFdErrorMsg); BPatch_funcCallExpr devFdError(*perrorFuncs[0], devFdErrorArgs); BPatch_Vector<BPatch_snippet*> openErrorBlock; openErrorBlock.push_back(&devFdError); openErrorBlock.push_back(&exitOnErrorCall); // if (devFd < 0) { perror(...) } BPatch_ifExpr devFdBlock(devFdCheck, BPatch_sequence(openErrorBlock)); mainEntryBlock.push_back(&openDevice); mainEntryBlock.push_back(&devFdBlock); /************************************************************************* * Send ioctl IMITATE_APP_RECORD to module * *************************************************************************/ // find ioctl() BPatch_Vector<BPatch_function*> ioctlFunctions; appImage->findFunction("ioctl", ioctlFunctions); if (ioctlFunctions.size() == 0) appImage->findFunction("_ioctl", ioctlFunctions); if (ioctlFunctions.size() == 0) appImage->findFunction("__ioctl", ioctlFunctions); if(ioctlFunctions.size() == 0) { fprintf(stderr, "Could not find ioctl() function"); return 2; } // ioctl() arguments BPatch_Vector<BPatch_snippet*> ioctlArgs; BPatch_constExpr operation(IMITATE_APP_RECORD); fprintf(stderr, "PPID: %d\n", getppid()); BPatch_constExpr monitorPid(getppid()); ioctlArgs.push_back(devFd); ioctlArgs.push_back(&operation); ioctlArgs.push_back(&monitorPid); // ioctl() call BPatch_funcCallExpr ioctlCall(*ioctlFunctions[0], ioctlArgs); // ioctl() result check BPatch_boolExpr ioctlCheck(BPatch_lt, ioctlCall, BPatch_constExpr(0)); // perror message BPatch_Vector<BPatch_snippet*> ioctlErrorArgs; BPatch_constExpr ioctlErrorMsg("Notifying imitate kernel driver of RECORD"); ioctlErrorArgs.push_back(&ioctlErrorMsg); BPatch_funcCallExpr ioctlError(*perrorFuncs[0], ioctlErrorArgs); BPatch_Vector<BPatch_snippet*> ioctlErrorBlock; ioctlErrorBlock.push_back(&ioctlError); ioctlErrorBlock.push_back(&exitOnErrorCall); // if (ioctl(...) < 0) { perror(...) } BPatch_ifExpr ioctlBlock(ioctlCheck, BPatch_sequence(ioctlErrorBlock)); // Add ioctl check to entry block mainEntryBlock.push_back(&ioctlBlock); /************************************************************************* * Counter mmap() * *************************************************************************/ // Find the mmap function BPatch_Vector<BPatch_function*> mmapFuncs; appImage->findFunction("mmap", mmapFuncs); if (mmapFuncs.size() == 0) appImage->findFunction("_mmap", mmapFuncs); if (mmapFuncs.size() == 0) appImage->findFunction("__mmap", mmapFuncs); if(mmapFuncs.size() == 0) { fprintf(stderr, "Could not find mmap() function"); return 2; } // Allocate counter BPatch_variableExpr *counterAddr = appProc->malloc(sizeof(sched_counter_t*)); sched_counter_t counterVal = 0; counterAddr->writeValue(&counterVal, sizeof(sched_counter_t*), false); // Notify kernel of address BPatch_Vector<BPatch_snippet*> mmapArgs; BPatch_constExpr mmapStart(0); BPatch_constExpr mmapLength(sizeof(sched_counter_t)); BPatch_constExpr mmapProt(PROT_READ | PROT_WRITE); BPatch_constExpr mmapFlags(MAP_SHARED); BPatch_constExpr mmapOffset(0); mmapArgs.push_back(&mmapStart); mmapArgs.push_back(&mmapLength); mmapArgs.push_back(&mmapProt); mmapArgs.push_back(&mmapFlags); mmapArgs.push_back(devFd); mmapArgs.push_back(&mmapOffset); // mmap() call BPatch_funcCallExpr mmapCall(*mmapFuncs[0], mmapArgs); // assign result to counterAddr BPatch_arithExpr mmapAssign(BPatch_assign, *counterAddr, mmapCall); // Add to entry block mainEntryBlock.push_back(&mmapAssign); // mmap() result check BPatch_boolExpr mmapCheck(BPatch_eq, *counterAddr, BPatch_constExpr(MAP_FAILED)); // perror message BPatch_Vector<BPatch_snippet*> mmapErrorArgs; BPatch_constExpr mmapErrorMsg("Memory mapping schedule (back edge) counter"); mmapErrorArgs.push_back(&mmapErrorMsg); BPatch_funcCallExpr mmapError(*perrorFuncs[0], mmapErrorArgs); BPatch_Vector<BPatch_snippet*> mmapErrorBlock; mmapErrorBlock.push_back(&mmapError); mmapErrorBlock.push_back(&exitOnErrorCall); // if (mmap(...) == MAP_FAILED) { perror(...) } BPatch_ifExpr mmapBlock(mmapCheck, BPatch_sequence(mmapErrorBlock)); mainEntryBlock.push_back(&mmapBlock); // Patch main entry BPatch_sequence mainEntrySeq(mainEntryBlock); appProc->insertSnippet(mainEntrySeq, *mainPoints); /************************************************************************* * Back-edge patching * *************************************************************************/ #if 0 printf("intCounter address: %x\n PID: %d\n", intCounter->getBaseAddr(), appProc->getPid()); fflush(stdout); #endif // Find the mutex lock/unlock functions BPatch_Vector<BPatch_function*> mutexLockFunctions; appImage->findFunction("pthread_mutex_lock", mutexLockFunctions); if (mutexLockFunctions.size() == 0) appImage->findFunction("_pthread_mutex_lock", mutexLockFunctions); if (mutexLockFunctions.size() == 0) appImage->findFunction("__pthread_mutex_lock", mutexLockFunctions); if(mutexLockFunctions.size() == 0) { fprintf(stderr, "Could not find pthread_mutex_lock() function"); return 2; } BPatch_Vector<BPatch_function*> mutexUnlockFunctions; appImage->findFunction("pthread_mutex_unlock", mutexUnlockFunctions); if (mutexUnlockFunctions.size() == 0) appImage->findFunction("_pthread_mutex_unlock", mutexUnlockFunctions); if (mutexUnlockFunctions.size() == 0) appImage->findFunction("__pthread_mutex_unlock", mutexUnlockFunctions); if(mutexUnlockFunctions.size() == 0) { fprintf(stderr, "Could not find pthread_mutex_unlock() function"); return 2; } // Allocate a mutex pthread_mutex_t mutexValue = PTHREAD_MUTEX_INITIALIZER; BPatch_variableExpr *mutex = appProc->malloc(sizeof(pthread_mutex_t)); mutex->writeValue(&mutexValue, sizeof(pthread_mutex_t), false); // Build mutex lock call BPatch_Vector<BPatch_snippet*> mutexArgs; BPatch_constExpr mutexAddress(mutex->getBaseAddr()); mutexArgs.push_back(&mutexAddress); BPatch_funcCallExpr mutexLockCall(*mutexLockFunctions[0], mutexArgs); BPatch_funcCallExpr mutexUnlockCall(*mutexUnlockFunctions[0], mutexArgs); BPatch_arithExpr derefCounter(BPatch_deref, *counterAddr); // Create 'increment counter' snippet BPatch_arithExpr addOneToCounter(BPatch_assign, derefCounter, BPatch_arithExpr(BPatch_plus, derefCounter, BPatch_constExpr(1))); BPatch_Vector<BPatch_snippet*> snippet; snippet.push_back(&mutexLockCall); snippet.push_back(&addOneToCounter); snippet.push_back(&mutexUnlockCall); BPatch_sequence addOneAtomic(snippet); char *name = (char*) malloc(sizeof(char)*200); char *modname = (char*) malloc(sizeof(char)*200); if (! (name && modname)) { fprintf(stderr, "%s %d: Out of memory!", __FILE__, __LINE__); return 1; } appProc->beginInsertionSet(); // Iterate through the procedures for (int i = 0; i < functions->size(); i++) { (*functions)[i]->getName(name, 199); (*functions)[i]->getModuleName(modname, 199); if ((patchall && strcmp(modname, "DEFAULT_MODULE") != 0) || strncmp(name, "pthread", 7) == 0 || strncmp(modname, "libpthread", 10) == 0 || strncmp(modname, "libdyninst", 10) == 0 || (name[0] == '_' && name[1] != '_' && strncmp(modname, "libc", 4) == 0)) continue; fprintf(stderr, "patcher: Patching function: '%s' (%s)", name, modname); // Patch back-edge for call if (strcmp(name, "main") != 0) appProc->insertSnippet(addOneAtomic, *((*functions)[i]->findPoint(BPatch_entry))); // Get the control flow graph for the procedure BPatch_flowGraph *graph = (*functions)[i]->getCFG(); // Find the loops BPatch_Vector<BPatch_basicBlockLoop*> *loops = new BPatch_Vector<BPatch_basicBlockLoop*>(); graph->getLoops(*loops); // Patch the loop back-edges for(int j = 0; j < loops->size(); j++) { appProc->insertSnippet(addOneAtomic, *((*loops)[j]->getBackEdge()->getPoint())); fprintf(stderr, ".", (int) (*loops)[j]->getBackEdge()->getPoint()->getAddress()); } fprintf(stderr, "\n"); // Free the loops found delete(loops); } fprintf(stderr, "Finalising patches..."); fflush(stderr); appProc->finalizeInsertionSet(false); fprintf(stderr, "Done.\n----------------------------------------\n"); // Clear up memory used to store the name free(name); free(modname); #if 0 /************************************************************************* * Exit point counter print patch * *************************************************************************/ // Patch exit() function to print out no of back branches at the end // Get exit() exit point BPatch_Vector<BPatch_point*> *exitPoints = exitFuncs[0]->findPoint(BPatch_entry); // Build printf() call: // printf("Total Total Back-branches: %d\n", counter); // Build arguments to printf() BPatch_Vector<BPatch_snippet*> printfArgs; BPatch_constExpr formatString("Total Back-branches: %d\n"); printfArgs.push_back(&formatString); printfArgs.push_back(&derefCounter); // Build call to printf() BPatch_funcCallExpr printfCall(*printfFuncs[0], printfArgs); // Patch into exit() appProc->insertSnippet(printfCall, *exitPoints); #endif // Continue mutatee... appProc->continueExecution(); // Wait for mutatee to finish while (!appProc->isTerminated()) { bpatch.waitForStatusChange(); } fprintf(stderr, "----------------------------------------\n"); fprintf(stderr, "Done.\n"); return 0; }
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) test_results_t test_callback_2_Mutator::executeTest() { // a simple single threaded user messagin scenario where we want to send // async messages at function entry/exit and call points. // load libtest12.so -- currently only used by subtest 5, but make it generally // available const char *libname = "./libTest12.so"; test7err = false; test7done = false; callback_counter = 0; elog.resize(0); #if defined(arch_x86_64_test) if (appProc->getAddressWidth() == 4) libname = "./libTest12_m32.so"; #endif dprintf("%s[%d]: loading test library: %s\n", __FILE__, __LINE__, libname); if (!appProc->loadLibrary(libname)) { logerror("%s[%d]: failed to load library %s, cannot proceed\n", __FILE__, __LINE__, libname); appProc->terminateExecution(); return FAILED; } dprintf("%s[%d]: loaded test library: %s\n", __FILE__, __LINE__, libname); BPatchUserEventCallback cb = test7cb; if (!bpatch->registerUserEventCallback(cb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: could not register callback\n", __FILE__, __LINE__); appProc->terminateExecution(); return FAILED; } // instrument entry and exit of call7_1, as well as call points inside call7_1 const char *call1name = "test_callback_2_call1"; BPatch_function *call7_1 = findFunction(call1name, appImage,TESTNO, TESTNAME); BPatch_point *entry = findPoint(call7_1, BPatch_entry,TESTNO, TESTNAME); if (NULL == entry) { logerror("%s[%d]: Unable to find entry point to function %s\n", __FILE__, __LINE__, call1name); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } BPatch_point *exit = findPoint(call7_1, BPatch_exit,TESTNO, TESTNAME); if (NULL == entry) { logerror("%s[%d]: Unable to find exit point to function %s\n", __FILE__, __LINE__, call1name); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } BPatch_point *callsite = findPoint(call7_1, BPatch_subroutine,TESTNO, TESTNAME); if (NULL == callsite) { logerror("%s[%d]: Unable to find subroutine call point in function %s\n", __FILE__, __LINE__, call1name); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } // These are our asynchronous message functions (in libTest12) that we // attach to the "interesting" points BPatch_function *reportEntry = findFunction("reportEntry", appImage,TESTNO, TESTNAME); BPatch_function *reportExit = findFunction("reportExit", appImage,TESTNO, TESTNAME); BPatch_function *reportCallsite = findFunction("reportCallsite", appImage,TESTNO, TESTNAME); if (!reportEntry) { logerror("%s[%d]: reportEntry = NULL\n", FILE__, __LINE__); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } if (!reportExit) { logerror("%s[%d]: reportExit = NULL\n", FILE__, __LINE__); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } if (!reportCallsite) { logerror("%s[%d]: reportCallsite = NULL\n", FILE__, __LINE__); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } // Do the instrumentation BPatchSnippetHandle *entryHandle = at(entry, reportEntry, TESTNO, TESTNAME); BPatchSnippetHandle *exitHandle = at(exit, reportExit, TESTNO, TESTNAME); BPatchSnippetHandle *callsiteHandle = at(callsite, reportCallsite, TESTNO, TESTNAME); // "at" may set test7err if ((test7err) || (NULL == entryHandle) || (NULL == exitHandle) || (NULL == callsiteHandle) ) { logerror("%s[%d]: instrumentation failed, test7err = %d\n", FILE__, __LINE__, test7err); logerror("%s[%d]: entryHandle = %p\n", FILE__, __LINE__, entryHandle); logerror("%s[%d]: exitHandle = %p\n", FILE__, __LINE__, exitHandle); logerror("%s[%d]: callsiteHandle = %p\n", FILE__, __LINE__, callsiteHandle); bpatch->removeUserEventCallback(test7cb); return FAILED; } if (debugPrint()) { int one = 1; const char *varName = "libraryDebug"; if (setVar(varName, (void *) &one, TESTNO, TESTNAME)) { logerror("%s[%d]: Error setting variable '%s' in mutatee\n", FILE__, __LINE__, varName); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } } dprintf("%s[%d]: did instrumentation, continuing process...: %s\n", __FILE__, __LINE__, libname); // unset mutateeIdle to trigger mutatee to issue messages. int timeout = 0; appProc->continueExecution(); dprintf("%s[%d]: continued process...: %s\n", __FILE__, __LINE__, libname); // wait until we have received the desired number of events // (or timeout happens) while(!test7err && !test7done && (timeout < TIMEOUT)) { sleep_ms(SLEEP_INTERVAL/*ms*/); timeout += SLEEP_INTERVAL; bpatch->pollForStatusChange(); if (appProc->isTerminated()) { BPatch_exitType et = appProc->terminationStatus(); if (et == ExitedNormally) { int ecode = appProc->getExitCode(); logerror("%s[%d]: normal exit with code %d\n", __FILE__, __LINE__, ecode); } if (et == ExitedViaSignal) { int ecode = appProc->getExitSignal(); logerror("%s[%d]: caught signal %d\n", __FILE__, __LINE__, ecode); } log_res(); bpatch->removeUserEventCallback(test7cb); return FAILED; } } dprintf("%s[%d]: after wait loop: test7err = %s, test7done = %s, timeout = %d\n", __FILE__, __LINE__, test7err ? "true" : "false", test7done ? "true" : "false", timeout); if (timeout >= TIMEOUT) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: test timed out: %d ms\n", __FILE__, __LINE__, TIMEOUT); test7err = true; } if (!appProc->stopExecution()) { logerror("%s[%d]: stopExecution failed\n", __FILE__, __LINE__); } dprintf("%s[%d]: stopped process...\n", __FILE__, __LINE__ ); if (!bpatch->removeUserEventCallback(test7cb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to remove callback\n", __FILE__, __LINE__); appProc->terminateExecution(); log_res(); return FAILED; } dprintf("%s[%d]: removed callback...\n", __FILE__, __LINE__ ); if (!appProc->terminateExecution()) { // don't care //fprintf(stderr, "%s[%d]: terminateExecution failed\n", FILE__, __LINE__); //return FAILED; } #if 0 int one = 1; if (setVar("test_callback_2_idle", (void *) &one, TESTNO, TESTNAME)) { logerror("Error setting variable 'test_callback_2_idle' in mutatee\n"); test7err = true; appProc->terminateExecution(); } #endif #if 0 // And let it run out if (!appThread->isTerminated()) { appProc->continueExecution(); } while (!appThread->isTerminated()) { // Workaround for pgCC_high mutatee issue bpatch->waitForStatusChange(); } #endif if (!test7err) { PASS_MES(TESTNAME, TESTDESC); return PASSED; } log_res(); FAIL_MES(TESTNAME, TESTDESC); return FAILED; }
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); }
// static bool mutatorTest3and4(int testno, const char *testname) test_results_t test_thread_2_Mutator::executeTest() { test3_threadCreateCounter = 0; callback_tids.clear(); BPatchAsyncThreadEventCallback createcb = threadCreateCB; if (!bpatch->registerThreadEventCallback(BPatch_threadCreateEvent, createcb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to register thread callback\n", __FILE__, __LINE__); appThread->getProcess()->terminateExecution(); return FAILED; } #if 0 // unset mutateeIde to trigger thread (10) spawn. int zero = 0; // FIXME Check the return code for setVar setVar("mutateeIdle", (void *) &zero, TESTNO, TESTDESC); dprintf("%s[%d]: continue execution for test %d\n", __FILE__, __LINE__, TESTNO); appThread->continueExecution(); #endif if( !appProc->continueExecution() ) { logerror("%s[%d]: failed to continue process\n", FILE__, __LINE__); appProc->terminateExecution(); return FAILED; } // wait until we have received the desired number of events int err = 0; BPatch_Vector<BPatch_thread *> threads; BPatch_process *appProc = appThread->getProcess(); assert(appProc); appProc->getThreads(threads); int active_threads = 11; // FIXME Magic number threads.clear(); while (((test3_threadCreateCounter < TEST3_THREADS) || (active_threads > 1)) && !appProc->isTerminated() ) { dprintf("%s[%d]: waiting for completion for test; ((%d < %d) || (%d > 1)) && !(%d)\n", __FILE__, __LINE__, test3_threadCreateCounter, TEST3_THREADS, active_threads, 1, appProc->isTerminated()); if( !bpatch->waitForStatusChange() ) { logerror("%s[%d]: failed to wait for events\n", __FILE__, __LINE__); err = 1; break; } appProc->getThreads(threads); active_threads = threads.size(); threads.clear(); } if( appProc->isTerminated() ) { logerror("%s[%d]: BAD NEWS: somehow the process died\n", __FILE__, __LINE__); return FAILED; } dprintf("%s[%d]: ending test %d, num active threads = %d\n", __FILE__, __LINE__, TESTNO, active_threads); dprintf("%s[%d]: stop execution for test %d\n", __FILE__, __LINE__, TESTNO); appProc->stopExecution(); // read all tids from the mutatee and verify that we got them all unsigned long mutatee_tids[TEST3_THREADS]; const char *threads_varname = "test3_threads"; if (getVar(threads_varname, (void *) mutatee_tids, (sizeof(unsigned long) * TEST3_THREADS), TESTNO, TESTDESC)) { appProc->terminateExecution(); return FAILED; } if (debugPrint()) { dprintf("%s[%d]: read following tids for test%d from mutatee\n", __FILE__, __LINE__, TESTNO); for (unsigned int i = 0; i < TEST3_THREADS; ++i) { dprintf("\t%lu\n", mutatee_tids[i]); } } for (unsigned int i = 0; i < TEST3_THREADS; ++i) { bool found = false; for (unsigned int j = 0; j < callback_tids.size(); ++j) { if (callback_tids[j] == mutatee_tids[i]) { found = true; break; } } if (!found) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: could not find record for tid %lu: have these:\n", __FILE__, __LINE__, mutatee_tids[i]); for (unsigned int j = 0; j < callback_tids.size(); ++j) { logerror("%lu\n", callback_tids[j]); } err = 1; break; } } dprintf("%s[%d]: removing thread callback\n", __FILE__, __LINE__); if (!bpatch->removeThreadEventCallback(BPatch_threadCreateEvent, createcb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to remove thread callback\n", __FILE__, __LINE__); err = 1; } if (!err) { logerror("No error reported, terminating process and returning success\n"); PASS_MES(TESTNAME, TESTDESC); appProc->terminateExecution(); logerror("\t Process terminated\n"); return PASSED; } appProc->terminateExecution(); return FAILED; }
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; }