コード例 #1
0
ファイル: libltrace.c プロジェクト: mer-tools/ltrace
void
ltrace_init(int argc, char **argv) {
	struct opt_p_t *opt_p_tmp;

	atexit(normal_exit);
	signal(SIGINT, signal_exit);	/* Detach processes when interrupted */
	signal(SIGTERM, signal_exit);	/*  ... or killed */

	argv = process_options(argc, argv);
	init_global_config();
	while (opt_F) {
		/* If filename begins with ~, expand it to the user's home */
		/* directory. This does not correctly handle ~yoda, but that */
		/* isn't as bad as it seems because the shell will normally */
		/* be doing the expansion for us; only the hardcoded */
		/* ~/.ltrace.conf should ever use this code. */
		if (opt_F->filename[0] == '~') {
			char path[PATH_MAX];
			char *home_dir = getenv("HOME");
			if (home_dir) {
				strncpy(path, home_dir, PATH_MAX - 1);
				path[PATH_MAX - 1] = '\0';
				strncat(path, opt_F->filename + 1,
						PATH_MAX - strlen(path) - 1);
				read_config_file(path);
			}
		} else {
			read_config_file(opt_F->filename);
		}

		struct opt_F_t *next = opt_F->next;
		if (opt_F->own_filename)
			free(opt_F->filename);
		free(opt_F);
		opt_F = next;
	}
	if (command) {
		/* Check that the binary ABI is supported before
		 * calling execute_program.  */
		struct ltelf lte = {};
		open_elf(&lte, command);
		do_close_elf(&lte);

		pid_t pid = execute_program(command, argv);
		struct Process *proc = open_program(command, pid);
		if (proc == NULL) {
			fprintf(stderr, "couldn't open program '%s': %s\n",
				command, strerror(errno));
			exit(EXIT_FAILURE);
		}

		trace_set_options(proc);
		continue_process(pid);
	}
	opt_p_tmp = opt_p;
	while (opt_p_tmp) {
		open_pid(opt_p_tmp->pid);
		opt_p_tmp = opt_p_tmp->next;
	}
}
コード例 #2
0
ファイル: proc.c プロジェクト: daljung/ltrace_android
void
open_pid(pid_t pid) {
	Process *proc;
	char *filename;

	if (trace_pid(pid) < 0) {
		fprintf(stderr, "Cannot attach to pid %u: %s\n", pid,
			strerror(errno));
		return;
	}

	filename = pid2name(pid);

	if (!filename) {
		fprintf(stderr, "Cannot trace pid %u: %s\n", pid,
				strerror(errno));
		return;
	}

	proc = open_program(filename, pid);
	continue_process(pid);
    proc->breakpoints_enabled = 1;
    //modify for android
    attach_child_thread(proc);
}
コード例 #3
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_clone(Event * event) {
	Process *p;

	debug(DEBUG_FUNCTION, "handle_clone(pid=%d)", event->proc->pid);

	p = malloc(sizeof(Process));
	if (!p) {
		perror("malloc()");
		exit(1);
	}
	memcpy(p, event->proc, sizeof(Process));
	p->pid = event->e_un.newpid;
	p->parent = event->proc;

	/* We save register values to the arch pointer, and these need
	   to be per-thread.  */
	p->arch_ptr = NULL;

	if (pending_new(p->pid)) {
		pending_new_remove(p->pid);
		if (p->event_handler != NULL)
			destroy_event_handler(p);
		if (event->proc->state == STATE_ATTACHED && options.follow) {
			p->state = STATE_ATTACHED;
		} else {
			p->state = STATE_IGNORED;
		}
		continue_process(p->pid);
		add_process(p);
	} else {
		p->state = STATE_BEING_CREATED;
		add_process(p);
	}

	if (p->leader == p)
		clone_breakpoints(p, event->proc->leader);
	else
		/* Thread groups share breakpoints.  */
		p->breakpoints = NULL;

	if (event->type == EVENT_VFORK)
		continue_after_vfork(p);
	else
		continue_process(event->proc->pid);
}
コード例 #4
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_arch_sysret(Event *event) {
	debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
	if (event->proc->state != STATE_IGNORED) {
		if (opt_T || options.summary) {
			calc_time_spent(event->proc);
		}
		if (options.syscalls) {
			output_right(LT_TOF_SYSCALLR, event->proc,
					arch_sysname(event->proc, event->e_un.sysnum));
		}
		callstack_pop(event->proc);
	}
	continue_process(event->proc->pid);
}
コード例 #5
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_arch_syscall(Event *event) {
	debug(DEBUG_FUNCTION, "handle_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
	if (event->proc->state != STATE_IGNORED) {
		callstack_push_syscall(event->proc, 0xf0000 + event->e_un.sysnum);
		if (options.syscalls) {
			output_left(LT_TOF_SYSCALL, event->proc,
					arch_sysname(event->proc, event->e_un.sysnum));
		}
		if (event->proc->breakpoints_enabled == 0) {
			enable_all_breakpoints(event->proc);
		}
	}
	continue_process(event->proc->pid);
}
コード例 #6
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_new(Event * event) {
	Process * proc;

	debug(DEBUG_FUNCTION, "handle_new(pid=%d)", event->e_un.newpid);

	proc = pid2proc(event->e_un.newpid);
	if (!proc) {
		pending_new_insert(event->e_un.newpid);
	} else {
		assert(proc->state == STATE_BEING_CREATED);
		if (options.follow) {
			proc->state = STATE_ATTACHED;
		} else {
			proc->state = STATE_IGNORED;
		}
		continue_process(proc->pid);
	}
}
void
ltrace_init(int argc, char **argv)
{
	setlocale(LC_ALL, "");

	struct opt_p_t *opt_p_tmp;

	atexit(normal_exit);
	signal(SIGINT, signal_exit);	/* Detach processes when interrupted */
	signal(SIGTERM, signal_exit);	/*  ... or killed */

	argv = process_options(argc, argv);
	init_global_config();

	if (command) {
		/* Check that the binary ABI is supported before
		 * calling execute_program.  */
		{
			struct ltelf lte;
			if (ltelf_init(&lte, command) == 0)
				ltelf_destroy(&lte);
			else
				exit(EXIT_FAILURE);
		}

		pid_t pid = execute_program(command, argv);
		struct process *proc = open_program(command, pid);
		if (proc == NULL) {
			fprintf(stderr, "couldn't open program '%s': %s\n",
				command, strerror(errno));
			exit(EXIT_FAILURE);
		}

		trace_set_options(proc);
		continue_process(pid);
	}
	opt_p_tmp = opt_p;
	while (opt_p_tmp) {
		open_pid(opt_p_tmp->pid);
		opt_p_tmp = opt_p_tmp->next;
	}
}
コード例 #8
0
ファイル: tracer.cpp プロジェクト: Artorios/IDAplugins-1
//--------------------------------------------------------------------------
static int idaapi callback(void * /*user_data*/, int notification_code, va_list va)
{
  switch ( notification_code )
  {
    case dbg_process_start:
      // reset instruction counter
      g_nb_insn = 0;
      break;

    case dbg_run_to:
      msg("tracer: entrypoint reached\n");
      enable_insn_trace(true);
      continue_process();
      break;

    // A step occured (one instruction was executed). This event
    // notification is only generated if step tracing is enabled.
    case dbg_trace:
      {
        /*thid_t tid =*/ va_arg(va, thid_t);
        ea_t ip   = va_arg(va, ea_t);
        msg("[%d] tracing over: %a\n", g_nb_insn, ip);
        if ( g_nb_insn == g_max_insn )
        {
          // stop the trace mode and suspend the process
          disable_step_trace();
          suspend_process();
          msg("process suspended (traced %d instructions)\n", g_max_insn);
        }
        else
        {
          g_nb_insn++;
        }
      }
      break;

    case dbg_process_exit:
      unhook_from_notification_point(HT_DBG, callback, NULL);
      break;
  }
  return 0;
}
コード例 #9
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_exec(Event * event) {
	Process * proc = event->proc;
	pid_t saved_pid;

	debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid);
	if (proc->state == STATE_IGNORED) {
		untrace_pid(proc->pid);
		remove_process(proc);
		return;
	}
	output_line(proc, "--- Called exec() ---");
	proc->mask_32bit = 0;
	proc->personality = 0;
	proc->arch_ptr = NULL;
	free(proc->filename);
	proc->filename = pid2name(proc->pid);
	saved_pid = proc->pid;
	proc->pid = 0;
	breakpoints_init(proc, 0);
	proc->pid = saved_pid;
	proc->callstack_depth = 0;
	continue_process(proc->pid);
}
コード例 #10
0
ファイル: handle_event.c プロジェクト: KapJlcoH/ltrace
static void
handle_breakpoint(Event *event) {
	int i, j;
	Breakpoint *sbp;
	Process *leader = event->proc->leader;

	/* The leader has terminated.  */
	if (leader == NULL) {
		continue_process(event->proc->pid);
		return;
	}

	debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", event->proc->pid, event->e_un.brk_addr);
	debug(2, "event: breakpoint (%p)", event->e_un.brk_addr);

#ifdef __powerpc__
	/* Need to skip following NOP's to prevent a fake function from being stacked.  */
	long stub_addr = (long) get_count_register(event->proc);
	Breakpoint *stub_bp = NULL;
	char nop_instruction[] = PPC_NOP;

	stub_bp = address2bpstruct(leader, event->e_un.brk_addr);

	if (stub_bp) {
		unsigned char *bp_instruction = stub_bp->orig_value;

		if (memcmp(bp_instruction, nop_instruction,
			    PPC_NOP_LENGTH) == 0) {
			if (stub_addr != (long) event->e_un.brk_addr) {
				set_instruction_pointer (event->proc, event->e_un.brk_addr + 4);
				continue_process(event->proc->pid);
				return;
			}
		}
	}
#endif

	for (i = event->proc->callstack_depth - 1; i >= 0; i--) {
		if (event->e_un.brk_addr ==
		    event->proc->callstack[i].return_addr) {
#ifdef __powerpc__
			/*
			 * PPC HACK! (XXX FIXME TODO)
			 * The PLT gets modified during the first call,
			 * so be sure to re-enable the breakpoint.
			 */
			unsigned long a;
			struct library_symbol *libsym =
			    event->proc->callstack[i].c_un.libfunc;
			void *addr = sym2addr(event->proc, libsym);

			if (libsym->plt_type != LS_TOPLT_POINT) {
				unsigned char break_insn[] = BREAKPOINT_VALUE;

				sbp = address2bpstruct(leader, addr);
				assert(sbp);
				a = ptrace(PTRACE_PEEKTEXT, event->proc->pid,
					   addr);

				if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) {
					sbp->enabled--;
					insert_breakpoint(event->proc, addr,
							  libsym, 1);
				}
			} else {
				sbp = dict_find_entry(leader->breakpoints, addr);
				/* On powerpc, the breakpoint address
				   may end up being actual entry point
				   of the library symbol, not the PLT
				   address we computed.  In that case,
				   sbp is NULL.  */
				if (sbp == NULL || addr != sbp->addr) {
					insert_breakpoint(event->proc, addr,
							  libsym, 1);
				}
			}
#elif defined(__mips__)
			void *addr = NULL;
			struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc;
			struct library_symbol *new_sym;
			assert(sym);
			addr = sym2addr(event->proc, sym);
			sbp = dict_find_entry(leader->breakpoints, addr);
			if (sbp) {
				if (addr != sbp->addr) {
					insert_breakpoint(event->proc, addr, sym, 1);
				}
			} else {
				new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
				memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
				new_sym->next = leader->list_of_symbols;
				leader->list_of_symbols = new_sym;
				insert_breakpoint(event->proc, addr, new_sym, 1);
			}
#endif
			for (j = event->proc->callstack_depth - 1; j > i; j--) {
				callstack_pop(event->proc);
			}
			if (event->proc->state != STATE_IGNORED) {
				if (opt_T || options.summary) {
					calc_time_spent(event->proc);
				}
			}
			event->proc->return_addr = event->e_un.brk_addr;
			if (event->proc->state != STATE_IGNORED) {
				mock_return(LT_TOF_FUNCTIONR, event->proc,
						event->proc->callstack[i].c_un.libfunc->name);
				output_right(LT_TOF_FUNCTIONR, event->proc,
						event->proc->callstack[i].c_un.libfunc->name);
			}
			callstack_pop(event->proc);
			sbp = address2bpstruct(leader, event->e_un.brk_addr);
			continue_after_breakpoint(event->proc, sbp);
			return;
		}
	}

	if ((sbp = address2bpstruct(leader, event->e_un.brk_addr))) {
		if (sbp->libsym == NULL) {
			continue_after_breakpoint(event->proc, sbp);
			return;
		}

		if (strcmp(sbp->libsym->name, "") == 0) {
			debug(DEBUG_PROCESS, "Hit _dl_debug_state breakpoint!\n");
			arch_check_dbg(leader);
		}

		if (event->proc->state != STATE_IGNORED) {
			event->proc->stack_pointer = get_stack_pointer(event->proc);
			event->proc->return_addr =
				get_return_addr(event->proc, event->proc->stack_pointer);
			callstack_push_symfunc(event->proc, sbp->libsym);
			output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym->name);
		}
