A shell that runs x86_64 assembly
c
x86-64
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

shell_cmds.c 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /* Copyright Yann Weber <asmsh@yannweb.net>
  2. This file is part of asmsh.
  3. asmsh is free software: you can redistribute it and/or modify it under the
  4. terms of the GNU General Public License as published by the Free Software
  5. Foundation, either version 3 of the License, or any later version.
  6. asmsh is distributed in the hope that it will be useful, but WITHOUT ANY
  7. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  9. details.
  10. You should have received a copy of the GNU General Public License along
  11. with asmsh. If not, see <https://www.gnu.org/licenses/>.
  12. */
  13. #include "shell_cmds.h"
  14. const asmsh_cmd_t *asmsh_cmd_match(const char *text, int tlen)
  15. {
  16. for(const asmsh_cmd_t *cmd=asmsh_CMDS; cmd->str; cmd++)
  17. {
  18. const int clen = strlen(cmd->str);
  19. if(cmd->sm && tlen >= cmd->sm && tlen < clen)
  20. {
  21. if(!strncmp(cmd->str, text, tlen))
  22. {
  23. return cmd;
  24. }
  25. continue;
  26. }
  27. else if(tlen != clen) { continue; }
  28. else
  29. {
  30. int cmp = strncmp(text, cmd->str, tlen);
  31. if(cmp < 0)
  32. {
  33. break;
  34. }
  35. else if(!cmp)
  36. {
  37. return cmd;
  38. }
  39. }
  40. }
  41. return NULL;
  42. }
  43. asmsh_cmd_args_t *asmsh_cmd_parse(const char *cmd)
  44. {
  45. asmsh_cmd_args_t *ret;
  46. int cmdlen, err, argno;
  47. const char *ptr, *arg;
  48. if(!cmd || !*cmd) { return NULL; }
  49. if (*cmd != '.') { return NULL; }
  50. if(!(ret = malloc(sizeof(*ret))))
  51. {
  52. asmsh_log_fatal("Unable to allocate command");
  53. return NULL;
  54. }
  55. bzero(ret, sizeof(*ret));
  56. cmdlen=0;
  57. for(ptr=cmd; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ptr++)
  58. {
  59. cmdlen++;
  60. }
  61. if(cmdlen > ASMSH_CMD_MAXLEN)
  62. {
  63. asmsh_log_error("Invalid command"); //TODO printf command
  64. err=EINVAL;
  65. goto err;
  66. }
  67. strncpy(ret->cmd, cmd, cmdlen);
  68. ret->cmd[cmdlen] = '\0';
  69. // lstrip white chars
  70. for(; *ptr && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n'); ptr++);
  71. if(!*ptr)
  72. {
  73. // end of command
  74. ret->args[0] = NULL;
  75. return ret;
  76. }
  77. arg = ptr;
  78. argno=0;
  79. do
  80. {
  81. int arglen = 0;
  82. for(; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ptr++)
  83. {
  84. arglen++;
  85. }
  86. ret->args[argno] = strndup(arg, arglen);
  87. if(!ret->args[argno])
  88. {
  89. asmsh_log_error("strndup args failed");
  90. err=errno;
  91. goto err;
  92. }
  93. argno++;
  94. if(argno >= ASMSH_CMD_MAXARG)
  95. {
  96. //too many arguments
  97. asmsh_log_error("too many arguments");
  98. err=EINVAL;
  99. goto err;
  100. }
  101. // lstrip white chars
  102. for(; *ptr && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n'); ptr++);
  103. arg=ptr;
  104. }while(*ptr);
  105. ret->argc = argno;
  106. ret->args[argno] = NULL;
  107. return ret;
  108. err:
  109. for(char **p=ret->args; *p; p++) { free(*p); }
  110. errno = err;
  111. free(ret);
  112. return NULL;
  113. }
  114. void asmsh_cmd_args_free(asmsh_cmd_args_t *args)
  115. {
  116. if(!args) { return; }
  117. for(char **a=args->args; *a; a++)
  118. {
  119. free(*a);
  120. }
  121. free(args);
  122. }
  123. int asmsh_cmd_bcode_(asmsh_t *sh, char *argbuf, int bufsz, int argc, char **args)
  124. {
  125. asmsh_bytecode_t bcode;
  126. char _buf[256], *buf;
  127. char code[256];
  128. const char *instr;
  129. int ret;
  130. if(!argbuf)
  131. {
  132. buf=_buf;
  133. bufsz=256;
  134. }
  135. else
  136. {
  137. buf=argbuf;
  138. }
  139. if(argc == 0)
  140. {
  141. if(sh->last_instr == NULL)
  142. {
  143. asmsh_log_error("No instruction compiled yet");
  144. return -1;
  145. }
  146. bcode = sh->last_bcode;
  147. instr = sh->last_instr;
  148. }
  149. else
  150. {
  151. char **arg;
  152. int sz = 0;
  153. for(arg=args;*arg;arg++)
  154. {
  155. sz+=snprintf(code+sz, 255-sz, "%s", *arg);
  156. if(*(arg+1))
  157. {
  158. code[sz] = ' ';
  159. sz++;
  160. }
  161. }
  162. code[sz]='\0';
  163. if(asmsh_asmc_compile(sh->cctx, code, &bcode) < 0)
  164. {
  165. return -1;
  166. }
  167. instr = code;
  168. }
  169. ret = snprintf(buf, bufsz, "%s = (%02db) ",
  170. instr, bcode.size);
  171. for(int i=0; i<sizeof(bcode.bytes); i++)
  172. {
  173. char repr[3] = "..";
  174. if(i<bcode.size)
  175. {
  176. snprintf(repr, 3, "%02x", bcode.bytes[i]);
  177. }
  178. repr[2]='\0';
  179. ret += snprintf(buf+ret, bufsz-ret, "%s%s%s",
  180. i&&(i%4==0)?" ":"",i==8?" ":"",
  181. repr);
  182. }
  183. buf[ret] = '\0';
  184. return 0;
  185. }
  186. int asmsh_cmd_quit(asmsh_t *sh, asmsh_cmd_args_t *args)
  187. {
  188. asmsh_cleanup(sh);
  189. return 1;
  190. }
  191. int asmsh_cmd_bcode(asmsh_t *sh, asmsh_cmd_args_t *args)
  192. {
  193. char str[256];
  194. int ret;
  195. ret = asmsh_cmd_bcode_(sh, str, 256, args->argc, args->args);
  196. if(ret)
  197. {
  198. return ret;
  199. }
  200. printf("%s\n", str);
  201. return 0;
  202. }
  203. int asmsh_cmd_maps(asmsh_t *sh, asmsh_cmd_args_t *args)
  204. {
  205. if(asmsh_env_update_maps(sh->env) < 0)
  206. {
  207. perror("Unable to update maps info");
  208. return -1;
  209. }
  210. printf("%12s-%-12s perm %-8s %-6s %-10s %s\n", "start", "stop", "offset", "device",
  211. "inode", "path");
  212. for(int i=0; i<sh->env->mmap.size; i++)
  213. {
  214. const child_mmap_t *m = &sh->env->mmap.maps[i];
  215. printf("%012llx-%012llx %c%c%c %08lx %02lx:%02lx %10lu %s\n",
  216. (unsigned long long int)m->start,
  217. (unsigned long long int)m->stop,
  218. m->perm & PROT_READ ?'r':'-',
  219. m->perm & PROT_WRITE?'w':'-',
  220. m->perm & PROT_EXEC ?'x':'-',
  221. m->offset,
  222. (m->device & 0xFF00)>>8,
  223. m->device & 0xFF,
  224. m->inode,
  225. m->pathname);
  226. }
  227. return 0;
  228. }
  229. int asmsh_cmd_print_regs(asmsh_t *sh, asmsh_cmd_args_t *args)
  230. {
  231. asmsh_env_t *env = sh->env;
  232. asmsh_env_update_regs(env);
  233. struct user_regs_struct *r = &env->regs;
  234. #define FLG(b, l) ( (r->eflags & (1<<b))?l:'-' )
  235. printf("rax: %016llx rbx: %016llx rcx: %016llx rdx: %016llx\n\
  236. rbp: %016llx rsi: %016llx rdi: %016llx rsp: %016llx\n\
  237. r8: %016llx r9: %016llx r10: %016llx r11: %016llx\n\
  238. r12: %016llx r13: %016llx r14: %016llx r15: %016llx\n\
  239. rip: %016llx flg: %016llx\n\
  240. cs: %04llx ds: %04llx es: %04llx fs:%04llx gs: %04llx ss:%04llx\n\
  241. flags: %c%c%c%c|%c%c%c\n\
  242. ODSZ|APC\n\
  243. ", r->rax, r->rbx, r->rcx, r->rdx,\
  244. r->rbp, r->rsi, r->rdi, r->rsp,\
  245. r->r8, r->r9, r->r10, r->r11,\
  246. r->r12, r->r13, r->r14, r->r15,\
  247. r->rip, r->eflags,\
  248. r->cs, r->ds, r->es, r->fs, r->gs, r->ss,
  249. FLG(11,'O'), FLG(10, 'D'), FLG(7, 'S'), FLG(6, 'Z'),
  250. FLG(4, 'A'), FLG(2, 'P'), FLG(0, 'C'));
  251. #undef FLG
  252. return 0;
  253. }
  254. int asmsh_cmd_step(asmsh_t *sh, asmsh_cmd_args_t *args)
  255. {
  256. int ret, status;
  257. ret = asmsh_env_step(sh->env, &status);
  258. if(ret > 1)
  259. {
  260. return status;
  261. }
  262. return ret;
  263. }
  264. int asmsh_cmd_syscalls(asmsh_t *sh, asmsh_cmd_args_t *args)
  265. {
  266. const int sz = sizeof(syscall_infos)/sizeof(*syscall_infos);
  267. int printed;
  268. char buf[512];
  269. printed = 0;
  270. for(int i=0; i<sz; i++)
  271. {
  272. int ret = snprintf(buf, 512, "%3d 0x%03x %20s ",
  273. syscall_infos[i].nr,
  274. syscall_infos[i].nr,
  275. syscall_infos[i].name);
  276. buf[ret] = '\0';
  277. printed += ret;
  278. if(printed > 80)
  279. {
  280. printf("\n");
  281. printed = ret;
  282. }
  283. printf(buf);
  284. }
  285. printf("\n");
  286. return 0;
  287. }
  288. int asmsh_cmd_reset(asmsh_t *sh, asmsh_cmd_args_t *args)
  289. {
  290. char *childpath = sh->child_path?strdup(sh->child_path):NULL;
  291. asmsh_cleanup(sh);
  292. int ret = asmsh_init(sh, childpath)<0?2:0;
  293. if(childpath) { free(childpath); }
  294. return ret;
  295. }
  296. // Display CPU flag resister values
  297. int asmsh_cmd_flags(asmsh_t *sh, asmsh_cmd_args_t *args)
  298. {
  299. printf("Flags :\n");
  300. #define printFLG(name, b) printf(" (%2d)%16s : %d\n", b, name,\
  301. (sh->env->regs.eflags & (1<<b))?1:0);
  302. printFLG("Overflow", 11);
  303. printFLG("Direction", 10);
  304. printFLG("Sign", 7);
  305. printFLG("Zero", 6);
  306. printFLG("Auxiliary carry", 4);
  307. printFLG("Parity", 2);
  308. printFLG("Carry", 0);
  309. #undef printFLG
  310. #define EFLG(b,n) ((sh->env->regs.eflags & (1<<b))?n:'-')
  311. printf("%c%c%c%c %c%c%c\n",
  312. EFLG(11,'O'), EFLG(10, 'D'), EFLG(7,'S'), EFLG(6,'Z'),
  313. EFLG(4,'A'), EFLG(2, 'P'), EFLG(0, 'C'));
  314. return 0;
  315. }
  316. // Print help (command list + help)
  317. int asmsh_cmd_help_(asmsh_t *sh, asmsh_cmd_args_t *args)
  318. {
  319. char buf[4096], abuf[64];
  320. int ret;
  321. ret = snprintf(buf, 4096, "Available commands :\n");
  322. for(const asmsh_cmd_t *cmd = asmsh_CMDS; cmd->str; cmd++)
  323. {
  324. snprintf(abuf, 64, "%s %s", cmd->sms, cmd->usage);
  325. ret += snprintf(buf+ret, 4096-ret, " %-18s : %s\n",
  326. abuf, cmd->desc);
  327. }
  328. dprintf(2, buf);
  329. return 0;
  330. }