int run(struct emu *e, struct emu_env *env) { int j=0; int ret; //= emu_cpu_run(emu_cpu_get(e)); for( j=0;j< 1000000;j++ ) { struct emu_env_hook *hook = NULL; hook = emu_env_w32_eip_check(env); if( hook != NULL ) { if( strcmp(hook->hook.win->fnname,"ExitThread") == 0 ) break; if( hook->hook.win->fnhook == NULL ) { g_critical("unhooked call to %s", hook->hook.win->fnname); break; } } else { ret = emu_cpu_parse(emu_cpu_get(e)); struct emu_env_hook *hook =NULL; if( ret != -1 ) { hook = emu_env_linux_syscall_check(env); if( hook == NULL ) { ret = emu_cpu_step(emu_cpu_get(e)); } else { if( hook->hook.lin->fnhook != NULL ) hook->hook.lin->fnhook(env, hook); else break; } } if( ret == -1 ) { g_debug("cpu error %s", emu_strerror(e)); break; } } } return 0; }
void __cdecl main(void){ e = emu_new(); cpu = emu_cpu_get(e); mem = emu_memory_get(e); env = emu_env_new(e); //emu_log_level_set( emu_logging_get(e), EMU_LOG_DEBUG); if ( env == 0 ){ printf("%s\n%s\n", emu_strerror(e), strerror(emu_errno(e))); exit(-1);} int i = 0; void* stack; int stacksz; // 0 1 2 3 4 5 6 7 int regs[] = {0, 0, 0, 0, 0x12fe00,0x12fff0 ,0, 0}; //*regm[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}; for (i=0;i<8;i++) cpu->reg[(emu_reg32)i] = regs[i]; stacksz = regs[ebp] - regs[esp] + 500; stack = malloc(stacksz); memset(stack, 0, stacksz); //printf("writing initial stack space\n"); emu_memory_write_block(mem, regs[esp] - 250, stack, stacksz); emu_env_w32_export_new_hook(env, "LoadLibraryA", new_user_hook_LoadLibraryA, NULL); /* 00436A32 B8 00000000 MOV EAX,0 00436A37 40 INC EAX 00436A3D 68 6C333200 PUSH 32336C 00436A42 68 7368656C PUSH 6C656873 00436A47 54 PUSH ESP 00436A48 68 771D807C PUSH 7C801D77 00436A4D 59 POP ECX 00436A4E FFD1 CALL ECX 686C333200687368656C5468771D807C59FFD1 */ unsigned char shellcode[20] = { 0x68, 0x6C, 0x33, 0x32, 0x00, 0x68, 0x73, 0x68, 0x65, 0x6C, 0x54, 0x68, 0x77, 0x1D, 0x80, 0x7C, 0x59, 0xFF, 0xD1, 0xCC }; //write shellcode to memory emu_memory_write_block(mem, 0x401000, shellcode, 20); emu_cpu_eip_set(cpu, 0x401000); system("cls"); int step=0; char* buf = (char*)malloc(100); while(1){ struct emu_env_w32_dll_export *ex = NULL; ex = emu_env_w32_eip_check(env); if(ex != NULL){ //eip was found to be the start address of some dll export if(ex->fnhook == NULL){ //if fnhook != 0 then handler was executed by library already printf("Unhooked call to api %s\n", ex->fnname); //can insert generic handler here break; } } else{ emu_disasm_addr(cpu, cpu->eip, buf); printf("%x\t%s\n", cpu->eip, buf); if( emu_cpu_parse(cpu) == -1){ printf("step %d parse failed error: %s", step, emu_strerror(e)); break; } if( emu_cpu_step(cpu) == -1){ printf("step %d step failed error: %s", step, emu_strerror(e)); break; } step++; } } printf("Run complete step=%d eax is: %x\n\n", step, cpu->reg[eax]); getch(); }
void emulate_thread(gpointer data, gpointer user_data) { struct emu_emulate_ctx *ctx = user_data; struct emu_config *conf = ctx->config; struct emu *e = ctx->emu; struct emu_env *env = ctx->env; int ret; g_mutex_lock(&ctx->mutex); if( ctx->state == waiting ) ctx->state = running; if( ctx->time == NULL ) ctx->time = g_timer_new(); else g_timer_continue(ctx->time); while( ctx->state == running ) { if( (ctx->steps % (1024*1024)) == 0 ) { g_debug("steps %li", ctx->steps); if( ctx->steps > conf->limits.steps ) { g_info("shellcode took too many steps ... (%li steps)", ctx->steps); ctx->state = failed; break; } if( conf->limits.cpu > 0. ) { double elapsed = g_timer_elapsed(ctx->time, NULL); if( elapsed > conf->limits.cpu ) { g_info("shellcode took too long ... (%f seconds)", elapsed); ctx->state = failed; break; } } } ctx->steps++; struct emu_env_hook *hook = NULL; hook = emu_env_w32_eip_check(env); if( hook != NULL ) { if( hook->hook.win->fnhook == NULL ) { g_critical("unhooked call to %s", hook->hook.win->fnname); break; } else if( ctx->state == waiting ) /* for now, we stop! * had a blocking io call * callback from main will come at a given point * and requeue us to the threadpool */ goto unlock_and_return; } else { ret = emu_cpu_parse(emu_cpu_get(e)); struct emu_env_hook *hook =NULL; if( ret != -1 ) { hook = emu_env_linux_syscall_check(env); if( hook == NULL ) { ret = emu_cpu_step(emu_cpu_get(e)); } else { if( hook->hook.lin->fnhook != NULL ) { hook->hook.lin->fnhook(env, hook); if( ctx->state == waiting ) /* stop * as mentioned previously */ goto unlock_and_return; } } } if( ret == -1 ) { g_debug("cpu error %s", emu_strerror(e)); break; } } } g_timer_stop(ctx->time); if( ctx->state == failed ) g_debug("emulating shellcode failed"); g_mutex_unlock(&ctx->mutex); #ifdef DEBUG double elapsed = g_timer_elapsed(ctx->time, NULL); g_debug("shellcode took %f seconds on cpu, %li steps", elapsed, ctx->steps); #endif GAsyncQueue *aq = g_async_queue_ref(g_dionaea->threads->cmds); g_async_queue_push(aq, async_cmd_new(emulate_ctx_free, ctx)); g_async_queue_unref(aq); ev_async_send(g_dionaea->loop, &g_dionaea->threads->trigger); return; unlock_and_return: g_timer_stop(ctx->time); g_mutex_unlock(&ctx->mutex); }