예제 #1
0
파일: ui.c 프로젝트: idl3r/rappel
static const
pid_t _gen_child() {
	uint8_t buf[PAGE_SIZE];
	mem_assign(buf, PAGE_SIZE, TRAP, TRAP_SZ);

	uint8_t *elf;
	const size_t elf_sz = gen_elf(&elf, options.start, (uint8_t *)buf, PAGE_SIZE);

	const int exe_fd = write_exe(elf, elf_sz, options.savefile);

	free(elf);

	const pid_t tracee = fork();

	if (tracee < 0) {
		perror("fork");
		exit(EXIT_FAILURE);
	} else if (tracee == 0) {
		ptrace_child(exe_fd);
		abort();
	}

	// Parent
	close(exe_fd);

	return tracee;
}
예제 #2
0
const size_t gen_elf_x86(
		uint8_t **out,
		const unsigned long start,
		const uint8_t *const code,
		const size_t code_sz)
{
	/* We give the elf header and phdr an entire page, because the elf loader can
	 * only map the file at PAGE_SIZE offsets. So our file will look like this 
	 * for an invocation with some code and 2 data segments.
	 *
	 * +----------+
	 * | 1st page |
	 * | ehdr     |
	 * | phdr     |
	 * | shdr     |
	 * | shdr     |
	 * |----------|
	 * | 2nd page |
	 * | code     |
	 * |----------|
	 * | 3rd page |
	 * | data 1   |
	 * |----------|
	 * | 4th page |
	 * | data 2   |
	 * +----------+
	 *
	 * TODO add data section, section headers
	*/

	const size_t pg_align_dist = start - (start & ~0xffff);
	const size_t pad_sz = PAGE_SIZE - (PAGE_SIZE % code_sz);
	const size_t sz = PAGE_SIZE + pg_align_dist + code_sz + pad_sz;

	uint8_t *const e = xmalloc(sz);
	mem_assign(e, sz, TRAP, TRAP_SZ);

	Elf32_Ehdr *const ehdr = (Elf32_Ehdr *) e;
	
	ehdr->e_ident[0] = ELFMAG0;
	ehdr->e_ident[1] = ELFMAG1;
	ehdr->e_ident[2] = ELFMAG2;
	ehdr->e_ident[3] = ELFMAG3;
	ehdr->e_ident[4] = ELFCLASS32;
	ehdr->e_ident[5] = ELFDATA2LSB;
	ehdr->e_ident[6] = EV_CURRENT;
	ehdr->e_ident[7] = ELFOSABI_NONE;
	ehdr->e_ident[9] = 0;
	// Padding
	ehdr->e_type = ET_EXEC;
	ehdr->e_machine = EM_386;
	ehdr->e_version = EV_CURRENT;
	ehdr->e_entry = start;
	ehdr->e_phoff = sizeof(Elf32_Ehdr);
	ehdr->e_shoff = 0; // XXX
	ehdr->e_flags = 0;
	ehdr->e_ehsize = sizeof(Elf32_Ehdr);
	ehdr->e_phentsize = sizeof(Elf32_Phdr);
	ehdr->e_phnum = 1;
	ehdr->e_shentsize = 0;
	ehdr->e_shnum = 0;
	ehdr->e_shstrndx = 0;

	Elf32_Phdr *const phdr = (Elf32_Phdr *) ((uint8_t *) e + sizeof(Elf32_Ehdr));

	phdr->p_type = PT_LOAD;
	phdr->p_flags = PF_X | PF_R;
	phdr->p_offset = PAGE_SIZE;
	phdr->p_vaddr = start - pg_align_dist;
	phdr->p_paddr = 0;
	phdr->p_filesz = code_sz + pg_align_dist; 
	phdr->p_memsz = code_sz + pg_align_dist;
	phdr->p_align = 0x4;

	uint8_t *const data = (uint8_t *) e + PAGE_SIZE + pg_align_dist;
	memcpy(data, code, code_sz);

	*out = e;

	return sz;
}
예제 #3
0
const
size_t assemble_arm(
		uint8_t *const bytecode,
		const size_t bytecode_sz,
		const char *const assembly,
		const size_t asm_sz)
{
	size_t sz = 0;

	char path[PATH_MAX];
	snprintf(path, sizeof(path), "/tmp/rappel-output.XXXXXX");

	const int t = mkstemp(path);

	if (t == -1) {
		perror("mkstemp");
		exit(EXIT_FAILURE);
	}

	REQUIRE (unlink(path) == 0);

	int fildes[2];
	REQUIRE (pipe(fildes) == 0);

	const pid_t asm_pid = fork();

	if (asm_pid < 0) {
		perror("fork");
		exit(EXIT_FAILURE);
	} else if (asm_pid == 0) {
		_child_assemble(fildes, t);
		// Not reached
		abort();
	}

	verbose_printf("as is pid %d\n", asm_pid);

	REQUIRE (close(fildes[0]) == 0);

	write_data(fildes[1], (uint8_t *)assembly, asm_sz);

	REQUIRE (close(fildes[1]) == 0);

	int asm_status;
	REQUIRE (waitpid(asm_pid, &asm_status, 0) != -1);

	if (WIFSIGNALED(asm_status)) {
		fprintf(stderr, "as exited with signal %d.\n", WTERMSIG(asm_status));
	} else if (WIFEXITED(asm_status) && WEXITSTATUS(asm_status)) {
		fprintf(stderr, "as exited %d.\n", WEXITSTATUS(asm_status));
		goto exit;
	}

	REQUIRE (lseek(t, SEEK_SET, 0) != -1);

	int results[2];
	REQUIRE (pipe(results) == 0);

	const pid_t objcopy_pid = fork();

	if (objcopy_pid < 0) {
		perror("fork");
		exit(EXIT_FAILURE);
	} else if (objcopy_pid == 0) {
		_child_objcopy(results, t);
		// Not reached
		abort();
	}

	verbose_printf("objcopy is pid %d\n", objcopy_pid);

	REQUIRE (close(results[1]) == 0);

	mem_assign(bytecode, bytecode_sz, TRAP, TRAP_SZ);

	sz = read_data(results[0], bytecode, bytecode_sz);

	if (sz >= bytecode_sz) {
		fprintf(stderr, "Too much bytecode to handle, exiting...\n");
		exit(EXIT_FAILURE);
	}

	int objcopy_status;
	REQUIRE (waitpid(objcopy_pid, &objcopy_status, 0) != -1);

	if (WIFEXITED(objcopy_status) && WIFSIGNALED(objcopy_status))
		fprintf(stderr, "objcopy exited with signal %d.\n", WTERMSIG(objcopy_status));
	else if (WIFEXITED(objcopy_status) && WEXITSTATUS(objcopy_status))
		fprintf(stderr, "objcopy exited %d.\n", WEXITSTATUS(objcopy_status));

exit:
	REQUIRE (close(t) == 0);

	return sz;
}
예제 #4
0
파일: assemble.c 프로젝트: SRI-CSL/ripple
const
size_t assemble(
		uint8_t *const bytecode,
		const size_t bytecode_sz,
		const char *const assembly,
		const size_t asm_sz)
{
	char path[PATH_MAX];
	snprintf(path, sizeof(path), "/tmp/rappel-input.XXXXXX");

	const int t = mkstemp(path);

	if (t == -1) {
		perror("mkstemp");
		exit(EXIT_FAILURE);
	}

	REQUIRE (unlink(path) == 0);

	dprintf(t, BITSTR);
	dprintf(t, "section .text vstart=%ld\n", options.start);

	write_data(t, (uint8_t *)assembly, asm_sz);

	int fildes[2];
	REQUIRE (pipe(fildes) == 0);

	const pid_t asm_pid = fork();

	if (asm_pid < 0) {
		perror("fork");
		exit(EXIT_FAILURE);
	} else if (asm_pid == 0) {
		_child(fildes, t);
		// Not reached
		abort();
	}

	verbose_printf("nasm is pid %d\n", asm_pid);

	REQUIRE (close(fildes[1]) == 0);

	mem_assign(bytecode, bytecode_sz, TRAP, TRAP_SZ);

	size_t sz = read_data(fildes[0], bytecode, bytecode_sz);

	if (sz >= bytecode_sz) {
		fprintf(stderr, "Too much bytecode to handle, exiting...\n");
		exit(EXIT_FAILURE);
	}

	int status;
	REQUIRE (waitpid(asm_pid, &status, 0) != -1);

	if (WIFSIGNALED(status))
		fprintf(stderr, "nasm exited with signal %d.\n", WTERMSIG(status));
	else if (WIFEXITED(status) && WEXITSTATUS(status))
		fprintf(stderr, "nasm exited %d.\n", WEXITSTATUS(status));

	REQUIRE (close(t) == 0);

	return sz;
}