/* * syscall enter notification (analysis function) * * save the system call context and invoke the pre-syscall callback * function (if registered) * * @tid: thread id * @ctx: CPU context * @std: syscall standard (e.g., Linux IA-32, IA-64, etc) * @v: callback value */ static void sysenter_save(THREADID tid, CONTEXT *ctx, SYSCALL_STANDARD std, VOID *v) { /* get the thread context */ thread_ctx_t *thread_ctx = (thread_ctx_t *) PIN_GetContextReg(ctx, thread_ctx_ptr); /* get the syscall number */ size_t syscall_nr = PIN_GetSyscallNumber(ctx, std); /* unknown syscall; optimized branch */ if (unlikely(syscall_nr >= SYSCALL_MAX)) { LOG(string(__func__) + ": unknown syscall (num=" + decstr(syscall_nr) + ")\n"); /* syscall number is set to -1; hint for the sysexit_save() */ thread_ctx->syscall_ctx.nr = -1; /* no context save and no pre-syscall callback invocation */ return; } /* pass the system call number to sysexit_save() */ thread_ctx->syscall_ctx.nr = syscall_nr; /* * check if we need to save the arguments for that syscall * * we save only when we have a callback registered or the syscall * returns a value in the arguments */ if (syscall_desc[syscall_nr].save_args | syscall_desc[syscall_nr].retval_args) { /* * dump only the appropriate number of arguments * or yet another lame way to avoid a loop (vpk) */ switch (syscall_desc[syscall_nr].nargs) { /* 6 */ case SYSCALL_ARG5 + 1: thread_ctx->syscall_ctx.arg[SYSCALL_ARG5] = PIN_GetSyscallArgument(ctx, std, SYSCALL_ARG5); /* 5 */ case SYSCALL_ARG4 + 1: thread_ctx->syscall_ctx.arg[SYSCALL_ARG4] = PIN_GetSyscallArgument(ctx, std, SYSCALL_ARG4); /* 4 */ case SYSCALL_ARG3 + 1: thread_ctx->syscall_ctx.arg[SYSCALL_ARG3] = PIN_GetSyscallArgument(ctx, std, SYSCALL_ARG3); /* 3 */ case SYSCALL_ARG2 + 1: thread_ctx->syscall_ctx.arg[SYSCALL_ARG2] = PIN_GetSyscallArgument(ctx, std, SYSCALL_ARG2); /* 2 */ case SYSCALL_ARG1 + 1: thread_ctx->syscall_ctx.arg[SYSCALL_ARG1] = PIN_GetSyscallArgument(ctx, std, SYSCALL_ARG1); /* 1 */ case SYSCALL_ARG0 + 1: thread_ctx->syscall_ctx.arg[SYSCALL_ARG0] = PIN_GetSyscallArgument(ctx, std, SYSCALL_ARG0); /* default */ default: /* nothing to do */ break; } /* * dump the architectural state of the processor; * saved as "auxiliary" data */ thread_ctx->syscall_ctx.aux = ctx; /* call the pre-syscall callback (if any) */ if (syscall_desc[syscall_nr].pre != NULL) syscall_desc[syscall_nr].pre(&thread_ctx->syscall_ctx); } }
int whiteList_init(struct whiteList* list, const char* file_name){ FILE* file = NULL; long size; int i; int n; list->buffer = NULL; if ((file = fopen(file_name, "rb")) == NULL){ LOG("ERROR: unable to open file: "); LOG(file_name); LOG("\n"); goto error; } if (fseek(file, 0, SEEK_END)){ LOG("ERROR: unable to fseek\n"); goto error; } size = ftell(file); rewind(file); if ((list->buffer = (char*)malloc(size + 1)) == NULL){ LOG("ERROR: unable to allocate memory\n"); goto error; } if (fread(list->buffer, 1, size, file) != (size_t)size){ LOG("ERROR: unable to read file\n"); goto error; } fclose(file); file = NULL; list->buffer[size] = '\0'; for (i = size; i > 0; ){ i --; if (list->buffer[i] == '\0' || list->buffer[i] == '\n'){ list->buffer[i] = '\0'; } else{ break; } } for (i = 0, list->nb_entry = 1; i < size; i++){ if (list->buffer[i] == '\n'){ list->nb_entry ++; list->buffer[i] = '\0'; } } if ((list->entries = (char**)malloc(sizeof(char*)*list->nb_entry)) == NULL){ LOG("ERROR: unable to allocate memory\n"); goto error; } list->entries[0] = list->buffer; for (n = 1, i = 0; n < list->nb_entry; n++){ while ((i < size) && (list->buffer[i] != '\0')){ i++; } if (i >= size){ LOG("ERROR: searching for end of line fails at line " + decstr(n) + ":" + decstr(list->nb_entry) + "\n"); list->entries[n] = list->entries[n-1]; } else{ i++; list->entries[n] = list->buffer + i; } } qsort(list->entries, list->nb_entry, sizeof(char*), whiteList_compare); return 0; error: if (file != NULL){ fclose(file); } if (list->buffer != NULL){ free(list->buffer); } return -1; }
void post_write_hook(syscall_ctx_t *ctx) { /* ignore write() on not watched fd */ if (unlikely(fdset.find(_FD) == fdset.end())) return; /* write() was not successful; optimized branch; errno message may be incorrect */ if (unlikely(_N_WRITTEN < 0)) { LOG("ERROR " _CALL_LOG_STR + " (" + strerror(errno) + ")\n"); return; } LOG("OK " _CALL_LOG_STR + "\n"); const ufd_t ufd = ufdmap.get(_FD); off_t write_begin; range_map_t ranges; range_map_t ranges_prev; /* calculate begining of write */ if (IS_STDFD(_FD)) { write_begin = stdcount[_FD]; stdcount[_FD] += _N_WRITTEN; } else { write_begin = lseek(_FD, 0, SEEK_CUR) - _N_WRITTEN; if ( unlikely(write_begin < 0) ){ LOG("Error on L" + decstr(__LINE__) + " lseek-ing on fd" + decstr(_FD) + ": " + strerror(errno) + "\n"); return; } } for(ssize_t i=0; i<_N_WRITTEN; i++) { //loop through memory locations tag_t tag = tagmap_getb(_BUF+i); #ifdef __DEBUG_SYSCALL_WRITE LOG("---------------------- " + std::string((char *)(_BUF+i), 1) + "\n"); LOG("RANGES " + __RANGE2STR(ranges) + "\n"); LOG("RANGES_PREV " + __RANGE2STR(ranges_prev) + "\n"); #endif for (auto & tm : tag) { //loop taint marks for specific location // check if a single taint mark from the input is repeated in the output auto rlookup = tm; auto range_it = ranges_prev.find(rlookup); if (range_it != ranges_prev.end()) { // LOG("C1\n"); auto range_last = (*range_it).first; auto range_info = (*range_it).second; switch(range_info.type) { case range_info_t::SEQ: // adjust SEQ range range_last.second--; range_info.length--; ranges_prev.insert(range_it, std::make_pair(range_last, range_info)); ranges_prev.erase(range_it); // add a new REP range to next range set ranges.insert(std::make_pair(tm, (range_info_t){range_info_t::REP, i-1, 2})); continue; case range_info_t::NONE: // set range type to REP range_info.type = range_info_t::REP; case range_info_t::REP: // add info to next range set range_info.length++; ranges.insert(std::make_pair(tm, range_info)); // remove info from previous range set ranges_prev.erase(range_it); continue; } } // check if a sequence of taint marks from the input also appears in the output rlookup = tm; rlookup.second -= 1; range_it = ranges_prev.find(rlookup); if (range_it != ranges_prev.end()) { // LOG("C2\n"); auto range_info = (*range_it).second; switch(range_info.type) { case range_info_t::REP: // start a new range - we won't touch the old one ranges.insert(std::make_pair(tm, (range_info_t){range_info_t::NONE, i, 1})); continue; case range_info_t::NONE: // set range type to SEQ range_info.type = range_info_t::SEQ; case range_info_t::SEQ: // add info to next range set range_info.length++; ranges.insert(std::make_pair(tm, range_info)); // remove info from previous range set ranges_prev.erase(range_it); continue; } } // add taint mark as a new range // LOG("C3\n"); rlookup = tm; ranges.insert(std::make_pair(rlookup, (range_info_t){range_info_t::NONE, i, 1})); } //loop taint marks #ifdef __DEBUG_SYSCALL_WRITE LOG("~~~~~~~~~~~~~~\n"); LOG("RANGES " + __RANGE2STR(ranges) + "\n"); LOG("RANGES_PREV " + __RANGE2STR(ranges_prev) + "\n"); #endif //dump output for pattern sequences that were broken for (auto &tm : ranges_prev) PROVLOG_WRITE_RANGE(ufd, write_begin, tm.first, tm.second); // swap the two range sets and clear the ranges for next iteration ranges.swap(ranges_prev); ranges.clear(); } //loop memory locations //dump the remaining pattern sequences for (auto &tm : ranges_prev) PROVLOG_WRITE_RANGE(ufd, write_begin, tm.first, tm.second); }
VOID trace_instrument(TRACE trace, VOID *v){ for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)){ /* iterate over all basic blocks */ string codelet_string = ""; // this writes disassembly char codelet_buffer[65536*2]; int cbs = 0; INS head = BBL_InsHead(bbl); INS tail = BBL_InsTail(bbl); ADDRINT stage_entry = INS_Address( head ); ADDRINT target = 0; if (INS_IsCall(tail)){ if( INS_IsDirectBranchOrCall(tail)){ target = INS_DirectBranchOrCallTargetAddress(tail);}} INS cur ; int branch_id = slp_count; /* If compression is turned off (default), only output the addresses of * the BBL once */ if (!KnobNoCompress){ /* Instrument the head instruction right before it is called, but also * before we instrument the instructions in the basic block */ string msg_pre = "\n@@BBL(" + decstr( branch_id ) + ") STAGE " + Target2String(stage_entry)->c_str() + "\n" ; INS_InsertCall(head, IPOINT_BEFORE, AFUNPTR(string_report), IARG_PTR, new string(msg_pre), IARG_END); } /* Walk the list of instructions inside the BBL. Disassemble each, and add * it to the codelet string. Also, instrument each instruction at the * point before it is called with the do_count function. */ for ( cur = head; INS_Valid( cur ); cur = INS_Next(cur ) ){ cbs += sprintf( codelet_buffer + cbs , "\n\t@%llx\t%s", INS_Address( cur ), INS_Disassemble( cur ).c_str() ); INS_InsertCall(cur, IPOINT_BEFORE, (AFUNPTR)do_count, IARG_ADDRINT, INS_Address( cur ), IARG_END); } /* Finish off the codelet assembly string with an out message and * address ranges of the BBL */ cbs += sprintf( codelet_buffer + cbs , "\n\t}BBL.OUT [%d] %llx - %llx\n", branch_id, INS_Address( head ), INS_Address( tail )); /* If compression is turned on, output the codelet every single time we * hit the same block. */ if(KnobNoCompress){ INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(string_report), IARG_PTR, new string(codelet_buffer), IARG_END); slp_count ++; } else{ /* add the mapped BBL to output */ TraceFile.write(codelet_buffer, cbs); /* Instrument the tail instruction by inserting just before it is called */ string msg_post = "+@@BBL(" + decstr( branch_id ) + ") ACHIEVE : GOTO " + Target2String(target)->c_str(); INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(string_report), IARG_PTR, new string(msg_post), IARG_END); slp_count ++; } } }
string nocrypt(u_char* nocipher) { string decstr(reinterpret_cast<const char*>(nocipher)); return decstr; }