Exemple #1
0
static void
handle_msg( mol_dgram_t *dg )
{
	cmd_entry_t *ce = sv.cmd_root;
	int i, val;
	
	switch( dg->what ) {
	case kMDG_connect:
		printm("Debugger attached\n");
		sv.dbg_attached = 1;
		send_dgram( sv.sock, kMDG_connect );
		send_mregs();
		send_dgram( sv.sock, kMDG_refresh_debugger );

		/* send debugger commands */
		for( ce=sv.cmd_root; ce; ce=ce->next ) {
			int s = strlen( ce->cmdname ) + 1;
			int t = strlen( ce->help ) + 1;
			char *b = malloc( s + t );
			strcpy( b, ce->cmdname );
			strcpy( b+s, ce->help );
			send_dgram_buf2( sv.sock, kMDG_dbg_cmd, b, s+t, s, -1 /*dummy*/ );
			free( b );
		}
		break;

	case kMDG_disconnect:
		sv.dbg_attached = 0;
		close_sock();
		printm("Debugger detached\n");
		break;

	case kMDG_mregs:
		send_mregs();
		break;

	case kMDG_write_mregs:
		receive_mregs( (mac_regs_t*)dg->data );
		break;

	case kMDG_read_dpage: { /* ea, context, data_access */
		char buf[0x2000];

		dg->p0 &= ~0xfff;
		restore_breakpoints();
		for( i=0; i<2; i++ ) {
			char *lvptr;
			if( ea_to_lvptr( dg->p0 + i*0x1000, dg->p1, &lvptr, dg->p2 ) )
				memset( buf+i*0x1000, 0xDE, 0x1000 );
			else
				memcpy( buf+i*0x1000, lvptr, 0x1000 );
		}
		setup_breakpoints();
		send_dgram_buf( sv.sock, kMDG_dpage_data, buf, 0x2000 );
		break;
	}

	case kMDG_in_ppc_mode:	/* flag */
		sv.in_ppc_mode = dg->p0;
		break;

	case kMDG_debug_action: /* action (go, single-step, etc.) */
		debug_action( dg->p0 );
		break;

	case kMDG_add_breakpoint: /* addr, flags, data */
		add_breakpoint( dg->p0, dg->p1, dg->p2 );
		break;

	case kMDG_is_breakpoint: { /* mvptr */ 
		char breakbuf[ BREAK_BUF_SIZE ];
		for(i=0; i<BREAK_BUF_SIZE; i++ ){
			if( !is_breakpoint( dg->p0 + i*4, &breakbuf[i] ) )
				breakbuf[i] = 0;
		}
		send_dgram_buf1( sv.sock, kMDG_is_breakpoint, breakbuf, BREAK_BUF_SIZE, dg->p0 );
		break;
	}
	
	case kMDG_dbg_cmd:
		val = do_dbg_cmd( (remote_cmd_t*)dg->data );
		send_dgram1( sv.sock, kMDG_result, val );
		break;

	default:
		printm("Unknown dbg-message %d received\n", dg->what );
		break;
	}
}
Exemple #2
0
void debugger_proc(pid_t child_proc, struct execute_context *ctx)
{
    /* about child process */
    int child_stat;
    kern_return_t kret;
    mach_port_t task;
    int wait_cnt = 0;
    char **args = ctx->passing_args;

    /* related analysys of target process binary. */
    int i;
    int nsym;
    int text_section;
    uint64_t text_section_offset;
    uint64_t text_section_size;
    uint64_t text_section_vmaddr;
    struct symbol_info *psymbol_table;
    int init = 0;
    struct breakpoint_entry top;

    int stack_depth = 0;

    /* error check */
    if (child_proc == 0 || child_proc == -1)	return;

    /* initialize */
    memset(&top, 0x00, sizeof(top));

    /* open the port (do as an administrator) */
    kret = task_for_pid(mach_task_self(), child_proc, &task);
    if (kret != KERN_SUCCESS) {
        fprintf(stderr, "task_for_pid() failed\n");
        fprintf(stderr, "%s\n", mach_error_string(kret));
        exit(0);
    }

    fprintf(stderr, "[Tracer] child_proc: %d\n", child_proc);
    /* main loop */
    while(waitpid(child_proc, &child_stat, WUNTRACED)) {    /* {{{ */
        char buffer[128];
        char w_buf[128];
        w_buf[0] = 0x90;	/* nop */

        if (WIFEXITED(child_stat)) {
            /* Child Process Terminated */
            fprintf(stderr, "[Tracer]  Process :%d Terminated\n", child_proc);
            return;
        }
        memset(buffer, 0x00, 128);
        if(wait_cnt == 0) {
            /* The First time trapped   {{{ */
            /* -- The debugee program has not been expanded.-- */
            /* -- 	lookup named symbol	-- */
            struct file_info bininfo;
            ud_t ud_obj;
            uint64_t previous_eip;
            uint64_t func_start_addr;
            uint64_t func_end_addr;

            nsym = get_func_table(args[0], &psymbol_table, &text_section, &text_section_offset, &text_section_size, &text_section_vmaddr);
            debug_printf("nsym: %d\n", nsym);
            debug_printf("text section = %d\n", text_section);
            debug_printf("text section offset: 0x%llx\n", text_section_offset);
            debug_printf("text section size: 0x%llx\n", text_section_size);
            debug_printf("text section vmaddr: 0x%llx\n", text_section_vmaddr);

            qsort(psymbol_table, nsym, sizeof(struct symbol_info), symbolinfo_comp);

            /* XXX for debugging  */
            /*display_symbol_table(psymbol_table, nsym);  */

            /* code analysys */
            map_binary(args[0], &bininfo);
            ud_init(&ud_obj);
            ud_set_input_buffer(&ud_obj, bininfo.top + text_section_offset, text_section_size);
            ud_set_mode(&ud_obj, 64);

            previous_eip = text_section_vmaddr;
            /* set breakpoint at the entry and exit points of functions */
            for(i = 0; i < nsym; i++) {
                /* Set breakpoints {{{ */
                if (is_exclude_func(psymbol_table + i) == 1) {
                    continue;
                }
                /* 1, specifying the region of the function */
                func_start_addr = psymbol_table[i].nlist64.n_value;
                if (i != nsym - 1) {
                    /* next section's entry point - 1 */
                    func_end_addr = psymbol_table[i + 1].nlist64.n_value;
                } else {
                    func_end_addr = text_section_vmaddr + text_section_size + 1;
                }
                printf("%s: 0x%llx --> 0x%llx\n", psymbol_table[i].name, func_start_addr, func_end_addr);
                /*
                if (strstr(psymbol_table[i].name, "main") != NULL) {
                    __asm__("int3");
                }
                */
                psymbol_table[i].ret_address_num = 0;

                previous_eip = ud_obj.pc + text_section_vmaddr;

                while(ud_disassemble(&ud_obj) && previous_eip < func_start_addr) {
                    previous_eip = ud_obj.pc + text_section_vmaddr;
                }
                while(ud_disassemble(&ud_obj) && previous_eip < func_end_addr) {
                    if (func_start_addr <= previous_eip && ud_obj.mnemonic == UD_Iret) {
                        set_breakpoint(task, previous_eip, &top);
                        psymbol_table[i].ret_inst_address[ psymbol_table[i].ret_address_num ] = previous_eip;
                        psymbol_table[i].ret_address_num++;
                    }
                    previous_eip = ud_obj.pc + text_section_vmaddr;
                }
                /*
                if (0 < psymbol_table[i].ret_address_num) {
                    set_breakpoint(task, psymbol_table[i].nlist64.n_value, &top);
                }
                */
                set_breakpoint(task, psymbol_table[i].nlist64.n_value, &top);
                /* }}} */
            }
            debug_printf("break point insert\n");
            unmap_binary(&bininfo);
            /* }}} */
        } else {
            /* {{{ */
            /* break point */
            /* 1, Get current address from RIP value.
            * 2, Find current function name by EIP, and Logging.
            * 3, Substitute original instruction code for current break point code(0x90).
            * 4, Decrement EIP value.
            * 5, Execute only one op-code.
            * 6, Substitute 0x90 for oroginal code (located in entrance of function).
            * */
            uint64_t rip;
            read_process_register_64(task, RIP, &rip);
            if (is_breakpoint(rip - 1, &top) == 1) {
                stack_depth = breakpoint_handler(task, rip - 1, psymbol_table, nsym, stack_depth);
                write_process_register_64(task, RIP, RELATIVE_VAL, -1);
                disable_breakpoint(task, rip - 1, &top);
                ptrace(PT_STEP, child_proc, (caddr_t)1, 0);
                set_breakpoint(task, rip - 1, &top);
            }
            /* }}} */
        }
        wait_cnt++;
        ptrace(PT_CONTINUE, child_proc, (caddr_t)1, 0);
    }   /* }}} */
}