/* Copyright Yann Weber This file is part of asmsh. asmsh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. asmsh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with asmsh. If not, see . */ #include "shell_cmds.h" const asmsh_cmd_t *asmsh_cmd_match(const char *text, int tlen) { for(const asmsh_cmd_t *cmd=asmsh_CMDS; cmd->str; cmd++) { const int clen = strlen(cmd->str); if(cmd->sm && tlen >= cmd->sm && tlen < clen) { if(!strncmp(cmd->str, text, tlen)) { return cmd; } continue; } else if(tlen != clen) { continue; } else { int cmp = strncmp(text, cmd->str, tlen); if(cmp < 0) { break; } else if(!cmp) { return cmd; } } } return NULL; } asmsh_cmd_args_t *asmsh_cmd_parse(const char *cmd) { asmsh_cmd_args_t *ret; int cmdlen, err, argno; const char *ptr, *arg; if(!cmd || !*cmd) { return NULL; } if (*cmd != '.') { return NULL; } if(!(ret = malloc(sizeof(*ret)))) { asmsh_log_fatal("Unable to allocate command"); return NULL; } bzero(ret, sizeof(*ret)); cmdlen=0; for(ptr=cmd; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ptr++) { cmdlen++; } if(cmdlen > ASMSH_CMD_MAXLEN) { asmsh_log_error("Invalid command"); //TODO printf command err=EINVAL; goto err; } strncpy(ret->cmd, cmd, cmdlen); ret->cmd[cmdlen] = '\0'; // lstrip white chars for(; *ptr && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n'); ptr++); if(!*ptr) { // end of command ret->args[0] = NULL; return ret; } arg = ptr; argno=0; do { int arglen = 0; for(; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ptr++) { arglen++; } ret->args[argno] = strndup(arg, arglen); if(!ret->args[argno]) { asmsh_log_error("strndup args failed"); err=errno; goto err; } argno++; if(argno >= ASMSH_CMD_MAXARG) { //too many arguments asmsh_log_error("too many arguments"); err=EINVAL; goto err; } // lstrip white chars for(; *ptr && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n'); ptr++); arg=ptr; }while(*ptr); ret->argc = argno; ret->args[argno] = NULL; return ret; err: for(char **p=ret->args; *p; p++) { free(*p); } errno = err; free(ret); return NULL; } void asmsh_cmd_args_free(asmsh_cmd_args_t *args) { if(!args) { return; } for(char **a=args->args; *a; a++) { free(*a); } free(args); } int asmsh_cmd_bcode_(asmsh_t *sh, char *argbuf, int bufsz, int argc, char **args) { asmsh_bytecode_t bcode; char _buf[256], *buf; char code[256]; const char *instr; int ret; if(!argbuf) { buf=_buf; bufsz=256; } else { buf=argbuf; } if(argc == 0) { if(sh->last_instr == NULL) { asmsh_log_error("No instruction compiled yet"); return -1; } bcode = sh->last_bcode; instr = sh->last_instr; } else { char **arg; int sz = 0; for(arg=args;*arg;arg++) { sz+=snprintf(code+sz, 255-sz, "%s", *arg); if(*(arg+1)) { code[sz] = ' '; sz++; } } code[sz]='\0'; if(asmsh_asmc_compile(sh->cctx, code, &bcode) < 0) { return -1; } instr = code; } ret = snprintf(buf, bufsz, "%s = (%02db) ", instr, bcode.size); for(int i=0; iargc, args->args); if(ret) { return ret; } printf("%s\n", str); return 0; } int asmsh_cmd_maps(asmsh_t *sh, asmsh_cmd_args_t *args) { if(asmsh_env_update_maps(sh->env) < 0) { perror("Unable to update maps info"); return -1; } printf("%12s-%-12s perm %-8s %-6s %-10s %s\n", "start", "stop", "offset", "device", "inode", "path"); for(int i=0; ienv->mmap.size; i++) { const child_mmap_t *m = &sh->env->mmap.maps[i]; printf("%012llx-%012llx %c%c%c %08lx %02lx:%02lx %10lu %s\n", (unsigned long long int)m->start, (unsigned long long int)m->stop, m->perm & PROT_READ ?'r':'-', m->perm & PROT_WRITE?'w':'-', m->perm & PROT_EXEC ?'x':'-', m->offset, (m->device & 0xFF00)>>8, m->device & 0xFF, m->inode, m->pathname); } return 0; } int asmsh_cmd_print_regs(asmsh_t *sh, asmsh_cmd_args_t *args) { asmsh_env_t *env = sh->env; asmsh_env_update_regs(env); struct user_regs_struct *r = &env->regs; #define FLG(b, l) ( (r->eflags & (1<rax, r->rbx, r->rcx, r->rdx,\ r->rbp, r->rsi, r->rdi, r->rsp,\ r->r8, r->r9, r->r10, r->r11,\ r->r12, r->r13, r->r14, r->r15,\ r->rip, r->eflags,\ r->cs, r->ds, r->es, r->fs, r->gs, r->ss, FLG(11,'O'), FLG(10, 'D'), FLG(7, 'S'), FLG(6, 'Z'), FLG(4, 'A'), FLG(2, 'P'), FLG(0, 'C')); #undef FLG return 0; } int asmsh_cmd_syscalls(asmsh_t *sh, asmsh_cmd_args_t *args) { const int sz = sizeof(syscall_infos)/sizeof(*syscall_infos); int printed; char buf[512]; printed = 0; for(int i=0; i 80) { printf("\n"); printed = ret; } printf(buf); } printf("\n"); return 0; } int asmsh_cmd_reset(asmsh_t *sh, asmsh_cmd_args_t *args) { char *childpath = sh->child_path?strdup(sh->child_path):NULL; asmsh_cleanup(sh); int ret = asmsh_init(sh, childpath)<0?2:0; if(childpath) { free(childpath); } return ret; } // Display CPU flag resister values int asmsh_cmd_flags(asmsh_t *sh, asmsh_cmd_args_t *args) { printf("Flags :\n"); #define printFLG(name, b) printf(" (%2d)%16s : %d\n", b, name,\ (sh->env->regs.eflags & (1<env->regs.eflags & (1<str; cmd++) { snprintf(abuf, 64, "%s %s", cmd->sms, cmd->usage); ret += snprintf(buf+ret, 4096-ret, " %-18s : %s\n", abuf, cmd->desc); } dprintf(2, buf); return 0; }