VOID check_parameter_out(ADDRINT addr) { trace_enter(); if (call_stack.is_top_forgotten()) { trace_leave(); return; } FID fid = call_stack.top(); UINT64 sp = sp_stack.top(); if (sp + 1000 <= addr && addr < sp) { trace_leave(); return; } unsigned int param_val_size = 1 + nb_param_int[fid] + nb_param_int_stack[fid]; for (unsigned int pid = 1; pid < param_val_size; pid++) { if (param_val[fid][pid]->back() == addr) { nb_out[fid][pid]++; trace_leave(); return; } } trace_leave(); }
VOID fn_ret(CONTEXT *ctxt, UINT32 fid) { trace_enter(); counter += 1; if (!call_stack.is_top_forgotten()) { while (is_jump_stack.top()) { FID fid = call_stack.top(); if (is_instrumented[fid]) { param_t *new_ret = (param_t *) malloc(sizeof(param_t)); new_ret->fid = fid; new_ret->counter = counter; new_ret->val = val_from_reg(ctxt, 0); new_ret->is_addr = param_addr[fid][0]; param_out->push_front(new_ret); } call_stack.pop(); is_jump_stack.pop(); } FID fid = call_stack.top(); if (is_instrumented[fid]) { param_t *new_ret = (param_t *) malloc(sizeof(param_t)); new_ret->fid = fid; new_ret->counter = counter; new_ret->val = val_from_reg(ctxt, 0); new_ret->is_addr = param_addr[fid][0]; param_out->push_front(new_ret); } call_stack.pop(); is_jump_stack.pop(); } trace_leave(); return; }
void syslogd_open_sockets (struct socket *sockets) { struct socket *socket = sockets; #if SYSLOGD_TRACE trace_enter ("syslogd_open_sockets"); #endif do { socket = socket->next; if (socket->desc != -1) { continue; } if (socket->sockaddr == (struct sockaddr *)(0)) { syslogd_error (EINVAL, "Missing socket address"); continue; } #ifdef SYSLOGD_UNIXAF if (socket->sockaddr->sa_family == AF_UNIX) { struct sockaddr_un * sockaddr_un = (struct sockaddr_un *)(socket->sockaddr); syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "Opening host connection on %s", sockaddr_un->sun_path); socket->desc = syslogd_unix_socket (sockaddr_un); continue; } #endif #ifdef SYSLOGD_INETAF if (socket->sockaddr->sa_family == AF_INET) { char buffer [HOSTADDR_MAX]; struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)(socket->sockaddr); getsocketname (buffer, sizeof (buffer), sockaddr_in); syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "Opening inet connection on %s", buffer); socket->desc = syslogd_inet_socket (sockaddr_in); continue; } #endif } while (socket != sockets); #if SYSLOGD_TRACE trace_leave ("syslogd_open_sockets"); #endif return; }
void fn_registered( FID fid, unsigned int nb_param, vector<bool> type_param ) { trace_enter(); /* Set the number of parameters */ nb_p[fid] = nb_param; /* Set the array of booleans indicating which parameter is an ADDR */ param_addr[fid] = (bool *) calloc(nb_p[fid], sizeof(bool)); /* Is this function instrumented?*/ is_instrumented[fid] = false; /* Iteration on parameters */ for (unsigned int i = 0; i <= nb_p[fid]; i++) { if (type_param[i]) { param_addr[fid][i] = true; is_instrumented[fid] = true; } else param_addr[fid][i] = false; } trace_leave(); return; }
void syslogd_print (int priority, char const * format, ...) { extern char const * host_name; extern char const * program_name; char buffer [TEXTLINE_MAX] = "no error message"; size_t length = 0; #if SYSLOGD_TRACE trace_enter ("syslogd_error"); #endif if (program_name != (char const *) (0)) { length += snprintf (buffer + length, sizeof (buffer) - length, "%s: ", program_name); } if ((format != (char const *) (0)) && (* format != (char) (0))) { va_list arglist; va_start (arglist, format); length += vsnprintf (buffer + length, sizeof (buffer) - length, format, arglist); va_end (arglist); } syslogd_queue (priority, host_name, buffer); #if SYSLOGD_TRACE trace_leave ("syslogd_error"); #endif return; }
/* Instrumentation of each instruction * that uses a memory operand */ VOID Instruction(INS ins, VOID *v) { trace_enter(); if (!INS_IsStackRead(ins)) { for (UINT32 memopIdx = 0; memopIdx < INS_MemoryOperandCount(ins); memopIdx++) { if (INS_MemoryOperandIsWritten(ins, memopIdx)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) update_stack_heap_region, IARG_CONST_CONTEXT, IARG_MEMORYOP_EA, memopIdx, IARG_END); UINT32 opIdx = INS_MemoryOperandIndexToOperandIndex(ins, memopIdx); REG base_reg = INS_OperandMemoryBaseReg(ins, opIdx); if (base_reg != REG_INVALID()) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) check_parameter_out, IARG_REG_VALUE, base_reg, IARG_END); } } } } if (INS_IsCall(ins)) { if (INS_IsDirectCall(ins)) { ADDRINT addr = INS_DirectBranchOrCallTargetAddress(ins); FID fid = fn_lookup_by_address(addr); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_call, IARG_CONST_CONTEXT, IARG_UINT32, fid, IARG_END); } else { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_indirect_call, IARG_CONST_CONTEXT, IARG_BRANCH_TARGET_ADDR, IARG_END); } } if (INS_IsRet(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_ret, IARG_CONST_CONTEXT, IARG_END); } trace_leave(); }
VOID update_stack_heap_region(CONTEXT* ctxt, ADDRINT addr) { trace_enter(); if (!is_addr(addr)) { stack_heap_region.extend(addr); } trace_leave(); }
VOID fn_call(CONTEXT *ctxt, FID fid, bool is_jump) { trace_enter(); call_stack.push(fid); is_jump_stack.push(is_jump); counter += 1; bool param_pushed = false; if (!is_instrumented[fid]) { trace_leave(); return; } for (unsigned int i = 1; i <= nb_p[fid]; i++) { if (!param_addr[fid][i]) continue; param_t *new_param = (param_t *) malloc(sizeof(param_t)); new_param->fid = fid; new_param->counter = counter; new_param->val = val_from_reg(ctxt, i); new_param->is_addr = param_addr[fid][i]; new_param->pos = i; param_in->push_front(new_param); param_pushed = true; } /* If the function is instrumented (ie for instance has an ADDR as a return value) AND was not logged yet, create a special entry to log the date of call */ if (!param_pushed) { param_t *new_addr = (param_t *) malloc(sizeof(param_t)); new_addr->fid = fid; new_addr->counter = counter; new_addr->val = 0; // val_from_reg(ctxt, i); new_addr->pos = 0; new_addr->is_addr = false; // true; param_in->push_front(new_addr); } trace_leave(); return; }
VOID Fini(INT32 code, VOID *v) { trace_enter(); list<param_t *>::reverse_iterator it_in, it_out; it_in = param_in->rbegin(); it_out = param_out->rbegin(); int depth = 0; UINT64 last_date = -1; bool is_in = false; gettimeofday(&stop, NULL); ofile << "Elapsed time ] Commence ; Fini [ : " << (stop.tv_usec / 1000.0 + 1000 * stop.tv_sec - start.tv_sec * 1000 - start.tv_usec / 1000.0) / 1000.0 << "s" << endl; while (it_in != param_in->rend() || it_out != param_out->rend()) { // for (int i = 0; i < depth; i++) // ofile << " "; param_t *p; if (it_in == param_in->rend()) { p = *it_out; it_out++; is_in = false; ofile << "out:"; } else if (it_out == param_out->rend() || (*it_out)->counter >= (*it_in)->counter) { p = *it_in; it_in++; is_in = true; ofile << "in:"; } else { p = *it_out; it_out++; is_in = false; ofile << "out:"; } if (p->is_addr) ofile << "addr:"; else ofile << "int:"; if (last_date != p->counter) { if (is_in) depth++; else depth--; } last_date = p->counter; ofile << p->val << ":" << fn_img(p->fid) << ":" << fn_imgaddr(p->fid) << ":" << fn_name(p->fid) << ":" << p->pos << ":" << p->counter << endl; } ofile.close(); trace_leave(); return; }
VOID Commence() { trace_enter(); /* Init instruction counter */ counter = 0; init = true; string _addr, _name; if (ifile.is_open()) { while (ifile) { char m; unsigned int nb_param = 0; vector<bool> type_param; string img_name = read_part(&m); if (img_name.empty()) { continue; } ADDRINT img_addr = atol(read_part(&m).c_str()); string name = read_part(&m); /* Read parameters */ while (ifile && m != '\n') { string part = read_part(&m); switch (part[0]) { case 'A': type_param.push_back(true); break; case 'I': case 'V': type_param.push_back(false); break; case 'F': type_param.push_back(false); break; default: type_param.push_back(false); } nb_param += 1; } FID fid = fn_register(img_name, img_addr, name); if (fid != FID_UNKNOWN) { fn_registered(fid, nb_param - 1, type_param); } } } gettimeofday(&start, NULL); trace_leave(); return; }
VOID fn_icall(CONTEXT* ctxt, ADDRINT target, bool is_jump) { trace_enter(); // Indirect call, we have to look up the function each time // The functions `fn_lookup` & `fn_register` needs PIN's Lock. // Locking is not implicit in inserted call, as opposed // to callback added with *_AddInstrumentFunction(). PIN_LockClient(); FID fid = fn_lookup_by_address(target); if (is_jump && fid == FID_UNKNOWN) { trace_leave(); return; } PIN_UnlockClient(); fn_call(ctxt, fid, is_jump); trace_leave(); return; }
VOID image_loaded(IMG img, void* data) { trace_enter(); for (int i = 0; i < IMG_NumRegions(img); i++) { Region* region = data_regions + data_regions_size; data_regions_size++; region->low = IMG_RegionLowAddress(img, i); region->high = IMG_RegionHighAddress(img, i); } trace_leave(); }
void syslogd_stop (struct syslogd * syslogs, flag_t flags) { extern char const * program_name; struct syslogd * syslog; #if SYSLOGD_TRACE trace_enter ("syslogd_stop"); #endif syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "%s %s.%s stopped", program_name, VERSION, RELEASE); while (syslogs->next != syslogs) { syslog = syslogs->next; syslog->next->prev = syslogs; syslogs->next = syslog->next; if (syslog->f_repeat > 0) { syslogd_write (syslog, flags); } if (syslog->f_sockaddr_in != (struct sockaddr_in *) (0)) { free (syslog->f_sockaddr_in); syslog->f_sockaddr_in = (struct sockaddr_in *) (0); } switch (syslog->f_type) { case SYSLOGD_TYPE_HOST: case SYSLOGD_TYPE_FILE: case SYSLOGD_TYPE_PIPE: case SYSLOGD_TYPE_TERM: case SYSLOGD_TYPE_CONSOLE: close (syslog->f_desc); break; } syslog->prev = (struct syslogd *) (0); syslog->next = (struct syslogd *) (0); free (syslog->f_name); free (syslog); } #if SYSLOGD_TRACE trace_leave ("syslogd_stop"); #endif return; }
ADDRINT val_from_reg(CONTEXT *ctxt, unsigned int pid) { trace_enter(); REG reg; switch (pid) { case 0: reg = REG_RAX; break; case 1: reg = REG_RDI; break; case 2: reg = REG_RSI; break; case 3: reg = REG_RDX; break; case 4: reg = REG_RCX; break; case 5: reg = REG_R8; break; case 6: reg = REG_R9; break; default: trace_leave(); return 0; } trace_leave(); return PIN_GetContextReg(ctxt, reg); }
VOID add_val(unsigned int fid, CONTEXT *ctxt, unsigned int pid, UINT64 sp) { trace_enter(); if (param_val[fid][pid]->size() >= MAX_VALS_TO_COLLECT) { trace_leave(); return; } UINT64 val; if (pid < 1 + nb_param_int[fid]) { PIN_GetContextRegval(ctxt, param_reg(pid), (UINT8*) &val); } else { unsigned int sp_offset = pid - (1 + nb_param_int[fid]); UINT64* addr = (UINT64*) (sp + sp_offset * 8); val = *addr; } if (val != 0) param_val[fid][pid]->push_front(val); trace_leave(); }
VOID fn_ret(CONTEXT *ctxt) { trace_enter(); if (!call_stack.is_top_forgotten()) { FID fid = call_stack.top(); if (has_return[fid] == 1) { add_val(fid, ctxt, 0, 0); } } call_stack.pop(); sp_stack.pop(); trace_leave(); }
void syslogd_configure (struct syslogd * syslogs, flag_t flags, char const * filename) { file_t fd; char string [TEXTLINE_MAX]; size_t lineno = 0; #if SYSLOGD_TRACE trace_enter ("syslogd_configure"); #endif if ((fd = open (filename, O_RDONLY)) == - 1) { syslogd_error (errno, "cant open %s", filename); return; } while (statement (fd, string, sizeof (string), & lineno)) { if (* string != (char) (0)) { struct syslogd * syslog = NEW (struct syslogd); syslogd_parse (syslog, flags, string); if (syslog->f_type == SYSLOGD_TYPE_NONE) { free (syslog->f_name); free (syslog); continue; } syslog->prev = syslogs->prev; syslogs->prev->next = syslog; syslogs->prev = syslog; syslog->next = syslogs; } } close (fd); #if SYSLOGD_TRACE trace_leave ("syslogd_configure"); #endif return; }
VOID fn_call(CONTEXT *ctxt, FID fid) { trace_enter(); call_stack.push(fid); UINT64 sp; PIN_GetContextRegval(ctxt, REG_RSP, (UINT8*) &sp); sp_stack.push(sp); nb_call[fid]++; unsigned int param_val_size = 1 + nb_param_int[fid] + nb_param_int_stack[fid]; for (unsigned int pid = 1; pid < param_val_size; pid++) { if (!param_is_not_addr[fid][pid]) add_val(fid, ctxt, pid, sp); } trace_leave(); }
void syslogd_admin (struct syslogd * syslogs, flag_t flags, char const * filename) { FILE * fp; struct syslogd * syslog; #if SYSLOGD_TRACE trace_enter ("syslogd_admin"); #endif if ((filename == (char *) (0)) || (* filename == (char) (0))) { return; } if ((fp = fopen (filename, "w")) == (FILE *) (0)) { syslogd_error (errno, "can't open %s", filename); return; } syslogd_enumerate (syslogs, flags, fp); for (syslog = syslogs->next; syslog != syslogs; syslog = syslog->next) { syslogd_state (syslog, flags, fp); } syslogd_state (syslog, flags, fp); fclose (fp); #if SYSLOGD_TRACE trace_leave ("syslogd_admin"); #endif return; }
void syslogd_start (struct syslogd * syslogs, flag_t flags, char const * filename) { extern char const * program_name; char buffer [TEXTLINE_MAX]; size_t lineno = 0; file_t fd; #if SYSLOGD_TRACE trace_enter ("syslogd_start"); #endif if ((fd = open (filename, O_RDONLY)) == - 1) { syslogd_error (errno, "Can't open %s", filename); return; } while (statement (fd, buffer, sizeof (buffer), & lineno)) { struct syslogd * syslog = NEW (struct syslogd); memset (syslog, 0, sizeof (struct syslogd)); syslog->f_type = SYSLOGD_TYPE_NONE; syslog->f_name = ""; syslog->f_line = lineno; syslog->f_desc = - 1; syslog->f_time = time ((time_t *) (0)); syslogd_parse (syslog, flags, buffer); syslogd_ready (syslog, flags); if (syslog->f_type == SYSLOGD_TYPE_NONE) { free (syslog->f_name); free (syslog); continue; } syslog->prev = syslogs->prev; syslogs->prev->next = syslog; syslogs->prev = syslog; syslog->next = syslogs; for (syslog = syslogs->next; syslog != syslogs->prev; syslog = syslog->next) { if (!strcmp (syslog->f_name, syslogs->prev->f_name)) { syslogd_print (SYSLOG_SYSLOG | SYSLOG_WARNING, "New %s selections on line %d replace old ones on line %d", syslogs->prev->f_name, syslogs->prev->f_line, syslog->f_line); syslog->next->prev = syslog->prev; syslog->prev->next = syslog->next; syslog->prev = (struct syslogd *) (0); syslog->next = (struct syslogd *) (0); free (syslog->f_name); free (syslog); break; } } } close (fd); syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "%s %s.%s started", program_name, VERSION, RELEASE); syslogd_print (SYSLOG_SYSLOG | SYSLOG_INFO, "Configured with %s", filename); #if SYSLOGD_TRACE trace_leave ("syslogd_start"); #endif return; }
VOID Fini(INT32 code, VOID *v) { trace_enter(); #define append_type(type) \ if (need_comma) \ ofile << "," ; \ ofile << (type); \ need_comma = true for(unsigned int fid = 1; fid <= fn_nb(); fid++) { if (nb_call[fid] < NB_CALLS_TO_CONCLUDE) continue; ofile << fn_img(fid) << ":" << fn_imgaddr(fid) << ":" << fn_name(fid) << ":"; bool need_comma = false; unsigned int param_val_size = 1 + nb_param_int[fid] + nb_param_int_stack[fid]; for (unsigned int pid = 0; pid < param_val_size; pid++) { if (((float) nb_out[fid][pid]) > 0.75 * ((float) nb_call[fid])) { debug("Found 'out parameter' candidate : [%s@%lX] %s %u (%u <=> %u)\n", fn_img(fid).c_str(), fn_imgaddr(fid), fn_name(fid).c_str(), pid, nb_out[fid][pid], nb_call[fid]); } if (pid == 0 && has_return[fid] == 0) { append_type("VOID"); } else if (pid == 0 && has_return[fid] == 2) { append_type("FLOAT"); } else if (pid < 1 + nb_param_int[fid] && param_is_not_addr[fid][pid]) { append_type("INT"); } else if (param_val[fid][pid]->size() == 0) { append_type("UNDEF"); } else { int param_addr = 0; for (list<UINT64>::iterator it = param_val[fid][pid]->begin(); it != param_val[fid][pid]->end(); it++) { if (is_addr(*it)) { param_addr++; } } float coef = ((float) param_addr) / ((float) param_val[fid][pid]->size()); append_type(coef > THRESHOLD ? "ADDR" : "INT"); ofile << "(" << coef << ")"; } } for (unsigned int pid = 0; pid < nb_param_float[fid] + nb_param_float_stack[fid]; pid++) { append_type("FLOAT"); } ofile << endl; } ofile.close(); trace_leave(); }
VOID Fini(INT32 code, VOID *v) { trace_enter(); list<param_t *>::reverse_iterator it_in, it_out; it_in = param_in->rbegin(); it_out = param_out->rbegin(); int depth = 0; UINT64 last_date = -1; bool is_in = false; gettimeofday(&stop, NULL); ofile << "Elapsed time ] Commence ; Fini [ : " << (stop.tv_usec / 1000.0 + 1000 * stop.tv_sec - start.tv_sec * 1000 - start.tv_usec / 1000.0) / 1000.0 << "s" << endl; while (it_in != param_in->rend() || it_out != param_out->rend()) { param_t *p; if (it_in == param_in->rend()) { p = *it_out; it_out++; is_in = false; } else if (it_out == param_out->rend() || (*it_out)->counter >= (*it_in)->counter) { p = *it_in; it_in++; is_in = true; } else { p = *it_out; it_out++; is_in = false; } #if 0 if (p->is_addr) ofile << "a:"; else ofile << "n:"; #endif if (last_date != p->counter) { if (is_in) depth++; else depth--; } last_date = p->counter; char head = 0x00; /* Construct the first byte */ /* First two bits are for i/o and addr/not addr */ head |= 0x80 & ((is_in?1:0) << 7); head |= 0x40 & ((p->is_addr?1:0) << 6); /* Then we encode the position of the parameter */ head |= 0x3F & p->pos; if (!pushed_in_log[p->fid]) { ofile << '\xff' << p->fid << ":" << fn_img(p->fid) << ":" << fn_imgaddr(p->fid) << ":" << fn_name(p->fid) << endl; pushed_in_log[p->fid] = true; } ofile << head; ofile << p->fid << ":" << p->counter << ":" << p->val << endl; #if 0 ofile << p->val << ":" << fn_img(p->fid) << ":" << fn_imgaddr(p->fid) << ":" << fn_name(p->fid) << ":" << p->pos << ":" << p->counter << endl; #endif } ofile.close(); trace_leave(); return; }