#ifdef PLT_REINITALISATION_BP
		if (event->proc->need_to_reinitialize_breakpoints
		    && (strcmp(sbp->libsym->name, PLTs_initialized_by_here) ==
			0))
			reinitialize_breakpoints(leader);
#endif

		continue_after_breakpoint(event->proc, sbp);
		return;
	}

	if (event->proc->state != STATE_IGNORED && !options.no_plt) {
		output_line(event->proc, "unexpected breakpoint at %p",
				(void *)event->e_un.brk_addr);
	}
	continue_process(event->proc->pid);
}
コード例 #11
0
//--------------------------------------------------------------------------
static int idaapi callback(
    void * /*user_data*/,
    int notification_code,
    va_list va)
{
  static int stage = 0;
  static bool is_dll;
  static char needed_file[QMAXPATH];

  switch ( notification_code )
  {
    case dbg_process_start:
    case dbg_process_attach:
      get_input_file_path(needed_file, sizeof(needed_file));
      // no break
    case dbg_library_load:
      if ( stage == 0 )
      {
        const debug_event_t *pev = va_arg(va, const debug_event_t *);
        if ( !strieq(pev->modinfo.name, needed_file) )
          break;
        if ( notification_code == dbg_library_load )
          is_dll = true;
        // remember the current module bounds
        if ( pev->modinfo.rebase_to != BADADDR )
          curmod.startEA = pev->modinfo.rebase_to;
        else
          curmod.startEA = pev->modinfo.base;
        curmod.endEA = curmod.startEA + pev->modinfo.size;
        deb(IDA_DEBUG_PLUGIN, "UUNP: module space %a-%a\n", curmod.startEA, curmod.endEA);
        ++stage;
      }
      break;

    case dbg_library_unload:
      if ( stage != 0 && is_dll )
      {
        const debug_event_t *pev = va_arg(va, const debug_event_t *);
        if ( curmod.startEA == pev->modinfo.base
          || curmod.startEA == pev->modinfo.rebase_to )
        {
          deb(IDA_DEBUG_PLUGIN, "UUNP: unload unpacked module\n");
          if ( stage > 2 )
            enable_step_trace(false);
          stage = 0;
          curmod.startEA = 0;
          curmod.endEA = 0;
          _hide_wait_box();
        }
      }
      break;

    case dbg_run_to:   // Parameters: const debug_event_t *event
      dbg->stopped_at_debug_event(true);
      bp_gpa = get_name_ea(BADADDR, "kernel32_GetProcAddress");
#ifndef __X64__
      if( (LONG)GetVersion() < 0 )  // win9x mode -- use thunk's
      {
        is_9x = true;
        win9x_resolve_gpa_thunk();
      }
#endif
      if ( bp_gpa == BADADDR )
      {
        bring_debugger_to_front();
        warning("Sorry, could not find kernel32.GetProcAddress");
FORCE_STOP:
        stage = 4;  // last stage
        clear_requests_queue();
        request_exit_process();
        run_requests();
        break;
      }
      else if( !my_add_bpt(bp_gpa) )
      {
        bring_debugger_to_front();
        warning("Sorry, can not set bpt to kernel32.GetProcAddress");
        goto FORCE_STOP;
      }
      else
      {
        ++stage;
        set_wait_box("Waiting for a call to GetProcAddress()");
      }
      continue_process();
      break;

    case dbg_bpt:      // A user defined breakpoint was reached.
                       // Parameters: thid_t tid
                       //             ea_t        breakpoint_ea
                       //             int        *warn = -1
                       //             Return (in *warn):
                       //              -1 - to display a breakpoint warning dialog
                       //                   if the process is suspended.
                       //               0 - to never display a breakpoint warning dialog.
                       //               1 - to always display a breakpoint warning dialog.
      {
        thid_t tid = va_arg(va, thid_t); qnotused(tid);
        ea_t ea   = va_arg(va, ea_t);
        //int *warn = va_arg(va, int*);
        if ( stage == 2 )
        {
          if ( ea == bp_gpa )
          {
            regval_t rv;
            if ( get_reg_val(REGNAME_ESP, &rv) )
            {
              ea_t esp = ea_t(rv.ival);
              invalidate_dbgmem_contents(esp, 1024);
              ea_t gpa_caller = getPtr(esp);
              if ( !is_library_entry(gpa_caller) )
              {
                ea_t nameaddr;
                if ( ptrSz == 4 )
                {
                  nameaddr = get_long(esp+8);
                }
                else
                {
                  get_reg_val(REGNAME_ECX, &rv);
                  nameaddr = ea_t(rv.ival);
                }
                invalidate_dbgmem_contents(nameaddr, 1024);
                char name[MAXSTR];
                size_t len = get_max_ascii_length(nameaddr, ASCSTR_C, ALOPT_IGNHEADS);
                name[0] = '\0';
                get_ascii_contents2(nameaddr, len, ASCSTR_C, name, sizeof(name));
                if ( !ignore_win32_api(name) )
                {
                  deb(IDA_DEBUG_PLUGIN, "%a: found a call to GetProcAddress(%s)\n", gpa_caller, name);
                  if ( !my_del_bpt(bp_gpa) || !my_add_bpt(gpa_caller) )
                    error("Can not modify breakpoint");
                }
              }
            }
          }
          else if ( ea == bpt_ea )
          {
            my_del_bpt(ea);
            if ( !is_library_entry(ea) )
            {
              msg("Uunp: reached unpacker code at %a, switching to trace mode\n", ea);
              enable_step_trace(true);
              ++stage;
              uint64 eax;
              if ( get_reg_val(REGNAME_EAX, &eax) )
                an_imported_func = ea_t(eax);
              set_wait_box("Waiting for the unpacker to finish");
            }
            else
            {
              warning("%a: bpt in library code", ea); // how can it be?
              my_add_bpt(bp_gpa);
            }
          }
          // not our bpt? skip it
          else
          {
            // hide the wait box to allow others plugins to properly stop
            _hide_wait_box();
            break;
          }
        }
      }
      // while continue_process() would work here too, request+run is more universal
      // because they do not ignore the request queue
      request_continue_process();
      run_requests();
      break;

    case dbg_trace:    // A step occured (one instruction was executed). This event
                       // notification is only generated if step tracing is enabled.
                       // Parameter:  none
      if ( stage == 3 )
      {
        thid_t tid = va_arg(va, thid_t); qnotused(tid);
        ea_t ip   = va_arg(va, ea_t);

        // ip reached the OEP range?
        if ( oep_area.contains(ip) )
        {
          // stop the trace mode
          enable_step_trace(false);
          msg("Uunp: reached OEP %a\n", ip);
          set_wait_box("Reanalyzing the unpacked code");

          // reanalyze the unpacked code
          do_unknown_range(oep_area.startEA, oep_area.size(), DOUNK_EXPAND);
          auto_make_code(ip); // plan to make code
          noUsed(oep_area.startEA, oep_area.endEA); // plan to reanalyze
          auto_mark_range(oep_area.startEA, oep_area.endEA, AU_FINAL); // plan to analyze
          move_entry(ip); // mark the program's entry point

          _hide_wait_box();

          // inform the user
          bring_debugger_to_front();
          if ( askyn_c(1,
                       "HIDECANCEL\n"
                       "The universal unpacker has finished its work.\n"
                       "Do you want to take a memory snapshot and stop now?\n"
                       "(you can do it yourself if you want)\n") > 0 )
          {
            set_wait_box("Recreating the import table");
            invalidate_dbgmem_config();

            if ( is_9x )
              find_thunked_imports();

            create_impdir();

            set_wait_box("Storing resources to 'resource.res'");
            if ( resfile[0] != '\0' )
              extract_resource(resfile);

            _hide_wait_box();
            if ( take_memory_snapshot(true) )
              goto FORCE_STOP;
          }
          suspend_process();
          unhook_from_notification_point(HT_DBG, callback, NULL);
        }
      }
      break;

    case dbg_process_exit:
      {
        stage = 0;
        // stop the tracing
        _hide_wait_box();
        unhook_from_notification_point(HT_DBG, callback, NULL);
        if ( success )
          jumpto(inf.beginEA, -1);
        else
          tell_about_failure();
      }
      break;

    case dbg_exception:// Parameters: const debug_event_t *event
                       //             int                 *warn = -1
                       //             Return (in *warn):
                       //              -1 - to display an exception warning dialog
                       //                   if the process is suspended.
                       //               0 - to never display an exception warning dialog.
                       //               1 - to always display an exception warning dialog.

    {
//      const debug_event_t *event = va_arg(va, const debug_event_t *);
//      int *warn = va_arg(va, int *);
      // FIXME: handle code which uses SEH to unpack itself
      if ( askyn_c(1,
                   "AUTOHIDE DATABASE\n"
                   "HIDECANCEL\n"
                   "An exception occurred in the program.\n"
                   "UUNP does not support exceptions yet.\n"
                   "The execution has been suspended.\n"
                   "Do you want to continue the unpacking?") <= 0 )
      {
        _hide_wait_box();
        stage = 0;
        enable_step_trace(false); // stop the trace mode
        suspend_process();
      }
      else
      {
        continue_process();
      }
    }
    break;

    case dbg_request_error:
                       // An error occured during the processing of a request.
                       // Parameters: ui_notification_t  failed_command
                       //             dbg_notification_t failed_dbg_notification
      {
        ui_notification_t  failed_cmd = va_arg(va, ui_notification_t);
        dbg_notification_t failed_dbg_notification = va_arg(va, dbg_notification_t);
        _hide_wait_box();
        stage = 0;
        warning("dbg request error: command: %d notification: %d",
                        failed_cmd, failed_dbg_notification);
      }
      break;
  }
  return 0;
}
コード例 #12
0
ファイル: proc.c プロジェクト: mer-tools/ltrace
static enum callback_status
start_one_pid(Process * proc, void * data)
{
	continue_process(proc->pid);
	return CBS_CONT;
}