Пример #1
0
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;
}
Пример #2
0
void profile(struct emu_config *conf, struct connection *con, void *data, unsigned int size, unsigned int offset)
{
	struct emu *e = emu_new();
	struct emu_env *env = emu_env_new(e);
	env->profile = emu_profile_new();

//	struct emu_cpu *cpu = emu_cpu_get(e);
	struct emu_memory *mem = emu_memory_get(e);
	emu_cpu_reg32_set(emu_cpu_get(e), esp, 0x0012fe98);

	emu_memory_write_block(mem, CODE_OFFSET, data,  size);
	emu_cpu_eip_set(emu_cpu_get(e), CODE_OFFSET + offset);
	run(e, env);

	bool needemu = false;

	struct emu_profile_function *function;
	for( function = emu_profile_functions_first(env->profile->functions); !emu_profile_functions_istail(function); function = emu_profile_functions_next(function) )
	{
		if( strcmp("recv", function->fnname) == 0 )
		{
			g_message("Can not profile %s, emulating instead", function->fnname);
			needemu = true;
		}
	}


	if( needemu == true )
	{
		emulate(conf, con, data, size, offset);
	} else
	{
		GString *str = g_string_new(NULL);
		json_profile_debug(env->profile, str);
		//printf("%s", str->str);
		struct incident *i = incident_new("dionaea.module.emu.profile");
		incident_value_string_set(i, "profile", str);
		incident_value_con_set(i, "con", con);
		connection_ref(con);
		GAsyncQueue *aq = g_async_queue_ref(g_dionaea->threads->cmds);
		g_async_queue_push(aq, async_cmd_new(async_incident_report, i));
		g_async_queue_unref(aq);
		ev_async_send(g_dionaea->loop, &g_dionaea->threads->trigger);
	}

	emu_env_free(env);
	emu_free(e);
}
Пример #3
0
void proc_emu_on_io_in(struct connection *con, struct processor_data *pd)
{
	g_debug("%s con %p pd %p", __PRETTY_FUNCTION__, con, pd);
	struct emu_ctx *ctx = pd->ctx;

	int offset = MAX(ctx->offset-300, 0);
	void *streamdata = NULL;
	int32_t size = bistream_get_stream(pd->bistream, bistream_in, offset, -1, &streamdata);
	int ret = 0;
	if( size != -1 )
	{
		struct emu *e = emu_new();
#if 0
		emu_cpu_debugflag_set(emu_cpu_get(e), instruction_string);
		emu_log_level_set(emu_logging_get(e),EMU_LOG_DEBUG);
#endif
		ret = emu_shellcode_test(e, streamdata, size);
		emu_free(e);
		ctx->offset += size;
		if( ret >= 0 )
		{
			struct incident *ix = incident_new("dionaea.shellcode.detected");
			GAsyncQueue *aq = g_async_queue_ref(g_dionaea->threads->cmds);
			g_async_queue_push(aq, async_cmd_new(async_incident_report, ix));
			g_async_queue_unref(aq);
			ev_async_send(g_dionaea->loop, &g_dionaea->threads->trigger);
			g_debug("shellcode found offset %i", ret);
			profile(ctx->config, con, streamdata, size, ret);

			pd->state = processor_done;
		}
		g_free(streamdata);
	}
}
Пример #4
0
const char *env_linux_socketcall(struct emu_env_linux *env)
{
	static const char *socketcall_table [] =
	{
		/*  0 */ NULL,
		/*  1 */ "socket",
		/*  2 */ "bind",
		/*  3 */ "connect",
		/*  4 */ "listen",
		/*  5 */ "accept",
		/*  6 */ "getsockname",
		/*  7 */ "getpeername",
		/*  8 */ "socketpair",
		/*  9 */ "send",
		/* 10 */ "recv",
		/* 11 */ "sendto",
		/* 12 */ "recvfrom",
		/* 13 */ "shutdown",
		/* 14 */ "setsockopt",
		/* 15 */ "getsockopt",
		/* 16 */ "sendmsg",
		/* 17 */ "recvmsg",
	};
	struct emu_cpu *cpu = emu_cpu_get(env->emu);

	if (cpu->reg[ebx] == 0 || cpu->reg[ebx] > 17)
		return NULL;

	return socketcall_table[cpu->reg[ebx]];
}
int32_t env_linux_hook_fork(struct emu_env *env, struct emu_env_hook *hook)
{
	printf("sys_fork(2)\n");
	struct emu_cpu *c = emu_cpu_get(env->emu);
	emu_profile_function_add(env->profile, "fork");

	emu_cpu_reg32_set(c, eax, 4711);
	return 0;
}
int32_t env_hook_SHGetSpecialFolderPathA(struct emu_env *env, struct emu_env_hook *hook)
{

	struct emu_cpu *c = emu_cpu_get(env->emu);
	struct emu_memory *mem = emu_memory_get(env->emu);

	uint32_t eip_save;

	POP_DWORD(c, &eip_save);

/*
   CopyBOOL SHGetSpecialFolderPath(
                 HWND hwndOwner,
   __out  LPTSTR lpszPath,
   __in   int csidl,
   __in   BOOL fCreate
   );

 */
	uint32_t hwnd;
	POP_DWORD(c, &hwnd);

	uint32_t buf;
	POP_DWORD(c, &buf);

	uint32_t csidl;
	POP_DWORD(c, &csidl);

	uint32_t fCreate;
	POP_DWORD(c, &fCreate);

	char buf255[255];
	memset(buf255,0,254);
	GetSHFolderName(csidl, (char*)&buf255);

	emu_memory_write_block(mem,buf,buf255,strlen(buf255));

	emu_cpu_reg32_set(c, eax, 0);

	if ( env->profile != NULL )
	{
		emu_profile_function_add(env->profile, "SHGetSpecialFolderPath");
		emu_profile_argument_add_int(env->profile, "HWND", "hwndOwner", hwnd);
		emu_profile_argument_add_ptr(env->profile, "LPCSTR", "lpszPath", buf);
		emu_profile_argument_add_string(env->profile, "", "", buf255);
		emu_profile_argument_add_int(env->profile, "int", "csidl", csidl);
		emu_profile_argument_add_int(env->profile, "BOOL", "fCreate", fCreate);
		emu_profile_function_returnvalue_int_set(env->profile, "BOOL", c->reg[eax]);
	}

	emu_cpu_eip_set(c, eip_save);
	return 0;
}
Пример #7
0
int32_t emu_track_instruction_check(struct emu *e, struct emu_track_and_source *et)
{
	struct emu_cpu *c = emu_cpu_get(e);
	int i;

	if (c->instr.is_fpu)
	{
		if (c->instr.track.need.fpu  > et->track.fpu )
			return -1;

		et->track.fpu |= c->instr.track.init.fpu;

	}else
	{
//		debug_instruction(&c->instr);
/*
		if (c->cpu_instr_info->function == instr_xchg_9x)
		{
			uint32_t reg1 = et->reg[eax];
			et->reg[eax] = et->reg[c->instr.cpu.opc & 7];
			et->reg[c->instr.cpu.opc & 7] = reg1;
		}
*/
		for (i=0;i<8;i++)
		{
			if (i == esp)
				continue;

//			printf("0x%08x 0x%08x\n", c->instr.cpu.track.need.reg[i], et->reg[i]);
			if (c->instr.track.need.reg[i] > et->track.reg[i])
				return -1;
		}

		for (i=0;i<8;i++)
		{
//			printf("0x%1x 0x%1x\n", (c->instr.cpu.track.need.eflags & 1 << i), (et->eflags & 1 << i));
			if ( (c->instr.track.need.eflags & 1 << i) > (et->track.eflags & 1 << i))
				return -1;
		}

		for (i=0;i<8;i++)
		{
//			printf("reg %i before %08x after %08x\n", i, et->reg[i], c->instr.cpu.track.init.reg[i]);
			et->track.reg[i] |= c->instr.track.init.reg[i];
		}

		et->track.eflags |= c->instr.track.init.eflags;

	}


	return 0;
}
int32_t env_linux_hook_chmod(struct emu_env *env, struct emu_env_hook *hook)
{
	printf("sys_chmod(2)\n");
	struct emu_cpu *c = emu_cpu_get(env->emu);
	emu_profile_function_add(env->profile, "chmod");

	if (hook->hook.lin->userhook != NULL)
	{
		uint32_t r = hook->hook.lin->userhook(env, hook, c->reg[ebx]);
		emu_cpu_reg32_set(c, eax, r);
	}else
		emu_cpu_reg32_set(c, eax, 0);

	return 0;
}
int32_t	env_w32_hook__execv(struct emu_env *env, struct emu_env_hook *hook)
{
	logDebug(env->emu, "Hook me Captain Cook!\n");
	logDebug(env->emu, "%s:%i %s\n",__FILE__,__LINE__,__FUNCTION__);

	struct emu_cpu *c = emu_cpu_get(env->emu);

	uint32_t eip_save;

	POP_DWORD(c, &eip_save);

/*
intptr_t _execv( 
   const char *cmdname,
   const char *const *argv 
);
intptr_t _wexecv( 
   const wchar_t *cmdname,
   const wchar_t *const *argv 
);
*/

	uint32_t p_cmdname;
	POP_DWORD(c, &p_cmdname);

	struct emu_string *cmdname = emu_string_new();
	emu_memory_read_string(c->mem, p_cmdname, cmdname, 512);



	uint32_t p_argv;
	POP_DWORD(c, &p_argv);


	if ( env->profile != NULL )
	{
		emu_profile_function_add(env->profile, "_execv");
		emu_profile_argument_add_ptr(env->profile, "const char *", "cmdname", p_cmdname);
		emu_profile_argument_add_string(env->profile, "", "", emu_string_char(cmdname)); 
		emu_profile_argument_add_ptr(env->profile, "const char *const *", "argv", p_argv);
		emu_profile_argument_add_none(env->profile);
		emu_profile_function_returnvalue_int_set(env->profile, "int ", 0);
	}

	emu_string_free(cmdname);
    emu_cpu_eip_set(c, eip_save);
	return 0;
}
Пример #10
0
int32_t env_linux_hook_exit(struct emu_env *env, struct emu_env_hook *hook)
{
	printf("sys_exit(2)\n");
	struct emu_cpu *c = emu_cpu_get(env->emu);
	emu_profile_function_add(env->profile, "exit");
	emu_profile_argument_add_int(env->profile, "int", "status", c->reg[ebx]);

	if (hook->hook.lin->userhook != NULL)
	{
		uint32_t r = hook->hook.lin->userhook(env, hook, c->reg[ebx]);
		emu_cpu_reg32_set(c, eax, r);
	}else
		emu_cpu_reg32_set(c, eax, 0);

	
	return 0;
}
Пример #11
0
int32_t env_linux_hook_dup2(struct emu_env *env, struct emu_env_hook *hook)
{
	struct emu_cpu *c = emu_cpu_get(env->emu);

	printf("int dup2(int oldfd=%i, int newfd=%i);\n", c->reg[ebx], c->reg[ecx]);

	if ( env->profile != NULL )
	{
		emu_profile_function_add(env->profile, "dup2");
		emu_profile_argument_add_int(env->profile, "int", "oldfd", c->reg[ebx]);
		emu_profile_argument_add_int(env->profile, "int", "newfd", c->reg[ecx]);

		emu_profile_function_returnvalue_int_set(env->profile, "int", c->reg[ecx]);
	}

	emu_cpu_reg32_set(c, eax, c->reg[ecx]);
	return 0;
}
Пример #12
0
struct emu_env_hook *emu_env_linux_syscall_check(struct emu_env *env)
{
	struct emu_cpu *cpu = emu_cpu_get(env->env.lin->emu);

