A shell that runs x86_64 assembly
c
x86-64
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

shell_cmds.c 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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 = (%2d Bytes) ",
  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_label(asmsh_t *sh, asmsh_cmd_args_t *args)
  204. {
  205. const unsigned long rip = sh->env->regs.rip;
  206. unsigned long addr;
  207. if(args->argc == 0)
  208. {
  209. if(sh->env->labels.syms_sz == 0)
  210. {
  211. printf("No label defined...\n");
  212. asmsh_log_info("Use '.label NAME [addr]' to define a label");
  213. return 0;
  214. }
  215. printf("%3ld labels :\n", sh->env->labels.syms_sz);
  216. for(size_t i=0; i<sh->env->labels.syms_sz; i++)
  217. {
  218. printf("\t%c%s\t %016lx\n",
  219. ASMSH_LABEL_SYM,
  220. sh->env->labels.syms[i].name,
  221. sh->env->labels.syms[i].addr);
  222. }
  223. return 0;
  224. }
  225. if(args->argc == 1)
  226. {
  227. addr = rip;
  228. }
  229. else
  230. {
  231. if(asmsh_cmd_parse_addr_expr(args, 1, rip, &addr) < 0)
  232. {
  233. asmsh_log_addr_expr_usage();
  234. return -1;
  235. }
  236. }
  237. int ret;
  238. const char *label = args->args[0];
  239. if(addr == 0)
  240. {
  241. ret = asmsh_symtable_del(&sh->env->labels, label);
  242. if(ret < 0)
  243. {
  244. asmsh_log_perror("Unable to delete label");
  245. return -1;
  246. }
  247. else if(ret > 0)
  248. {
  249. asmsh_log_warning("No label '%c%s'",
  250. ASMSH_LABEL_SYM, label);
  251. return -1;
  252. }
  253. asmsh_log_info("Label '%c%s' deleted",
  254. ASMSH_LABEL_SYM, label);
  255. return 0;
  256. }
  257. ret = asmsh_symtable_add(&sh->env->labels, label, addr);
  258. if(ret < 0)
  259. {
  260. asmsh_log_perror("Unable to add label");
  261. return -1;
  262. }
  263. else if(ret > 0)
  264. {
  265. asmsh_log_warning("Label '%c%s' updated to %016x",
  266. ASMSH_LABEL_SYM, label, addr);
  267. return 0;
  268. }
  269. asmsh_log_info("Label '%c%s' %016lx added",
  270. ASMSH_LABEL_SYM, label, addr);
  271. return ret;
  272. }
  273. int asmsh_cmd_maps(asmsh_t *sh, asmsh_cmd_args_t *args)
  274. {
  275. if(asmsh_env_update_maps(sh->env) < 0)
  276. {
  277. perror("Unable to update maps info");
  278. return -1;
  279. }
  280. printf("%12s-%-12s perm %-8s %-6s %-10s %s\n", "start", "stop", "offset", "device",
  281. "inode", "path");
  282. for(int i=0; i<sh->env->mmap.size; i++)
  283. {
  284. const child_mmap_t *m = &sh->env->mmap.maps[i];
  285. printf("%012llx-%012llx %c%c%c %08lx %02lx:%02lx %10lu %s\n",
  286. (unsigned long long int)m->start,
  287. (unsigned long long int)m->stop,
  288. m->perm & PROT_READ ?'r':'-',
  289. m->perm & PROT_WRITE?'w':'-',
  290. m->perm & PROT_EXEC ?'x':'-',
  291. m->offset,
  292. (m->device & 0xFF00)>>8,
  293. m->device & 0xFF,
  294. m->inode,
  295. m->pathname);
  296. }
  297. return 0;
  298. }
  299. int asmsh_cmd_print_regs(asmsh_t *sh, asmsh_cmd_args_t *args)
  300. {
  301. asmsh_env_t *env = sh->env;
  302. asmsh_env_update_regs(env);
  303. struct user_regs_struct *r = &env->regs;
  304. #define FLG(b, l) ( (r->eflags & (1<<b))?l:'-' )
  305. printf("rax: %016llx rbx: %016llx rcx: %016llx rdx: %016llx\n\
  306. rbp: %016llx rsi: %016llx rdi: %016llx rsp: %016llx\n\
  307. r8: %016llx r9: %016llx r10: %016llx r11: %016llx\n\
  308. r12: %016llx r13: %016llx r14: %016llx r15: %016llx\n\
  309. rip: %016llx flg: %016llx\n\
  310. cs: %04llx ds: %04llx es: %04llx fs:%04llx gs: %04llx ss:%04llx\n\
  311. flags: %c%c%c%c|%c%c%c\n\
  312. ODSZ|APC\n\
  313. ", r->rax, r->rbx, r->rcx, r->rdx,\
  314. r->rbp, r->rsi, r->rdi, r->rsp,\
  315. r->r8, r->r9, r->r10, r->r11,\
  316. r->r12, r->r13, r->r14, r->r15,\
  317. r->rip, r->eflags,\
  318. r->cs, r->ds, r->es, r->fs, r->gs, r->ss,
  319. FLG(11,'O'), FLG(10, 'D'), FLG(7, 'S'), FLG(6, 'Z'),
  320. FLG(4, 'A'), FLG(2, 'P'), FLG(0, 'C'));
  321. #undef FLG
  322. return 0;
  323. }
  324. int asmsh_cmd_step(asmsh_t *sh, asmsh_cmd_args_t *args)
  325. {
  326. int ret, status;
  327. ret = asmsh_env_step(sh->env, &status);
  328. if(ret > 1)
  329. {
  330. return status;
  331. }
  332. return ret;
  333. }
  334. int asmsh_cmd_syscalls(asmsh_t *sh, asmsh_cmd_args_t *args)
  335. {
  336. const int sz = sizeof(syscall_infos)/sizeof(*syscall_infos);
  337. int printed;
  338. char buf[512];
  339. printed = 0;
  340. for(int i=0; i<sz; i++)
  341. {
  342. int ret = snprintf(buf, 512, "%3d 0x%03x %20s ",
  343. syscall_infos[i].nr,
  344. syscall_infos[i].nr,
  345. syscall_infos[i].name);
  346. buf[ret] = '\0';
  347. printed += ret;
  348. if(printed > 80)
  349. {
  350. printf("\n");
  351. printed = ret;
  352. }
  353. printf("%s", buf);
  354. }
  355. printf("\n");
  356. return 0;
  357. }
  358. int asmsh_cmd_run(asmsh_t *sh, asmsh_cmd_args_t *args)
  359. {
  360. int ret, status;
  361. ret = asmsh_env_run(sh->env, &status);
  362. if(ret < 0)
  363. {
  364. perror("Unable to run as expected");
  365. asmsh_log_fatal("Error while child runs...");
  366. return -1;
  367. }
  368. else if(ret > 0)
  369. {
  370. return 1+WEXITSTATUS(status);
  371. }
  372. return 0;
  373. }
  374. int asmsh_cmd_reset(asmsh_t *sh, asmsh_cmd_args_t *args)
  375. {
  376. char *childpath = sh->child_path?strdup(sh->child_path):NULL;
  377. asmsh_cleanup(sh);
  378. int ret = asmsh_init(sh, childpath)<0?2:0;
  379. if(childpath) { free(childpath); }
  380. return ret;
  381. }
  382. // Display CPU flag resister values
  383. int asmsh_cmd_flags(asmsh_t *sh, asmsh_cmd_args_t *args)
  384. {
  385. printf("Flags :\n");
  386. #define printFLG(name, b) printf(" (%2d)%16s : %d\n", b, name,\
  387. (sh->env->regs.eflags & (1<<b))?1:0);
  388. printFLG("Overflow", 11);
  389. printFLG("Direction", 10);
  390. printFLG("Sign", 7);
  391. printFLG("Zero", 6);
  392. printFLG("Auxiliary carry", 4);
  393. printFLG("Parity", 2);
  394. printFLG("Carry", 0);
  395. #undef printFLG
  396. #define EFLG(b,n) ((sh->env->regs.eflags & (1<<b))?n:'-')
  397. printf("%c%c%c%c %c%c%c\n",
  398. EFLG(11,'O'), EFLG(10, 'D'), EFLG(7,'S'), EFLG(6,'Z'),
  399. EFLG(4,'A'), EFLG(2, 'P'), EFLG(0, 'C'));
  400. return 0;
  401. }
  402. // Print help (command list + help)
  403. int asmsh_cmd_help_(asmsh_t *sh, asmsh_cmd_args_t *args)
  404. {
  405. char buf[4096], abuf[64];
  406. int ret;
  407. ret = snprintf(buf, 4096, "Available commands :\n");
  408. for(const asmsh_cmd_t *cmd = asmsh_CMDS; cmd->str; cmd++)
  409. {
  410. snprintf(abuf, 64, "%s %s", cmd->sms, cmd->usage);
  411. ret += snprintf(buf+ret, 4096-ret, " %-18s : %s\n",
  412. abuf, cmd->desc);
  413. }
  414. dprintf(2, "%s", buf);
  415. return 0;
  416. }