예제 #1
0
void ptrace_attach(int pid) {
    regs_t regs;
    int status = 0;
    if (ptrace(PTRACE_ATTACH, pid, NULL, NULL ) < 0) {
        perror("ptrace_attach");
        exit(-1);
    }
    status = ptrace_wait_for_signal(pid, SIGSTOP);
    LOGD("ptrace_wait_for_signal: %d %d\n", __LINE__, status);
    //waitpid(pid, NULL, WUNTRACED);

    ptrace_readreg(pid, &regs);
    memcpy(&oldregs, &regs, sizeof(regs));

    ptrace_dump_regs(&oldregs, "old regs");
#ifdef ANDROID
#ifdef THUMB
    regs.ARM_pc = 0x11;
    regs.ARM_cpsr |=0x30;
#else
    regs.ARM_pc= 0;
#endif
#else
    regs.rip = 0;
#endif
    ptrace_writereg(pid, &regs);

    ptrace_cont(pid);

    LOGD("waiting.. sigal...\n");

    status = ptrace_wait_for_signal(pid, SIGSEGV);
    LOGD("ptrace_wait_for_signal2: %d %d\n", __LINE__, status);

}
예제 #2
0
int ptrace_mymath_add(pid_t pid, long mymath_add_addr, int a, int b) {
#ifdef ANDROID
    regs_t regs;
    //int stat;
    ptrace_readreg(pid, &regs);
    ptrace_dump_regs(&regs, "before call to ptrace_mymath_add\n");

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

    regs.ARM_r0= a;
    regs.ARM_r1= b;

    regs.ARM_pc= mymath_add_addr;
    ptrace_writereg(pid, &regs);
    ptrace_cont(pid);
    ptrace_wait_for_signal(pid, SIGSEGV);
    ptrace_readreg(pid, &regs);
    ptrace_dump_regs(&regs, "before return ptrace_mymath_add\n");
    return regs.ARM_r0;
#endif
}
예제 #3
0
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
}
예제 #4
0
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
}
예제 #5
0
/* x86_64     rdi    rsi    rdx    r10    r8     r9      -    */
static register_t inject_syscall(pid_t pid, int nb_args, register_t syscallid,
                                 ...) {

  /* If we have more than 6 arguments, we must put them on the stack */
  /* For the moment, we don't handle this case  */
  assert(NB_MAX_ARGS >= nb_args);

  /* We do the backup of registers */
  long r;
  register_t ret;
  struct user_regs_struct regs, regs_backup;

  ptrace_getregs(pid, &regs);
  regs_backup = regs;

  /* We get back arguments and adequately put them in registers */

  int i = 0;
  va_list vargs;
  va_start(vargs, syscallid);

  long long unsigned *regs_ptr[NB_MAX_ARGS] = {&(regs.rdi), &(regs.rsi),
                                               &(regs.rdx), &(regs.r10),
                                               &(regs.r8),  &(regs.r9)};

  regs.rip = (register_t)tracer_buff->syscall;
  regs.rax = syscallid;

  if (syscallid == SYS_unprotect_protect) {
    regs.rip = (register_t)tracer_buff->unprotect_protect;
    regs.rax = SYS_mprotect;
    regs.r12 = SYS_mprotect;
    regs_ptr[3] = &(regs.r13);
    regs_ptr[4] = &(regs.r14);
    regs_ptr[5] = &(regs.r15);
  }

  for (i = 0; i < nb_args; i++) {
    *(regs_ptr[i]) = va_arg(vargs, long long unsigned);

  }
  va_end(vargs);

  ptrace_setregs(pid, &regs);

  ptrace_cont(pid);
  wait_event(pid);
  ptrace_getregs(pid, &regs);
  ret = regs.rax;

  ptrace_setregs(pid, &regs_backup);

  return ret;
}
예제 #6
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");
}
예제 #7
0
파일: inject.c 프로젝트: demirten/tracedump
void inject_restore_socketcall(struct tracedump *td, struct pid *sp)
{
	/* int 0x80, int3 */
	unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 };
	char backup[4];
	struct user_regs_struct regs2;

	/* backup */
	ptrace_read(sp, sp->regs.eip, backup, 4);

	/* exec */
	sp->regs.eax = sp->regs.orig_eax;
	ptrace_setregs(sp, &sp->regs);
	ptrace_write(sp, sp->regs.eip, code, 4);
	ptrace_cont(sp, 0, true);

	/* read the return code */
	ptrace_getregs(sp, &regs2);
	sp->regs.eax = regs2.eax;

	/* restore */
	ptrace_setregs(sp, &sp->regs);
	ptrace_write(sp, sp->regs.eip, backup, 4);
}
예제 #8
0
파일: inject.c 프로젝트: demirten/tracedump
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...)
{
	/* int 0x80, int3 */
	unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 };
	char backup[4];
	struct user_regs_struct regs, regs2;
	int ss_vals, ss_mem, ss;
	va_list vl;
	enum arg_type type;
	uint32_t sv;
	void *ptr;
	uint8_t *stack, *stack_mem;
	uint32_t *stack32;
	int i, j;

	/*
	 * get the required amount of stack space
	 */
	ss_vals = 0;
	ss_mem = 0;
	va_start(vl, sc_code);
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;
		sv  = va_arg(vl, uint32_t);

		/* each socketcall argument takes 4 bytes */
		ss_vals += 4;

		/* if its memory, it takes additional sv bytes */
		if (type == AT_MEM_IN || type == AT_MEM_INOUT) {
			ss_mem += sv;
			ptr = va_arg(vl, void *);
		}
	} while (true);
	va_end(vl);
	ss = ss_vals + ss_mem;

	/*
	 * backup
	 */
	ptrace_getregs(sp, &regs);
	memcpy(&regs2, &regs, sizeof regs);
	ptrace_read(sp, regs.eip, backup, sizeof backup);

	/*
	 * write the stack
	 */
	stack = mmatic_zalloc(td->mm, ss);
	stack32 = (uint32_t *) stack;
	stack_mem = stack + ss_vals;

	va_start(vl, sc_code);
	i = 0; j = 0;
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;

		sv  = va_arg(vl, uint32_t);

		if (type == AT_VALUE) {
			stack32[i++] = sv;
		} else { /* i.e. its a memory arg */
			stack32[i++] = regs.esp - ss_mem + j;

			/* copy the memory */
			ptr = va_arg(vl, void *);
			memcpy(stack_mem + j, ptr, sv);
			j += sv;
		}
	} while (true);
	va_end(vl);

	ptrace_write(sp, regs.esp - ss, stack, ss);

	/*
	 * write the code and run
	 */
	regs2.eax = 102; // socketcall
	regs2.ebx = sc_code;
	regs2.ecx = regs.esp - ss;

	ptrace_write(sp, regs.eip, code, sizeof code);
	ptrace_setregs(sp, &regs2);
	ptrace_cont(sp, 0, true);

	/*
	 * read back
	 */
	ptrace_getregs(sp, &regs2);
	ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem);

	va_start(vl, sc_code);
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;

		sv = va_arg(vl, uint32_t);
		if (type == AT_VALUE) continue;

		ptr = va_arg(vl, void *);
		if (type == AT_MEM_IN) continue;

		memcpy(ptr, stack_mem, sv);
		stack_mem += sv;
	} while (true);
	va_end(vl);

	/* restore */
	ptrace_write(sp, regs.eip, backup, sizeof backup);
	ptrace_setregs(sp, &regs);

	mmatic_free(stack);

	return regs2.eax;
}
예제 #9
0
파일: ui.c 프로젝트: idl3r/rappel
void interact(
		const char *const argv_0)
{
	EditLine *const el = el_init(argv_0, stdin, stdout, stderr);
	el_set(el, EL_PROMPT, &prompt);
	el_set(el, EL_EDITOR, "emacs");

	History *const hist = history_init();
	if (!hist) {
		fprintf(stderr, "Could not initalize history\n");
		exit(EXIT_FAILURE);
	}

	HistEvent ev;
	history(hist, &ev, H_SETSIZE, 100);

	el_set(el, EL_HIST, history, hist);

	const pid_t child_pid = _gen_child();

	verbose_printf("child process is %d\n", child_pid);

	if (options.verbose) help();

	char buf[PAGE_SIZE];
	size_t buf_sz = 0;
	int end = 0;

	struct proc_info_t info = {};
	ARCH_INIT_PROC_INFO(info);

	ptrace_launch(child_pid);
	ptrace_cont(child_pid, &info);
	ptrace_reap(child_pid, &info);

	display(&info);

	for (;;) {
		int count;
		const char *const line = el_gets(el, &count);

		if (count == -1) {
			perror("el_gets");
			exit(EXIT_FAILURE);
		}

		// count is 0 == ^d
		if (!count || strcasestr(line, ".quit") || strcasestr(line, ".exit")) break;

		// We have input, add it to the our history
		history(hist, &ev, H_ENTER, line);

		// If we start with a ., we have a command
		if (line[0] == '.') {
			if (strcasestr(line, "help")) {
				help();
				continue;
			}

			if (strcasestr(line, "info")) {
				display(&info);
				continue;
			}

			if (strcasestr(line, "showmap")) {
				char cmd[PATH_MAX] = { 0 };
				snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", child_pid);

				if (system(cmd))
					fprintf(stderr, "sh: %s failed\n", cmd);

				continue;
			}


			if (strcasestr(line, "read")) {
				ui_read(child_pid, line);
				continue;
			}

			if (strcasestr(line, "write")) {
				continue;
			}

			if (strcasestr(line, "begin")) {
				in_block = 1;
				continue;
			}

			// Note the lack of continue. Need to fall through...
			if (strcasestr(line, "end")) {
				in_block = 0;
				end = 1;
			}
		}

		if (buf_sz + count > sizeof(buf)) {
			printf("Buffer full (max: 0x%lx), please use '.end'\n", sizeof(buf));
			continue;
		}

		// Since we fell through, we want to avoid adding adding .end to our buffer
		if (!end) {
			memcpy(buf + buf_sz, line, count);
			buf_sz += count;
		}

		if (!in_block) {
			verbose_printf("Trying to assemble(%zu):\n%s", buf_sz, buf);

			uint8_t bytecode[PAGE_SIZE];
			const size_t bytecode_sz = assemble(bytecode, sizeof(bytecode), buf, buf_sz);

			memset(buf, 0, sizeof(buf));
			buf_sz = 0;
			end    = 0;

			verbose_printf("Got asm(%zu):\n", bytecode_sz);
			verbose_dump(bytecode, bytecode_sz, -1);

			if (!bytecode_sz) {
				fprintf(stderr, "'%s' assembled to 0 length bytecode\n", buf);
				continue;
			}

			ptrace_write(child_pid, (void *)options.start, bytecode, bytecode_sz);
			ptrace_reset(child_pid, options.start);

			ptrace_cont(child_pid, &info);
			ptrace_reap(child_pid, &info);

			display(&info);
		}
	}

	ptrace_detatch(child_pid, &info);

	printf("\n");

	history_end(hist);
	el_end(el);
}
예제 #10
0
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;
}
예제 #11
0
void gain_code_exec(pid_t remote_pid) {
   malloc_stub();

   ptrace_detach(remote_pid);
   exit(1);
 
   int status;

   // Find remote function adresses for malloc, free, __libc_dlopen_mode
   unsigned long remote_malloc_addr = find_remote_function("libc", find_libc_function("malloc"), remote_pid);
   unsigned long remote_free_addr = find_remote_function("libc", find_libc_function("free"), remote_pid);
   unsigned long remote_dlopen_addr = find_remote_function("libc", find_libc_function("__libc_dlopen_mode"), remote_pid);
   
   // Initialize global regs structs variables
   memset(&_regs_backup, 0, sizeof(struct user_regs_struct));
   memset(&_regs_fiddle, 0, sizeof(struct user_regs_struct));
   ptrace_getregs(remote_pid, &_regs_backup);
   reset_regs_fiddle();

   // Get Addr to write our initial stub to:
   unsigned long free_space_addr = find_free_space_addr(remote_pid);
   
   // Set RIP to addr start (2 byte long start instruction)
   _regs_fiddle.rip = free_space_addr + 2;
   
   // TODO TMP
   // Setup parameters in registers (see malloc_stub definition)
   _regs_fiddle.rbx = 1073741824; // exactly one GB
   _regs_fiddle.rax = remote_malloc_addr;
   
   // Upload registers
   printf("Uploading payload regs\n");
   ptrace_setregs(remote_pid, &_regs_fiddle);
   
   // Figure out stub size
   size_t stub_size = (intptr_t)malloc_stub_end - (intptr_t)malloc_stub;
   
   // Create buffer holdig our stub
   printf("Crafting payload stub\n");
   char* stub_code = malloc(stub_size * sizeof(char));
   memset(stub_code, 0, stub_size * sizeof(char));
   memcpy(stub_code, malloc_stub, stub_size);

   // Backup everything that we'll overwrite in target location
   printf("Backing up data\n");
   char* backup = malloc(stub_size * sizeof(char));
   read_data(remote_pid, free_space_addr, backup, stub_size);
   
   // Write our code to target location
   printf("Uploading payload\n");
   write_data(remote_pid, free_space_addr, stub_code, stub_size);
   
   // Continue execution and wait for int3
   printf("Code injection successfull, executing\n"); 
   ptrace_cont(remote_pid);
   sleep(1);
   printf("Pid returned ... probably\n");
   
   // Reupload old data
   printf("Reuploading old data\n");
   write_data(remote_pid, free_space_addr, backup, stub_size);
   ptrace_setregs(remote_pid, &_regs_backup);
   printf("Reset execution flow, continuing execution");
   
   ptrace_cont(remote_pid);
   
   free(backup);
   free(stub_code);
   
   printf("TMP; HALTING FOR 30 seconds\n");
   sleep(30);
}