	if ( cpu->instr.is_fpu == false 
		 &&  cpu->instr.opc == 0xcd 
		 &&  *cpu->instr.cpu.imm8 == 0x80 )
	{
		uint8_t callnum = *cpu->reg8[al];
		if ( callnum < sizeof(env_linux_syscalls) / sizeof(struct emu_env_linux_syscall_entry) )
		{
			const char *name = NULL ;
			if ( env_linux_syscalls[callnum].name != NULL )
			{
				name = env_linux_syscalls[callnum].name;
			}
			else
			if ( env_linux_syscalls[callnum].fnhook != NULL )
			{
				name = env_linux_syscalls[callnum].fnhook(env->env.lin);
			}

			if ( name != NULL )
			{
				struct emu_hashtable_item *ehi = emu_hashtable_search(env->env.lin->syscall_hooks_by_name, (void *)name);
				if ( ehi != NULL )
				{
					return (struct emu_env_hook *)ehi->value;
				}
			}
		}
	}


	return NULL;
}
int32_t	env_w32_hook_fclose(struct emu_env *env, struct emu_env_hook *hook)
{
	logDebug(env->emu, "Hook me Captain Cook!\n");
	logDebug(env->emu, "%s:%i %s\n",__FILE__,__LINE__,__FUNCTION__);

	struct emu_cpu *c = emu_cpu_get(env->emu);

	uint32_t eip_save;

	POP_DWORD(c, &eip_save);

/*
int _fcloseall( void );
int fclose( FILE *stream );
*/

	uint32_t p_stream;
	MEM_DWORD_READ(c, c->reg[esp], &p_stream);



	logDebug(env->emu, "fclose(0x%08x)\n", p_stream);
	
	emu_cpu_reg32_set(c, eax, 0);

	if (env->profile != NULL)
	{
		emu_profile_function_add(env->profile, "fclose");
		emu_profile_argument_add_ptr(env->profile, "FILE *", "stream", p_stream);
		emu_profile_argument_add_none(env->profile);
		emu_profile_function_returnvalue_int_set(env->profile, "int", 0);
	}

    emu_cpu_eip_set(c, eip_save);
	return 0;
}
Пример #14
0
int32_t emu_shellcode_test(struct emu *e, uint8_t *data, uint16_t size)
{
	logPF(e);
/*

	
	bool found_good_candidate_after_getpc = false;

	uint32_t best_eip=0;
*/
	// This check avoids a floating point exception further down the line
	if(size < 2)
	{
		return -1;
	}

	uint32_t offset;
	struct emu_list_root *el;
	el = emu_list_create();


	for ( offset=0; offset<size ; offset++ )
	{
		if ( emu_getpc_check(e, (uint8_t *)data, size, offset) != 0 )
		{
			logDebug(e, "possible getpc at offset %i (%08x)\n", offset, offset);
			struct emu_list_item *eli = emu_list_item_create();
			eli->uint32 = offset;
			emu_list_insert_last(el, eli);
		}
	}

	if ( emu_list_length(el) == 0 )
	{
		emu_list_destroy(el);
		return -1;
	}

	{
		struct emu_cpu *cpu = emu_cpu_get(e);
		struct emu_memory *mem = emu_memory_get(e);

		/* write the code to the offset */
		emu_memory_write_block(mem, STATIC_OFFSET, data, size);

		/* set the registers to the initial values */
		int reg;
		for ( reg=0;reg<8;reg++ )
			emu_cpu_reg32_set(cpu,reg ,0x0);

		emu_cpu_reg32_set(cpu, esp, 0x00120000);
		emu_cpu_eip_set(cpu, 0);

		/* set the flags */
		emu_cpu_eflags_set(cpu,0x0);
	}

	struct emu_track_and_source *etas = emu_track_and_source_new();

	logDebug(e, "creating static callgraph\n");
	/* create the static analysis graph 
	set memory read only so instructions can't change it*/
	emu_memory_mode_ro(emu_memory_get(e));
	emu_source_instruction_graph_create(e, etas, STATIC_OFFSET, size);
	emu_memory_mode_rw(emu_memory_get(e));

	struct emu_hashtable *eh = emu_hashtable_new(size+4/4, emu_hashtable_ptr_hash, emu_hashtable_ptr_cmp);
	struct emu_list_item *eli;
//	struct emu_env_w32 *env = emu_env_w32_new(e);
	

	struct emu_list_root *results = emu_list_create();

	for ( eli = emu_list_first(el); !emu_list_attail(eli); eli = emu_list_next(eli) )
	{
		logDebug(e, "testing offset %i %08x\n", eli->uint32, eli->uint32);
		emu_shellcode_run_and_track(e, data, size, eli->uint32, 256, etas, eh,
									results, false);
	}

	

	/* for all positions we got, take the best, maybe take memory access into account later */
	emu_list_qsort(results, tested_positions_cmp);
	if ( ((struct emu_stats *)emu_list_first(results)->data)->cpu.steps != 256 )
	{
		emu_hashtable_free(eh);
		eh = emu_hashtable_new(size+4/4, emu_hashtable_ptr_hash, emu_hashtable_ptr_cmp);
		logDebug(e, "brute force!\n");
		struct emu_list_root *new_results = emu_list_create();
		for ( eli = emu_list_first(results); !emu_list_attail(eli); eli = emu_list_next(eli) )
		{
			struct emu_stats *es = (struct emu_stats *)eli->data;
			logDebug(e, "brute at offset 0x%08x \n",es->eip - STATIC_OFFSET);
			emu_shellcode_run_and_track(e, data, size, es->eip - STATIC_OFFSET, 256, etas, eh,
										new_results, true);
			
		}

		emu_list_concat(results, new_results);
		emu_list_destroy(new_results);
		emu_list_qsort(results, tested_positions_cmp);

		/* uniq */
		for ( eli = emu_list_first(results); !emu_list_attail(eli); eli = emu_list_next(eli) )
		{
			struct emu_list_item *next = emu_list_next(eli);
			if (!emu_list_attail(next) &&
            	((struct emu_stats *)eli->data)->eip == ((struct emu_stats *)next->data)->eip )
			{
				emu_stats_free(next->data);
				emu_list_remove(next);
				free(next);
			}
		}
	}

	

	emu_hashtable_free(eh);
	emu_list_destroy(el);
//	emu_env_w32_free(env);
	emu_track_and_source_free(etas);


	{
		struct emu_list_item *eli;
		for ( eli = emu_list_first(results); !emu_list_attail(eli); eli = emu_list_next(eli) )
		{
			struct emu_stats *es = (struct emu_stats *)eli->data;
			logDebug(e, "b offset 0x%08x steps %i\n",es->eip, es->cpu.steps);
		}
	}

	eli = emu_list_first(results);
	struct emu_stats *es = (struct emu_stats *)eli->data;

	if ( es->cpu.steps > 100 )
	{
		offset = es->eip;
	}
	else
	{
		offset = -1;
	}

	for (eli = emu_list_first(results); !emu_list_attail(eli); eli = emu_list_next(eli))
	{
		emu_stats_free((struct emu_stats *)eli->data);
	}
	emu_list_destroy(results);

	return offset - STATIC_OFFSET;
}
Пример #15
0
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);
}
int32_t	env_w32_hook_fwrite(struct emu_env *env, struct emu_env_hook *hook)
{
	logDebug(env->emu, "Hook me Captain Cook!\n");
	logDebug(env->emu, "%s:%i %s\n",__FILE__,__LINE__,__FUNCTION__);

	struct emu_cpu *c = emu_cpu_get(env->emu);

	uint32_t eip_save;

	POP_DWORD(c, &eip_save);

/*
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
*/

	uint32_t p_buffer;
	MEM_DWORD_READ(c, c->reg[esp], &p_buffer);
	

    uint32_t size;
	MEM_DWORD_READ(c, (c->reg[esp]+4), &size);



	uint32_t count;
	MEM_DWORD_READ(c, (c->reg[esp]+8), &count);

	unsigned char *buffer = malloc(size*count);
	emu_memory_read_block(emu_memory_get(env->emu), p_buffer, buffer, size*count);



	uint32_t p_stream;
	MEM_DWORD_READ(c, c->reg[esp]+12, &p_stream);
	

	uint32_t returnvalue;
	if ( hook->hook.win->userhook != NULL )
	{
		returnvalue = hook->hook.win->userhook(env, hook, 
											   buffer,
											   size,
											   count,
											   p_stream);
	}else
	{
		returnvalue	= size*count;
	}


	logDebug(env->emu, "fwrite(0x%08x, %d, %d, 0x%08x)\n", p_buffer, size, count, p_stream);
	
	emu_cpu_reg32_set(c, eax, returnvalue);

	if ( env->profile != NULL )
	{
		emu_profile_function_add(env->profile, "fwrite");
		emu_profile_function_returnvalue_int_set(env->profile, "size_t", returnvalue);
		emu_profile_argument_add_ptr(env->profile, "const void *", "buffer", p_buffer);
		emu_profile_argument_add_bytea(env->profile, "", "", buffer, size*count);
		emu_profile_argument_add_int(env->profile, "size_t", "size", size);
		emu_profile_argument_add_int(env->profile, "count_t", "count", count);
		emu_profile_argument_add_ptr(env->profile, "FILE *", "stream", p_stream);
		emu_profile_argument_add_none(env->profile);
	}

	free(buffer);

    emu_cpu_eip_set(c, eip_save);
	return 0;
}
Пример #17
0
int32_t env_linux_hook_execve(struct emu_env *env, struct emu_env_hook *hook)
{
	printf("execve\n");
	struct emu_cpu *c = emu_cpu_get(env->emu);

	struct emu_string *name = emu_string_new();
	emu_memory_read_string(emu_memory_get(c->emu), c->reg[ebx], name, 255);

	if ( env->profile != NULL )
	{
		emu_profile_function_add(env->profile, "execve");
		emu_profile_argument_add_ptr(env->profile, "const char *", "dateiname", c->reg[ebx]);

		emu_profile_argument_add_string(env->profile, "", "", emu_string_char(name));
//	emu_profile_argument_add_ptr(env->profile, "", "", c->reg[ecx]);
		emu_profile_argument_array_start(env->profile, "const char *", "argv[]");
	}

	uint32_t p_array = c->reg[ecx];
	uint32_t p_arg = -1;
	emu_memory_read_dword(emu_memory_get(c->emu), p_array, &p_arg);
	int i=1;
//	char **argv = NULL;
	while (p_arg != 0)
	{
//		argv = realloc(argv, (i+1) * sizeof(char *));
//		argv[i] = NULL;

		struct emu_string *arg = emu_string_new();
		emu_memory_read_string(emu_memory_get(c->emu), p_arg, arg, 128);
//		argv[i-1] = strdup(emu_string_char(arg));

		if( emu_string_char(arg) == NULL )
		{
			emu_string_free(arg);
			break;
		}

		if ( env->profile != NULL )
		{
			emu_profile_argument_add_ptr(env->profile, "", "", p_array+((i-1)*4));
			emu_profile_argument_add_ptr(env->profile, "", "", p_arg);
			emu_profile_argument_add_string(env->profile, "", "", emu_string_char(arg));
		}

		emu_string_free(arg);
		emu_memory_read_dword(emu_memory_get(c->emu), p_array+(i*4), &p_arg);
		i++;
	}

	if ( env->profile != NULL )
	{
		emu_profile_argument_add_ptr(env->profile, "", "", p_arg);
		emu_profile_argument_add_none(env->profile);

//	printf("arg is %s\n", emu_string_char(arg));

		emu_profile_argument_array_end(env->profile);

		emu_profile_argument_add_ptr(env->profile, "const char *", "envp[]", c->reg[edx]);
		emu_profile_argument_add_none(env->profile);

		emu_profile_function_returnvalue_int_set(env->profile, "int", 0);
	}
	printf("int execve (const char *dateiname=%08x={%s}, const char * argv[], const char *envp[]);\n", 
		   c->reg[ebx],
		   emu_string_char(name));

	emu_string_free(name);
	return 0;
}
Пример #18
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();
	

}
Пример #19
0
void emulate(struct emu_config *conf, struct connection *con, void *data, unsigned int size, unsigned int offset)
{
	struct emu_emulate_ctx *ctx = g_malloc0(sizeof(struct emu_emulate_ctx));
	ctx->config = conf;

	ctx->sockets = g_hash_table_new(g_int_hash, g_int_equal);
	ctx->processes = g_hash_table_new(g_int_hash, g_int_equal);
	ctx->files = g_hash_table_new(g_int_hash, g_int_equal);

	ctx->ctxcon = con;
	if( con )
		connection_ref(ctx->ctxcon);

	ctx->emu = emu_new();
	ctx->env = emu_env_new(ctx->emu);
	struct emu_env * env = ctx->env;
	struct emu *e = ctx->emu;
	struct emu_cpu *cpu = emu_cpu_get(ctx->emu);
	ctx->env->userdata = ctx;
	g_mutex_init(&ctx->mutex);
	ctx->serial = 67;

	emu_env_w32_load_dll(env->env.win,"ws2_32.dll");
	emu_ll_w32_export_hook(env, "accept", ll_win_hook_accept, NULL);
	emu_env_w32_export_hook(env, "bind", user_hook_bind, NULL);
	emu_env_w32_export_hook(env, "closesocket", user_hook_close, NULL);
	emu_env_w32_export_hook(env, "connect", user_hook_connect, NULL);

	emu_env_w32_export_hook(env, "listen", user_hook_listen, NULL);
	emu_ll_w32_export_hook(env, "recv", ll_win_hook_recv, NULL);
	emu_env_w32_export_hook(env, "send", user_hook_send, NULL);
	emu_env_w32_export_hook(env, "socket", user_hook_socket, NULL);
	emu_env_w32_export_hook(env, "WSASocketA", user_hook_WSASocket, NULL);
	emu_env_w32_export_hook(env, "CreateProcessA", user_hook_CreateProcess, NULL);
	emu_env_w32_export_hook(env, "WaitForSingleObject", user_hook_WaitForSingleObject, NULL);

	emu_env_w32_export_hook(env, "CreateFileA", user_hook_CreateFile, NULL);
	emu_env_w32_export_hook(env, "WriteFile", user_hook_WriteFile, NULL);
	emu_env_w32_export_hook(env, "CloseHandle", user_hook_CloseHandle, NULL);

	emu_env_w32_export_hook(env, "_lcreat", user_hook__lcreat, NULL);
	emu_env_w32_export_hook(env, "_lwrite", user_hook__lwrite, NULL);
	emu_env_w32_export_hook(env, "_lclose", user_hook__lclose, NULL);

//	emu_env_linux_syscall_hook(env, "exit", user_hook_exit, NULL);
//	emu_env_linux_syscall_hook(env, "socket", user_hook_socket, NULL);
//	emu_env_linux_syscall_hook(env, "bind", user_hook_bind, NULL);
//	emu_env_linux_syscall_hook(env, "listen", user_hook_listen, NULL);
//	emu_env_linux_syscall_hook(env, "accept", user_hook_accept, NULL);

#define CODE_OFFSET 0x417000

	int j;
	for( j=0; j<8; j++ )
		emu_cpu_reg32_set(cpu,j , 0);

// set flags
	emu_cpu_eflags_set(cpu, 0);

// write code to offset
	emu_memory_write_block(emu_memory_get(ctx->emu), CODE_OFFSET, data,  size);

// set eip to code
	emu_cpu_eip_set(emu_cpu_get(e), CODE_OFFSET + offset);
	emu_cpu_reg32_set(emu_cpu_get(e), esp, 0x0012fe98);
	emulate_thread(NULL, ctx);
}
Пример #20
0
/**
 * This function takes the emu, the offset and tries to run 
 * steps iterations. If it fails due to uninitialized 
 * registers/eflags it will try to use the information passed by 
 * etas to traverse the instruction tree and find an instruction
 * path in the tree which satisfies the initialization 
 * requirements.
 *  
 * To avoid testing the same positions over and over, the 
 * already-tested positions are held in the known_positions 
 * hashtable.
 *  
 * The result is returned in the tested_positions_list.
 * 
 *  
 * The function is called for every GetPC candidate in the 
 * suspected shellcode, therefore the known_positions prevent 
 * testing the same locations for different starting points in 
 * the data too.
 *  
 * It is the vital part of libemu's shellcode detection, hard to
 * understand, hard to improve and hard to fix.
 *  
 * Messing this function up, destroys libemu's shellcode 
 * detection.
 *  
 * The function is a mess, given the complexity of the loops it 
 * is too long and the variable names do not provide any help.
 *  
 * The bruteforce flag is useful, as it allows bfs even if some 
 * instructions initializations are not set properly, but you'll 
 * definitely miss its impact on the behaviour when making a 
 * guess why something does not work. 
 *  
 * short explanation of the logic: 
 *  
 * the first starting point is our offset 
 *  
 * while we have starting points: 
 *     run the shellcode: error?
 *  	   no!
 * 		   continue
 *     yes!
 *     use the current starting eip as starting point to bfs 
 *     look for instructions which satisfy the requirements OR
 *     brutefore
 * 	       queue these new instructions as starting points
 *  
 *  
 *  
 * History has proven the the function to be susceptible to 
 * denial of service attacks, running the system out of memory 
 * or cycles. 
 * So, if you experience a 'problem', this is the first place to 
 * look at, and the last one you want to look at, if you want to
 * cause a 'problem', same rules apply. 
 *  
 * This comment was written when patching one of these dos 
 * problems 
 * The known_positions arg has been unused for the time before, 
 * seems like there was a good idea when writing the function 
 * initially, but this good idea was abandoned once 'it worked'
 *  
 * 
 * 
 * @param e         the emu to run
 * @param data      the data we run
 * @param datasize  the data size
 * @param eipoffset the offset for eip
 * @param steps     how many steps to try running
 * @param etas      the track and source tree - the substantial
 *                  information to run the breath first search
 * @param known_positions
 *                  already tested positions
 * @param stats_tested_positions_list
 *                  the result list
 * @param brute_force
 *                  be aggressive?
 * 
 * @return 
 */
