Exemplo n.º 1
0
int
main (int argc, char *argv[])
{
  int pid;
  struct link_map *map;
  char sym_name[256];
  unsigned long sym_addr;
  unsigned long new_addr, old_addr, rel_addr;

  pid = atoi (argv[1]);

  ptrace_attach (pid);

  map = get_linkmap (pid);

  sym_addr = find_symbol (pid, map, "_dl_open");
  printf ("found _dl_open at addr %p\n", sym_addr);
  call_dl_open (pid, sym_addr,
		"/home/joker/JustForFun/Injectso/passwd/so.so");

/* 找到我们的新函数newread的地址 */
  strcpy (sym_name, "newread");	/* intercept */
  sym_addr = find_symbol (pid, map, sym_name);
  printf ("%s addr\t %p\n", sym_name, sym_addr);

  /* 找到read的RELOCATION地址 */
  strcpy (sym_name, "read");
  rel_addr = find_sym_in_rel (pid, sym_name);
  printf ("%s rel addr\t %p\n", sym_name, rel_addr);

  /* 找到用于保存read地址的指针 */
  strcpy (sym_name, "oldread");
  old_addr = find_symbol (pid, map, sym_name);
  printf ("%s addr\t %p\n", sym_name, old_addr);

  /* 函数重定向 */
  puts ("intercept...");	/* intercept */
  ptrace_read (pid, rel_addr, &new_addr, sizeof (new_addr));
  ptrace_write (pid, old_addr, &new_addr, sizeof (new_addr));
  ptrace_write (pid, rel_addr, &sym_addr, sizeof (sym_addr));
  puts ("injectso ok");

  /* 脱离进程 */
  ptrace_detach (pid);

  exit (0);
}
Exemplo n.º 2
0
unsigned long ptrace_push(int pid, regs_t *regs, void *paddr, int size) {
#ifdef ANDROID
    unsigned long arm_sp;
    arm_sp = regs->ARM_sp;
    arm_sp -= size;
    arm_sp = arm_sp - arm_sp % 8;
    regs->ARM_sp= arm_sp;
    ptrace_write(pid, arm_sp, paddr, size);
    return arm_sp;
#else
    unsigned long esp;
    regs_t regs;
    ptrace_readreg(pid, &regs);
    esp = regs.esp;
    esp -= size;
    esp = esp - esp % 8;
    regs.esp = esp;
    ptrace_writereg(pid, &regs);
    ptrace_write(pid, esp, paddr, size);
    return esp;
#endif
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
static void _prepare(struct pid *sp)
{
	FILE *fp;
	char buf[128];
	unsigned char code[4] = { 0xcd, 0x80, 0, 0 }; // int 0x80

	if (sp->vdso_addr)
		return;

	/* find VDSO address */
	snprintf(buf, sizeof buf, "/proc/%d/maps", sp->pid);
	fp = fopen(buf, "r");
	while (fgets(buf, sizeof buf, fp)) {
		if (strlen(buf) < 49 + 6)
			continue;

		/* found it? */
		if (strncmp(buf + 49, "[vdso]", 6) == 0) {
			/* parse address */
			buf[8] = 0;
			sp->vdso_addr = strtoul(buf, NULL, 16);
			break;
		}
	}
	fclose(fp);

	if (!sp->vdso_addr)
		dbg(0, "pid %d: no [vdso] memory region\n", sp->pid);

#ifdef VDSO_PIGGYBACK
	/* on x86-32 the INT 0x80 is already there :) */
	sp->vdso_addr += 0x406;
#else
	/* inject our code */
	dbg(3, "pid %d: installing code at 0x%x\n", sp->pid, sp->vdso_addr);
	ptrace_write(sp, sp->vdso_addr, code, sizeof code);
#endif
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...)
{
	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;  // stack space for immediate values
	ss_mem = 0;   // stack space for pointer values
	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);

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

	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
	 */
	_prepare(sp);

	regs2.eax = 102;            // socketcall
	regs2.ebx = sc_code;
	regs2.ecx = regs.esp - ss;
	regs2.eip = sp->vdso_addr;  // gateway to int3

	ptrace_setregs(sp, &regs2);
	ptrace_cont_syscall(sp, 0, true);   // enter...
	ptrace_cont_syscall(sp, 0, true);   // ...and exit

	/*
	 * 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_setregs(sp, &regs);
	mmatic_free(stack);

	return regs2.eax;
}
Exemplo n.º 7
0
Arquivo: ui.c Projeto: 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);
}