diff options
Diffstat (limited to 'misplays.c')
-rw-r--r-- | misplays.c | 320 |
1 files changed, 273 insertions, 47 deletions
@@ -1,85 +1,311 @@ +#include <signal.h> #include <stdlib.h> -#include <sys/syscall.h> +#include <string.h> +#include <sys/ptrace.h> +#include <linux/ptrace.h> #include <unistd.h> +#include <capstone/capstone.h> + #include "console.h" +#include "debugger.h" #include "helpers.h" -static char *const SPLOITCMD[] = { - "/bin/bash", "-c", "sploit <(echo 'io.interact()') cat", - NULL -}; - static PANEL *left, *right; -static struct console p1, p2; +static struct console cons; static int mode = 0; +static void describe_status(struct tracee *_dbg, PANEL *pan) { + struct tracee dbg = *_dbg; + int status = dbg.status; + struct ptrace_syscall_info info; + + if (WIFEXITED(status)) { + pprintw(pan, "exited with code: %u\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + pprintw(pan, "terminated by signal: %s\n", strsignal(WTERMSIG(status))); + } else { + unsigned long msg; + if (ptrace(PTRACE_GETEVENTMSG, dbg.id, NULL, &msg) < 0) { + perror("PTRACE_GETEVENTMSG"); + } + + if (WIFSTOPPED(status)) { + switch (status >> 8) { + case ((PTRACE_EVENT_VFORK << 8) | SIGTRAP): + pprintw(pan, "child vfork()'d to: %lu\n", msg); + break; + case ((PTRACE_EVENT_FORK << 8) | SIGTRAP): + pprintw(pan, "child fork()'d to: %lu\n", msg); + break; + case ((PTRACE_EVENT_CLONE << 8) | SIGTRAP): + pprintw(pan, "child clone()'d to: %lu\n", msg); + break; + case ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP): + pprintw(pan, "finished vfork\n"); + break; + case ((PTRACE_EVENT_EXEC << 8) | SIGTRAP): + pprintw(pan, "child exec()'d from: %lu\n", msg); + break; + case ((PTRACE_EVENT_EXIT << 8) | SIGTRAP): + pprintw(pan, "exiting with code: %lu\n", msg); + break; + case ((PTRACE_EVENT_STOP << 8) | SIGTRAP): + pprintw(pan, "child stopped\n"); + break; + case ((PTRACE_EVENT_SECCOMP << 8) | SIGTRAP): + pprintw(pan, "child seccomp event\n"); + break; + + case (SIGTRAP | 0x80): + ptrace(PTRACE_GET_SYSCALL_INFO, dbg.id, sizeof(info), &info); + pprintw(pan, "child entering syscall: %llu (%llx, %llx, %llx, %llx, %llx, %llx)\n", + info.entry.nr, + info.entry.args[0], + info.entry.args[1], + info.entry.args[2], + info.entry.args[3], + info.entry.args[4], + info.entry.args[5]); + break; + + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + pprintw(pan, "child group-stopped\n"); + break; + + default: + pprintw(pan, "received signal: %s\n", strsignal(WSTOPSIG(status))); + break; + } + } else { + pprintw(pan, "child stop event unrecognized\n"); + } + } +} + +static void list_breakpoints(struct tracee *dbg, PANEL *pan) { + struct list *breaks = &dbg->breaks; + if (breaks->head != breaks->end) { + pprintw(pan, "---\n"); + + for (struct breakpoint *bp=breaks->head; bp!=breaks->end; bp=bp->next) { + pprintw(pan, "0x%lx ", bp->address); + } + pprintw(pan, "\n"); + } +} + +static void describe_states(struct tracee *dbg, PANEL *pan) { + struct list *states = &dbg->states; + for (struct state *s = states->head; s != states->end; s = s->next) { + pprintw(pan, "%c", (s == dbg->state ? '#' : '-')); + } + pprintw(pan, "\n"); +} + +static void dump_registers(struct tracee *dbg, PANEL *pan) { + struct user_regs_struct *regs = &dbg->state->regs; + pprintw(pan, "rax = 0x%016llx\n", regs->rax); + pprintw(pan, "rbx = 0x%016llx\n", regs->rbx); + pprintw(pan, "rcx = 0x%016llx\n", regs->rcx); + pprintw(pan, "rdx = 0x%016llx\n", regs->rdx); + pprintw(pan, "rdi = 0x%016llx\n", regs->rdi); + pprintw(pan, "rsi = 0x%016llx\n", regs->rsi); + pprintw(pan, "rsp = 0x%016llx\n", regs->rsp); + pprintw(pan, "rbp = 0x%016llx\n", regs->rbp); + pprintw(pan, "rip = 0x%016llx\n", regs->rip); +} + +static void dump_stack(struct tracee *dbg, PANEL *pan) { + unsigned long sp = dbg->state->regs.rsp; + for (size_t i = 0; i < 16; i++, sp += 8) { + unsigned long word = *(unsigned long *)deref(dbg, sp,sizeof(unsigned long)); + pprintw(pan, "0x%lx:\t0x%lx\n", sp, word); + } +} + +static void disasm(struct tracee *dbg, PANEL *pan) { + csh handle; + cs_insn *insn; + + if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) { + perror("capstone open"); + } else { + uint64_t address = dbg->state->regs.rip; + size_t codez = 128; + const uint8_t *code = deref(dbg, address, codez); + insn = cs_malloc(handle); + + for (size_t i = 0; i < 16; i++) { + if (!cs_disasm_iter(handle, &code, &codez, &address, insn)) { + break; + } + pprintw(pan, "0x%"PRIx64":\t%s %s\n", insn->address, insn->mnemonic, insn->op_str); + } + + cs_free(insn, 1); + cs_close(&handle); + } +} + +static void info_update(struct tracee *dbg, PANEL *pan) { + pclear(pan); + pprintw(pan, "PID: %li\n", (long)dbg->id); + if (!dbg->stopped) { + pprintw(pan, "Process is running...\n"); + } else { + describe_status(dbg, pan); + list_breakpoints(dbg, pan); + describe_states(dbg, pan); + dump_registers(dbg, pan); + pprintw(pan, "---\n"); + dump_stack(dbg, pan); + pprintw(pan, "---\n"); + disasm(dbg, pan); + } +} + static void layout(void) { int w = COLS/2; - reset_panel(left, LINES, w, 0, 0); - reset_panel(right, LINES, COLS-w, 0, w); - //reset_panel(left, 0, 0, 0, 0); - //reset_panel(right, 0, 0, 0, 0); + reset_panel(left, LINES-1, w, 0, 0); + reset_panel(right, LINES-1, COLS-w, 0, w); } -static void dofork(struct console *cons) { - if (fork() == 0) { - console_configslave(cons); - close_range(STDERR_FILENO+1, ~0U, CLOSE_RANGE_UNSHARE); - execvp(SPLOITCMD[0], SPLOITCMD); - exit(1); +int main(int argc, char **argv) { + if (argc < 3) { + fprintf(stderr, "Usage: %s <stop> <command>\n", argv[0]); + return 1; } -} -int main(void) { cursinit(); - left = newpan(0, 0, 0, 0); right = newpan(0, 0, 0, 0); layout(); - console_init(&p1); - console_init(&p2); - dofork(&p1); - dofork(&p2); + console_init(&cons); + + argv[argc] = NULL; + struct tracee dbg; + if (dbg_new_process(&dbg, argv+2, &cons)) { + pprintw(right, "Failed to start child\n"); + } + + unsigned long stop = strtoul(argv[1], NULL, 0); + if (stop != 0) { + struct breakpoint *b = xmalloc(sizeof(*b)); + b->address = stop; + b->stack = 0; + b->enabled = -1; + b->active = 0; + list_insert(dbg.breaks.end, b); + dbg_cont(&dbg, PTRACE_CONT); + } int quit = 0; while (!quit) { - console_update(&p1, left); - console_update(&p2, right); + //if (dbg.stopped == NULL) { + dbg_wait(&dbg); + //} + console_update(&cons, right); + info_update(&dbg, left); cursupdate(); + int ch = getch(); if (mode == 0) { switch (ch) { - case 'q': - quit = 1; - break; case KEY_RESIZE: layout(); break; - case KEY_F(1): + case 'q': + quit = 1; + break; + case 'i': mode = 1; - console_enter(&p1, left); + console_enter(&cons, right); break; - case KEY_F(2): - mode = 2; - console_enter(&p2, right); + case 'j': + if (dbg.stopped) { + if (dbg.state != dbg.states.tail) { + dbg.state = dbg.state->next; + } else { + dbg_stepover(&dbg); + } + } break; - } - } else if (mode == 1) { - switch (ch) { - case KEY_RESIZE: - layout(); + case 'k': + if (dbg.stopped) { + if (dbg.state != dbg.states.head) { + dbg.state = dbg.state->prev; + } + } break; - case 0x1b: - mode = 0; - console_leave(&p1, left); + case 'l': + if (dbg.stopped) { + if (dbg.state != dbg.states.tail) { + //dbg.state = dbg.state->next; + } else { + dbg_stepin(&dbg); + } + } break; - case ERR: + //case 'h': + // if (dbg.stopped) { + // dbg_stepout(&dbg); + // } + // break; + case 'g': + if (dbg.stopped) { + dbg.state = dbg.states.head; + } break; - default: - console_input(&p1, ch); + case 'G': + if (dbg.stopped) { + dbg.state = dbg.states.tail; + } + break; + case 's': + if (dbg.stopped) { + dbg_cont(&dbg, PTRACE_SYSCALL); + } + break; + case 'c': + if (dbg.stopped) { + dbg_cont(&dbg, PTRACE_CONT); + } + break; + case 'p': + if (!dbg.stopped) { + tgkill(dbg.id, dbg.id, SIGSTOP); + } + break; + case ':': + mvprintw(LINES-1, 0, ":"); + curs_set(TRUE); + echo(); + timeout(-1); + char cmd[128] = {0}; + getstr(cmd); + curs_set(FALSE); + noecho(); + timeout(25); + clear(); + refresh(); + + char *t = cmd; + struct breakpoint *b = xmalloc(sizeof(*b)); + b->enabled = 1; + b->active = 0; + if (t[0] == '!') { + b->enabled = -1; + t++; + } + b->address = strtoul(t, NULL, 0); + b->stack = 0; + list_insert(dbg.breaks.end, b); break; } } else { @@ -89,12 +315,12 @@ int main(void) { break; case 0x1b: mode = 0; - console_leave(&p2, right); + console_leave(&cons, right); break; case ERR: break; default: - console_input(&p2, ch); + console_input(&cons, ch); break; } } |