int32_t     emu_shellcode_run_and_track(struct emu *e, 
										uint8_t *data, 
										uint16_t datasize, 
										uint16_t eipoffset,
										uint32_t steps,
//										struct emu_env_w32 *env, 
										struct emu_track_and_source *etas,
										struct emu_hashtable *known_positions,
										struct emu_list_root *stats_tested_positions_list,
										bool brute_force
									   )
{
	struct emu_cpu *cpu = emu_cpu_get(e);
	struct emu_memory *mem = emu_memory_get(e);


	struct emu_queue *eq = emu_queue_new();
	emu_queue_enqueue(eq, (void *)((uintptr_t)(uint32_t)eipoffset+STATIC_OFFSET));

//	struct emu_list_root *tested_positions = emu_list_create();

	struct emu_env *env = NULL;

	{ // mark all vertexes white

		struct emu_vertex *x;
		for ( x= emu_vertexes_first(etas->static_instr_graph->vertexes); !emu_vertexes_attail(x); x = emu_vertexes_next(x))
		{
			x->color = white;
		}

	}		 

	while ( !emu_queue_empty(eq) )
	{
		
		uint32_t current_offset = (uint32_t)(uintptr_t)emu_queue_dequeue(eq);

		/* init the cpu/memory 
		 * scooped to keep number of used varnames small 
		 */
        {
			logDebug(e, "running at offset %i %08x\n", current_offset, current_offset);

			emu_memory_clear(mem);
			if (env)
				emu_env_free(env);

			/* write the code to the offset */
			emu_memory_write_block(mem, STATIC_OFFSET, data, datasize);
			
			env = emu_env_new(e);

			/* set the registers to the initial values */
			int reg;
			for ( reg=0;reg<8;reg++ )
				emu_cpu_reg32_set(cpu,reg ,0x0);

			emu_cpu_reg32_set(cpu, esp, 0x00120000);
			emu_cpu_eip_set(cpu, current_offset);

			/* set the flags */
			emu_cpu_eflags_set(cpu,0x0);

			cpu->tracking = etas;
		}

		emu_tracking_info_clear(&etas->track);

		int j;
		for ( j=0;j<steps;j++ )
		{
//			emu_cpu_debug_print(cpu);
			uint32_t eipsave;
			eipsave = emu_cpu_eip_get(cpu);

			struct emu_env_hook *hook = NULL;

			hook = emu_env_w32_eip_check(env);


			if ( hook != NULL )
			{
				if ( hook->hook.win->fnhook == NULL )
					break;
			}
			else
			{

				int32_t ret = emu_cpu_parse(emu_cpu_get(e));
				if ( ret == -1 )
				{
					logDebug(e, "error at %s\n", cpu->instr_string);
					break;
				}

				ret = emu_cpu_step(emu_cpu_get(e));
				if ( ret == -1 )
				{
					logDebug(e, "error at %s (%s)\n", cpu->instr_string, strerror(emu_errno(e)));
					if (brute_force)
					{
						logDebug(e, "goto traversal\n");
						goto traversal;
					}
					else
						break;
				}

				if ( emu_track_instruction_check(e, etas) == -1 )
				{
traversal:
					logDebug(e, "failed instr %s\n", cpu->instr_string);
					logDebug(e, "tracking at eip %08x\n", eipsave);
					if ( 0 && cpu->instr.is_fpu )
					{

					}
					else
					{

						/* save the requirements of the failed instruction */
//						struct emu_tracking_info *instruction_needs_ti = emu_tracking_info_new();
//						emu_tracking_info_copy(&cpu->instr.cpu.track.need, instruction_needs_ti);

						struct emu_queue *bfs_queue = emu_queue_new();

						/*
						 * the current starting point is the first position used to bfs
						 * scooped to avoid varname collisions 
						 */
						{ 
							struct emu_tracking_info *eti = emu_tracking_info_new();
							emu_tracking_info_diff(&cpu->instr.track.need, &etas->track, eti);
							eti->eip = current_offset;
							emu_tracking_info_debug_print(eti);

							if( emu_hashtable_search(known_positions, (void *)(uintptr_t)(uint32_t)current_offset) != NULL)
							{
								logDebug(e, "Known %p %x\n", eti, eti->eip);
								emu_tracking_info_free(eti);
								emu_queue_free(bfs_queue);
								break;
							}

							emu_queue_enqueue(bfs_queue, eti);
						}
						while ( !emu_queue_empty(bfs_queue) )
						{
							logDebug(e, "loop %s:%i\n", __FILE__, __LINE__);

							struct emu_tracking_info *current_pos_ti_diff = (struct emu_tracking_info *)emu_queue_dequeue(bfs_queue);
							struct emu_hashtable_item *current_pos_ht = emu_hashtable_search(etas->static_instr_table, (void *)(uintptr_t)(uint32_t)current_pos_ti_diff->eip);
							if (current_pos_ht == NULL)
							{
								logDebug(e, "current_pos_ht is NULL?\n");
								exit(-1);
							}

							struct emu_vertex *current_pos_v = (struct emu_vertex *)current_pos_ht->value;
							struct emu_source_and_track_instr_info *current_pos_satii = (struct emu_source_and_track_instr_info *)current_pos_v->data;

							if( emu_hashtable_search(known_positions, (void *)(uintptr_t)(uint32_t)current_pos_satii->eip) != NULL )
							{
								logDebug(e, "Known Again %p %x\n", current_pos_satii, current_pos_satii->eip);
								current_pos_v->color = red;
								emu_tracking_info_free(current_pos_ti_diff);
								continue;
							}

							if (current_pos_v->color == red)
							{
								logDebug(e, "is red %p %x: %s\n", (uintptr_t)current_pos_v, current_pos_satii->eip, current_pos_satii->instrstring);
								emu_tracking_info_free(current_pos_ti_diff);
								continue;
							}

							logDebug(e, "marking red %p %x: %s \n", (uintptr_t)current_pos_v, current_pos_satii->eip, current_pos_satii->instrstring);
							current_pos_v->color = red;

							emu_hashtable_insert(known_positions, (void *)(uintptr_t)(uint32_t)current_pos_satii->eip, NULL);

							while ( !emu_tracking_info_covers(&current_pos_satii->track.init, current_pos_ti_diff) || brute_force )
							{
								logDebug(e, "loop %s:%i\n", __FILE__, __LINE__);

								if ( current_pos_v->backlinks == 0 )
								{
									break;
								}
								else
								if ( current_pos_v->backlinks > 1 )
								{ /* queue all to diffs to the bfs queue */
									struct emu_edge *ee;
									struct emu_vertex *ev;
									for ( ee = emu_edges_first(current_pos_v->backedges); !emu_edges_attail(ee); ee=emu_edges_next(ee) )
									{
										ev = ee->destination;
										/**
										 * ignore positions we've visited already 
										 * avoids dos for jz 0 
										 *  
										 * try the next position instead 
										 */
										if( ev->color == red )
											continue;

										struct emu_source_and_track_instr_info *next_pos_satii =  (struct emu_source_and_track_instr_info *)ev->data;
										

										

										logDebug(e, "EnqueueLoop %p %x %s\n", next_pos_satii, next_pos_satii->eip, next_pos_satii->instrstring);
										struct emu_tracking_info *eti = emu_tracking_info_new();
										emu_tracking_info_diff(current_pos_ti_diff, &current_pos_satii->track.init, eti);
										eti->eip = next_pos_satii->eip;
										emu_queue_enqueue(bfs_queue, eti);
									}
									/**
									 * the new possible positions and requirements got queued into the bfs queue, 
									 *  we break here, so the new queued positions can try to work it out
									 */
									break;
								}
								else
								if ( current_pos_v->backlinks == 1 )
								{ /* follow the single link */
									/**
									 * ignore loops	to self 
									 * avoids dos for "\xe3\xfe\xe8" 
									 * breaks the upper loop 
									 *  
									 */
									if( current_pos_v == emu_edges_first(current_pos_v->backedges)->destination )
										break;
									
									current_pos_v = emu_edges_first(current_pos_v->backedges)->destination;
									/**
									 * again, ignore already visited positions 
									 * breaks the upper loop 
									 */
									if( current_pos_v->color == red )
										break;

									current_pos_v->color = red;
									
									struct emu_source_and_track_instr_info *next_pos_satii =  (struct emu_source_and_track_instr_info *)current_pos_v->data;
									logDebug(e, "FollowSingle %p %i %x %s\n", next_pos_satii, current_pos_v->color, next_pos_satii->eip, next_pos_satii->instrstring);
									current_pos_satii = (struct emu_source_and_track_instr_info *)current_pos_v->data;
									emu_tracking_info_diff(current_pos_ti_diff, &current_pos_satii->track.init, current_pos_ti_diff);
								}
							}

							if ( emu_tracking_info_covers(&current_pos_satii->track.init, current_pos_ti_diff) || brute_force )
							{
								/**
								 * we have a new starting point, this starting point may fail
								 * too - if further backwards traversal is required
								 * therefore we mark it white, so it can be processed again
								 */
								logDebug(e, "found position which satiesfies the requirements %i %08x\n", current_pos_satii->eip, current_pos_satii->eip);
								current_pos_ht = emu_hashtable_search(etas->static_instr_table, (void *)(uintptr_t)(uint32_t)current_pos_satii->eip);
								current_pos_v = (struct emu_vertex *)current_pos_ht->value;

								if(current_pos_satii->eip != current_offset )
								{
									logDebug(e, "marking white %p %x: %s \n", (uintptr_t)current_pos_v, current_pos_satii->eip, current_pos_satii->instrstring);
									current_pos_v->color = white;
								}
								emu_tracking_info_debug_print(&current_pos_satii->track.init);
								emu_queue_enqueue(eq, (void *)((uintptr_t)(uint32_t)current_pos_satii->eip));
							}
//discard:
							emu_tracking_info_free( current_pos_ti_diff);
						}
						emu_queue_free(bfs_queue);
					}
					/** 
					 * the shellcode did not run correctly as he was missing instructions initializing required registers
					 * we did what we could do in the prev lines of code to find better offsets to start from
					 * the working offsets got queued into the main queue, so we break here to give them a chance
                     */
					break;
				}else
				{
					logDebug(e, "%s\n", cpu->instr_string);
				}
			}
		}

		struct emu_stats *es = emu_stats_new();
		es->eip = current_offset;
		es->cpu.steps = j;
		struct emu_list_item *eli = emu_list_item_create();
		eli->data = es;
		logDebug(e, "INSERT %i %x steps %i\n", current_offset, current_offset, j);
		emu_list_insert_last(stats_tested_positions_list, eli);
	}

	emu_queue_free(eq);
	emu_env_free(env);

	/* sort all tested positions by the number of steps ascending */
	emu_list_qsort(stats_tested_positions_list, tested_positions_cmp);

	struct emu_list_item *eli = emu_list_first(stats_tested_positions_list);
	struct emu_stats *es = (struct emu_stats *)eli->data;
	uint32_t best_offset = es->eip;

	return best_offset - STATIC_OFFSET;
}
int32_t	env_w32_hook_fopen(struct emu_env *env, struct emu_env_hook *hook)
{
	logDebug(env->emu, "Hook me Captain Cook!\n");
	logDebug(env->emu, "%s:%i %s\n",__FILE__,__LINE__,__FUNCTION__);

	struct emu_cpu *c = emu_cpu_get(env->emu);

	uint32_t eip_save;

	POP_DWORD(c, &eip_save);

/*
FILE *fopen( const char *filename, const char *mode );
FILE *_wfopen( const wchar_t *filename, const wchar_t *mode );
*/

	uint32_t p_filename;
	MEM_DWORD_READ(c, c->reg[esp], &p_filename);

	struct emu_string *filename = emu_string_new();
	emu_memory_read_string(c->mem, p_filename, filename, 512);
	
	uint32_t p_mode;
	MEM_DWORD_READ(c, c->reg[esp]+4, &p_mode);
	struct emu_string *mode = emu_string_new();
	emu_memory_read_string(c->mem, p_mode, mode, 512);



//	printf("fopen(%s, %s)\n", emu_string_char(filename), (char *)mode->data);
	

	uint32_t returnvalue;
	if ( hook->hook.win->userhook != NULL )
	{
		returnvalue = hook->hook.win->userhook(env, hook, 
											   emu_string_char(filename),
											   emu_string_char(mode));
	}else
	{
		returnvalue	= 0x89898989;
	}

	emu_cpu_reg32_set(c, eax, returnvalue);

	if (env->profile != NULL)
	{
		emu_profile_function_add(env->profile, "fopen");
		emu_profile_argument_add_ptr(env->profile, "const char *", "filename", p_filename);
		emu_profile_argument_add_string(env->profile, "", "", emu_string_char(filename));
		emu_profile_argument_add_ptr(env->profile, "const char *", "mode", p_mode);
		emu_profile_argument_add_string(env->profile,  "", "", emu_string_char(mode));
		emu_profile_function_returnvalue_ptr_set(env->profile, "FILE *", returnvalue);
		emu_profile_argument_add_none(env->profile);
	}



	emu_string_free(filename);
	emu_string_free(mode);

    emu_cpu_eip_set(c, eip_save);
	return 0;
}
Пример #22
0
int32_t env_linux_hook_socketcall(struct emu_env *env, struct emu_env_hook *hook)
{
	struct emu_cpu *c = emu_cpu_get(env->emu);

#define AL(x) (x)
	static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
		AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
		AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
#undef AL

	uint32_t a[6];
	int i;
	for ( i=0;i<nargs[c->reg[ebx]];i++ )
	{
		emu_memory_read_dword(emu_memory_get(c->emu),c->reg[ecx]+4*i,a+i);
	}

	uint32_t returnvalue = 0;

	switch ( c->reg[ebx] )
	{
	case 1:	// SYS_SOCKET 
		printf("int socket(int domain=%i, int type=%i, int protocol=%i);\n",
			   a[0],
			   a[1],
			   a[2]);

		if (hook->hook.lin->userhook != NULL)
			returnvalue = hook->hook.lin->userhook(env, hook, a[0], a[1],  a[2]);
		else
			returnvalue = 14;

		if ( env->profile != NULL )
		{
			emu_profile_function_add(env->profile, "socket");
			emu_profile_argument_add_int(env->profile, "int", "domain",     a[0]);
			emu_profile_argument_add_int(env->profile, "int", "type",       a[1]);
			emu_profile_argument_add_int(env->profile, "int", "protocol",   a[2]);

			emu_profile_function_returnvalue_int_set(env->profile, "int", returnvalue);
		}

		emu_cpu_reg32_set(c, eax, returnvalue);

		break;

	case 2:	// SYS_BIND 
		{

/*
			printf("int bind(int sockfd=%i, struct sockaddr *my_addr=%08x={host %s port %i}, int addrlen);\n",
				   a[0],
				   a[1], inet_ntoa(*(struct in_addr *)&((struct sockaddr_in *)&sa)->sin_addr), ntohs(((struct sockaddr_in *)&sa)->sin_port) 
				  );
*/



			struct sockaddr sa;
			memset(&sa, 0, sizeof(struct sockaddr));
			emu_memory_read_block(emu_memory_get(c->emu), a[1], &sa, sizeof(struct sockaddr));


			if (hook->hook.lin->userhook != NULL)
				returnvalue = hook->hook.lin->userhook(env, hook, a[0], &sa,  a[2]);
			else
				returnvalue = 0;

			if (env->profile != NULL)
			{
				emu_profile_function_add(env->profile, "bind");
				emu_profile_argument_add_int(env->profile, "int", "sockfd", a[0]);
				emu_profile_argument_add_sockaddr_ptr(env->profile, "my_addr", a[1], sa);
				emu_profile_argument_add_int(env->profile, "int", "addrlen", a[2]);
				emu_profile_function_returnvalue_int_set(env->profile, "int", returnvalue);
			}
			
			emu_cpu_reg32_set(c, eax, returnvalue);

		}


		break;

	case 3:	// SYS_CONNECT 
		{

			printf("connect\n");

			struct sockaddr sa;
			memset(&sa, 0, sizeof(struct sockaddr));
			emu_memory_read_block(emu_memory_get(c->emu), a[1], &sa, sizeof(struct sockaddr));


			if (hook->hook.lin->userhook != NULL)
				returnvalue = hook->hook.lin->userhook(env, hook, a[0], &sa,  a[2]);
			else
				returnvalue = 0;

			if (env->profile != NULL)
			{
				emu_profile_function_add(env->profile, "connect");
				emu_profile_argument_add_int(env->profile, "int", "sockfd", a[0]);
				emu_profile_argument_add_sockaddr_ptr(env->profile, "serv_addr", a[1], sa);
				emu_profile_argument_add_int(env->profile, "int", "addrlen", a[2]);
				emu_profile_function_returnvalue_int_set(env->profile, "int", returnvalue);
			}

			emu_cpu_reg32_set(c, eax, returnvalue);
		}
		break;

	case 4:	// SYS_LISTEN 
		printf("int listen(int s=%i, int backlog=%i);\n", 
			   a[0], 
			   a[1]);

		if (hook->hook.lin->userhook != NULL)
			returnvalue = hook->hook.lin->userhook(env, hook, a[0], a[1]);
		else
			returnvalue = 0;

		if (env->profile != NULL)
		{
			emu_profile_function_add(env->profile, "listen");
			emu_profile_argument_add_int(env->profile, "int", "s", a[0]);
			emu_profile_argument_add_int(env->profile, "int", "backlog", a[1]);
			emu_profile_function_returnvalue_int_set(env->profile, "int", returnvalue);
		}
		
		emu_cpu_reg32_set(c, eax, returnvalue);

		break;

	case 5:	// SYS_ACCEPT 
		printf("int accept(int s=%i, struct sockaddr *addr=%08x, int *addrlen=%08x);\n",
			   a[0],
			   a[1],
			   a[2]);


		struct sockaddr sa;
		memset(&sa, 0, sizeof(struct sockaddr));
		emu_memory_read_block(emu_memory_get(c->emu), a[1], &sa, sizeof(struct sockaddr));


		if (hook->hook.lin->userhook != NULL)
			returnvalue = hook->hook.lin->userhook(env, hook, a[0], &sa, a[2]);
		else
			returnvalue = 19;


		if (env->profile != NULL)
		{
			emu_profile_function_add(env->profile, "accept");
			emu_profile_argument_add_int(env->profile, "int", "sockfd", a[0]);

			emu_profile_argument_add_ptr(env->profile, "sockaddr_in *", "addr", a[1]);
			emu_profile_argument_add_none(env->profile);

			emu_profile_argument_add_ptr(env->profile, "int", "addrlen", a[2]);
			emu_profile_argument_add_none(env->profile);
		
			emu_profile_function_returnvalue_int_set(env->profile, "int", returnvalue);
		}
		emu_cpu_reg32_set(c, eax, returnvalue);
		break;

	case 6:	// SYS_GETSOCKNAME 
		printf("sys_getsockname(2)\n");
		break;

	case 7:	// SYS_GETPEERNAME 
		printf("sys_getpeername(2)\n");
		break;

	case 8:	// SYS_SOCKETPAIR 
		printf("sys_socketpair(2)\n");
		break;

	case 9:	// SYS_SEND 
		printf("sys_send(2)\n");
		break;

	case 10: // SYS_RECV 
		printf("sys_recv(2)\n");
		break;

	case 11: // SYS_SENDTO 
		printf("sys_sendto(2)\n");
		break;

	case 12: // SYS_RECVFROM 
		printf("sys_recvfrom(2)\n");
		break;

	case 13: // SYS_SHUTDOWN 
		printf("sys_shutdown(2)\n");
		break;

	case 14: // SYS_SETSOCKOPT 
		printf("sys_setsockopt(2)\n");
		break;

	case 15: // SYS_GETSOCKOPT 
		printf("sys_getsockopt(2)\n");
		break;

	case 16: // SYS_SENDMSG 
		printf("sys_sendmsg(2)\n");
		break;

	case 17: // SYS_RECVMSG 
		printf("sys_recvmsg(2)\n");
		break;

	default:
		printf("syscall %i (%x) unknown",  c->reg[ebx], c->reg[ebx]);
	}

	return 0;
}
Пример #23
0
Emulator_LibEmu::Emulator_LibEmu() {
    e = emu_new();
    cpu = emu_cpu_get(e);
    mem = emu_memory_get(e);
    im_base=0;
}