void check_call(DECAF_Callback_Params *param) { uint32_t eip, cr3, insn_buf; CPUState *env = NULL; //If we've gotten this far, params is not null if(calls<MAXCALLS) { env = param->be.env; if(env!=NULL) { eip=DECAF_getPC(env); cr3=DECAF_getPGD(env); } else { eip=0x0; cr3=0x0; } DECAF_printf("sysenter_eip: (0x%x)\n", env->sysenter_eip); fprintf(tracefile, "sysenter_eip: (0x%x)\n", env->sysenter_eip); fprintf(tracefile, "sysenter_esp: (0x%x)\n", env->sysenter_esp); fprintf(tracefile, "current esp: (0x%x)\n", env->regs[R_ESP]-env->sysenter_eip); //fprintf(tracefile, "idt base: (0x%x) \n", env->idt.base); //Read 32bits worth of code... will be used to identify this later DECAF_read_mem(env,param->be.cur_pc,sizeof(uint32_t),&insn_buf); DECAF_printf("call: (0x%x@0x%x) 0x%x\n", eip-env->sysenter_eip, cr3, insn_buf); fprintf(tracefile, "call: (0x%x@0x%x) 0x%x\n", eip-env->sysenter_eip, cr3, insn_buf); fprintf(tracefile, "call (-esp): (0x%x@0x%x) 0x%x\n", eip-env->sysenter_esp, cr3, insn_buf); calls++; } }
static int instruction_tracer_init(void) { DECAF_printf("initializing instruction tracer...\n"); processbegin_handle = VMI_register_callback(VMI_CREATEPROC_CB, &instruction_tracer_load_main_module_callback, NULL); if (processbegin_handle == DECAF_NULL_HANDLE) { DECAF_printf("Could not register initial callback\n"); } return 0; }
static void NtCreateFile_ret(void *param) { NtCreateFile_hook_context_t *ctx = (NtCreateFile_hook_context_t *)param; DECAF_printf("NtCreateFile exit:"); hookapi_remove_hook(ctx->hook_handle); uint32_t out_handle; DECAF_read_mem(NULL, ctx->call_stack[1], 4, &out_handle); DECAF_printf("out_handle=%08x\n", out_handle); free(ctx); }
static void VirtualAlloc_ret(void *param) { NtCreateFile_hook_context_t *ctx = (NtCreateFile_hook_context_t *)param; DECAF_printf("VirtualAlloc exit:"); hookapi_remove_hook(ctx->hook_handle); DECAF_printf("lpAddress=%08x, dwSize=%d, ret=%08x\n", ctx->call_stack[1], ctx->call_stack[2], cpu_single_env->regs[R_EAX]); free(ctx); }
plugin_interface_t* init_plugin(void) { DECAF_printf("start init_plugin\n"); instruction_tracer_interface.mon_cmds = instruction_tracer_term_cmds; DECAF_printf("mon_cmds done\n"); instruction_tracer_interface.plugin_cleanup = &instraction_tracer_cleanup; DECAF_printf("plugin_cleanup done\n"); instruction_tracer_init(); DECAF_printf("instruction_tracer done\n"); return (&instruction_tracer_interface); }
static int hookapitests_init(void) { DECAF_output_init(NULL); DECAF_printf("Hello World\n"); //register for process create and process remove events processbegin_handle = VMI_register_callback(VMI_CREATEPROC_CB, &createproc_callback, NULL); removeproc_handle = VMI_register_callback(VMI_REMOVEPROC_CB, &removeproc_callback, NULL); if ((processbegin_handle == DECAF_NULL_HANDLE) || (removeproc_handle == DECAF_NULL_HANDLE)) { DECAF_printf( "Could not register for the create or remove proc events\n"); } return (0); }
void do_read_taint_mem(DECAF_Callback_Params *param) { uint32_t eip = cpu_single_env->eip; uint32_t cr3 = cpu_single_env->cr[3]; char name[128]; dmodule * dm = NULL; dm = locate_module(eip,cr3,name); if(!dm) return; if(param->rt.size <=4) DECAF_printf("READ 0x%08x 0x%08x 0x%08x %s\n",param->rt.vaddr,param->rt.paddr,*((uint32_t *)param->rt.taint_info),dm->name); else DECAF_printf("READ 0x%08x 0x%08x 0x%16x %s\n",param->rt.vaddr,param->rt.paddr,*((uint32_t *)param->rt.taint_info),dm->name); }
static void instruction_tracer_process_finished_callback(VMI_Callback_Params* params) { if (target_cr3 == params->rp.cr3) { DECAF_printf("target process finished...\n"); fflush(disas_logfile); } }
/* * Since we cannot get process id at translation phase, in order to reduce the performance * overhead, we first lookup 'curPC' in the traced process to get in which module the current * instruction locates. Then, if the returned module is in 'blacklistLibs', we perform * instrumentation; or if it isn't in 'whitelistLibs', we perform instrumentation too. */ int nd_in_blacklist(gva_t addr){ char moduleName[128]; moduleName[0] = '\0'; gva_t startAddr = -1; gva_t endAddr = -1; //check current pc if(addr < 0 || addr >= 0xC0000000){ return (0); } //if(ND_GLOBAL_TRACING_PID == getCurrentPID()){ //Note that during translation phase, getCurrentPID() returns //process running rather than process being translated getExecutableModuleInfo(ND_GLOBAL_TRACING_PID, moduleName, 128, &startAddr, &endAddr, addr); if('\0' != moduleName[0]){ //in blacklist if(StringHashtable_exist(blacklistLibs, moduleName)){ return (1); } //not in whitelist if(!StringHashtable_exist(whitelistLibs, moduleName)){ DECAF_printf("Add %s to blacklist\n", moduleName); StringHashtable_add(blacklistLibs, moduleName); return (1); } } else{ if(addr != -1 && addr >= GIVEN_LIB_START_ADDR && addr <= GIVEN_LIB_END_ADDR){ return (1); } } return (0); }
inline void get_symbol(CPUState* env, gpid_t pid, gva_t addr) { char name[128]; name[0] = '\0'; getNearestSymbol(name, 128, pid, addr); DECAF_printf("%08x is in %s\n", addr, name); }
static void instruction_tracer_cpu_exec_callback(DECAF_Callback_Params* params) { int i; if (params->ce.env == NULL) { DECAF_printf("NULL\n"); return; } if (is_target_program(params->ce.env)) { /* if (params->ce.tb_size == 0) { */ /* DECAF_printf("\nnull is detected -> eip: 0x%x\n", params->ce.env->eip); */ /* fprintf(disas_logfile, "null member is detected\n"); */ /* return; */ /* } */ if (!params->ce.is_valid) { DECAF_printf("not valid\n\n"); fprintf(disas_logfile, "null member is detected\n\n"); return; } target_ulong d_pc = params->ce.tb_pc; target_ulong d_size = params->ce.tb_size; target_disas(disas_logfile, d_pc, d_size, 0); fprintf(disas_logfile, "=\n"); for (i = 0; i < d_size && i < MAX_CODE_BUF; i++) { code_buf[i] = ldub_code(d_pc + i); fprintf(disas_logfile, "%02x", code_buf[i]); } /* if (i => MAX_CODE_BUF) { */ /* DECAF_printf("code buffer overflown\n"); */ /* code_buf[MAX_CODE_BUF - 1] = '\0'; */ /* } else { */ /* code_buf[i] = '\0'; */ /* } */ //fwrite(code_buf, sizeof(unsigned char), i - 1, disas_logfile); fprintf(disas_logfile, "\n\n"); } }
static void instraction_tracer_cleanup(void) { DECAF_printf("cleaning up instruction tracer...\n"); if (disas_logfile != NULL) { fclose(disas_logfile); } if (processbegin_handle != DECAF_NULL_HANDLE) { VMI_unregister_callback(VMI_CREATEPROC_CB, processbegin_handle); processbegin_handle = DECAF_NULL_HANDLE; } if (instruction_tracer_cpu_exec_handle != DECAF_NULL_HANDLE) { DECAF_unregister_callback(DECAF_CPU_EXEC_CB, instruction_tracer_cpu_exec_handle); instruction_tracer_cpu_exec_handle = DECAF_NULL_HANDLE; } if (processfinish_handle != DECAF_NULL_HANDLE) { VMI_unregister_callback(VMI_REMOVEPROC_CB, processfinish_handle); processfinish_handle = DECAF_NULL_HANDLE; } DECAF_printf("cleaned up\n"); }
static int DIT_init(void) { DIT_handle = DS_Dalvik_register_callback(DS_DALVIK_INSN_BEGIN_CB, &DIT_IBCallback, NULL); if (DIT_handle == DECAF_NULL_HANDLE) { DECAF_printf("Could not register for Dalvik Instruction Begin \n"); return (-1); } return (0); }
static void VirtualAlloc_call(void *opaque) { DECAF_printf("VirtualAlloc entry\n"); NtCreateFile_hook_context_t *ctx = (NtCreateFile_hook_context_t*) malloc(sizeof(NtCreateFile_hook_context_t)); if(!ctx) //run out of memory return; DECAF_read_mem(NULL, cpu_single_env->regs[R_ESP], 12*4, ctx->call_stack); ctx->hook_handle = hookapi_hook_return(ctx->call_stack[0], VirtualAlloc_ret, ctx, sizeof(*ctx)); }
void do_instruction_trace(Monitor* monitor, const QDict* qdict) { if (target_cr3 != 0) { return; } DECAF_printf("do_instruction_trace\n"); if ((qdict != NULL) && (qdict_haskey(qdict, DICT_KEY_PROCNAME))) { strncpy(target_name, qdict_get_str(qdict, DICT_KEY_PROCNAME), TARGET_NAME_BUF_SIZE); target_name_len = strlen(target_name); } target_name[TARGET_NAME_BUF_SIZE - 1] = '\0'; }
static void createproc_callback(VMI_Callback_Params* params) { if(targetcr3 != 0) //if we have found the process, return immediately return; if (strcasecmp(targetname, params->cp.name) == 0) { targetpid = params->cp.pid; targetcr3 = params->cp.cr3; register_hooks(); DECAF_printf("Process found: pid=%d, cr3=%08x\n", targetpid, targetcr3); } }
static int tracing_init(void) { int err = 0; procname_clear(); // Parse configuration file err = check_ini(ini_main_default_filename); if (err) { DECAF_printf( "Could not find INI file: %s\n" "Use the command 'load_config <filename> to provide it.\n", ini_main_default_filename); } return 0; }
static void instruction_tracer_load_main_module_callback(VMI_Callback_Params* params) { if (target_cr3 != 0) { return; } if (params->cp.name == NULL) { return; } if (strncmp(params->cp.name, target_name, target_name_len) == 0) { DECAF_printf("Process %s(cr3: %d, pid: %d) you specified starts\n", params->cp.name, params->cp.cr3, params->cp.pid); target_cr3 = params->cp.cr3; instruction_tracer_cpu_exec_handle = DECAF_register_callback(DECAF_CPU_EXEC_CB, &instruction_tracer_cpu_exec_callback, NULL); processfinish_handle = VMI_register_callback(VMI_REMOVEPROC_CB, &instruction_tracer_process_finished_callback, NULL); if ((disas_logfile = fopen(LOGFILE_PATH, "w+")) == NULL) { DECAF_printf("log file open error!\n"); } } }
static void DIT_IBCallback(Dalvik_Callback_Params* params) { int insnWidth = 0; DecodedInstruction decInsn; u2 insns[128]; if (params == NULL) { return; } CPUState* env = params->ib.env; gva_t rpc = params->ib.dalvik_pc; if (getDalvikInstruction(env, rpc, &insnWidth, insns, 128) != 0) { DECAF_printf("Could not read the instruction at [%x]\n", rpc); return; } if (eLogLevel == LOG_LEVEL_SIMPLE) { char symbolName[128]; if (getSymbol(symbolName, 128, getCurrentPID(), rpc) == 0) { DECAF_printf(" ***** %s ***** \n", symbolName); } DECAF_printf("[%08x] %s ", rpc, dalvikOpcodeToString(params->ib.opcode)); int i = 0; for (i = 0; i < 8; i++) { if (i < insnWidth) { if (i == 7) { DECAF_printf(" ... "); } else { /* print 16-bit value in little-endian order */ const u1* bytePtr = (const u1*) &insns[i]; DECAF_printf(" %02x%02x", bytePtr[0], bytePtr[1]); } } else { DECAF_printf(" "); } } DECAF_printf("\n"); return; } decodeDalvikInstruction(insns, &decInsn); dumpDalvikInstruction(stdout, env, insns, 0, insnWidth, &decInsn, 0, rpc, eLogLevel); }
static void my_loadmainmodule_notify(VMI_Callback_Params * params) { char *name = params->cp.name; if (procname_is_set()) { if (procname_match(name)) { do_tracing_internal(params->cp.pid, tracefile); trackproc_start(params->cp.pid); DECAF_printf( "Tracing %s\n", procname_get()); procname_clear(); } } }
void do_tracing(Monitor *mon, const QDict *qdict) { uint32_t pid = qdict_get_int(qdict, "pid"); const char *filename = qdict_get_str(qdict, "filepath"); char proc_name[512]; uint32_t cr3; if( VMI_find_process_by_pid_c(pid, proc_name, 512, &cr3)!= -1){ procname_set(proc_name); strncpy(tracefile, filename, 256); do_tracing_internal(pid, filename); trackproc_start(pid); } else DECAF_printf("Unable to find process %d \n", pid); }
/* * NTSTATUS NtCreateFile( __out PHANDLE FileHandle, __in ACCESS_MASK DesiredAccess, __in POBJECT_ATTRIBUTES ObjectAttributes, __out PIO_STATUS_BLOCK IoStatusBlock, __in_opt PLARGE_INTEGER AllocationSize, __in ULONG FileAttributes, __in ULONG ShareAccess, __in ULONG CreateDisposition, __in ULONG CreateOptions, __in PVOID EaBuffer, __in ULONG EaLength ); * */ void NtCreateFile_ret_handler(void *opaque) { monitor_printf(default_mon, "NtCreateFile_ret\n"); uint32_t esp, offset; uint32_t i,j; CPUState *cpu; cpu = cpu_single_env; UNICODE_STRING ObjectName; char *Buffer = NULL; ULONG Length=0; uint8_t unicode_str[1024]; POBJECT_ATTRIBUTES po = NULL; /* Populate out arguments */ esp = cpu->regs[R_ESP]; //offset = esp; uint32_t stack_data[11]; DECAF_read_mem(cpu,esp,4*11,(void *)stack_data); uint64_t data_temp=(uint64_t)stack_data[2]; po = malloc(sizeof(OBJECT_ATTRIBUTES)); ; DECAF_read_mem(cpu,stack_data[2],sizeof(OBJECT_ATTRIBUTES),(void *)po); if(po->ObjectName){ DECAF_read_mem(cpu,(uint32_t)po->ObjectName, sizeof(UNICODE_STRING), (void *)&ObjectName); monitor_printf(default_mon, "\t\tObjectName.Length: %d\n", ObjectName.Length); monitor_printf(default_mon, "\t\tObjectName.MaximumLength: %d\n", ObjectName.MaximumLength); monitor_printf(default_mon, "\t\tObjectName.Buffer: 0x%p\n", ObjectName.Buffer); if(ObjectName.Buffer && ObjectName.Length){ Buffer = (char *) malloc (sizeof(char) * ObjectName.Length); if(Buffer != '\0') { cpu_memory_rw_debug(cpu_single_env, (target_ulong)ObjectName.Buffer, (uint8_t *)&unicode_str, ObjectName.Length, 0); for (i = 0, j = 0; i < ObjectName.Length; i+=2, j++) Buffer[j] = unicode_str[i]; Buffer[j] = '\0'; DECAF_printf("%s\n",Buffer); monitor_printf(default_mon, "\t\t\tBuffer: %s \n", Buffer); free(Buffer); } } } }
//Cheap copy+paste: do the same as calls, but don't print void check_ret(DECAF_Callback_Params *param) { uint32_t eip, cr3; CPUState *env = NULL; //If we've gotten this far, params is not null if(calls<MAXCALLS) { env = param->be.env; if(env!=NULL) { eip=DECAF_getPC(env); cr3=DECAF_getPGD(env); } else { eip=0x0; cr3=0x0; } DECAF_printf("ret: (0x%x@0x%x)\n", eip-env->sysenter_eip, cr3); fprintf(tracefile, "ret: (0x%x@0x%x)\n", eip-env->sysenter_eip, cr3); } }
static void do_tracing_by_name_internal(const char *progname, const char *filename) { /* If process already running, start tracing */ uint32_t pid = VMI_find_pid_by_name_c(progname); uint32_t minus_one = (uint32_t)(-1); if (pid != minus_one) { procname_set(progname); strncpy(tracefile, filename, 256); do_tracing_internal(pid, filename); trackproc_start(pid); return; } /* Otherwise, start monitoring for process start */ procname_set(progname); strncpy(tracefile, filename, 256); DECAF_printf( "Waiting for process %s to start\n", progname); }
static void do_tracing_internal(uint32_t pid, const char *filename) { /* if pid = 0, stop trace */ if (0 == pid) tracing_stop(); else { if (!io_logging_initialized) { //TODO: fix this -hu //netwk_monitor_init(filename); io_logging_initialized = 1; } int retval = tracing_start(pid, filename); if (retval < 0) DECAF_printf( "Unable to open log file '%s'\n", filename); } /* Print configuration variables */ //print_conf_vars(); }
void DECAF_set_output_file(const char* fileName) { if (ofp != NULL) { return; } if (strcmp(fileName, "stdout") == 0) { DECAF_output_cleanup(); return; } //open the file ofp = fopen(fileName, "w"); if (ofp == NULL) { DECAF_printf("Could not open the file [%s]\n", fileName); } }
static void hookapitests_cleanup(void) { // procmod_Callback_Params params; DECAF_printf("Bye world\n"); if (processbegin_handle != DECAF_NULL_HANDLE) { VMI_unregister_callback(VMI_CREATEPROC_CB, processbegin_handle); processbegin_handle = DECAF_NULL_HANDLE; } if (removeproc_handle != DECAF_NULL_HANDLE) { VMI_unregister_callback(VMI_REMOVEPROC_CB, removeproc_handle); removeproc_handle = DECAF_NULL_HANDLE; } if (blockbegin_handle != DECAF_NULL_HANDLE) { DECAF_unregister_callback(DECAF_BLOCK_BEGIN_CB, blockbegin_handle); blockbegin_handle = DECAF_NULL_HANDLE; } }
void block_begin_callback(DECAF_Callback_Params *param) { //uint32_t address; uint32_t cr3; int i, found_cr3=0; if(param==NULL) { DECAF_printf("Null params!\n"); return; } pthread_mutex_lock(&mutex); /* if(was_int) { address = param->bb.env->eip; if(use_sysenter) address -= param->bb.env->sysenter_eip; //fprintf(tracefile, "eip: %x:\n", address); was_int--; } */ cr3 = DECAF_getPGD(param->be.env); if(cr3_changes < CR3_TO_TRACK && cr3 != last_cr3) { for(i=0;i<CR3_TO_TRACK;i++) { if(cr3s_this_keystroke[i]==cr3) { found_cr3=1; break; } } //Only increment our global list if this change is unique to the keystroke //We are trying to correlate how many CR3s consistently show up if(!found_cr3) { cr3s_this_keystroke[cr3_changes]=cr3; cr3s[cr3>>12]++; } cr3_changes++; last_cr3 = cr3; }
/** * Instruction Begin callback. */ void nd_instruction_begin_callback(DECAF_Callback_Params* params){ DEFENSIVE_CHECK0(params == NULL); DEFENSIVE_CHECK0(getCurrentPID() != ND_GLOBAL_TRACING_PID); CPUState* env = params->ib.env; gva_t cur_pc = params->ib.cur_pc; //since for thumb instruction, the last bit is '1' gva_t cur_pc_even = cur_pc & 0xfffffffe; if(!nd_in_blacklist(cur_pc_even)){ return; } //ARM Instruction union _tmpARMInsn{ target_ulong insn; char chars[4]; } tmpARMInsn; //Thumb Instruction union _tmpThumbInsn{ unsigned short insn; char chars[2]; } tmpThumbInsn; //Thumb2 Instruction union _tmpThumb2Insn{ target_ulong insn; char chars[4]; } tmpThumb2Insn; //undefined instruction if(cur_pc == -1){ return; } //the first instruction of target native method SourcePolicy* sourcePolicy = findSourcePolicy(cur_pc_even); if(sourcePolicy != NULL){ DECAF_printf("Step into Native\n"); sourcePolicy->handler(sourcePolicy, env); } //DECAF_printf("%x %x\n", cur_pc_even, lastCallSysLibAddrRet); //return from JNI API calls/system library calls if(cur_pc_even == lastCallJNIAddrRet){ if(lastJniHandler != NULL){ lastJniHandler(env, 0); lastJniHandler = NULL; lastCallJNIAddrRet = -1; } } if(cur_pc_even == lastCallSysLibAddrRet){ if(lastSysLibHandler != NULL){ lastSysLibHandler(env, 0); lastSysLibHandler = NULL; lastCallSysLibAddrRet = -1; } } //Thumb instruction if(env->thumb == 1){ if(DECAF_read_mem(env, cur_pc_even, tmpThumbInsn.chars, 2) != -1){ darm_t d; //darm_str_t str; // magic table constructed based on section A6.1 of the ARM manual static uint8_t is_thumb2[0x20] = { [0x01d] = 1, [0x01e] = 1, [0x01f] = 1, }; if(is_thumb2[tmpThumbInsn.insn >> 11]){ //Thumb2 instruction if(DECAF_read_mem(env, cur_pc_even, tmpThumb2Insn.chars, 4) != -1){ if(darm_thumb2_disasm(&d, tmpThumb2Insn.insn & 0x0000ffff, tmpThumb2Insn.insn >> 16, env) == 0){ //if(darm_str(&d, &str, env) == 0){ //DECAF_printf("T2 %x: %s\n", cur_pc, str.total); //} } } }else{ //Thumb instruction if(darm_thumb_disasm(&d, tmpThumbInsn.insn, env) == 0){ //if(darm_str(&d, &str, env) == 0){ //DECAF_printf("T %x: %s\n", cur_pc, str.total); //} } } }
inline void get_symbol_address(Monitor* mon, int pid, const char* strModule, const char* strName) { DECAF_printf("%s is at [%x]\n", strName, getSymbolAddress(pid, strModule, strName)); }