// typedef void (*on_NtOpenFile_return_t)(CPUState *cpu,target_ulong pc,uint32_t FileHandle,uint32_t DesiredAccess,uint32_t ObjectAttributes,uint32_t IoStatusBlock,uint32_t ShareAccess,uint32_t OpenOptions); void windows_open_return(CPUState *cpu, target_ulong pc, uint32_t FileHandle, uint32_t DesiredAccess, uint32_t ObjectAttributes, uint32_t IoStatusBlock, uint32_t ShareAccess, uint32_t OpenOptions) { uint32_t Handle; panda_virtual_memory_rw(cpu, FileHandle, (uint8_t *)&Handle, 4, 0); if (debug) printf ("asid=0x%x filehandle=%d filename=[%s]\n", (uint)panda_current_asid(cpu), FileHandle, the_windows_filename.c_str()); windows_filenames[panda_current_asid(cpu)][FileHandle] = the_windows_filename; open_return(cpu, Handle); }
void open_return(CPUState* env,target_ulong pc,target_ulong filename,int32_t flags,int32_t mode) { // printf ("returning from open\n"); if (saw_open && the_asid == panda_current_asid(env)) { saw_open = false; // get return value, which is the file descriptor for this file the_asid = panda_current_asid(env); the_fd = EAX; printf ("saw return from open of [%s]: asid=0x%x fd=%d\n", taint_filename, the_asid, the_fd); } }
static stackid get_stackid(CPUArchState* env) { #ifdef USE_STACK_HEURISTIC target_ulong asid; // Track all kernel-mode stacks together if (in_kernelspace(env)) asid = 0; else asid = panda_current_asid(ENV_GET_CPU(env)); // Invalidate cached stack pointer on ASID change if (cached_asid == 0 || cached_asid != asid) { cached_sp = 0; cached_asid = asid; } target_ulong sp = get_stack_pointer(env); // We can short-circuit the search in most cases if (std::abs(sp - cached_sp) < MAX_STACK_DIFF) { return std::make_pair(asid, cached_sp); } auto &stackset = stacks_seen[asid]; if (stackset.empty()) { stackset.insert(sp); cached_sp = sp; return std::make_pair(asid,sp); } else { // Find the closest stack pointer we've seen auto lb = std::lower_bound(stackset.begin(), stackset.end(), sp); target_ulong stack1 = *lb; lb--; target_ulong stack2 = *lb; target_ulong stack = (std::abs(stack1 - sp) < std::abs(stack2 - sp)) ? stack1 : stack2; int diff = std::abs(stack-sp); if (diff < MAX_STACK_DIFF) { return std::make_pair(asid,stack); } else { stackset.insert(sp); cached_sp = sp; return std::make_pair(asid,sp); } } #else return panda_current_asid(ENV_GET_CPU(env)); #endif }
// get current process before each bb execs // which will probably help us actually know the current process int osi_foo(CPUState *env, TranslationBlock *tb) { if (panda_in_kernel(env)) { OsiProc *p = get_current_process(env); //some sanity checks on what we think the current process is // this means we didnt find current task if (p->offset == 0) return 0; // or the name if (p->name == 0) return 0; // this is just not ok if (((int) p->pid) == -1) return 0; uint32_t n = strnlen(p->name, 32); // name is one char? if (n<2) return 0; uint32_t np = 0; for (uint32_t i=0; i<n; i++) { np += (isprint(p->name[i]) != 0); } // name doesnt consist of solely printable characters // printf ("np=%d n=%d\n", np, n); if (np != n) return 0; target_ulong asid = panda_current_asid(env); if (running_procs.count(asid) == 0) { printf ("adding asid=0x%x to running procs. cmd=[%s] task=0x%x\n", (unsigned int) asid, p->name, (unsigned int) p->offset); } running_procs[asid] = *p; } return 0; }
void get_prog_point(CPUState* cpu, prog_point *p) { CPUArchState* env = (CPUArchState*)cpu->env_ptr; if (!p) return; // Get address space identifier target_ulong asid = panda_current_asid(ENV_GET_CPU(env)); // Lump all kernel-mode CR3s together if(!in_kernelspace(env)) p->cr3 = asid; // Try to get the caller int n_callers = 0; n_callers = get_callers(&p->caller, 1, cpu); if (n_callers == 0) { #ifdef TARGET_I386 // fall back to EBP on x86 int word_size = (env->hflags & HF_LMA_MASK) ? 8 : 4; panda_virtual_memory_rw(cpu, env->regs[R_EBP]+word_size, (uint8_t *)&p->caller, word_size, 0); #endif #ifdef TARGET_ARM p->caller = env->regs[14]; // LR #endif } p->pc = cpu->panda_guest_pc; }
// get current process before each bb executes // which will probably help us actually know the current process int osi_foo(CPUState *cpu, TranslationBlock *tb) { if (panda_in_kernel(cpu)) { OsiProc *p = get_current_process(cpu); //some sanity checks on what we think the current process is // this means we didnt find current task if (p->offset == 0) return 0; // or the name if (p->name == 0) return 0; // weird -- this is just not ok if (((int) p->pid) == -1) return 0; uint32_t n = strnlen(p->name, 32); // yuck -- name is one char if (n<2) return 0; uint32_t np = 0; for (uint32_t i=0; i<n; i++) { np += (isprint(p->name[i]) != 0); } // yuck -- name doesnt consist of solely printable characters if (np != n) return 0; target_ulong asid = panda_current_asid(cpu); if (running_procs.count(asid) == 0) { if (debug) printf ("adding asid=0x%x to running procs. cmd=[%s] task=0x%x\n", (unsigned int) asid, p->name, (unsigned int) p->offset); } if (running_procs.count(asid) != 0) { /* OsiProc *p2 = running_procs[asid]; // something there already if (p2) free_osiproc(p2); */ } running_procs[asid] = *p; } return 0; }
void linux_mmap_pgoff_return(CPUState *cpu,target_ulong pc,uint32_t addr,uint32_t len,uint32_t prot,uint32_t flags,uint32_t fd,uint32_t pgoff) { CPUArchState *env = (CPUArchState*)cpu->env_ptr; target_ulong asid = panda_current_asid(cpu); if (running_procs.count(asid) == 0) { //printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d -- dont know about that asid. discarding \n", (unsigned int) asid, (int) fd); return; } if ((int32_t) fd == -1){ //printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d flags=%x -- not valid fd . . . \n", (unsigned int) asid, (int) fd, flags); return; } OsiProc proc = running_procs[asid]; char *filename = osi_linux_fd_to_filename(cpu, &proc, fd); // gets us offset into the file. could be useful //uint64_t pos = osi_linux_fd_to_pos(env, &proc, fd); // if a filename exists and permission is executable // TODO: fix this magic constant of 0x04 for PROT_EXEC if (filename != NULL && ((prot & 0x04) == 0x04)) { if (debug) { printf ("[loaded] linux_mmap_pgoff(fd=%d filename=[%s] " "len=%d prot=%x flags=%x " "pgoff=%d)=" TARGET_FMT_lx "\n", (int) fd, filename, len, prot, flags, pgoff, env->regs[R_EAX]); } PPP_RUN_CB(on_library_load, cpu, pc, filename, env->regs[R_EAX], len) } else if ((prot & 0x04) == 0x04) {
void linux_pread_enter(CPUState *cpu, target_ulong pc, uint32_t fd, uint32_t buf, uint32_t count, uint64_t pos) { target_ulong asid = panda_current_asid(cpu); if (running_procs.count(asid) == 0) { if (debug) printf ("linux_read_enter for asid=0x%x fd=%d -- dont know about that asid. discarding \n", (unsigned int) asid, (int) fd); return; } char *filename; if (taint_stdin) { filename = stdin_filename; pos = 0; } else { OsiProc& proc = running_procs[asid]; filename = osi_linux_fd_to_filename(cpu, &proc, fd); if (pos == (uint64_t)-1) { pos = osi_linux_fd_to_pos(cpu, &proc, fd); } if (filename==NULL) { if (debug) printf ("linux_read_enter for asid=0x%x pid=%d cmd=[%s] fd=%d -- that asid is known but resolving fd failed. discarding\n", (unsigned int) asid, (int) proc.pid, proc.name, (int) fd); return; } if (debug) printf ("linux_read_enter for asid==0x%x fd=%d filename=[%s] count=%d pos=%u\n", (unsigned int) asid, (int) fd, filename, count, (unsigned int) pos); } read_enter(cpu, pc, filename, pos, buf, count); }
// 3 long sys_read(unsigned int fd, char __user *buf, size_t count); // typedef void (*on_sys_read_return_t)(CPUState *cpu,target_ulong pc,uint32_t fd,target_ulong buf,uint32_t count); void read_return(CPUState *cpu, target_ulong pc, uint32_t buf, uint32_t actual_count) { if (saw_read && panda_current_asid(cpu) == the_asid) { // These are the start and end of the current range of labels. uint32_t read_start = last_pos; uint32_t read_end = last_pos + actual_count; if (debug) printf ("returning from read of [%s] count=%u\n", taint_filename, actual_count); // check if we overlap the range we want to label. if (read_start < end_label && read_end > start_label) { uint32_t range_start = std::max(read_start, start_label); uint32_t range_end = std::min(read_end, end_label); printf("*** applying %s taint labels %u..%u to buffer @ %lu\n", positional_labels ? "positional" : "uniform", range_start, range_end - 1, rr_get_guest_instr_count()); uint32_t num_labeled = 0; uint32_t i = 0; for (uint32_t l = range_start; l < range_end; l++) { if (label_byte(cpu, last_read_buf + i, positional_labels ? l : 1)) num_labeled ++; i ++; } printf("%u bytes labeled for this read\n", range_end - range_start); } last_pos += actual_count; // printf (" ... done applying labels\n"); saw_read = false; } }
void read_enter(CPUState *cpu, target_ulong pc, std::string filename, uint64_t pos, uint32_t buf, uint32_t count) { // these things are only known at enter of read call the_asid = panda_current_asid(cpu); last_read_buf = buf; last_pos = pos; saw_read = false; if (debug) printf ("read_enter filename=[%s]\n", filename.c_str()); std::string read_filename = taint_stdin ? "stdin" : taint_filename; auto it = running_procs.find(the_asid); if (taint_stdin) { if (it == running_procs.end()) { if (debug) printf("read_enter unknown proc.\n"); return; } std::string proc_name = it->second.name; if (proc_name.find(taint_stdin) == std::string::npos) { if (debug) printf("read_enter wrong proc %s.\n", proc_name.c_str()); return; } } if (filename.find(read_filename) != std::string::npos) { if (debug) printf ("read_enter: asid=0x%x saw read of %d bytes in file we want to taint\n", the_asid, count); saw_read = true; } }
void read_enter(CPUState* env,target_ulong pc,uint32_t fd,target_ulong buf,uint32_t count) { uint32_t asid = panda_current_asid(env); char *filename = 0; if (asidfd_to_filename.count(std::make_pair(asid, fd)) != 0) { filename = asidfd_to_filename[std::make_pair(asid, fd)]; } if (filename !=0) { printf ("filename = [%s]\n", filename); } /* else { printf ("filename is not known\n"); } */ // these things are only known at enter of read call last_read_fd = fd; last_read_count = count; last_read_buf = buf; if (asid == the_asid && fd == the_fd) { printf ("saw read of %d bytes in file we want to taint\n", count); saw_read = true; } }
void read_enter(CPUState* env,target_ulong pc,uint32_t fd,target_ulong buf,uint32_t count) { if (panda_current_asid(env) == the_asid && fd == the_fd) { the_buf = buf; the_count = count; printf ("saw read of [%s] %d bytes\n", taint_filename, count); saw_read = true; } }
void open_return(CPUState *cpu, uint32_t fd) { // printf ("returning from open\n"); if (saw_open && the_asid == panda_current_asid(cpu)) { saw_open = false; // get return value, which is the file descriptor for this file the_fd = fd; // printf ("saw return from open of [%s]: asid=0x%x fd=%d\n", taint_filename, the_asid, the_fd); } }
void open_enter(CPUState *cpu, target_ulong pc, std::string filename, int32_t flags, int32_t mode) { if (!filename.empty()) { if (debug) printf ("open_enter: saw open of [%s]\n", filename.c_str()); } if (filename.find(taint_filename) != std::string::npos) { saw_open = true; printf ("saw open of file we want to taint: [%s] insn %" PRId64 "\n", taint_filename, rr_get_guest_instr_count()); the_asid = panda_current_asid(cpu); if (enable_taint_on_open && !no_taint && !taint2_enabled()) { uint64_t ins = rr_get_guest_instr_count(); taint2_enable_taint(); if (debug) printf ("file_taint: enabled taint2 @ ins %" PRId64 "\n", ins); } } }
// 3 long sys_read(unsigned int fd, char __user *buf, size_t count); // typedef void (*on_sys_read_return_t)(CPUState* env,target_ulong pc,uint32_t fd,target_ulong buf,uint32_t count); void read_return(CPUState* env,target_ulong pc,uint32_t fd,target_ulong buf,uint32_t count) { if (saw_read && panda_current_asid(env) == the_asid) { count = EAX; printf ("count=%d\n", count); printf ("returning from read of [%s] count=%d\n", taint_filename, count); printf ("*** applying %s taint labels %d..%d to buffer\n", positional_labels ? "positional" : "uniform", taint_label_number_start, taint_label_number_start + count - 1); for (uint32_t i=0; i<count; i++ ) { target_phys_addr_t pa = panda_virt_to_phys(env, the_buf+i); if (pandalog) { Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT; ple.has_taint_label_virtual_addr = 1; ple.has_taint_label_physical_addr = 1; ple.has_taint_label_number = 1; ple.taint_label_virtual_addr = the_buf + i; ple.taint_label_physical_addr = pa; if (positional_labels) { ple.taint_label_number = taint_label_number_start + i; } else { ple.taint_label_number = 1; } pandalog_write_entry(&ple); } if (!no_taint) { if (positional_labels) { if (use_taint2) taint2_label_ram(pa, taint_label_number_start + i); else taint_label_ram(pa, i); } else { if (use_taint2) taint2_label_ram(pa, 1); else taint_label_ram(pa, 1); } } } taint_label_number_start += count; printf (" ... done applying labels\n"); saw_read = false; } }
void tbranch_on_branch_taint2(Addr a, uint64_t size) { if (pandalog) { // a is an llvm reg assert (a.typ == LADDR); // count number of tainted bytes on this reg // NB: assuming 8 bytes uint32_t num_tainted = 0; for (uint32_t o=0; o<size; o++) { Addr ao =a; ao.off = o; num_tainted += (taint2_query(ao) != 0); } if (num_tainted > 0) { if (summary) { CPUState *cpu = first_cpu; target_ulong asid = panda_current_asid(cpu); tainted_branch[asid].insert(panda_current_pc(cpu)); } else { Panda__TaintedBranch *tb = (Panda__TaintedBranch *) malloc(sizeof(Panda__TaintedBranch)); *tb = PANDA__TAINTED_BRANCH__INIT; tb->call_stack = pandalog_callstack_create(); tb->n_taint_query = num_tainted; tb->taint_query = (Panda__TaintQuery **) malloc (sizeof (Panda__TaintQuery *) * num_tainted); uint32_t i=0; for (uint32_t o=0; o<size; o++) { Addr ao = a; ao.off = o; if (taint2_query(ao)) { tb->taint_query[i++] = taint2_query_pandalog(ao, o); } } Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT; ple.tainted_branch = tb; pandalog_write_entry(&ple); pandalog_callstack_free(tb->call_stack); for (uint32_t i=0; i<num_tainted; i++) { pandalog_taint_query_free(tb->taint_query[i]); } free(tb); } } } }
// Derive taint ops int before_block_exec(CPUState *env, TranslationBlock *tb){ shadow->asid = panda_current_asid(env); //printf("%s\n", tcg_llvm_get_func_name(tb)); if (taintEnabled){ // process taint ops in io thread taint op buffer // NB: we don't need a dynval buffer here. tob_process(tob_io_thread, shadow, NULL); tob_clear(tob_io_thread); taintfpm->run(*(tb->llvm_function)); DynValBuffer *dynval_buffer = PIFP->PIV->getDynvalBuffer(); clear_dynval_buffer(dynval_buffer); } return 0; }
void taint_change(Addr a) { if (taint2_query(a)) { extern CPUState *cpu_single_env; CPUState *env = cpu_single_env; target_ulong asid = panda_current_asid(env); if (asid != last_asid) { Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT; ple.has_asid = 1; ple.asid = asid; pandalog_write_entry(&ple); last_asid = asid; } Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT; ple.tainted_instr = true; pandalog_write_entry(&ple); taint2_query_pandalog(a,0); callstack_pandalog(); } }
// 3 long sys_read(unsigned int fd, char __user *buf, size_t count); // typedef void (*on_sys_read_return_t)(CPUState* env,target_ulong pc,uint32_t fd,target_ulong buf,uint32_t count); void read_return(CPUState* env,target_ulong pc,uint32_t fd,target_ulong buf,uint32_t count) { if (saw_read && panda_current_asid(env) == the_asid) { count = EAX; // These are the start and end of the current range of labels. uint32_t read_start = file_pos; uint32_t read_end = file_pos + count; printf ("returning from read of [%s] count=%u\n", taint_filename, count); // check if we overlap the range we want to label. if (prob_label_u32 < 1e-9 && read_start < end_label && read_end > start_label) { uint32_t range_start = std::max(read_start, start_label); uint32_t range_end = std::min(read_end, end_label); printf("*** applying %s taint labels %u..%u to buffer\n", positional_labels ? "positional" : "uniform", range_start, range_end - 1); for (uint32_t i = range_start; i < range_end; i++) { label_byte(env, last_read_buf + i, positional_labels ? i : 0); } printf("%u bytes labeled for this read\n", range_end - range_start); } else { // iterate over uint32 blobs for (uint32_t i=0; i<count/4; i++) { if (pdice(prob_label_u32)) { uint32_t label_num = read_start + i*4; printf ("labeling uint32 %d..%d\n", i*4, i*4+3); // we will label this uint32 for (uint32_t j=0; j<4; j++) { uint32_t offset = i*4 + j; label_byte(env, last_read_buf + offset, label_num); } } } } file_pos += count; // printf (" ... done applying labels\n"); saw_read = false; } }
int before_block_exec(CPUState *env, TranslationBlock *tb){ if (tubtf_on) { char *llvm_fn_name = (char *) tcg_llvm_get_func_name(tb); uint32_t pc, unk; sscanf(llvm_fn_name, "tcg-llvm-tb-%d-%x", &unk, &pc); env->panda_guest_pc = pc; tubtf_write_el_64(panda_current_asid(env), pc, TUBTFE_LLVM_FN, unk, 0, 0, 0); } else { fprintf(funclog, "%s\n", tcg_llvm_get_func_name(tb)); DynValBuffer *dynval_buffer = PIFP->PIV->getDynvalBuffer(); if (dynval_buffer->cur_size > 0){ // Buffer wasn't flushed before, have to flush it now fwrite(dynval_buffer->start, dynval_buffer->cur_size, 1, memlog); } clear_dynval_buffer(dynval_buffer); } return 0; }
int coverage_before_block_exec(CPUState *env, TranslationBlock *tb) { #ifdef CONFIG_SOFTMMU OsiProc *p = get_current_process(env); uint64_t asid = panda_current_asid(env); if (process_asid == 0) { // look for process matching the one we want if (p && p->name) { if (strcmp(process_name, p->name) == 0) { process_asid = asid; printf ("coverage plugin: saw cr3=0x%" PRIx64 " for process=[%s]\n", asid, process_name); } } } if (process_asid !=0 && process_asid == asid) { // collect bb for this asid process_bb.insert(tb->pc); // and count number of bb executed (regardless of repetetion) process_total_bb ++; } free_osiproc(p); #endif return 0; }
void open_enter(CPUState* env,target_ulong pc,target_ulong filename,int32_t flags,int32_t mode) { uint32_t i; char the_filename[MAX_FILENAME]; the_filename[0] = 0; for (i=0; i<MAX_FILENAME; i++) { uint8_t c; panda_virtual_memory_rw(env, filename+i, &c, 1, 0); the_filename[i] = c; if (c==0) { break; } } the_filename[MAX_FILENAME-1] = 0; if (i != 0 ) { printf ("saw open of [%s]\n", the_filename); } if (i == strlen(taint_filename)) { if (strncmp(the_filename, taint_filename, strlen(the_filename)) == 0) { saw_open = true; printf ("saw open of file we want to taint: [%s]\n", taint_filename); the_asid = panda_current_asid(env); } } }
void write_dynval_buffer(DynValBuffer *dynval_buf, DynValEntry *entry){ if (tubtf_on) { // XXX Fixme: note that when using tubt format, we still create that DynValBuffer. Waste of memory uint64_t cr3, pc, typ; uint64_t arg1, arg2, arg3, arg4; arg1 = arg2 = arg3 = arg4 = 0; assert (tubtf->colw == TUBTF_COLW_64); uint32_t element_size = tubtf_element_size(); // assert that there must be enough room in dynval buffer uint32_t bytes_used = dynval_buf->ptr - dynval_buf->start; uint32_t bytes_left = dynval_buf->max_size - bytes_used; assert (bytes_left > element_size); cr3 = panda_current_asid(env); // virtual address space -- cr3 for x86 pc = panda_current_pc(env); typ = 0; switch (entry->entrytype) { case ADDRENTRY: { LogOp op = entry->entry.memaccess.op; assert (op == LOAD ||op == STORE); Addr *a = &(entry->entry.memaccess.addr); typ = TUBTFE_LLVM_DV_LOAD; if (op == STORE) { typ = TUBTFE_LLVM_DV_STORE; } // a->type fits easily in a byte -- 1 .. 5 arg1 = (a->typ) | ((a->flag & 0xff) << 8) | (a->off << 16); uint64_t val; switch (a->typ) { case HADDR: val = a->val.ha; break; case MADDR: val = a->val.ma; break; case IADDR: val = a->val.ia; break; case LADDR: val = a->val.la; break; case GREG: val = a->val.gr; break; case GSPEC: val = a->val.gs; break; case UNK: val = a->val.ua; break; case CONST: val = a->val.con; break; case RET: val = a->val.ret; break; default: assert (1==0); } arg2 = val; break; } case PADDRENTRY: { LogOp op = entry->entry.portaccess.op; assert (op == PLOAD ||op == PSTORE); Addr *a = &(entry->entry.portaccess.addr); typ = TUBTFE_LLVM_DV_LOAD; if (op == PSTORE) { typ = TUBTFE_LLVM_DV_STORE; } // a->type fits easily in a byte -- 1 .. 5 arg1 = (a->typ) | ((a->flag & 0xff) << 8) | (a->off << 16); uint64_t val; switch (a->typ) { case PADDR: val = a->val.pa; break; default: assert (1==0); } arg2 = val; break; } case BRANCHENTRY: { typ = TUBTFE_LLVM_DV_BRANCH; arg1 = entry->entry.branch.br; break; } case SELECTENTRY: { typ = TUBTFE_LLVM_DV_SELECT; arg1 = entry->entry.select.sel; break; } case SWITCHENTRY: { typ = TUBTFE_LLVM_DV_SWITCH; arg1 = entry->entry.switchstmt.cond; break; } case EXCEPTIONENTRY: { typ = TUBTFE_LLVM_EXCEPTION; } } tubtf_write_el_64(cr3, pc, typ, arg1, arg2, arg3, arg4); } else { uint32_t bytes_used = dynval_buf->ptr - dynval_buf->start; assert(dynval_buf->max_size - bytes_used >= sizeof(DynValEntry)); memcpy(dynval_buf->ptr, entry, sizeof(DynValEntry)); dynval_buf->ptr += sizeof(DynValEntry); dynval_buf->cur_size = dynval_buf->ptr - dynval_buf->start; } }
void linux_open_enter(CPUState *cpu, target_ulong pc, uint32_t filename, int32_t flags, int32_t mode) { char the_filename[MAX_FILENAME]; guest_strncpy(cpu, the_filename, MAX_FILENAME, filename); if (debug) printf ("linux open asid=0x%x filename=[%s]\n", (unsigned int) panda_current_asid(cpu), the_filename); open_enter(cpu, pc, the_filename, flags, mode); }