コード例 #1
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;
}
コード例 #2
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;
}
コード例 #3
0
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;
}
コード例 #4
0
void Emulator_LibEmu::begin(char* & buf, const uint len, const uint entry_point, const uint base) {
    im_base=base;
    for (int i=0; i<8; i++) {
        emu_cpu_reg32_set(cpu, (emu_reg32) i, 0);
    }
    emu_cpu_reg32_set(cpu, esp, int(im_base/2));


    emu_memory_clear(mem);
    emu_memory_write_block(mem, im_base, (void*)buf, len);
    /*
    int i=0;
    for (i=0; i<len; i++){
    	emu_memory_write_byte(mem, 0x20000000L+i, buf[i]);
    }
    */
    emu_memory_write_byte(mem, im_base+len, '\xcc');
    jump(entry_point);
}
コード例 #5
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;
}
コード例 #6
0
ファイル: profile.c プロジェクト: CZ-NIC/dionaea
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);
}
コード例 #7
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;
}
コード例 #8
0
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;
}
コード例 #9
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;
}
コード例 #10
0
ファイル: emu_shellcode.c プロジェクト: bwall/libemu
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;
}
コード例 #11
0
ファイル: emu_shellcode.c プロジェクト: bwall/libemu
/**
 * 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;
}
コード例 #12
0
ファイル: emulate.c プロジェクト: CZ-NIC/dionaea
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);
}
コード例 #13
0
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;
}
コード例 #14
0
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;
}