/* radare - LGPL - Copyright 2009-2013 - pancake */ static int cmd_help(void *data, const char *input) { RCore *core = (RCore *)data; const char *k; char *p, out[128]; ut64 n, n2; int i; switch (input[0]) { case 'r': { // TODO : Add support for 64bit random numbers ut64 b = 0; ut32 r = UT32_MAX; if (input[1]) { strncpy (out, input+(input[1]==' '? 2: 1), sizeof (out)-1); p = strchr (out+1, ' '); if (p) { *p = 0; b = (ut32)r_num_math (core->num, out); r = (ut32)r_num_math (core->num, p+1)-b; } else r = (ut32)r_num_math (core->num, out); } else r = 0LL; if (r == 0) r = UT32_MAX>>1; core->num->value = (ut64) (b + r_num_rand (r)); r_cons_printf ("0x%"PFMT64x"\n", core->num->value); } break; case 'b': n = r_num_get (core->num, input+1); r_num_to_bits (out, n); r_cons_printf ("%sb\n", out); break; case 'B': k = r_str_chop_ro (input+1); r_core_get_boundaries (core, k, &n, &n2); r_cons_printf ("0x%"PFMT64x" 0x%"PFMT64x"\n", n, n2); break; case 'd': if (input[1]==' '){ char *d = r_asm_describe (core->assembler, input+2); if (d && *d) { r_cons_printf ("%s\n", d); free (d); } else eprintf ("Unknown opcode\n"); } else eprintf ("Use: ?d [opcode] to get the description of the opcode\n"); break; case 'h': if (input[1]==' ') { r_cons_printf ("0x%08x\n", (ut32)r_str_hash (input+2)); } else eprintf ("Usage: ?h [string-to-hash]\n"); break; case 'y': for (input++; input[0]==' '; input++); if (*input) { r_core_yank_set_str (core, R_CORE_FOREIGN_ADDR, input, strlen (input)+1); } else { r_core_yank_cat (core, r_num_math (core->num, input+1)); } break; case 'F': r_cons_flush (); break; case 'f': if (input[1]==' ') { char *q, *p = strdup (input+2); if (!p) { eprintf ("Cannot strdup\n"); return 0; } q = strchr (p, ' '); if (q) { *q = 0; n = r_num_get (core->num, p); r_str_bits (out, (const ut8*)&n, sizeof (n), q+1); r_cons_printf ("%s\n", out); } else eprintf ("Usage: \"?b value bitstring\"\n"); free (p); } else eprintf ("Whitespace expected after '?f'\n"); break; case 'o': n = r_num_math (core->num, input+1); r_cons_printf ("0%"PFMT64o"\n", n); break; case 'u': { char unit[32]; n = r_num_math (core->num, input+1); r_num_units (unit, n); r_cons_printf ("%s\n", unit); } break; case ' ': { char unit[32]; ut32 n32, s, a; float f; n = r_num_math (core->num, input+1); n32 = (ut32)n; memcpy (&f, &n32, sizeof (f)); /* decimal, hexa, octal */ s = n>>16<<12; a = n & 0x0fff; r_num_units (unit, n); r_cons_printf ("%"PFMT64d" 0x%"PFMT64x" 0%"PFMT64o" %s %04x:%04x ", n, n, n, unit, s, a); if (n>>32) r_cons_printf ("%"PFMT64d" ", (st64)n); else r_cons_printf ("%d ", (st32)n); /* binary and floating point */ r_str_bits (out, (const ut8*)&n, sizeof (n), NULL); r_cons_printf ("%s %.01lf %f\n", out, core->num->fvalue, f); } break; case 'v': n = (input[1] != '\0') ? r_num_math (core->num, input+2) : 0; switch (input[1]) { case '?': r_cons_printf ("|Usage: ?v[id][ num] # Show value\n" "| No argument shows $? value\n" "|?vi will show in decimal instead of hex\n"); break; case '\0': r_cons_printf ("%d\n", core->num->value); break; case 'i': if (n>>32) r_cons_printf ("%"PFMT64d"\n", (st64)n); else r_cons_printf ("%d\n", (st32)n); break; case 'd': r_cons_printf ("%"PFMT64d"\n", n); break; default: r_cons_printf ("0x%"PFMT64x"\n", n); } core->num->value = n; // redundant break; case '=': // set num->value if (input[1]) { r_num_math (core->num, input+1); } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value); break; case '+': if (input[1]) { st64 n = (st64)core->num->value; if (n>0) r_core_cmd (core, input+1, 0); } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value); break; case '-': if (input[1]) { st64 n = (st64)core->num->value; if (n<0) r_core_cmd (core, input+1, 0); } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value); break; case '!': // ?? if (input[1]) { if (!core->num->value) r_core_cmd (core, input+1, 0); } else r_cons_printf ("0x%"PFMT64x"\n", core->num->value); break; case '@': r_cons_printf ( "|Usage: ... @[(f|s|b)]:] [@iter] expr[!size] [~grep]\n" "|Pipes:\n" "| x > foo pipe output of 'x' command to 'foo' file\n" "| x >> foo concatenate output of 'x' in 'foo' file\n" "| x | less pipe output of 'x' command to less program\n" "|Command evaluation:\n" "| `pdi~push:0[0]` replace output of command inside the line\n" "| .!rabin2 -ri $FILE load imports by running rabin2\n" "| .:8080 expect commands at tcp port 8080\n" "|Special suffixes to temporary set the contents of block:\n" "| @f:/bin/ls from file contents\n" "| @s:hello from given string\n" "| @b:909192 from hex pairs string\n" "|Temporary seeks:\n" "| @ 0x1024 seek to 0x1024 offset\n" "| @ sym.main+3 seek to the evaluated math expressions\n" "| @ 32!128 blocksize = 128, offset = 32\n" "|Repeaters:\n" "| @@=1 2 3 repeat previous command at offsets 1, 2 and 3\n" "| @@ hit* repeat command for all flags matching 'hit*' glob\n" // TODO: documentate @@ glob1 glob2 glob3 "|Internal grep:\n" "| ~? count lines\n" "| ~mov grep lines matching 'mov'\n" "| ~!mov grep lines not matching 'mov'\n" "| ~mov[0] get first column of lines matching 'mov'\n" "| ~mov:3[0] get 1st column from the 4th line matching 'mov'\n" "|Misc:\n" "| 0 go to begining of file\n" "| 0x33 go to 0x33'\n" ); return 0; case '$': r_cons_printf ( "|RNum $variables usable in math expressions:\n" "| $$ here (current virtual seek)\n" "| $o here (current disk io offset)\n" "| $s file size\n" "| $b block size\n" "| $w get word size, 4 if asm.bits=32, 8 if 64, ...\n" "| $c,$r get width and height of terminal\n" "| $S section offset\n" "| $SS section size\n" "| $j jump address (e.g. jmp 0x10, jz 0x10 => 0x10)\n" "| $f jump fail address (e.g. jz 0x10 => next instruction)\n" "| $I number of instructions of current function\n" "| $F current function size \n" "| $Jn get nth jump of function\n" "| $Cn get nth call of function\n" "| $Dn get nth data reference in function\n" "| $Xn get nth xref of function\n" "| $m opcode memory reference (e.g. mov eax,[0x10] => 0x10)\n" "| $l opcode length\n" "| $e 1 if end of block, else 0\n" "| ${ev} get value of eval config variable # TODO: use ?k too\n" "| $? last comparision value\n" ); return R_TRUE; case 'V': if (!strcmp (R2_VERSION, GIT_TAP)) r_cons_printf ("%s\n", R2_VERSION); else r_cons_printf ("%s aka %s\n", R2_VERSION, GIT_TAP); break; case 'l': for (input++; input[0]==' '; input++); core->num->value = strlen (input); break; case 'X': for (input++; input[0]==' '; input++); n = r_num_math (core->num, input); r_cons_printf ("%"PFMT64x"\n", n); break; case 'x': for (input++; input[0]==' '; input++); if (!memcmp (input, "0x", 2) || (*input>='0' && *input<='9')) { ut64 n = r_num_math (core->num, input); int bits = r_num_to_bits (NULL, n) / 8; for (i=0; i>(i*8)) &0xff)); r_cons_newline (); } else { for (i=0; input[i]; i++) r_cons_printf ("%02x", input[i]); r_cons_newline (); } break; case 'e': // echo for (input++; *input==' '; input++); r_cons_printf ("%s\n", input); break; case 's': // sequence from to step { ut64 from, to, step; char *p, *p2; for (input++; *input==' '; input++); p = strchr (input, ' '); if (p) { *p='\0'; from = r_num_math (core->num, input); p2 = strchr (p+1, ' '); if (p2) { *p2='\0'; step = r_num_math (core->num, p2+1); } else step = 1; to = r_num_math (core->num, p+1); for (;from<=to; from+=step) r_cons_printf ("%"PFMT64d" ", from); r_cons_newline (); } } break; case 'P': if (core->io->va) { ut64 o, n = (input[0] && input[1])? r_num_math (core->num, input+2): core->offset; o = r_io_section_offset_to_vaddr (core->io, n); r_cons_printf ("0x%08"PFMT64x"\n", o); } else eprintf ("io.va is false\n"); break; case 'p': if (core->io->va) { // physical address ut64 o, n = (input[0] && input[1])? r_num_math (core->num, input+2): core->offset; o = r_io_section_vaddr_to_offset (core->io, n); r_cons_printf ("0x%08"PFMT64x"\n", o); } else eprintf ("Virtual addresses not enabled!\n"); break; case 'S': { // section name RIOSection *s; ut64 n = (input[0] && input[1])? r_num_math (core->num, input+2): core->offset; n = r_io_section_vaddr_to_offset (core->io, n); s = r_io_section_get (core->io, n); if (s && s->name) r_cons_printf ("%s\n", s->name); } break; case '_': // hud input r_core_yank_hud_file (core, input+1); break; case 'i': // input num if (!r_config_get_i (core->config, "scr.interactive")) { eprintf ("Not running in interactive mode\n"); } else switch (input[1]) { case 'f': core->num->value = !r_num_conditional (core->num, input+2); eprintf ("%s\n", r_str_bool (!core->num->value)); break; case 'm': r_cons_message (input+2); break; case 'p': { core->num->value = r_core_yank_hud_path (core, input+2, 0) == R_TRUE; } break; case 'k': r_cons_any_key (); break; case 'y': for (input+=2; *input==' '; input++); core->num->value = r_cons_yesno (1, "%s? (Y/n)", input); break; case 'n': for (input+=2; *input==' '; input++); core->num->value = r_cons_yesno (0, "%s? (y/N)", input); break; default: { char foo[1024]; r_cons_flush (); for (input++; *input==' '; input++); // TODO: use prompt input eprintf ("%s: ", input); fgets (foo, sizeof (foo)-1, stdin); foo[strlen (foo)-1] = 0; r_core_yank_set_str (core, R_CORE_FOREIGN_ADDR, foo, strlen(foo)+1); core->num->value = r_num_math (core->num, foo); } break; } break; case 't': { struct r_prof_t prof; r_prof_start (&prof); r_core_cmd (core, input+1, 0); r_prof_end (&prof); core->num->value = (ut64)(int)prof.result; eprintf ("%lf\n", prof.result); } break; case '?': // ??? if (input[1]=='?') { if (input[2]=='?') { r_cons_printf ("What are you doing?\n"); return 0; } if (input[2]) { if (core->num->value) r_core_cmd (core, input+1, 0); break; } r_cons_printf ( "|Usage: ?[?[?]] expression\n" "| ? eip-0x804800 show hex and dec result for this math expr\n" "| ?= eip-0x804800 same as above without user feedback\n" "| ?? show value of operation\n" "| ?? [cmd] ? == 0 run command when math matches\n" "| ?_ hudfile load hud menu with given file\n" "| ?b [num] show binary value of number\n" "| ?B [elem] show range boundaries like 'e?search.in\n" "| ?d opcode describe opcode for asm.arch\n" "| ?e string echo string\n" "| ?f [num] [str] map each bit of the number as flag string index\n" "| ?h [str] calculate hash for given string\n" "| ?iy prompt yesno input prompt\n" "| ?i[ynmkp] arg prompt for number or Yes,No,Msg,Key,Path and store in $$?\n" "| ?in prompt yesno input prompt\n" "| ?im message show message centered in screen\n" "| ?ik press any key input dialog\n" "| ?l str returns the length of string (0 if null)\n" "| ?o num get octal value\n" "| ?p vaddr get physical address for given virtual address\n" "| ?P paddr get virtual address for given physical one\n" "| ?r [from] [to] generate random number between from-to\n" "| ?s from to step sequence of numbers from to by steps\n" "| ?S addr return section name of given address\n" "| ?t cmd returns the time to run a command\n" "| ?u num get value in human units (KB, MB, GB, TB)\n" "| ?v eip-0x804800 show hex value of math expr\n" "| ?vi rsp-rbp show decimal value of math expr\n" "| ?V show library version of r_core\n" "| ?x num|0xnum|str returns the hexpair of number or string\n" "| ?X num|expr returns the hexadecimal value numeric expr\n" "| ?y [str] show contents of yank buffer, or set with string\n" "| ?! [cmd] ? != 0\n" "| ?+ [cmd] ? > 0\n" "| ?- [cmd] ? < 0\n" "| ??? show this help\n"); return 0; } else if (input[1]) { if (core->num->value == UT64_MIN) r_core_cmd (core, input+1, 0); } else r_cons_printf ("%"PFMT64d"\n", core->num->value); break; case '\0': default: r_cons_printf ( "|Usage: [.][times][cmd][~grep][@[@iter]addr!size][|>pipe] ; ...\n" "|Append '?' to any char command to get detailed help\n" "|Prefix with number to repeat command N times (f.ex: 3x)\n" "| %%var=value alias for 'env' command\n" "| *off[=[0x]value] pointer read/write data/values (see ?v, wx, wv)\n" "| $alias=value alias commands (simple macros)\n" "| (macro arg0 arg1) manage scripting macros\n" "| .[ -|file|!sh|cmd] interpret cparse, r2 or rlang file (see -?)\n" "| = [cmd] run this command via rap://\n" "| /[xmp/] search for bytes, regexps, patterns, ..\n" "| ![cmd] run given command as in system(3)\n" "| #[algo] [len] calculate hash checksum of current block\n" "| a perform analysis of code\n" "| b [bsz] get or change block size\n" "| c[dqxXfg] [arg] compare block with given data\n" "| C[Cf..] code metadata management\n" "| d[hrscb] debugger commands\n" "| e [a[=b]] list/get/set config evaluable vars\n" "| f [name][sz][at] set flag at current address\n" "| g[wcilper] [arg] go compile shellcodes with r_egg\n" "| i[acdeiIosSz] [file] get info about opened file\n" "| l[-num][ num| msg] log utility\n" "| m[lyogfdps] mountpoints commands\n" "| o [file] (addr) open file at optional address\n" "| p[?] [len] print current block with format and length\n" "| P[osi?] project management utilities\n" "| q [ret] quit program with a return value\n" "| r[+- ][len] resize file\n" "| s [addr] seek to address (also for '0x', '0x1' == 's 0x1')\n" "| S?[size] [vaddr] io section manipulation information\n" "| t[-odfsl] [arg] cparse types management\n" "| V[vcmds] enter visual mode (vcmds=visualvisual keystrokes)\n" "| w[mode] [arg] multiple write operations\n" "| x [len] alias for 'px' (print hexadecimal)\n" "| y [len] [off] yank/paste bytes from/to memory\n" "| ?[??] [expr] help or evaluate math expression\n" "| ?$? show available '$' variables\n" "| ?@? misc help for '@' (seek), '~' (grep) (see ~?""?)\n" ); break; } return 0; }