コード例 #1
0
ファイル: ptrace.c プロジェクト: CoolSnow/Undercover
void *ptrace_dlsym(pid_t pid, void *handle, const char *symbol) {

#ifdef ANDROID
    regs_t regs;
    //int stat;
    ptrace_readreg(pid, &regs);
    ptrace_dump_regs(&regs, "before call to ptrace_dlsym\n");

#ifdef THUMB

    regs.ARM_lr = 1;
#else
    regs.ARM_lr= 0;
#endif

    regs.ARM_r0= (long)handle;
    regs.ARM_r1= (long)ptrace_push(pid,&regs, (void*)symbol,strlen(symbol)+1);

    regs.ARM_pc= ldl.l_dlsym;
    ptrace_writereg(pid, &regs);
    ptrace_cont(pid);
    ptrace_wait_for_signal(pid, SIGSEGV);
    ptrace_readreg(pid, &regs);
    ptrace_dump_regs(&regs, "before return ptrace_dlsym\n");
    return (void*) regs.ARM_r0;
#endif
}
コード例 #2
0
ファイル: ptrace.c プロジェクト: CoolSnow/Undercover
void *ptrace_dlopen(pid_t pid, const char *filename, int flag) {
#ifdef ANDROID
    regs_t regs;
    //int stat;
    ptrace_readreg(pid, &regs);

    ptrace_dump_regs(&regs, "before call to ptrace_dlopen\n");

#ifdef THUMB
    regs.ARM_lr = 1;
#else
    regs.ARM_lr= 0;
#endif

    regs.ARM_r0= (long)ptrace_push(pid,&regs, (void*)filename,strlen(filename)+1);
    regs.ARM_r1= flag;
    regs.ARM_pc= ldl.l_dlopen;
    ptrace_writereg(pid, &regs);
    ptrace_cont(pid);
    ptrace_wait_for_signal(pid, SIGSEGV);
    ptrace_readreg(pid, &regs);
    ptrace_dump_regs(&regs, "before return ptrace_call\n");
    return (void*) regs.ARM_r0;
#endif
}
コード例 #3
0
void call_shit(struct elf_info *einfo) {
    unsigned long addr2 = 0;
    unsigned long rel_addr = find_sym_in_rel(einfo, "math_shit");
    regs_t regs;
    ptrace_read(einfo->pid, rel_addr, &addr2, sizeof(long));
    printf("math_shit rel addr\t %lx\n", rel_addr);
    printf("addr2 is \t %lx\n", addr2);
    ptrace_readreg(einfo->pid, &regs);
    ptrace_dump_regs(&regs,"before call to call_shit\n");
#ifdef THUMB
    regs.ARM_lr = 1;
#else
    regs.ARM_lr = 0;
#endif
    regs.ARM_r0 = 5;
    regs.ARM_r1 = 6;
    regs.ARM_r2 = 7;
    regs.ARM_r3 = 8;
    {
        int a5 = 9;
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        ptrace_push(einfo->pid, &regs, &a5, 4);
        a5 = 10;
        ptrace_push(einfo->pid, &regs, &a5, 4);
    }
    regs.ARM_pc = addr2;
    ptrace_writereg(einfo->pid, &regs);
    ptrace_cont(einfo->pid);
    printf("done %d\n",  ptrace_wait_for_signal(einfo->pid,SIGSEGV));
    ptrace_readreg(einfo->pid, &regs);
    ptrace_dump_regs(&regs,"before return call_shit\n");
}
コード例 #4
0
ファイル: injso.c プロジェクト: ecit241/JustForFun
void
call_dl_open (int pid, unsigned long addr, char *libname)
{
  void *pRLibName;
  struct user_regs_struct regs;

  /*
     先找个空间存放要装载的共享库名,我们可以简单的把它放入堆栈
   */
  pRLibName = ptrace_push (pid, libname, strlen (libname) + 1);

  /* 设置参数到寄存器 */
  ptrace_readreg (pid, &regs);
  regs.eax = (unsigned long) pRLibName;
  regs.ecx = 0x0;
  regs.edx = RTLD_LAZY;
  ptrace_writereg (pid, &regs);

  /* 调用_dl_open */
  ptrace_call (pid, addr);
  puts ("call _dl_open ok");
}
コード例 #5
0
ファイル: ptrace.c プロジェクト: CoolSnow/Undercover
int ptrace_call(int pid, long proc, int argc, ptrace_arg *argv) {
    int i = 0;
#define ARGS_MAX 64
    regs_t regs;
    ptrace_readreg(pid, &regs);
    ptrace_dump_regs(&regs, "before ptrace_call\n");

    /*prepare stacks*/
    for (i = 0; i < argc; i++) {
        ptrace_arg *arg = &argv[i];
        if (arg->type == PAT_STR) {
            arg->_stackid = ptrace_push(pid, &regs, arg->s, strlen(arg->s) + 1);
        } else if (arg->type == PAT_MEM) {
            //LOGD("push data %p to stack[%d] :%d \n", arg->mem.addr, stackcnt, *((int*)arg->mem.addr));
            arg->_stackid = ptrace_push(pid, &regs, arg->mem.addr, arg->mem.size);
        }
    }
    for (i = 0; (i < 4) && (i < argc); i++) {
        ptrace_arg *arg = &argv[i];
        if (arg->type == PAT_INT) {
            regs.uregs[i] = arg->i;
        } else if (arg->type == PAT_STR) {
            regs.uregs[i] = arg->_stackid;
        } else if (arg->type == PAT_MEM) {
            regs.uregs[i] = arg->_stackid;
        } else {
            LOGD("unkonwn arg type\n");
        }
    }

    for (i = argc - 1; i >= 4; i--) {
        ptrace_arg *arg = &argv[i];
        if (arg->type == PAT_INT) {
            ptrace_push(pid, &regs, &arg->i, sizeof(int));
        } else if (arg->type == PAT_STR) {
            ptrace_push(pid, &regs, &arg->_stackid, sizeof(unsigned long));
        } else if (arg->type == PAT_MEM) {
            ptrace_push(pid, &regs, &arg->_stackid, sizeof(unsigned long));
        } else {
            LOGD("unkonwn arg type\n");
        }
    }
#ifdef THUMB
    regs.ARM_lr = 1;
#else
    regs.ARM_lr= 0;
#endif
    regs.ARM_pc= proc;
    ptrace_writereg(pid, &regs);
    ptrace_cont(pid);
    ptrace_wait_for_signal(pid, SIGSEGV);
    ptrace_readreg(pid, &regs);
    ptrace_dump_regs(&regs, "before return ptrace_call\n");

    //sync memory
    for (i = 0; i < argc; i++) {
        ptrace_arg *arg = &argv[i];
        if (arg->type == PAT_STR) {
        } else if (arg->type == PAT_MEM) {
            ptrace_read(pid, arg->_stackid, arg->mem.addr, arg->mem.size);
        }
    }

    return regs.ARM_r0;
}
コード例 #6
0
ファイル: gdbloader.c プロジェクト: pi3orama/Snitchaser
static void
inject_memory(void)
{
	struct mem_region * stack_r = NULL;

	SYS_TRACE("nr_regions=%d\n", cf->nr_regions);

	/* for each mem region in ckpt file */
	for (int i = 0; i < cf->nr_regions; i++) {

		struct mem_region * r = cf->regions[i];

		SYS_TRACE("range %d: 0x%x--0x%x (0x%x:0x%x): %s\n",
				i, r->start, r->end, r->prot, r->offset, r->fn);

		/* find the region already mapped */
		struct proc_entry e;
		bool_t res;
		uint32_t start, end;
		start = r->start;
		end = r->end;
		do {
			res = proc_find_in_range(&e, child_pid, start, end);

			if (res) {
				start = e.end;
				SYS_TRACE("\talready mapped in target: 0x%x--0x%x (0x%x:0x%x): %s\n",
						e.start, e.end, e.prot, e.offset, e.fn);


				/* check if 2 maps are same */
				if ((e.start != r->start) ||
						(e.end != r->end) ||
						(e.prot != r->prot) ||
						(strcmp(e.fn, r->fn) != 0))
				{
					/* different */
					/* special treat [heap] and [stack] */
					if (strcmp(e.fn, "[heap]") == 0) {
						/* heap size is different */
						/* that shouldn't happen, we restore heap address before
						 * calling this function*/
						THROW(EXCEPTION_FATAL, "heap address inconsistent");
					} else if (strcmp(e.fn, "[stack]") == 0) {
						if (strcmp(r->fn, "[stack]") != 0) {
							/* that shouldn't happen... */
							THROW(EXCEPTION_FATAL, "stack inconsistent");
						}
						/* stack can auto expand */
					} else if (strcmp(e.fn, "[vdso]") == 0) {
						THROW(EXCEPTION_FATAL, "vdso inconsistent");
					} else {
						/* unmap the already mapped file */
						/* first, check eip */
						struct user_regs_struct regs = ptrace_peekuser();
						if ((regs.eip >= e.start) && (regs.eip < e.end)) {
							/* target ckpt is special: it unmap itself... */
							/* currently we don't support it */
							THROW(EXCEPTION_FATAL, "eip (0x%x) inconsistent",
									(uint32_t)regs.eip);
						}

						/* now we can safely unmap that file or memregion */
						int err;
						SYS_TRACE("\tunmap 0x%x--0x%x\n", e.start, e.end);
						err = ptrace_syscall(munmap, 2, e.start, e.end - e.start);
						if (err < 0)
							THROW(EXCEPTION_FATAL, "unmap memrigon 0x%x--0x%x failed: %d",
									e.start, e.end, err);
					}
				}
			} else {
				start = r->end;
			}
		} while (start < end);


		/* now the region has been cleaned up, there may be 2 situations:
		 * 1. the desired region is empty;
		 * 2. the desired region is mapped, but the same as ckpt.
		 * here we use procutils to check it again. */
		res = proc_find_in_range(&e, child_pid, r->start, r->end);
		if (res) {
			SYS_TRACE("\tdesired region is mapped\n");
			if ((e.start != r->start) ||
					(e.end != r->end) ||
					(e.prot != r->prot) ||
					(strcmp(e.fn, r->fn) != 0))
			{
				/* if the lower end of stack inconsistent, don't care.
				 * stack is auto expandable. */
				/* NOT(e.fn same as r->fn and e.fn is "[stack]") */
				if (!(!strcmp(e.fn, r->fn) && !strncmp(e.fn, "[stack]", 7))) {
					INJ_FATAL("this region is not cleaned up:\n");
					INJ_FATAL("\tstart : 0x%x 0x%x\n", e.start, r->start);
					INJ_FATAL("\tend   : 0x%x 0x%x\n", e.end, r->end);
					INJ_FATAL("\tprot  : 0x%x 0x%x\n", e.prot, r->prot);
					INJ_FATAL("\tfn:   : \"%s\" \"%s\"\n", e.fn, r->fn);
					THROW(EXCEPTION_FATAL, "Shouldn't happed...\n");
				}
			}
		} else {
			SYS_TRACE("\tdesired region is unmapped\n");
			/* from the ckpt, find the file and do the map */
			uint32_t map_addr = r->start;
			uint32_t size = r->end - r->start;
			uint32_t prot = r->prot;
			uint32_t flags = MAP_FIXED | MAP_EXECUTABLE | MAP_PRIVATE;
			if ((r->fn_len <= 1) || (r->fn[0] == '\0')) {
				/* this is not a file map */
				uint32_t ret_addr;
				flags |= MAP_ANONYMOUS;
				SYS_TRACE("\tdo the anonymouse map\n");
				ret_addr = ptrace_syscall(mmap2, 6,
						map_addr, size, prot,
						flags, 0, 0);
				CTHROW(map_addr == ret_addr, "mmap2 failed, return 0x%x, not 0x%x",
						ret_addr, map_addr);
			} else {
				/* this is a file map */
				uint32_t fn_pos;
				/* push the filename */
				fn_pos = ptrace_push(r->fn, strlen(r->fn) + 1, TRUE);

				int fd = ptrace_syscall(open, 3, fn_pos, O_RDONLY, 0);
				CTHROW(fd >= 0, "open file %s failed: %d", r->fn, fd);

				SYS_TRACE("\tdo the map\n");
				uint32_t off = r->offset;
				uint32_t ret_addr = ptrace_syscall(mmap2, 6,
						map_addr, size, prot,
						flags, fd, off >> PAGE_SHIFT);
				CTHROW(ret_addr == map_addr, "mmap2 file %s failed: return 0x%x",
						r->fn, ret_addr);

				ptrace_syscall(close, 1, fd);
			}
		}

		/* now the memory region has been built up, we then poke
		 * memory into it */
		/* don't update stack here. although in most case the stack
		 * is the last region we meet, there are some special situations.
		 * for example in compat memlayout. the stack may be polluted by
		 * pervious ptrace_push operation. */
		if (strcmp(r->fn, "[stack]") == 0)
			stack_r = r;
		else if (strcmp(r->fn, "[vdso]") != 0)	/* chkp don't contain vdso */
			ptrace_updmem(r->f_pos + cf->ckpt_img,
					r->start,
					r->end - r->start);
	}


	CTHROW(stack_r != NULL, "no \"[stack]\" found");
	/* we poke stack at last */
	ptrace_updmem(stack_r->f_pos + cf->ckpt_img,
			stack_r->start,
			stack_r->end - stack_r->start);
}
コード例 #7
0
ファイル: gdbloader.c プロジェクト: pi3orama/Snitchaser
static void
gdbloader_main(const char * target_fn)
{
	/* check: target_fn should be same as argv[0] */
	if (strcmp(target_fn, cf->cmdline[0]) != 0) {
		SYS_FATAL("target should be %s, not %s\n", cf->cmdline[0], target_fn);
		THROW(EXCEPTION_FATAL, "cmdline error");
	}

	/* execve child */
	child_pid = ptrace_execve(target_fn, cf->cmdline, cf->environ);

	/* inject memory */
	/* before we inject memory, we need to restore heap */
	uint32_t heap_end;
	heap_end = ptrace_syscall(brk, 1, cf->state->brk);
	CTHROW(heap_end == cf->state->brk, "restore heap failed: %d",
			heap_end);
	SYS_TRACE("restore heap to 0x%x\n", heap_end);

	inject_memory();

	/* then, we retrive the inject so file, enter from
	 * __debug_entry. we need to push:
	 * nothing.
	 * process can retrive all from state vector.
	 * and we cannot use stack now
	 * */
	/* NOTICE: the state_vector should be saved in the ckpt memory,
	 * we needn't restore them in ptrace process. let the inject so
	 * to do it. */

	/* from the opts get the so-file bias */
	uint32_t inj_bias = opts->inj_bias;
	/* use procutils to get the file */
	struct proc_entry e;
	e.start = inj_bias;
	e.bits = PE_START; 
	proc_fill_entry(&e, child_pid);
	SYS_TRACE("inject so is %s\n", e.fn);

	/* use elfutils to retrive the symbol */
	void * img = load_file(e.fn);
	struct elf_handler * inj_so = elf_init(img, inj_bias);

	uintptr_t debug_entry = elf_get_symbol_address(inj_so,
			opts->entry);
	SYS_TRACE("symbol %s at 0x%x\n", opts->entry, debug_entry);

	/* inject the injector opts */
	inject_injopts(inj_so);

	elf_cleanup(inj_so);
	free(img);

	/* we have to restore register here... */
	SYS_FORCE("pid=%d\n", child_pid);
	SYS_FORCE("eip=0x%x\n", cf->state->regs.eip);
	ptrace_pokeuser(cf->state->regs);
	SYS_TRACE("eax=0x%x\n", cf->state->regs.eax);
	SYS_TRACE("ebx=0x%x\n", cf->state->regs.ebx);
	SYS_TRACE("ecx=0x%x\n", cf->state->regs.ecx);
	SYS_TRACE("edx=0x%x\n", cf->state->regs.edx);
	SYS_TRACE("esi=0x%x\n", cf->state->regs.esi);
	SYS_TRACE("edi=0x%x\n", cf->state->regs.edi);
	SYS_TRACE("ebp=0x%x\n", cf->state->regs.ebp);
	SYS_TRACE("esp=0x%x\n", cf->state->regs.esp);
//	SYS_TRACE("gs=0x%x\n", cf->state->regs.gs);
//	SYS_TRACE("es=0x%x\n", cf->state->regs.es);

	/* we push eip at the top of the new stack */
	ptrace_push(&cf->state->regs.eip, sizeof(uint32_t), FALSE);

	/* fix libpthread problem:
	 *
	 * when gdb attaches to target, if it find libpthread, gdb
	 * will try to use libthread_db to retrive thread-local info.
	 * some data, like `errno', is TLS and need those info.
	 *
	 * When gdb does the work, it use ptrace to peek memory from target image.
	 * so gdb will see the original thread info, the tid is different from
	 * current pid, therefore gdb will think there are at least 2 threads and
	 * then it will try to attach to the 'old' one and definitely fail. When this
	 * failure occures, gdb print a warning message.
	 *
	 * We have 2 ways to solve this problem:
	 *
	 * 1. add a syscall into kernel's code, change its pid. it is simple.
	 * 2. change the image when gdb attach.
	 *
	 * We choose the 2nd one because we prefer user space solution.
	 *
	 * */
	uint32_t sym_stack_used = 0, sym_stack_user = 0;
	if (opts->fix_pthread_tid) {
		fix_libpthread(&sym_stack_used, &sym_stack_user);
		SYS_WARNING("sym_stack_used=0x%x, sym_stack_user=0x%x\n",
				sym_stack_used, sym_stack_user);
	}

	/* we push those 2 addresses onto the stack */
	ptrace_push(&sym_stack_used, sizeof(uint32_t), FALSE);
	ptrace_push(&sym_stack_user, sizeof(uint32_t), FALSE);

	/* move eip and detach, let the target process to run */
	ptrace_goto(debug_entry);

	/* detach in main */
	return;
}
コード例 #8
0
ファイル: test_wrapper.c プロジェクト: pi3orama/currf2
static void
map_wrap_so(const char * so_file, uintptr_t load_bias,
            uint32_t * pvdso_entrance,
            uint32_t * pvdso_ehdr)
{
    uint32_t name_pos;
    int fd, err;

    struct stat s;
    err = stat(so_file, &s);
    assert_errno_throw("stat file %s failed", so_file);
    assert_throw(S_ISREG(s.st_mode), "file %s not a regular file", so_file);
    /* don't use off_t, it may not be a 32 bit word! */
    int32_t fsize = s.st_size;
    SYS_TRACE("desired so file length is %d\n", fsize);

    /* elf operations */
    void * so_image = load_file(so_file);
    struct elf_handler * h = elf_init(so_image, load_bias);
    /* load program headers */
    int nr_phdr = 0;
    struct elf32_phdr * phdr = elf_get_phdr_table(h, &nr_phdr);
    assert_throw(((phdr != NULL) && (nr_phdr != 0)),
                 "load phdr of file %s failed\n", so_file);
    /* find the entry symbol */
    uintptr_t entry_addr = elf_get_symbol_address(h, "syscall_wrapper_entrace");
    SYS_TRACE("wrapper func address will be 0x%x\n", entry_addr);


    name_pos = ptrace_push(so_file, strlen(so_file), TRUE);
    fd = ptrace_syscall(open, 3, name_pos, O_RDONLY, 0);
    assert_throw(fd >= 0, "open sofile for child failed, return %d", fd);
    SYS_TRACE("open so file for child, fd=%d\n", fd);


    /* for each program header */
    for (int i = 0; i < nr_phdr; i++, phdr ++) {
        SYS_FORCE("phdr %d, type=0x%x, flag=0x%x\n", i,
                  phdr->p_type, phdr->p_flags);
        if (phdr->p_type != PT_LOAD)
            continue;

        int elf_prot = 0, elf_flags = 0;

        if (phdr->p_flags & PF_R)
            elf_prot |= PROT_READ;
        if (phdr->p_flags & PF_W)
            elf_prot |= PROT_WRITE;
        if (phdr->p_flags & PF_X)
            elf_prot |= PROT_EXEC;

        elf_flags = MAP_PRIVATE | MAP_EXECUTABLE;

        unsigned long size = phdr->p_filesz + ELF_PAGEOFFSET(phdr->p_vaddr);
        unsigned long off = phdr->p_offset - ELF_PAGEOFFSET(phdr->p_vaddr);
        int32_t map_addr = load_bias + phdr->p_vaddr - ELF_PAGEOFFSET(phdr->p_vaddr);

        map_addr = ptrace_syscall(mmap2, 6,
                                  map_addr, size,
                                  elf_prot, elf_flags | MAP_FIXED,
                                  fd, off);
        assert_throw(map_addr != 0xffffffff, "map wrap so failed, return 0x%x", map_addr);
    }
    elf_cleanup(h);
    free(so_image);

    if (pvdso_ehdr)
        *pvdso_ehdr = load_bias;
    if (pvdso_entrance)
        *pvdso_entrance = entry_addr;
}