Rizin
unix-like reverse engineering framework and cli tools
cmd_search.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2010-2021 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <ht_uu.h>
5 #include <rz_asm.h>
6 #include <rz_core.h>
7 #include <rz_io.h>
8 #include <rz_list.h>
9 #include <rz_types_base.h>
10 #include "../core_private.h"
11 
12 #include "cmd_search_rop.c"
13 
14 #define USE_EMULATION 0
15 
16 #define AES_SEARCH_LENGTH 40
17 #define PRIVATE_KEY_SEARCH_LENGTH 11
18 
19 static const char *help_msg_search_esil[] = {
20  "/E", " [esil-expr]", "search offsets matching a specific esil expression",
21  "/Ej", " [esil-expr]", "same as above but using the given magic file",
22  "/E?", " ", "show this help",
23  "\nExamples:", "", "",
24  "", "/E $$,0x100001060,-,!", "hit when address is 0x100001060",
25  NULL
26 };
27 
28 static const char *help_msg_slash_m[] = {
29  "/m", "", "search for known magic patterns",
30  "/m", " [file]", "same as above but using the given magic file",
31  "/mb", "", "search recognized RzBin headers",
32  NULL
33 };
34 
35 static const char *help_msg_slash[] = {
36  "Usage:", "/[!bf] [arg]", "Search stuff (see 'e??search' for options)\n"
37  "|Use io.va for searching in non virtual addressing spaces",
38  "/", " foo\\x00", "search for string 'foo\\0'",
39  "/j", " foo\\x00", "search for string 'foo\\0' (json output)",
40  "/!", " ff", "search for first occurrence not matching, command modifier",
41  "/!x", " 00", "inverse hexa search (find first byte != 0x00)",
42  "/+", " /bin/sh", "construct the string with chunks",
43  "//", "", "repeat last search",
44  "/a", "[?][1aoditfmsltf] jmp eax", "assemble opcode and search its bytes",
45  "/b", "", "search backwards, command modifier, followed by other command",
46  "/c", "[?][adr]", "search for crypto materials",
47  "/d", " 101112", "search for a deltified sequence of bytes",
48  "/e", " /E.F/i", "match regular expression",
49  "/E", " esil-expr", "offset matching given esil expressions $$ = here",
50  "/f", "", "search forwards, (command modifier)",
51  "/F", " file [off] [sz]", "search contents of file with offset and size",
52  // TODO: add subcommands to find paths between functions and filter only function names instead of offsets, etc
53  "/g", "[g] [from]", "find all graph paths A to B (/gg follow jumps, see search.count and analysis.depth)",
54  "/h", "[t] [hash] [len]", "find block matching this hash. See ph",
55  "/i", " foo", "search for string 'foo' ignoring case",
56  "/m", "[?][ebm] magicfile", "search for magic, filesystems or binary headers",
57  "/o", " [n]", "show offset of n instructions backward",
58  "/O", " [n]", "same as /o, but with a different fallback if analysis cannot be used",
59  "/p", " patternsize", "search for pattern of given size",
60  "/P", " patternsize", "search similar blocks",
61  "/s", "[*] [threshold]", "find sections by grouping blocks with similar entropy",
62  "/r[rwx]", "[?] sym.printf", "analyze opcode reference an offset",
63  "/R", " [grepopcode]", "search for matching ROP gadgets, semicolon-separated",
64  // moved into /as "/s", "", "search for all syscalls in a region (EXPERIMENTAL)",
65  "/v", "[1248] value", "look for an `cfg.bigendian` 32bit value",
66  "/V", "[1248] min max", "look for an `cfg.bigendian` 32bit value in range",
67  "/w", " foo", "search for wide string 'f\\0o\\0o\\0'",
68  "/wi", " foo", "search for wide string ignoring case 'f\\0o\\0o\\0'",
69  "/x", " ff..33", "search for hex string ignoring some nibbles",
70  "/x", " ff0033", "search for hex string",
71  "/x", " ff43:ffd0", "search for hexpair with mask",
72  "/z", " min max", "search for strings of given size",
73  "/*", " [comment string]", "add multiline comment, end it with '*/'",
74 #if 0
75  "\nConfiguration:", "", " (type `e??search.` for a complete list)",
76  "e", " cmd.hit = x", "command to execute on every search hit",
77  "e", " search.in = ?", "specify where to search stuff (depends on .from/.to)",
78  "e", " search.align = 4", "only catch aligned search hits",
79  "e", " search.from = 0", "start address",
80  "e", " search.to = 0", "end address",
81  "e", " search.flags = true", "if enabled store flags on keyword hits",
82 #endif
83  NULL
84 };
85 
86 static const char *help_msg_slash_a[] = {
87  "Usage:", "/a[?] [arg]", "Search for assembly instructions matching given properties",
88  "/a", " push rbp", "Assemble given instruction and search the bytes",
89  "/a1", " [number]", "Find valid assembly generated by changing only the nth byte",
90  "/aI", "", "Search for infinite loop instructions (jmp $$)",
91  "/aa", " mov eax", "Linearly find aproximated assembly (case insensitive strstr)",
92  "/ac", " mov eax", "Same as /aa, but case-sensitive",
93  "/ad", "[/*j] push;mov", "Match ins1 followed by ins2 in linear disasm",
94  "/ad/", " ins1;ins2", "Search for regex instruction 'ins1' followed by regex 'ins2'",
95  "/ad/a", " instr", "Search for every byte instruction that matches regexp 'instr'",
96  "/ae", " esil", "Search for esil expressions matching substring",
97  "/af", "[l] family", "Search for instruction of specific family (afl=list",
98  "/ai", "[j] 0x300 [0x500]", "Find all the instructions using that immediate (in range)",
99  "/al", "", "Same as aoml, list all opcodes",
100  "/am", " opcode", "Search for specific instructions of specific mnemonic",
101  "/ao", " instr", "Search for instruction 'instr' (in all offsets)",
102  "/as", "[l] ([type])", "Search for syscalls (See /at swi and /af priv)",
103  "/at", "[l] ([type])", "Search for instructions of given type",
104  NULL
105 };
106 
107 static const char *help_msg_slash_c[] = {
108  "Usage: /c", "", "Search for crypto materials",
109  "/ca", "", "Search for AES keys expanded in memory",
110  "/cc", "[algo] [digest]", "Find collisions (bruteforce block length values until given checksum is found)",
111  "/cd", "", "Search for ASN1/DER certificates",
112  "/cr", "", "Search for ASN1/DER private keys (RSA and ECC)",
113  NULL
114 };
115 
116 static const char *help_msg_slash_r[] = {
117  "Usage:", "/r[acerwx] [address]", " search references to this specific address",
118  "/r", " [addr]", "search references to this specific address",
119  "/ra", "", "search all references",
120  "/rc", "", "search for call references",
121  "/rr", "", "Find read references",
122  "/rw", "", "Find write references",
123  "/rx", "", "Find exec references",
124  NULL
125 };
126 
127 static const char *help_msg_slash_R[] = {
128  "Usage: /R", "", "Search for ROP gadgets",
129  "/R", " [filter-by-string]", "Show gadgets",
130  "/R/", " [filter-by-regexp]", "Show gadgets [regular expression]",
131  "/R/j", " [filter-by-regexp]", "JSON output [regular expression]",
132  "/R/q", " [filter-by-regexp]", "Show gadgets in a quiet manner [regular expression]",
133  "/Rj", " [filter-by-string]", "JSON output",
134  "/Rk", " [select-by-class]", "Query stored ROP gadgets",
135  "/Rq", " [filter-by-string]", "Show gadgets in a quiet manner",
136  NULL
137 };
138 
139 static const char *help_msg_slash_Rk[] = {
140  "Usage: /Rk", "", "Query stored ROP gadgets",
141  "/Rk", " [nop|mov|const|arithm|arithm_ct]", "Show gadgets",
142  "/Rkj", "", "JSON output",
143  "/Rkq", "", "List Gadgets offsets",
144  NULL
145 };
146 
147 static const char *help_msg_slash_x[] = {
148  "Usage:", "/x [hexpairs]:[binmask]", "Search in memory",
149  "/x ", "9090cd80", "search for those bytes",
150  "/x ", "9090cd80:ffff7ff0", "search with binary mask",
151  NULL
152 };
153 
154 static int preludecnt = 0;
155 static int searchflags = 0;
156 static int searchshow = 0;
157 static const char *searchprefix = NULL;
158 
162  const char *mode;
163  const char *cmd_hit;
164  PJ *pj;
165  int outmode; // 0 or RZ_MODE_RIZINCMD or RZ_MODE_JSON
166  bool inverse;
169 };
170 
171 struct endlist_pair {
174 };
175 
176 static int search_hash(RzCore *core, const char *hashname, const char *hashstr, ut32 minlen, ut32 maxlen, struct search_parameters *param) {
177  RzIOMap *map;
178  ut8 *buf;
179  int i, j;
180  RzListIter *iter;
181 
182  if (!minlen || minlen == UT32_MAX) {
183  minlen = core->blocksize;
184  }
185  if (!maxlen || maxlen == UT32_MAX) {
186  maxlen = minlen;
187  }
188 
190  for (j = minlen; j <= maxlen; j++) {
191  ut32 len = j;
192  eprintf("Searching %s for %d byte length.\n", hashname, j);
193  rz_list_foreach (param->boundaries, iter, map) {
194  if (rz_cons_is_breaked()) {
195  break;
196  }
197  ut64 from = map->itv.addr, to = rz_itv_end(map->itv);
198  st64 bufsz;
199  bufsz = to - from;
200  if (len > bufsz) {
201  eprintf("Hash length is bigger than range 0x%" PFMT64x "\n", from);
202  continue;
203  }
204  buf = malloc(bufsz);
205  if (!buf) {
206  eprintf("Cannot allocate %" PFMT64d " bytes\n", bufsz);
207  goto fail;
208  }
209  eprintf("Search in range 0x%08" PFMT64x " and 0x%08" PFMT64x "\n", from, to);
210  int blocks = (int)(to - from - len);
211  eprintf("Carving %d blocks...\n", blocks);
212  (void)rz_io_read_at(core->io, from, buf, bufsz);
213  for (i = 0; (from + i + len) < to; i++) {
214  if (rz_cons_is_breaked()) {
215  break;
216  }
217  char *s = rz_hash_cfg_calculate_small_block_string(core->hash, hashname, buf + i, len, NULL, false);
218  if (!s) {
219  eprintf("Hash fail\n");
220  break;
221  }
222  if (!(i % 5)) {
223  eprintf("%d\r", i);
224  }
225  // eprintf ("0x%08"PFMT64x" %s\n", from+i, s);
226  if (!strcmp(s, hashstr)) {
227  eprintf("Found at 0x%" PFMT64x "\n", from + i);
228  rz_cons_printf("f hash.%s.%s @ 0x%" PFMT64x "\n",
229  hashname, hashstr, from + i);
230  free(s);
231  free(buf);
232  return 1;
233  }
234  free(s);
235  }
236  free(buf);
237  }
238  }
240  eprintf("No hashes found\n");
241  return 0;
242 fail:
243  return -1;
244 }
245 
246 static void cmd_search_bin(RzCore *core, RzInterval itv) {
247  ut64 from = itv.addr, to = rz_itv_end(itv);
248  int size; // , sz = sizeof (buf);
249 
250  int fd = core->file->fd;
253  while (from < to) {
254  if (rz_cons_is_breaked()) {
255  break;
256  }
257  RzBuffer *ref = rz_buf_new_slice(b, from, to);
258  RzBinPlugin *plug = rz_bin_get_binplugin_by_buffer(core->bin, ref);
259  if (plug) {
260  rz_cons_printf("0x%08" PFMT64x " %s\n", from, plug->name);
261  if (plug->size) {
262  RzBinOptions opt = {
263  .pluginname = plug->name,
264  .obj_opts = { 0 },
265  .sz = 4096,
266  .xtr_idx = 0,
267  .fd = fd,
268  };
269  rz_bin_open_io(core->bin, &opt);
270  size = plug->size(core->bin->cur);
271  if (size > 0) {
272  rz_cons_printf("size %d\n", size);
273  }
274  }
275  }
276  rz_buf_free(ref);
277  from++;
278  }
279  rz_buf_free(b);
281 }
282 
283 static int __prelude_cb_hit(RzSearchKeyword *kw, void *user, ut64 addr) {
284  RzCore *core = (RzCore *)user;
285  int depth = rz_config_get_i(core->config, "analysis.depth");
286  // eprintf ("ap: Found function prelude %d at 0x%08"PFMT64x"\n", preludecnt, addr);
288  preludecnt++;
289  return 1;
290 }
291 
292 RZ_API int rz_core_search_prelude(RzCore *core, ut64 from, ut64 to, const ut8 *buf, int blen, const ut8 *mask, int mlen) {
293  ut64 at;
294  ut8 *b = (ut8 *)malloc(core->blocksize);
295  if (!b) {
296  return 0;
297  }
298  // TODO: handle sections ?
299  if (from >= to) {
300  eprintf("aap: Invalid search range 0x%08" PFMT64x " - 0x%08" PFMT64x "\n", from, to);
301  free(b);
302  return 0;
303  }
305  rz_search_kw_add(core->search, rz_search_keyword_new(buf, blen, mask, mlen, NULL));
306  rz_search_begin(core->search);
308  preludecnt = 0;
309  for (at = from; at < to; at += core->blocksize) {
310  if (rz_cons_is_breaked()) {
311  break;
312  }
313  if (!rz_io_is_valid_offset(core->io, at, 0)) {
314  break;
315  }
316  (void)rz_io_read_at(core->io, at, b, core->blocksize);
317  if (rz_search_update(core->search, at, b, core->blocksize) == -1) {
318  eprintf("search: update read error at 0x%08" PFMT64x "\n", at);
319  break;
320  }
321  }
322  // rz_search_reset might also benifet from having an if(s->data) RZ_FREE(s->data), but im not sure.
323  // add a commit that puts it in there to this PR if it wouldn't break anything. (don't have to worry about this happening again, since all searches start by resetting core->search)
324  // For now we will just use rz_search_kw_reset
325  rz_search_kw_reset(core->search);
326  free(b);
327  return preludecnt;
328 }
329 
331  int ret = -1;
332  ut64 from = UT64_MAX;
333  ut64 to = UT64_MAX;
334  int keyword_length = 0;
335  ut8 *keyword = NULL;
336  const char *prelude = rz_config_get(core->config, "analysis.prelude");
337  const char *where = rz_config_get(core->config, "analysis.in");
338 
339  RzList *list = rz_core_get_boundaries_prot(core, RZ_PERM_X, where, "search");
340  RzList *arch_preludes = NULL;
341  RzListIter *iter = NULL, *iter2 = NULL;
342  RzIOMap *p = NULL;
343  RzSearchKeyword *kw = NULL;
344 
345  if (!list) {
346  return -1;
347  }
348 
349  if (RZ_STR_ISNOTEMPTY(prelude)) {
350  keyword = malloc(strlen(prelude) + 1);
351  if (!keyword) {
352  RZ_LOG_ERROR("aap: cannot allocate 'analysis.prelude' buffer\n");
354  return -1;
355  }
356  keyword_length = rz_hex_str2bin(prelude, keyword);
357  } else {
358  arch_preludes = rz_analysis_preludes(core->analysis);
359  if (!arch_preludes) {
361  return -1;
362  }
363  }
364 
365  rz_list_foreach (list, iter, p) {
366  if (!(p->perm & RZ_PERM_X)) {
367  continue;
368  }
369  from = p->itv.addr;
370  to = rz_itv_end(p->itv);
371  if (keyword && keyword_length > 0) {
372  ret = rz_core_search_prelude(core, from, to, keyword, keyword_length, NULL, 0);
373  } else {
374  rz_list_foreach (arch_preludes, iter2, kw) {
375  ret = rz_core_search_prelude(core, from, to,
376  kw->bin_keyword, kw->keyword_length,
377  kw->bin_binmask, kw->binmask_length);
378  }
379  }
380  }
381  free(keyword);
383  rz_list_free(arch_preludes);
384  return ret;
385 }
386 
387 /* TODO: maybe move into util/str */
388 static char *getstring(char *b, int l) {
389  char *r, *res = malloc(l + 1);
390  int i;
391  if (!res) {
392  return NULL;
393  }
394  for (i = 0, r = res; i < l; b++, i++) {
395  if (IS_PRINTABLE(*b)) {
396  *r++ = *b;
397  }
398  }
399  *r = 0;
400  return res;
401 }
402 
403 static int _cb_hit(RzSearchKeyword *kw, void *user, ut64 addr) {
404  struct search_parameters *param = user;
405  RzCore *core = param->core;
406  const RzSearch *search = core->search;
407  ut64 base_addr = 0;
408  bool use_color = core->print->flags & RZ_PRINT_FLAGS_COLOR;
409  int keyword_len = kw ? kw->keyword_length + (search->mode == RZ_SEARCH_DELTAKEY) : 0;
410 
411  if (searchshow && kw && kw->keyword_length > 0) {
412  int len, i, extra, mallocsize;
413  char *s = NULL, *str = NULL, *p = NULL;
414  extra = (param->outmode == RZ_MODE_JSON) ? 3 : 1;
415  const char *type = "hexpair";
416  ut8 *buf = malloc(keyword_len);
417  if (!buf) {
418  return 0;
419  }
420  switch (kw->type) {
422  const int ctx = 16;
423  const int prectx = addr > 16 ? ctx : addr;
424  char *pre, *pos, *wrd;
425  const int len = keyword_len;
426  char *buf = calloc(1, len + 32 + ctx * 2);
427  type = "string";
428  rz_io_read_at(core->io, addr - prectx, (ut8 *)buf, len + (ctx * 2));
429  pre = getstring(buf, prectx);
430  pos = getstring(buf + prectx + len, ctx);
431  if (!pos) {
432  pos = strdup("");
433  }
434  if (param->outmode == RZ_MODE_JSON) {
435  wrd = getstring(buf + prectx, len);
436  s = rz_str_newf("%s%s%s", pre, wrd, pos);
437  } else {
438  wrd = rz_str_utf16_encode(buf + prectx, len);
439  s = rz_str_newf(use_color ? ".%s" Color_YELLOW "%s" Color_RESET "%s."
440  : "\"%s%s%s\"",
441  pre, wrd, pos);
442  }
443  free(buf);
444  free(pre);
445  free(wrd);
446  free(pos);
447  }
448  free(p);
449  break;
450  default:
451  len = keyword_len; // 8 byte context
452  mallocsize = (len * 2) + extra;
453  str = (len > 0xffff) ? NULL : malloc(mallocsize);
454  if (str) {
455  p = str;
456  memset(str, 0, len);
457  rz_io_read_at(core->io, base_addr + addr, buf, keyword_len);
458  if (param->outmode == RZ_MODE_JSON) {
459  p = str;
460  }
461  const int bytes = (len > 40) ? 40 : len;
462  for (i = 0; i < bytes; i++) {
463  sprintf(p, "%02x", buf[i]);
464  p += 2;
465  }
466  if (bytes != len) {
467  strcpy(p, "...");
468  p += 3;
469  }
470  *p = 0;
471  } else {
472  eprintf("Cannot allocate %d\n", mallocsize);
473  }
474  s = str;
475  str = NULL;
476  break;
477  }
478 
479  if (param->outmode == RZ_MODE_JSON) {
480  pj_o(param->pj);
481  pj_kN(param->pj, "offset", base_addr + addr);
482  pj_ks(param->pj, "type", type);
483  pj_ks(param->pj, "data", s);
484  pj_end(param->pj);
485  } else {
486  rz_cons_printf("0x%08" PFMT64x " %s%d_%d %s\n",
487  base_addr + addr, searchprefix, kw->kwidx, kw->count, s);
488  }
489  free(s);
490  free(buf);
491  free(str);
492  } else if (kw) {
493  if (param->outmode == RZ_MODE_JSON) {
494  pj_o(param->pj);
495  pj_kN(param->pj, "offset", base_addr + addr);
496  pj_ki(param->pj, "len", keyword_len);
497  pj_end(param->pj);
498  } else {
499  if (searchflags) {
500  rz_cons_printf("%s%d_%d\n", searchprefix, kw->kwidx, kw->count);
501  } else {
502  rz_cons_printf("f %s%d_%d %d @ 0x%08" PFMT64x "\n", searchprefix,
503  kw->kwidx, kw->count, keyword_len, base_addr + addr);
504  }
505  }
506  }
507  if (searchflags && kw) {
508  const char *flag = sdb_fmt("%s%d_%d", searchprefix, kw->kwidx, kw->count);
509  rz_flag_set(core->flags, flag, base_addr + addr, keyword_len);
510  }
511  if (*param->cmd_hit) {
512  ut64 here = core->offset;
513  rz_core_seek(core, base_addr + addr, true);
514  rz_core_cmd(core, param->cmd_hit, 0);
515  rz_core_seek(core, here, true);
516  }
517  return true;
518 }
519 
520 static int c = 0;
521 
522 static inline void print_search_progress(ut64 at, ut64 to, int n, struct search_parameters *param) {
523  if ((++c % 64) || (param->outmode == RZ_MODE_JSON)) {
524  return;
525  }
526  if (rz_cons_singleton()->columns < 50) {
527  eprintf("\r[ ] 0x%08" PFMT64x " hits = %d \r%s",
528  at, n, (c % 2) ? "[ #]" : "[# ]");
529  } else {
530  eprintf("\r[ ] 0x%08" PFMT64x " < 0x%08" PFMT64x " hits = %d \r%s",
531  at, to, n, (c % 2) ? "[ #]" : "[# ]");
532  }
533 }
534 
535 static void append_bound(RzList *list, RzIO *io, RzInterval search_itv, ut64 from, ut64 size, int perms) {
537  if (!map) {
538  return;
539  }
540  if (io && io->desc) {
541  map->fd = rz_io_fd_get_current(io);
542  }
543 
544  map->perm = perms;
545  RzInterval itv = { from, size };
546  if (size == -1) {
547  eprintf("Warning: Invalid range. Use different search.in=? or analysis.in=dbg.maps.x\n");
548  free(map);
549  return;
550  }
551  // TODO UT64_MAX is a valid address. search.from and search.to are not specified
552  if (search_itv.addr == UT64_MAX && !search_itv.size) {
553  map->itv = itv;
555  } else if (rz_itv_overlap(itv, search_itv)) {
556  map->itv = rz_itv_intersect(itv, search_itv);
557  if (map->itv.size) {
559  } else {
560  free(map);
561  }
562  } else {
563  free(map);
564  }
565 }
566 
567 static bool maskMatches(int perm, int mask, bool only) {
568  if (mask) {
569  if (only) {
570  return ((perm & 7) != mask);
571  }
572  return (perm & mask) != mask;
573  }
574  return false;
575 }
576 
577 RZ_API RZ_OWN RzList /*<RzIOMap *>*/ *rz_core_get_boundaries_prot(RzCore *core, int perm, const char *mode, const char *prefix) {
579 
580  RzList *list = rz_list_newf(free); // XXX rz_io_map_free);
581  if (!list) {
582  return NULL;
583  }
584 
585  char bound_in[32];
586  char bound_from[32];
587  char bound_to[32];
588  snprintf(bound_in, sizeof(bound_in), "%s.%s", prefix, "in");
589  snprintf(bound_from, sizeof(bound_from), "%s.%s", prefix, "from");
590  snprintf(bound_to, sizeof(bound_to), "%s.%s", prefix, "to");
591  const ut64 search_from = rz_config_get_i(core->config, bound_from),
592  search_to = rz_config_get_i(core->config, bound_to);
593  const RzInterval search_itv = { search_from, search_to - search_from };
594  if (!mode) {
595  mode = rz_config_get(core->config, bound_in);
596  }
597  if (!rz_config_get_b(core->config, "cfg.debug") && !core->io->va) {
598  append_bound(list, core->io, search_itv, 0, rz_io_size(core->io), 7);
599  } else if (!strcmp(mode, "file")) {
600  append_bound(list, core->io, search_itv, 0, rz_io_size(core->io), 7);
601  } else if (!strcmp(mode, "block")) {
602  append_bound(list, core->io, search_itv, core->offset, core->blocksize, 7);
603  } else if (!strcmp(mode, "io.map")) {
605  if (m) {
606  append_bound(list, core->io, search_itv, m->itv.addr, m->itv.size, m->perm);
607  }
608  } else if (!strcmp(mode, "io.maps")) { // Non-overlapping RzIOMap parts not overridden by others (skyline)
609  ut64 begin = UT64_MAX;
610  ut64 end = UT64_MAX;
611 #define USE_SKYLINE 0
612 #if USE_SKYLINE
613  const RzPVector *skyline = &core->io->map_skyline;
614  size_t i;
615  for (i = 0; i < rz_pvector_len(skyline); i++) {
616  const RzIOMapSkyline *part = rz_pvector_at(skyline, i);
617  ut64 from = rz_itv_begin(part->itv);
618  ut64 to = rz_itv_end(part->itv);
619  // XXX skyline's fake map perms are wrong
621  int rwx = m ? m->perm : part->map->perm;
622 #else
623  void **it;
625  rz_pvector_foreach (maps, it) {
626  RzIOMap *map = *it;
627  ut64 from = rz_itv_begin(map->itv);
628  ut64 to = rz_itv_end(map->itv);
629  int rwx = map->perm;
630 #endif
631  // eprintf ("--------- %llx %llx (%llx %llx)\n", from, to, begin, end);
632  if (begin == UT64_MAX) {
633  begin = from;
634  }
635  if (end == UT64_MAX) {
636  end = to;
637  } else {
638  if (end == from) {
639  end = to;
640  } else {
641  append_bound(list, NULL, search_itv,
642  begin, end - begin, rwx);
643  begin = from;
644  end = to;
645  }
646  }
647  }
648  if (end != UT64_MAX) {
649  append_bound(list, NULL, search_itv, begin, end - begin, 7);
650  }
651  } else if (rz_str_startswith(mode, "io.maps.")) {
652  int len = strlen("io.maps.");
653  int mask = (mode[len - 1] == '.') ? rz_str_rwx(mode + len) : 0;
654  // bool only = (bool)(size_t)strstr (mode, ".only");
655 
656  void **it;
658  rz_pvector_foreach (maps, it) {
659  RzIOMap *map = *it;
660  ut64 from = rz_itv_begin(map->itv);
661  // ut64 to = rz_itv_end (map->itv);
662  int rwx = map->perm;
663  if ((rwx & mask) != mask) {
664  continue;
665  }
666  append_bound(list, core->io, search_itv, from, rz_itv_size(map->itv), rwx);
667  }
668  } else if (rz_str_startswith(mode, "io.sky.")) {
669  int len = strlen("io.sky.");
670  int mask = (mode[len - 1] == '.') ? rz_str_rwx(mode + len) : 0;
671  bool only = (bool)(size_t)strstr(mode, ".only");
672  RzVector *skyline = &core->io->map_skyline.v;
673  ut64 begin = UT64_MAX;
674  ut64 end = UT64_MAX;
675  size_t i;
676  for (i = 0; i < rz_vector_len(skyline); i++) {
677  const RzSkylineItem *part = rz_vector_index_ptr(skyline, i);
678  ut64 from = part->itv.addr;
679  ut64 to = part->itv.addr + part->itv.size;
680  int perm = ((RzIOMap *)part->user)->perm;
681  if (maskMatches(perm, mask, only)) {
682  continue;
683  }
684  // eprintf ("--------- %llx %llx (%llx %llx)\n", from, to, begin, end);
685  if (begin == UT64_MAX) {
686  begin = from;
687  }
688  if (end == UT64_MAX) {
689  end = to;
690  } else {
691  if (end == from) {
692  end = to;
693  } else {
694  // eprintf ("[%llx - %llx]\n", begin, end);
695  append_bound(list, NULL, search_itv, begin, end - begin, perm);
696  begin = from;
697  end = to;
698  }
699  }
700  }
701  if (end != UT64_MAX) {
702  append_bound(list, NULL, search_itv, begin, end - begin, 7);
703  }
704  } else if (rz_str_startswith(mode, "bin.segments")) {
705  int len = strlen("bin.segments.");
706  int mask = (mode[len - 1] == '.') ? rz_str_rwx(mode + len) : 0;
707  bool only = (bool)(size_t)strstr(mode, ".only");
709  if (obj) {
710  RzBinSection *s;
711  RzListIter *iter;
712  rz_list_foreach (obj->sections, iter, s) {
713  if (!s->is_segment) {
714  continue;
715  }
716  if (maskMatches(s->perm, mask, only)) {
717  continue;
718  }
719  ut64 addr = core->io->va ? s->vaddr : s->paddr;
720  ut64 size = core->io->va ? s->vsize : s->size;
721  append_bound(list, core->io, search_itv, addr, size, s->perm);
722  }
723  }
724  } else if (rz_str_startswith(mode, "code")) {
726  if (obj) {
727  ut64 from = UT64_MAX;
728  ut64 to = 0;
729  RzBinSection *s;
730  RzListIter *iter;
731  rz_list_foreach (obj->sections, iter, s) {
732  if (s->is_segment) {
733  continue;
734  }
735  if (maskMatches(s->perm, 1, false)) {
736  continue;
737  }
738  ut64 addr = core->io->va ? s->vaddr : s->paddr;
739  ut64 size = core->io->va ? s->vsize : s->size;
740  from = RZ_MIN(addr, from);
741  to = RZ_MAX(to, addr + size);
742  }
743  if (from == UT64_MAX) {
744  int mask = 1;
745  void **it;
747  rz_pvector_foreach (maps, it) {
748  RzIOMap *map = *it;
749  ut64 from = rz_itv_begin(map->itv);
750  ut64 size = rz_itv_size(map->itv);
751  int rwx = map->perm;
752  if ((rwx & mask) != mask) {
753  continue;
754  }
755  append_bound(list, core->io, search_itv, from, size, rwx);
756  }
757  }
758  append_bound(list, core->io, search_itv, from, to - from, 1);
759  }
760  } else if (rz_str_startswith(mode, "bin.sections")) {
761  int len = strlen("bin.sections.");
762  int mask = (mode[len - 1] == '.') ? rz_str_rwx(mode + len) : 0;
763  bool only = (bool)(size_t)strstr(mode, ".only");
765  if (obj) {
766  RzBinSection *s;
767  RzListIter *iter;
768  rz_list_foreach (obj->sections, iter, s) {
769  if (s->is_segment) {
770  continue;
771  }
772  if (maskMatches(s->perm, mask, only)) {
773  continue;
774  }
775  ut64 addr = core->io->va ? s->vaddr : s->paddr;
776  ut64 size = core->io->va ? s->vsize : s->size;
777  append_bound(list, core->io, search_itv, addr, size, s->perm);
778  }
779  }
780  } else if (!strcmp(mode, "bin.segment")) {
782  if (obj) {
783  RzBinSection *s;
784  RzListIter *iter;
785  rz_list_foreach (obj->sections, iter, s) {
786  if (!s->is_segment) {
787  continue;
788  }
789  ut64 addr = core->io->va ? s->vaddr : s->paddr;
790  ut64 size = core->io->va ? s->vsize : s->size;
791  if (RZ_BETWEEN(addr, core->offset, addr + size)) {
792  append_bound(list, core->io, search_itv, addr, size, s->perm);
793  }
794  }
795  }
796  } else if (!strcmp(mode, "bin.section")) {
798  if (obj) {
799  RzBinSection *s;
800  RzListIter *iter;
801  rz_list_foreach (obj->sections, iter, s) {
802  if (s->is_segment) {
803  continue;
804  }
805  ut64 addr = core->io->va ? s->vaddr : s->paddr;
806  ut64 size = core->io->va ? s->vsize : s->size;
807  if (RZ_BETWEEN(addr, core->offset, addr + size)) {
808  append_bound(list, core->io, search_itv, addr, size, s->perm);
809  }
810  }
811  }
812  } else if (!strcmp(mode, "analysis.fcn") || !strcmp(mode, "analysis.bb")) {
815  if (f) {
817 
818  /* Search only inside the basic block */
819  if (!strcmp(mode, "analysis.bb")) {
820  RzListIter *iter;
821  RzAnalysisBlock *bb;
822 
823  rz_list_foreach (f->bbs, iter, bb) {
824  ut64 at = core->offset;
825  if ((at >= bb->addr) && (at < (bb->addr + bb->size))) {
826  from = bb->addr;
827  size = bb->size;
828  break;
829  }
830  }
831  }
832  append_bound(list, core->io, search_itv, from, size, 5);
833  } else {
834  eprintf("WARNING: search.in = ( analysis.bb | analysis.fcn )"
835  "requires to seek into a valid function\n");
836  append_bound(list, core->io, search_itv, core->offset, 1, 5);
837  }
838  } else if (!strncmp(mode, "dbg.", 4)) {
839  if (core->bin->is_debugger) {
840  int mask = 0;
841  int add = 0;
842  bool heap = false;
843  bool stack = false;
844  bool all = false;
845  bool first = false;
846  RzListIter *iter;
847  RzDebugMap *map;
848 
850 
851  if (!strcmp(mode, "dbg.map")) {
852  int perm = 0;
853  ut64 from = core->offset;
854  ut64 to = core->offset;
855  rz_list_foreach (core->dbg->maps, iter, map) {
856  if (from >= map->addr && from < map->addr_end) {
857  from = map->addr;
858  to = map->addr_end;
859  perm = map->perm;
860  break;
861  }
862  }
863  if (perm) {
864  RzIOMap *nmap = RZ_NEW0(RzIOMap);
865  if (nmap) {
866  // nmap->fd = core->io->desc->fd;
867  nmap->itv.addr = from;
868  nmap->itv.size = to - from;
869  nmap->perm = perm;
870  nmap->delta = 0;
871  rz_list_append(list, nmap);
872  }
873  }
874  } else {
875  bool only = false;
876  mask = 0;
877  if (!strcmp(mode, "dbg.program")) {
878  first = true;
879  mask = RZ_PERM_X;
880  } else if (!strcmp(mode, "dbg.maps")) {
881  all = true;
882  } else if (rz_str_startswith(mode, "dbg.maps.")) {
883  mask = rz_str_rwx(mode + 9);
884  only = (bool)(size_t)strstr(mode, ".only");
885  } else if (!strcmp(mode, "dbg.heap")) {
886  heap = true;
887  } else if (!strcmp(mode, "dbg.stack")) {
888  stack = true;
889  }
890 
891  ut64 from = UT64_MAX;
892  ut64 to = 0;
893  rz_list_foreach (core->dbg->maps, iter, map) {
894  if (!all && maskMatches(map->perm, mask, only)) {
895  continue;
896  }
897  add = (stack && strstr(map->name, "stack")) ? 1 : 0;
898  if (!add && (heap && (map->perm & RZ_PERM_W)) && strstr(map->name, "heap")) {
899  add = 1;
900  }
901  if ((mask && (map->perm & mask)) || add || all) {
902  if (!list) {
904  }
905  RzIOMap *nmap = RZ_NEW0(RzIOMap);
906  if (!nmap) {
907  break;
908  }
909  nmap->itv.addr = map->addr;
910  nmap->itv.size = map->addr_end - map->addr;
911  if (nmap->itv.addr) {
912  from = RZ_MIN(from, nmap->itv.addr);
913  to = RZ_MAX(to - 1, rz_itv_end(nmap->itv) - 1) + 1;
914  }
915  nmap->perm = map->perm;
916  nmap->delta = 0;
917  rz_list_append(list, nmap);
918  if (first) {
919  break;
920  }
921  }
922  }
923  }
924  }
925  } else {
926  /* obey temporary seek if defined '/x 8080 @ addr:len' */
927  if (core->tmpseek) {
928  append_bound(list, core->io, search_itv, core->offset, core->blocksize, 5);
929  } else {
930  // TODO: repeat last search doesnt works for /a
931  ut64 from = rz_config_get_i(core->config, bound_from);
932  if (from == UT64_MAX) {
933  from = core->offset;
934  }
935  ut64 to = rz_config_get_i(core->config, bound_to);
936  if (to == UT64_MAX) {
937  if (core->io->va) {
938  /* TODO: section size? */
939  } else {
940  if (core->file) {
941  to = rz_io_fd_size(core->io, core->file->fd);
942  }
943  }
944  }
945  append_bound(list, core->io, search_itv, from, to - from, 5);
946  }
947  }
948  return list;
949 }
950 
951 static bool is_end_gadget(const RzAnalysisOp *aop, const ut8 crop) {
953  return false;
954  }
955  switch (aop->type) {
968  return true;
969  }
970  if (crop) { // if conditional jumps, calls and returns should be used for the gadget-search too
971  switch (aop->type) {
977  return true;
978  }
979  }
980  return false;
981 }
982 
983 static bool insert_into(void *user, const ut64 k, const ut64 v) {
984  HtUU *ht = (HtUU *)user;
985  ht_uu_insert(ht, k, v);
986  return true;
987 }
988 
989 // TODO: follow unconditional jumps
990 static RzList *construct_rop_gadget(RzCore *core, ut64 addr, ut8 *buf, int buflen, int idx, const char *grep, int regex, RzList *rx_list, struct endlist_pair *end_gadget, HtUU *badstart) {
991  int endaddr = end_gadget->instr_offset;
992  int branch_delay = end_gadget->delay_size;
993  RzAnalysisOp aop = { 0 };
994  const char *start = NULL, *end = NULL;
995  char *grep_str = NULL;
996  RzCoreAsmHit *hit = NULL;
997  RzList *hitlist = rz_core_asm_hit_list_new();
998  ut8 nb_instr = 0;
999  const ut8 max_instr = rz_config_get_i(core->config, "rop.len");
1000  bool valid = false;
1001  int grep_find;
1002  int search_hit;
1003  char *rx = NULL;
1004  HtUUOptions opt = { 0 };
1005  HtUU *localbadstart = ht_uu_new_opt(&opt);
1006  int count = 0;
1007 
1008  if (grep) {
1009  start = grep;
1010  end = strchr(grep, ';');
1011  if (!end) { // We filter on a single opcode, so no ";"
1012  end = start + strlen(grep);
1013  }
1014  grep_str = calloc(1, end - start + 1);
1015  strncpy(grep_str, start, end - start);
1016  if (regex) {
1017  // get the first regexp.
1018  if (rz_list_length(rx_list) > 0) {
1019  rx = rz_list_get_n(rx_list, count++);
1020  }
1021  }
1022  }
1023 
1024  bool found;
1025  ht_uu_find(badstart, idx, &found);
1026  if (found) {
1027  valid = false;
1028  goto ret;
1029  }
1030  while (nb_instr < max_instr) {
1031  ht_uu_insert(localbadstart, idx, 1);
1032 
1034  if (error < 0 || (nb_instr == 0 && (is_end_gadget(&aop, 0) || aop.type == RZ_ANALYSIS_OP_TYPE_NOP))) {
1035  valid = false;
1036  goto ret;
1037  }
1038 
1039  const int opsz = aop.size;
1040  // opsz = rz_strbuf_length (asmop.buf);
1041  char *opst = aop.mnemonic;
1042  if (!opst) {
1043  RZ_LOG_WARN("Analysis plugin %s did not return disassembly\n", core->analysis->cur->name);
1044  RzAsmOp asmop;
1046  if (rz_asm_disassemble(core->rasm, &asmop, buf + idx, buflen - idx) < 0) {
1047  valid = false;
1048  goto ret;
1049  }
1050  opst = strdup(rz_asm_op_get_asm(&asmop));
1051  rz_asm_op_fini(&asmop);
1052  }
1053  if (!rz_str_ncasecmp(opst, "invalid", strlen("invalid")) ||
1054  !rz_str_ncasecmp(opst, ".byte", strlen(".byte"))) {
1055  valid = false;
1056  goto ret;
1057  }
1058 
1060  if (hit) {
1061  hit->addr = addr;
1062  hit->len = opsz;
1063  rz_list_append(hitlist, hit);
1064  }
1065 
1066  // Move on to the next instruction
1067  idx += opsz;
1068  addr += opsz;
1069  if (rx) {
1070  grep_find = !rz_regex_match(rx, "e", opst);
1071  search_hit = (end && grep && (grep_find < 1));
1072  } else {
1073  search_hit = (end && grep && strstr(opst, grep_str));
1074  }
1075 
1076  // Handle (possible) grep
1077  if (search_hit) {
1078  if (end[0] == ';') { // fields are semicolon-separated
1079  start = end + 1; // skip the ;
1080  end = strchr(start, ';');
1081  end = end ? end : start + strlen(start); // latest field?
1082  free(grep_str);
1083  grep_str = calloc(1, end - start + 1);
1084  if (grep_str) {
1085  strncpy(grep_str, start, end - start);
1086  }
1087  } else {
1088  end = NULL;
1089  }
1090  if (regex) {
1091  rx = rz_list_get_n(rx_list, count++);
1092  }
1093  }
1094  if (endaddr <= (idx - opsz)) {
1095  valid = (endaddr == idx - opsz);
1096  goto ret;
1097  }
1098  rz_analysis_op_fini(&aop);
1099  nb_instr++;
1100  }
1101 ret:
1102  rz_analysis_op_fini(&aop);
1103  free(grep_str);
1104  if (regex && rx) {
1105  rz_list_free(hitlist);
1106  ht_uu_free(localbadstart);
1107  return NULL;
1108  }
1109  if (!valid || (grep && end)) {
1110  rz_list_free(hitlist);
1111  ht_uu_free(localbadstart);
1112  return NULL;
1113  }
1114  ht_uu_foreach(localbadstart, insert_into, badstart);
1115  ht_uu_free(localbadstart);
1116  // If our arch has bds then we better be including them
1117  if (branch_delay && rz_list_length(hitlist) < (1 + branch_delay)) {
1118  rz_list_free(hitlist);
1119  return NULL;
1120  }
1121  return hitlist;
1122 }
1123 
1124 static void print_rop(RzCore *core, RzList *hitlist, PJ *pj, int mode) {
1125  RzCoreAsmHit *hit = NULL;
1126  RzListIter *iter;
1127  RzList *ropList = NULL;
1128  unsigned int size = 0;
1130  RzAsmOp asmop;
1131  Sdb *db = NULL;
1132  const bool colorize = rz_config_get_i(core->config, "scr.color");
1133  const bool rop_comments = rz_config_get_i(core->config, "rop.comments");
1134  const bool esil = rz_config_get_i(core->config, "asm.esil");
1135  const bool rop_db = rz_config_get_i(core->config, "rop.db");
1136 
1137  if (rop_db) {
1138  db = sdb_ns(core->sdb, "rop", true);
1139  ropList = rz_list_newf(free);
1140  if (!db) {
1141  eprintf("Error: Could not create SDB 'rop' namespace\n");
1142  rz_list_free(ropList);
1143  return;
1144  }
1145  }
1146 
1147  switch (mode) {
1148  case 'j':
1149  pj_o(pj);
1150  pj_ka(pj, "opcodes");
1151  rz_list_foreach (hitlist, iter, hit) {
1152  ut8 *buf = malloc(hit->len);
1153  if (!buf) {
1154  return;
1155  }
1156  rz_io_read_at(core->io, hit->addr, buf, hit->len);
1157  rz_asm_set_pc(core->rasm, hit->addr);
1158  rz_asm_disassemble(core->rasm, &asmop, buf, hit->len);
1160  size += hit->len;
1161  if (analop.type != RZ_ANALYSIS_OP_TYPE_RET) {
1162  char *opstr_n = rz_str_newf(" %s", RZ_STRBUF_SAFEGET(&analop.esil));
1163  rz_list_append(ropList, (void *)opstr_n);
1164  }
1165  pj_o(pj);
1166  pj_kN(pj, "offset", hit->addr);
1167  pj_ki(pj, "size", hit->len);
1168  pj_ks(pj, "opcode", rz_asm_op_get_asm(&asmop));
1169  pj_ks(pj, "type", rz_analysis_optype_to_string(analop.type));
1170  pj_end(pj);
1171  free(buf);
1173  }
1174  pj_end(pj);
1175  if (db && hit) {
1176  const ut64 addr = ((RzCoreAsmHit *)hitlist->head->data)->addr;
1177  // rz_cons_printf ("Gadget size: %d\n", (int)size);
1178  const char *key = sdb_fmt("0x%08" PFMT64x, addr);
1179  rop_classify(core, db, ropList, key, size);
1180  }
1181  if (hit) {
1182  pj_kN(pj, "retaddr", hit->addr);
1183  pj_ki(pj, "size", size);
1184  }
1185  pj_end(pj);
1186  break;
1187  case 'q':
1188  // Print gadgets in a 'linear manner', each sequence
1189  // on one line.
1190  rz_cons_printf("0x%08" PFMT64x ":",
1191  ((RzCoreAsmHit *)hitlist->head->data)->addr);
1192  rz_list_foreach (hitlist, iter, hit) {
1193  ut8 *buf = malloc(hit->len);
1194  rz_io_read_at(core->io, hit->addr, buf, hit->len);
1195  rz_asm_set_pc(core->rasm, hit->addr);
1196  rz_asm_disassemble(core->rasm, &asmop, buf, hit->len);
1198  size += hit->len;
1199  const char *opstr = RZ_STRBUF_SAFEGET(&analop.esil);
1200  if (analop.type != RZ_ANALYSIS_OP_TYPE_RET) {
1201  rz_list_append(ropList, rz_str_newf(" %s", opstr));
1202  }
1203  if (esil) {
1204  rz_cons_printf("%s\n", opstr);
1205  } else if (colorize) {
1206  RzStrBuf *colored_asm, *bw_str = rz_strbuf_new(rz_asm_op_get_asm(&asmop));
1207  colored_asm = rz_asm_colorize_asm_str(bw_str, core->print, rz_asm_get_parse_param(core->analysis->reg, analop.type), asmop.asm_toks);
1208  rz_cons_printf(" %s%s;", rz_strbuf_get(colored_asm), Color_RESET);
1209  rz_strbuf_free(colored_asm);
1210  } else {
1211  rz_cons_printf(" %s;", rz_asm_op_get_asm(&asmop));
1212  }
1213  free(buf);
1215  }
1216  if (db && hit) {
1217  const ut64 addr = ((RzCoreAsmHit *)hitlist->head->data)->addr;
1218  // rz_cons_printf ("Gadget size: %d\n", (int)size);
1219  const char *key = sdb_fmt("0x%08" PFMT64x, addr);
1220  rop_classify(core, db, ropList, key, size);
1221  }
1222  break;
1223  default:
1224  // Print gadgets with new instruction on a new line.
1225  rz_list_foreach (hitlist, iter, hit) {
1226  const char *comment = rop_comments ? rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, hit->addr) : NULL;
1227  if (hit->len < 0) {
1228  eprintf("Invalid hit length here\n");
1229  continue;
1230  }
1231  ut8 *buf = malloc(1 + hit->len);
1232  if (!buf) {
1233  break;
1234  }
1235  buf[hit->len] = 0;
1236  rz_io_read_at(core->io, hit->addr, buf, hit->len);
1237  rz_asm_set_pc(core->rasm, hit->addr);
1238  rz_asm_disassemble(core->rasm, &asmop, buf, hit->len);
1240  size += hit->len;
1241  if (analop.type != RZ_ANALYSIS_OP_TYPE_RET) {
1242  char *opstr_n = rz_str_newf(" %s", RZ_STRBUF_SAFEGET(&analop.esil));
1243  rz_list_append(ropList, (void *)opstr_n);
1244  }
1245  char *asm_op_hex = rz_asm_op_get_hex(&asmop);
1246  if (colorize) {
1247  RzStrBuf *colored_asm, *bw_str = rz_strbuf_new(rz_asm_op_get_asm(&asmop));
1248  colored_asm = rz_asm_colorize_asm_str(bw_str, core->print, rz_asm_get_parse_param(core->analysis->reg, analop.type), asmop.asm_toks);
1249  if (comment) {
1250  rz_cons_printf(" 0x%08" PFMT64x " %18s %s%s ; %s\n",
1251  hit->addr, asm_op_hex, rz_strbuf_get(colored_asm), Color_RESET, comment);
1252  } else {
1253  rz_cons_printf(" 0x%08" PFMT64x " %18s %s%s\n",
1254  hit->addr, asm_op_hex, rz_strbuf_get(colored_asm), Color_RESET);
1255  }
1256  rz_strbuf_free(colored_asm);
1257  } else {
1258  if (comment) {
1259  rz_cons_printf(" 0x%08" PFMT64x " %18s %s ; %s\n",
1260  hit->addr, asm_op_hex, rz_asm_op_get_asm(&asmop), comment);
1261  } else {
1262  rz_cons_printf(" 0x%08" PFMT64x " %18s %s\n",
1263  hit->addr, asm_op_hex, rz_asm_op_get_asm(&asmop));
1264  }
1265  }
1266  free(asm_op_hex);
1267  free(buf);
1269  }
1270  if (db && hit) {
1271  const ut64 addr = ((RzCoreAsmHit *)hitlist->head->data)->addr;
1272  // rz_cons_printf ("Gadget size: %d\n", (int)size);
1273  const char *key = sdb_fmt("0x%08" PFMT64x, addr);
1274  rop_classify(core, db, ropList, key, size);
1275  }
1276  }
1277  if (mode != 'j') {
1278  rz_cons_newline();
1279  }
1280  rz_list_free(ropList);
1281 }
1282 
1283 static int rz_core_search_rop(RzCore *core, RzInterval search_itv, int opt, const char *grep, int regexp, struct search_parameters *param) {
1284  const ut8 crop = rz_config_get_i(core->config, "rop.conditional"); // decide if cjmp, cret, and ccall should be used too for the gadget-search
1285  const ut8 subchain = rz_config_get_i(core->config, "rop.subchains");
1286  const ut8 max_instr = rz_config_get_i(core->config, "rop.len");
1287  const char *arch = rz_config_get(core->config, "asm.arch");
1288  int max_count = rz_config_get_i(core->config, "search.maxhits");
1289  int i = 0, end = 0, mode = 0, increment = 1, ret, result = true;
1290  RzList /*<endlist_pair>*/ *end_list = rz_list_newf(free);
1291  RzList /*<RzRegex>*/ *rx_list = NULL;
1292  int align = core->search->align;
1293  RzListIter *itermap = NULL;
1294  char *tok, *gregexp = NULL;
1295  char *grep_arg = NULL;
1296  char *rx = NULL;
1297  int delta = 0;
1298  ut8 *buf;
1299  RzIOMap *map;
1300  RzAsmOp asmop;
1301 
1302  Sdb *gadgetSdb = NULL;
1303  if (rz_config_get_i(core->config, "rop.sdb")) {
1304  if (!(gadgetSdb = sdb_ns(core->sdb, "gadget_sdb", false))) {
1305  gadgetSdb = sdb_ns(core->sdb, "gadget_sdb", true);
1306  }
1307  }
1308  if (max_count == 0) {
1309  max_count = -1;
1310  }
1311  if (max_instr <= 1) {
1312  rz_list_free(end_list);
1313  eprintf("ROP length (rop.len) must be greater than 1.\n");
1314  if (max_instr == 1) {
1315  eprintf("For rop.len = 1, use /c to search for single "
1316  "instructions. See /c? for help.\n");
1317  }
1318  return false;
1319  }
1320 
1321  if (!strcmp(arch, "mips")) { // MIPS has no jump-in-the-middle
1322  increment = 4;
1323  } else if (!strcmp(arch, "arm")) { // ARM has no jump-in-the-middle
1324  increment = rz_config_get_i(core->config, "asm.bits") == 16 ? 2 : 4;
1325  } else if (!strcmp(arch, "avr")) { // AVR is halfword aligned.
1326  increment = 2;
1327  }
1328 
1329  // Options, like JSON, linear, ...
1330  grep_arg = strchr(grep, ' ');
1331  if (*grep) {
1332  if (grep_arg) {
1333  mode = *(grep_arg - 1);
1334  } else {
1335  mode = *grep;
1336  ++grep;
1337  }
1338  }
1339  if (grep_arg) {
1340  grep_arg = strdup(grep_arg);
1341  grep_arg = rz_str_replace(grep_arg, ",,", ";", true);
1342  grep = grep_arg;
1343  }
1344 
1345  if (*grep == ' ') { // grep mode
1346  for (++grep; *grep == ' '; grep++) {
1347  ;
1348  }
1349  } else {
1350  grep = NULL;
1351  }
1352 
1353  // Deal with the grep guy.
1354  if (grep && regexp) {
1355  if (!rx_list) {
1356  rx_list = rz_list_newf(free);
1357  }
1358  gregexp = strdup(grep);
1359  tok = strtok(gregexp, ";");
1360  while (tok) {
1361  rx = strdup(tok);
1362  rz_list_append(rx_list, rx);
1363  tok = strtok(NULL, ";");
1364  }
1365  }
1366  if (param->outmode == RZ_MODE_JSON) {
1367  pj_a(param->pj);
1368  }
1370 
1371  rz_list_foreach (param->boundaries, itermap, map) {
1372  HtUUOptions opt = { 0 };
1373  HtUU *badstart = ht_uu_new_opt(&opt);
1374  if (!rz_itv_overlap(search_itv, map->itv)) {
1375  continue;
1376  }
1377  RzInterval itv = rz_itv_intersect(search_itv, map->itv);
1378  ut64 from = itv.addr, to = rz_itv_end(itv);
1379  if (rz_cons_is_breaked()) {
1380  break;
1381  }
1382  delta = to - from;
1383  buf = calloc(1, delta);
1384  if (!buf) {
1385  result = false;
1386  goto bad;
1387  }
1388  (void)rz_io_read_at(core->io, from, buf, delta);
1389 
1390  // Find the end gadgets.
1391  for (i = 0; i + 32 < delta; i += increment) {
1392  RzAnalysisOp end_gadget = RZ_EMPTY;
1393  // Disassemble one.
1394  if (rz_analysis_op(core->analysis, &end_gadget, from + i, buf + i,
1395  delta - i, RZ_ANALYSIS_OP_MASK_BASIC) < 1) {
1396  rz_analysis_op_fini(&end_gadget);
1397  continue;
1398  }
1399  if (is_end_gadget(&end_gadget, crop)) {
1400 #if 0
1401  if (search->maxhits && rz_list_length (end_list) >= search->maxhits) {
1402  // limit number of high level rop gadget results
1403  rz_analysis_op_fini (&end_gadget);
1404  break;
1405  }
1406 #endif
1407  struct endlist_pair *epair = RZ_NEW0(struct endlist_pair);
1408  if (epair) {
1409  // If this arch has branch delay slots, add the next instr as well
1410  if (end_gadget.delay) {
1411  epair->instr_offset = i + increment;
1412  epair->delay_size = end_gadget.delay;
1413  } else {
1414  epair->instr_offset = (intptr_t)i;
1415  epair->delay_size = end_gadget.delay;
1416  }
1417  rz_list_append(end_list, (void *)(intptr_t)epair);
1418  }
1419  }
1420  rz_analysis_op_fini(&end_gadget);
1421  if (rz_cons_is_breaked()) {
1422  break;
1423  }
1424  // Right now we have a list of all of the end/stop gadgets.
1425  // We can just construct gadgets from a little bit before them.
1426  }
1427  rz_list_reverse(end_list);
1428  // If we have no end gadgets, just skip all of this search nonsense.
1429  if (!rz_list_empty(end_list)) {
1430  int prev, next, ropdepth;
1431  const int max_inst_size_x86 = 15;
1432  // Get the depth of rop search, should just be max_instr
1433  // instructions, x86 and friends are weird length instructions, so
1434  // we'll just assume 15 byte instructions.
1435  ropdepth = increment == 1 ? max_instr * max_inst_size_x86 /* wow, x86 is long */ : max_instr * increment;
1436  if (rz_cons_is_breaked()) {
1437  break;
1438  }
1439  struct endlist_pair *end_gadget = (struct endlist_pair *)rz_list_pop(end_list);
1440  next = end_gadget->instr_offset;
1441  prev = 0;
1442  // Start at just before the first end gadget.
1443  for (i = next - ropdepth; i < (delta - max_inst_size_x86) && max_count; i += increment) {
1444  if (increment == 1) {
1445  // give in-boundary instructions a shot
1446  if (i < prev - max_inst_size_x86) {
1447  i = prev - max_inst_size_x86;
1448  }
1449  } else {
1450  if (i < prev) {
1451  i = prev;
1452  }
1453  }
1454  if (i < 0) {
1455  i = 0;
1456  }
1457  if (rz_cons_is_breaked()) {
1458  break;
1459  }
1460  if (i >= next) {
1461  // We've exhausted the first end-gadget section,
1462  // move to the next one.
1463  free(end_gadget);
1464  if (rz_list_get_n(end_list, 0)) {
1465  prev = i;
1466  end_gadget = (struct endlist_pair *)rz_list_pop(end_list);
1467  next = end_gadget->instr_offset;
1468  i = next - ropdepth;
1469  if (i < 0) {
1470  i = 0;
1471  }
1472  } else {
1473  break;
1474  }
1475  }
1476  if (i >= end) { // read by chunk of 4k
1477  rz_io_read_at(core->io, from + i, buf + i,
1478  RZ_MIN((delta - i), 4096));
1479  end = i + 2048;
1480  }
1481  ret = rz_asm_disassemble(core->rasm, &asmop, buf + i, delta - i);
1482  if (ret) {
1483  rz_asm_set_pc(core->rasm, from + i);
1484  RzList *hitlist = construct_rop_gadget(core,
1485  from + i, buf, delta, i, grep, regexp,
1486  rx_list, end_gadget, badstart);
1487  if (!hitlist) {
1488  continue;
1489  }
1490  if (align && (0 != ((from + i) % align))) {
1491  continue;
1492  }
1493  if (gadgetSdb) {
1494  RzListIter *iter;
1495 
1496  RzCoreAsmHit *hit = (RzCoreAsmHit *)hitlist->head->data;
1497  char *headAddr = rz_str_newf("%" PFMT64x, hit->addr);
1498  if (!headAddr) {
1499  result = false;
1500  goto bad;
1501  }
1502 
1503  rz_list_foreach (hitlist, iter, hit) {
1504  char *addr = rz_str_newf("%" PFMT64x "(%" PFMT32d ")", hit->addr, hit->len);
1505  if (!addr) {
1506  free(headAddr);
1507  result = false;
1508  goto bad;
1509  }
1510  sdb_concat(gadgetSdb, headAddr, addr, 0);
1511  free(addr);
1512  }
1513  free(headAddr);
1514  }
1515 
1516  if (param->outmode == RZ_MODE_JSON) {
1517  mode = 'j';
1518  }
1519  if ((mode == 'q') && subchain) {
1520  do {
1521  print_rop(core, hitlist, NULL, mode);
1522  hitlist->head = hitlist->head->n;
1523  } while (hitlist->head->n);
1524  } else {
1525  print_rop(core, hitlist, param->pj, mode);
1526  }
1527  rz_list_free(hitlist);
1528  if (max_count > 0) {
1529  max_count--;
1530  if (max_count < 1) {
1531  break;
1532  }
1533  }
1534  }
1535  if (increment != 1) {
1536  i = next;
1537  }
1538  }
1539  }
1540  free(buf);
1541  }
1542  if (rz_cons_is_breaked()) {
1543  eprintf("\n");
1544  }
1546 
1547  if (param->outmode == RZ_MODE_JSON) {
1548  pj_end(param->pj);
1549  }
1550 bad:
1551  rz_list_free(rx_list);
1552  rz_list_free(end_list);
1553  free(grep_arg);
1554  free(gregexp);
1555  return result;
1556 }
1557 
1558 static bool esil_addrinfo(RzAnalysisEsil *esil) {
1559  RzCore *core = (RzCore *)esil->cb.user;
1560  ut64 num = 0;
1561  char *src = rz_analysis_esil_pop(esil);
1562  if (src && *src && rz_analysis_esil_get_parm(esil, src, &num)) {
1563  num = rz_core_analysis_address(core, num);
1565  } else {
1566  // error. empty stack?
1567  return false;
1568  }
1569  free(src);
1570  return true;
1571 }
1572 
1573 static void do_esil_search(RzCore *core, struct search_parameters *param, const char *input) {
1574  const int hit_combo_limit = rz_config_get_i(core->config, "search.esilcombo");
1575  const bool cfgDebug = rz_config_get_b(core->config, "cfg.debug");
1576  RzSearch *search = core->search;
1578  if (input[0] != 'E') {
1579  return;
1580  }
1581  if (input[1] == 'j') { // "/Ej"
1582  pj_a(param->pj);
1583  param->outmode = RZ_MODE_JSON;
1584  input++;
1585  }
1586  if (input[1] != ' ') { // "/E?"
1588  return;
1589  }
1590  if (!core->analysis->esil) {
1591  // initialize esil vm
1593  if (!core->analysis->esil) {
1594  eprintf("Cannot initialize the ESIL vm\n");
1595  return;
1596  }
1597  }
1598  RzIOMap *map;
1599  RzListIter *iter;
1600  rz_list_foreach (param->boundaries, iter, map) {
1601  const int iotrap = rz_config_get_i(core->config, "esil.iotrap");
1602  const int stacksize = rz_config_get_i(core->config, "esil.stacksize");
1603  int nonull = rz_config_get_i(core->config, "esil.nonull");
1604  bool hit_happens = false;
1605  size_t hit_combo = 0;
1606  char *res;
1607  ut64 nres, addr;
1608  ut64 from = map->itv.addr;
1609  ut64 to = rz_itv_end(map->itv);
1610  unsigned int addrsize = rz_config_get_i(core->config, "esil.addr.size");
1611  if (!core->analysis->esil) {
1612  core->analysis->esil = rz_analysis_esil_new(stacksize, iotrap, addrsize);
1613  }
1614  /* hook addrinfo */
1615  core->analysis->esil->cb.user = core;
1617  /* hook addrinfo */
1618  rz_analysis_esil_setup(core->analysis->esil, core->analysis, 1, 0, nonull);
1620  core->analysis->esil->verbose = 0;
1621 
1623  for (addr = from; addr < to; addr++) {
1624  if (core->search->align) {
1625  if ((addr % core->search->align)) {
1626  continue;
1627  }
1628  }
1629 #if 0
1630  // we need a way to retrieve info from a speicif address, and make it accessible from the esil search
1631  // maybe we can just do it like this: 0x804840,AddressType,3,&, ... bitmask
1632  // executable = 1
1633  // writable = 2
1634  // inprogram
1635  // instack
1636  // inlibrary
1637  // inheap
1638  rz_analysis_esil_set_op (core->analysis->esil, "AddressInfo", esil_search_address_info);
1639 #endif
1640  if (rz_cons_is_breaked()) {
1641  eprintf("Breaked at 0x%08" PFMT64x "\n", addr);
1642  break;
1643  }
1645  if (!rz_analysis_esil_parse(core->analysis->esil, input + 2)) {
1646  // XXX: return value doesnt seems to be correct here
1647  eprintf("Cannot parse esil (%s)\n", input + 2);
1648  break;
1649  }
1650  hit_happens = false;
1651  res = rz_analysis_esil_pop(core->analysis->esil);
1652  if (rz_analysis_esil_get_parm(core->analysis->esil, res, &nres)) {
1653  if (cfgDebug) {
1654  eprintf("RES 0x%08" PFMT64x " %" PFMT64d "\n", addr, nres);
1655  }
1656  if (nres) {
1657  eprintf("hits: %d\r", kw.count);
1658  hit_happens = true;
1659  if (param->outmode != RZ_MODE_JSON) {
1660  if (!_cb_hit(&kw, param, addr)) {
1661  free(res);
1662  break;
1663  }
1664  // eprintf (" HIT AT 0x%"PFMT64x"\n", addr);
1665  kw.type = 0; // RZ_SEARCH_TYPE_ESIL;
1666  kw.kwidx = search->n_kws;
1667  kw.count++;
1668  kw.keyword_length = 0;
1669  }
1670  }
1671  } else {
1672  eprintf("Cannot parse esil (%s)\n", input + 2);
1674  free(res);
1675  break;
1676  }
1678  free(res);
1679 
1680  if (hit_happens) {
1681  if (param->outmode == RZ_MODE_JSON) {
1682  pj_o(param->pj);
1683  pj_kn(param->pj, "addr", addr);
1684  pj_kn(param->pj, "value", nres);
1685  pj_end(param->pj);
1686  }
1687  hit_combo++;
1688  if (hit_combo > hit_combo_limit) {
1689  eprintf("Hit search.esilcombo reached (%d). Stopping search. Use f-\n", hit_combo_limit);
1690  break;
1691  }
1692  } else {
1693  hit_combo = 0;
1694  }
1695  }
1696  rz_config_set_i(core->config, "search.kwidx", search->n_kws); // TODO remove
1698  }
1699  rz_cons_clear_line(1);
1700  if (param->outmode == RZ_MODE_JSON) {
1701  pj_end(param->pj);
1702  }
1703 }
1704 
1705 #define MAXINSTR 8
1706 #define SUMARRAY(arr, size, res) \
1707  do \
1708  (res) += (arr)[--(size)]; \
1709  while ((size))
1710 
1711 #if USE_EMULATION
1712 // IMHO This code must be deleted
1713 static int emulateSyscallPrelude(RzCore *core, ut64 at, ut64 curpc) {
1714  int i, inslen, bsize = RZ_MIN(64, core->blocksize);
1715  ut8 *arr;
1716  RzAnalysisOp aop;
1717  const int mininstrsz = rz_analysis_archinfo(core->analysis, RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE);
1718  const int minopcode = RZ_MAX(1, mininstrsz);
1719  const char *a0 = rz_reg_get_name(core->analysis->reg, RZ_REG_NAME_SN);
1720  const char *pc = rz_reg_get_name(core->dbg->reg, RZ_REG_NAME_PC);
1721  RzRegItem *r = rz_reg_get(core->dbg->reg, pc, -1);
1722  RzRegItem *reg_a0 = rz_reg_get(core->dbg->reg, a0, -1);
1723 
1724  arr = malloc(bsize);
1725  if (!arr) {
1726  eprintf("Cannot allocate %d byte(s)\n", bsize);
1727  free(arr);
1728  return -1;
1729  }
1730  rz_reg_set_value(core->dbg->reg, r, curpc);
1731  for (i = 0; curpc < at; curpc++, i++) {
1732  if (i >= (bsize - 32)) {
1733  i = 0;
1734  }
1735  if (!i) {
1736  rz_io_read_at(core->io, curpc, arr, bsize);
1737  }
1738  inslen = rz_analysis_op(core->analysis, &aop, curpc, arr + i, bsize - i, RZ_ANALYSIS_OP_MASK_BASIC);
1739  if (inslen > 0) {
1740  int incr = (core->search->align > 0) ? core->search->align - 1 : inslen - 1;
1741  if (incr < 0) {
1742  incr = minopcode;
1743  }
1744  i += incr;
1745  curpc += incr;
1746  if (rz_analysis_op_nonlinear(aop.type)) { // skip the instr
1747  rz_reg_set_value(core->dbg->reg, r, curpc + 1);
1748  } else { // step instr
1750  }
1751  }
1752  }
1753  free(arr);
1754  int sysno = rz_debug_reg_get(core->dbg, a0);
1755  rz_reg_set_value(core->dbg->reg, reg_a0, -2); // clearing register A0
1756  return sysno;
1757 }
1758 #endif
1759 
1760 static void do_syscall_search(RzCore *core, struct search_parameters *param) {
1761  RzSearch *search = core->search;
1762  ut64 at;
1763 #if USE_EMULATION
1764  ut64 curpc;
1765 #endif
1766  ut8 *buf;
1767  int curpos, idx = 0, count = 0;
1768  RzAnalysisOp aop = { 0 };
1769  int i, ret, bsize = RZ_MAX(64, core->blocksize);
1770  int kwidx = core->search->n_kws;
1771  RzIOMap *map;
1772  RzListIter *iter;
1773  const int mininstrsz = rz_analysis_archinfo(core->analysis, RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE);
1774  const int minopcode = RZ_MAX(1, mininstrsz);
1775  RzAnalysisEsil *esil;
1776  int align = core->search->align;
1777  int stacksize = rz_config_get_i(core->config, "esil.stack.depth");
1778  int iotrap = rz_config_get_i(core->config, "esil.iotrap");
1779  unsigned int addrsize = rz_config_get_i(core->config, "esil.addr.size");
1780 
1781  if (!(esil = rz_analysis_esil_new(stacksize, iotrap, addrsize))) {
1782  return;
1783  }
1784  int *previnstr = calloc(MAXINSTR + 1, sizeof(int));
1785  if (!previnstr) {
1786  rz_analysis_esil_free(esil);
1787  return;
1788  }
1789  buf = malloc(bsize);
1790  if (!buf) {
1791  eprintf("Cannot allocate %d byte(s)\n", bsize);
1792  rz_analysis_esil_free(esil);
1793  free(previnstr);
1794  return;
1795  }
1796  ut64 oldoff = core->offset;
1797  int syscallNumber = 0;
1799  const char *a0 = rz_reg_get_name(core->analysis->reg, RZ_REG_NAME_SN);
1800  char *esp = rz_str_newf("%s,=", a0);
1801  char *esp32 = NULL;
1802  if (core->analysis->bits == 64) {
1803  const char *reg = rz_reg_64_to_32(core->analysis->reg, a0);
1804  if (reg) {
1805  esp32 = rz_str_newf("%s,=", reg);
1806  }
1807  }
1808  rz_list_foreach (param->boundaries, iter, map) {
1809  ut64 from = map->itv.addr;
1810  ut64 to = rz_itv_end(map->itv);
1811  if (from >= to) {
1812  eprintf("Error: from must be lower than to\n");
1813  goto beach;
1814  }
1815  if (to == UT64_MAX) {
1816  eprintf("Error: Invalid destination boundary\n");
1817  goto beach;
1818  }
1819  for (i = 0, at = from; at < to; at++, i++) {
1820  if (rz_cons_is_breaked()) {
1821  break;
1822  }
1823  if (i >= (bsize - 32)) {
1824  i = 0;
1825  }
1826  if (align && (at % align)) {
1827  continue;
1828  }
1829  if (!i) {
1830  rz_io_read_at(core->io, at, buf, bsize);
1831  }
1832  ret = rz_analysis_op(core->analysis, &aop, at, buf + i, bsize - i, RZ_ANALYSIS_OP_MASK_ESIL);
1833  curpos = idx++ % (MAXINSTR + 1);
1834  previnstr[curpos] = ret; // This array holds prev n instr size + cur instr size
1835  if (aop.type == RZ_ANALYSIS_OP_TYPE_MOV) {
1836  const char *es = RZ_STRBUF_SAFEGET(&aop.esil);
1837  if (strstr(es, esp)) {
1838  if (aop.val != -1) {
1839  syscallNumber = aop.val;
1840  }
1841  } else if (esp32 && strstr(es, esp32)) {
1842  if (aop.val != -1) {
1843  syscallNumber = aop.val;
1844  }
1845  }
1846  }
1847  if ((aop.type == RZ_ANALYSIS_OP_TYPE_SWI) && ret) { // && (aop.val > 10)) {
1848  int scVector = -1; // int 0x80, svc 0x70, ...
1849  int scNumber = 0; // r0/eax/...
1850 #if USE_EMULATION
1851  // This for calculating no of bytes to be subtracted , to get n instr above syscall
1852  int nbytes = 0;
1853  int nb_opcodes = MAXINSTR;
1854  SUMARRAY(previnstr, nb_opcodes, nbytes);
1855  curpc = at - (nbytes - previnstr[curpos]);
1856  scNumber = emulateSyscallPrelude(core, at, curpc);
1857 #else
1858  scNumber = syscallNumber;
1859 #endif
1860  scVector = (aop.val > 0) ? aop.val : -1; // int 0x80 (aop.val = 0x80)
1861  RzSyscallItem *item = rz_syscall_get(core->analysis->syscall, scNumber, scVector);
1862  if (item) {
1863  rz_cons_printf("0x%08" PFMT64x " %s\n", at, item->name);
1864  }
1865  memset(previnstr, 0, (MAXINSTR + 1) * sizeof(*previnstr)); // clearing the buffer
1866  if (searchflags) {
1867  char *flag = rz_str_newf("%s%d_%d.%s", searchprefix, kwidx, count, item ? item->name : "syscall");
1868  rz_flag_set(core->flags, flag, at, ret);
1869  free(flag);
1870  }
1871  rz_syscall_item_free(item);
1872  if (*param->cmd_hit) {
1873  ut64 here = core->offset;
1874  rz_core_seek(core, at, true);
1875  rz_core_cmd(core, param->cmd_hit, 0);
1876  rz_core_seek(core, here, true);
1877  }
1878  count++;
1879  if (search->maxhits > 0 && count >= search->maxhits) {
1880  rz_analysis_op_fini(&aop);
1881  break;
1882  }
1883  syscallNumber = 0;
1884  }
1885  int inc = (core->search->align > 0) ? core->search->align - 1 : ret - 1;
1886  if (inc < 0) {
1887  inc = minopcode;
1888  }
1889  i += inc;
1890  at += inc;
1891  rz_analysis_op_fini(&aop);
1892  }
1893  }
1894 beach:
1895  rz_core_seek(core, oldoff, true);
1896  rz_analysis_esil_free(esil);
1898  free(buf);
1899  free(esp32);
1900  free(esp);
1901  free(previnstr);
1902 }
1903 
1904 static void do_ref_search(RzCore *core, ut64 addr, ut64 from, ut64 to, struct search_parameters *param) {
1905  const int size = 12;
1906  char str[512];
1907  RzAnalysisFunction *fcn;
1908  RzAnalysisXRef *xref;
1909  RzListIter *iter;
1910  ut8 buf[12];
1911  RzAsmOp asmop;
1913  if (list) {
1914  rz_list_foreach (list, iter, xref) {
1915  rz_io_read_at(core->io, xref->from, buf, size);
1916  rz_asm_set_pc(core->rasm, xref->from);
1917  rz_asm_disassemble(core->rasm, &asmop, buf, size);
1918  fcn = rz_analysis_get_fcn_in(core->analysis, xref->from, 0);
1919  RzAnalysisHint *hint = rz_analysis_hint_get(core->analysis, xref->from);
1920  rz_parse_filter(core->parser, xref->from, core->flags, hint, rz_strbuf_get(&asmop.buf_asm),
1921  str, sizeof(str), core->print->big_endian);
1922  rz_analysis_hint_free(hint);
1923  const char *comment = rz_meta_get_string(core->analysis, RZ_META_TYPE_COMMENT, xref->from);
1924  char *print_comment = NULL;
1925  const char *nl = comment ? strchr(comment, '\n') : NULL;
1926  if (nl) { // display only until the first newline
1927  comment = print_comment = rz_str_ndup(comment, nl - comment);
1928  }
1929  char *buf_fcn = comment
1930  ? rz_str_newf("%s; %s", fcn ? fcn->name : "(nofunc)", comment)
1931  : rz_str_newf("%s", fcn ? fcn->name : "(nofunc)");
1933  if (from <= xref->from && to >= xref->from) {
1934  rz_cons_printf("%s 0x%" PFMT64x " [%s] %s\n",
1935  buf_fcn, xref->from, rz_analysis_xrefs_type_tostring(xref->type), str);
1936  if (*param->cmd_hit) {
1937  ut64 here = core->offset;
1938  rz_core_seek(core, xref->from, true);
1939  rz_core_cmd(core, param->cmd_hit, 0);
1940  rz_core_seek(core, here, true);
1941  }
1942  }
1943  free(buf_fcn);
1944  }
1945  }
1946  rz_list_free(list);
1947 }
1948 
1949 static bool do_analysis_search(RzCore *core, struct search_parameters *param, const char *input) {
1950  RzSearch *search = core->search;
1951  ut64 at;
1952  RzAnalysisOp aop;
1953  int type = 0;
1954  int mode = 0;
1955  int kwidx = core->search->n_kws;
1956  int i, ret, count = 0;
1957 
1958  while (*input && *input != ' ') {
1959  switch (*input) {
1960  case 'j':
1961  case 'q':
1962  mode = *input;
1963  break;
1964  case 'l': // "/alt" "/alf"
1965  switch (type) {
1966  case 't': // "/alt"
1967  case 'f': // "/alf"
1968  for (i = 0; i < 64; i++) {
1969  const char *str = type == 'f'
1972  if (!str || !*str) {
1973  break;
1974  }
1975  if (!strcmp(str, "undefined")) {
1976  continue;
1977  }
1979  }
1980  break;
1981  case 's': { // "/als"
1982  RzListIter *iter;
1983  RzSyscallItem *si;
1985  rz_list_foreach (list, iter, si) {
1986  rz_cons_printf("%s = 0x%02x.%s\n",
1987  si->name, si->swi, syscallNumber(si->num));
1988  }
1989  rz_list_free(list);
1990  break;
1991  }
1992  case 0:
1993  rz_core_cmd0(core, "aoml");
1994  break;
1995  default:
1996  RZ_LOG_ERROR("/al%c - unknown command\n", type);
1997  break;
1998  }
1999  return false;
2000  case 'f': // "/af"
2001  case 's': // "/as"
2002  case 't': // "/at"
2003  case 'm': // "/am"
2004  case ' ':
2005  type = *input;
2006  break;
2007  case 0:
2008  case '?':
2009  default:
2011  return false;
2012  }
2013  input++;
2014  }
2015  if (type == 's') {
2017  return true;
2018  }
2019  if (mode == 'j') {
2020  pj_a(param->pj);
2021  }
2024  RzIOMap *map;
2025  RzListIter *iter;
2026  rz_list_foreach (param->boundaries, iter, map) {
2027  ut64 from = map->itv.addr;
2028  ut64 to = rz_itv_end(map->itv);
2029  for (i = 0, at = from; at < to; i++, at++) {
2030  if (rz_cons_is_breaked()) {
2031  break;
2032  }
2033  at = from + i;
2034  ut8 bufop[32];
2035  rz_io_read_at(core->io, at, bufop, sizeof(bufop));
2036  ret = rz_analysis_op(core->analysis, &aop, at, bufop, sizeof(bufop), RZ_ANALYSIS_OP_MASK_BASIC | RZ_ANALYSIS_OP_MASK_DISASM);
2037  if (ret > 0) {
2038  bool match = false;
2039  if (type == 'm') {
2040  const char *fam = aop.mnemonic;
2041  if (fam && (!*input || rz_str_startswith(fam, input))) {
2042  match = true;
2043  }
2044  } else if (type == 'f') {
2045  const char *fam = rz_analysis_op_family_to_string(aop.family);
2046  if (fam && (!*input || !strcmp(input, fam))) {
2047  match = true;
2048  }
2049  } else {
2050  const char *type = rz_analysis_optype_to_string(aop.type);
2051  if (type) {
2052  bool isCandidate = !*input;
2053  if (!strcmp(input, "cswi")) {
2054  if (!strcmp(input + 1, type)) {
2055  isCandidate = true;
2056  }
2057  } else {
2058  if (!strcmp(input, type)) {
2059  isCandidate = true;
2060  }
2061  }
2062  if (isCandidate) {
2063  if (strstr(input, "swi")) {
2064  if (*input == 'c') {
2065  match = true; // aop.cond;
2066  } else {
2067  match = !aop.cond;
2068  }
2069  } else {
2070  match = true;
2071  }
2072  }
2073  }
2074  }
2075  if (match) {
2076  // char *opstr = rz_core_disassemble_instr (core, at, 1);
2077  char *opstr = rz_core_op_str(core, at);
2078  switch (mode) {
2079  case 'j':
2080  pj_o(param->pj);
2081  pj_kN(param->pj, "addr", at);
2082  pj_ki(param->pj, "size", ret);
2083  pj_ks(param->pj, "opstr", opstr);
2084  pj_end(param->pj);
2085  break;
2086  case 'q':
2087  rz_cons_printf("0x%08" PFMT64x "\n", at);
2088  break;
2089  default:
2090  if (type == 'f') {
2091  const char *fam = rz_analysis_op_family_to_string(aop.family);
2092  rz_cons_printf("0x%08" PFMT64x " %d %s %s\n", at, ret, fam, opstr);
2093  } else {
2094  rz_cons_printf("0x%08" PFMT64x " %d %s\n", at, ret, opstr);
2095  }
2096  break;
2097  }
2098  RZ_FREE(opstr);
2099  if (*input && searchflags) {
2100  char flag[64];
2101  snprintf(flag, sizeof(flag), "%s%d_%d",
2102  searchprefix, kwidx, count);
2103  rz_flag_set(core->flags, flag, at, ret);
2104  }
2105  if (*param->cmd_hit) {
2106  ut64 here = core->offset;
2107  rz_core_seek(core, at, true);
2108  rz_core_cmd(core, param->cmd_hit, 0);
2109  rz_core_seek(core, here, true);
2110  }
2111  count++;
2112  if (search->maxhits && count >= search->maxhits) {
2113  goto done;
2114  }
2115  }
2116  int inc = (core->search->align > 0) ? core->search->align - 1 : ret - 1;
2117  if (inc < 0) {
2118  inc = 0;
2119  }
2120  i += inc;
2121  at += inc;
2122  }
2123  }
2124  }
2125 done:
2126  if (mode == 'j') {
2127  pj_end(param->pj);
2128  }
2130  return false;
2131 }
2132 
2133 static void do_section_search(RzCore *core, struct search_parameters *param, const char *input) {
2134  double threshold = 1;
2135  bool r2mode = false;
2136  if (input && *input) {
2137  if (*input == '*') {
2138  r2mode = true;
2139  }
2140  sscanf(input, "%lf", &threshold);
2141  if (threshold < 1) {
2142  threshold = 1;
2143  }
2144  }
2145  int buf_size = core->blocksize;
2146  ut8 *buf = malloc(buf_size);
2147  if (!buf) {
2148  return;
2149  }
2150  double oe = 0;
2151  RzListIter *iter;
2152  RzIOMap *map;
2153  ut64 begin = UT64_MAX;
2154  ut64 at, end = 0;
2155  int index = 0;
2156  bool lastBlock = true;
2158  rz_list_foreach (param->boundaries, iter, map) {
2159  ut64 from = map->itv.addr;
2160  ut64 to = rz_itv_end(map->itv);
2161  if (rz_cons_is_breaked()) {
2162  break;
2163  }
2164  for (at = from; at < to; at += buf_size) {
2165  if (begin == UT64_MAX) {
2166  begin = at;
2167  }
2168  rz_io_read_at(core->io, at, buf, buf_size);
2169  double e = rz_hash_entropy(core->hash, buf, buf_size);
2170  double diff = oe - e;
2171  diff = RZ_ABS(diff);
2172  end = at + buf_size;
2173  if (diff > threshold) {
2174  if (r2mode) {
2175  rz_cons_printf("f entropy_section_%d 0x%08" PFMT64x " @ 0x%08" PFMT64x "\n", index, end - begin, begin);
2176  } else {
2177  rz_cons_printf("0x%08" PFMT64x " - 0x%08" PFMT64x " ~ %lf\n", begin, end, e);
2178  }
2179  begin = UT64_MAX;
2180  index++;
2181  lastBlock = false;
2182  } else {
2183  lastBlock = true;
2184  }
2185  oe = e;
2186  }
2187  begin = UT64_MAX;
2188  }
2189  if (begin != UT64_MAX && lastBlock) {
2190  if (r2mode) {
2191  rz_cons_printf("f entropy_section_%d 0x%08" PFMT64x " @ 0x%08" PFMT64x "\n", index, end - begin, begin);
2192  } else {
2193  rz_cons_printf("0x%08" PFMT64x " - 0x%08" PFMT64x " ~ %d .. last\n", begin, end, 0);
2194  }
2195  index++;
2196  }
2198  free(buf);
2199 }
2200 
2201 static void do_asm_search(RzCore *core, struct search_parameters *param, const char *input, int mode, RzInterval search_itv) {
2202  RzCoreAsmHit *hit;
2203  RzListIter *iter, *itermap;
2204  int count = 0, maxhits = 0, filter = 0;
2205  int kwidx = core->search->n_kws; // (int)rz_config_get_i (core->config, "search.kwidx")-1;
2206  RzList *hits;
2207  RzIOMap *map;
2208  bool regexp = input[0] == '/'; // "/c/"
2209  bool everyByte = regexp && input[1] == 'a';
2210  char *end_cmd = strchr(input, ' ');
2211  switch ((end_cmd ? *(end_cmd - 1) : input[0])) {
2212  case 'j':
2213  param->outmode = RZ_MODE_JSON;
2214  break;
2215  case '*':
2216  param->outmode = RZ_MODE_RIZINCMD;
2217  break;
2218  default:
2219  break;
2220  }
2221  if (mode == 'o') {
2222  everyByte = true;
2223  }
2224 
2225  maxhits = (int)rz_config_get_i(core->config, "search.maxhits");
2226  filter = (int)rz_config_get_i(core->config, "asm.sub.names");
2227  if (param->outmode == RZ_MODE_JSON) {
2228  pj_a(param->pj);
2229  }
2231  if (everyByte) {
2232  input++;
2233  }
2234  rz_list_foreach (param->boundaries, itermap, map) {
2235  if (!rz_itv_overlap(search_itv, map->itv)) {
2236  continue;
2237  }
2238  ut64 from = map->itv.addr;
2239  ut64 to = rz_itv_end(map->itv);
2240  if (rz_cons_is_breaked()) {
2241  break;
2242  }
2243  if (maxhits && count >= maxhits) {
2244  break;
2245  }
2246  hits = rz_core_asm_strsearch(core, end_cmd,
2247  from, to, maxhits, regexp, everyByte, mode);
2248  if (hits) {
2249  const char *cmdhit = rz_config_get(core->config, "cmd.hit");
2250  rz_list_foreach (hits, iter, hit) {
2251  if (rz_cons_is_breaked()) {
2252  break;
2253  }
2254  if (cmdhit && *cmdhit) {
2255  rz_core_cmdf(core, "%s @ 0x%" PFMT64x, cmdhit, hit->addr);
2256  }
2257  switch (param->outmode) {
2258  case RZ_MODE_JSON:
2259  pj_o(param->pj);
2260  pj_kN(param->pj, "offset", hit->addr);
2261  pj_ki(param->pj, "len", hit->len);
2262  pj_ks(param->pj, "code", hit->code);
2263  pj_end(param->pj);
2264  break;
2265  case RZ_MODE_RIZINCMD:
2266  rz_cons_printf("f %s%d_%i @ 0x%08" PFMT64x "\n",
2267  searchprefix, kwidx, count, hit->addr);
2268  break;
2269  default:
2270  if (filter) {
2271  char tmp[128] = {
2272  0
2273  };
2274  RzAnalysisHint *hint = rz_analysis_hint_get(core->analysis, hit->addr);
2275  rz_parse_filter(core->parser, hit->addr, core->flags, hint, hit->code, tmp, sizeof(tmp),
2276  core->print->big_endian);
2277  rz_analysis_hint_free(hint);
2278  rz_cons_printf("0x%08" PFMT64x " # %i: %s\n",
2279  hit->addr, hit->len, tmp);
2280  } else {
2281  rz_cons_printf("0x%08" PFMT64x " # %i: %s\n",
2282  hit->addr, hit->len, hit->code);
2283  }
2284  break;
2285  }
2286  if (searchflags) {
2287  const char *flagname = sdb_fmt("%s%d_%d", searchprefix, kwidx, count);
2288  if (flagname) {
2289  rz_flag_set(core->flags, flagname, hit->addr, hit->len);
2290  }
2291  }
2292  count++;
2293  }
2294  rz_list_purge(hits);
2295  free(hits);
2296  }
2297  }
2298  if (param->outmode == RZ_MODE_JSON) {
2299  pj_end(param->pj);
2300  }
2302 }
2303 
2304 static void do_string_search(RzCore *core, RzInterval search_itv, struct search_parameters *param) {
2305  ut64 at;
2306  ut8 *buf;
2307  RzSearch *search = core->search;
2308 
2309  if (param->outmode == RZ_MODE_JSON) {
2310  pj_a(param->pj);
2311  }
2312  RzListIter *iter;
2313  RzIOMap *map;
2314  if (!searchflags && param->outmode != RZ_MODE_JSON) {
2315  rz_cons_printf("fs hits\n");
2316  }
2317  core->search->inverse = param->inverse;
2318  // TODO Bad but is to be compatible with the legacy behavior
2319  if (param->inverse) {
2320  core->search->maxhits = 1;
2321  }
2322  if (core->search->n_kws > 0) {
2323  /* set callback */
2324  /* TODO: handle last block of data */
2325  /* TODO: handle ^C */
2326  /* TODO: launch search in background support */
2327  // REMOVE OLD FLAGS rz_core_cmdf (core, "f-%s*", rz_config_get (core->config, "search.prefix"));
2328  rz_search_set_callback(core->search, &_cb_hit, param);
2329  if (!(buf = malloc(core->blocksize))) {
2330  return;
2331  }
2332  if (search->bckwrds) {
2334  }
2336  // TODO search cross boundary
2337  rz_list_foreach (param->boundaries, iter, map) {
2338  if (!rz_itv_overlap(search_itv, map->itv)) {
2339  continue;
2340  }
2341  const ut64 saved_nhits = search->nhits;
2342  RzInterval itv = rz_itv_intersect(search_itv, map->itv);
2343  if (rz_cons_is_breaked()) {
2344  break;
2345  }
2346  if (param->outmode != RZ_MODE_JSON) {
2347  RzSearchKeyword *kw = rz_list_first(core->search->kws);
2348  int lenstr = kw ? kw->keyword_length : 0;
2349  const char *bytestr = lenstr > 1 ? "bytes" : "byte";
2350  eprintf("Searching %d %s in [0x%" PFMT64x "-0x%" PFMT64x "]\n",
2351  kw ? kw->keyword_length : 0, bytestr, itv.addr, rz_itv_end(itv));
2352  }
2353  if (!core->search->bckwrds) {
2354  RzListIter *it;
2355  RzSearchKeyword *kw;
2356  rz_list_foreach (core->search->kws, it, kw) {
2357  kw->last = 0;
2358  }
2359  }
2360 
2361  const ut64 from = itv.addr, to = rz_itv_end(itv),
2362  from1 = search->bckwrds ? to : from,
2363  to1 = search->bckwrds ? from : to;
2364  ut64 len;
2365  for (at = from1; at != to1; at = search->bckwrds ? at - len : at + len) {
2366  print_search_progress(at, to1, search->nhits, param);
2367  if (rz_cons_is_breaked()) {
2368  eprintf("\n\n");
2369  break;
2370  }
2371  if (search->bckwrds) {
2372  len = RZ_MIN(core->blocksize, at - from);
2373  // TODO prefix_read_at
2374  if (!rz_io_is_valid_offset(core->io, at - len, 0)) {
2375  break;
2376  }
2377  (void)rz_io_read_at(core->io, at - len, buf, len);
2378  } else {
2379  len = RZ_MIN(core->blocksize, to - at);
2380  if (!rz_io_is_valid_offset(core->io, at, 0)) {
2381  break;
2382  }
2383  (void)rz_io_read_at(core->io, at, buf, len);
2384  }
2385  rz_search_update(core->search, at, buf, len);
2386  if (param->aes_search) {
2387  // Adjust length to search between blocks.
2388  if (len == core->blocksize) {
2389  len -= AES_SEARCH_LENGTH - 1;
2390  }
2391  } else if (param->privkey_search) {
2392  // Adjust length to search between blocks.
2393  if (len == core->blocksize) {
2395  }
2396  }
2397  if (core->search->maxhits > 0 && core->search->nhits >= core->search->maxhits) {
2398  goto done;
2399  }
2400  }
2401  print_search_progress(at, to1, search->nhits, param);
2402  rz_cons_clear_line(1);
2403  core->num->value = search->nhits;
2404  if (param->outmode != RZ_MODE_JSON) {
2405  eprintf("hits: %" PFMT64d "\n", search->nhits - saved_nhits);
2406  }
2407  }
2408  done:
2410  free(buf);
2411  } else {
2412  eprintf("No keywords defined\n");
2413  }
2414 
2415  if (param->outmode == RZ_MODE_JSON) {
2416  pj_end(param->pj);
2417  }
2418 }
2419 
2420 static void rop_kuery(void *data, const char *input, PJ *pj) {
2421  RzCore *core = (RzCore *)data;
2422  Sdb *db_rop = sdb_ns(core->sdb, "rop", false);
2423  SdbListIter *sdb_iter, *it;
2424  SdbList *sdb_list;
2425  SdbNs *ns;
2426  SdbKv *kv;
2427  char *out;
2428 
2429  if (!db_rop) {
2430  eprintf("Error: could not find SDB 'rop' namespace\n");
2431  return;
2432  }
2433 
2434  switch (*input) {
2435  case 'q':
2436  ls_foreach (db_rop->ns, it, ns) {
2437  sdb_list = sdb_foreach_list(ns->sdb, false);
2438  ls_foreach (sdb_list, sdb_iter, kv) {
2439  rz_cons_printf("%s ", sdbkv_key(kv));
2440  }
2441  }
2442  break;
2443  case 'j':
2444  pj_o(pj);
2445  pj_ka(pj, "gadgets");
2446  ls_foreach (db_rop->ns, it, ns) {
2447  sdb_list = sdb_foreach_list(ns->sdb, false);
2448  ls_foreach (sdb_list, sdb_iter, kv) {
2449  char *dup = strdup(sdbkv_value(kv));
2450  bool flag = false; // to free tok when doing strdup
2451  char *size = strtok(dup, " ");
2452  char *tok = strtok(NULL, "{}");
2453  if (!tok) {
2454  tok = strdup("NOP");
2455  flag = true;
2456  }
2457  pj_o(pj);
2458  pj_ks(pj, "address", sdbkv_key(kv));
2459  pj_ks(pj, "size", size);
2460  pj_ks(pj, "type", ns->name);
2461  pj_ks(pj, "effect", tok);
2462  pj_end(pj);
2463  free(dup);
2464  if (flag) {
2465  free(tok);
2466  }
2467  }
2468  }
2469  pj_end(pj);
2470  pj_end(pj);
2471  break;
2472  case ' ':
2473  if (!strcmp(input + 1, "nop")) {
2474  out = sdb_querys(core->sdb, NULL, 0, "rop/nop/*");
2475  if (out) {
2477  free(out);
2478  }
2479  } else if (!strcmp(input + 1, "mov")) {
2480  out = sdb_querys(core->sdb, NULL, 0, "rop/mov/*");
2481  if (out) {
2483  free(out);
2484  }
2485  } else if (!strcmp(input + 1, "const")) {
2486  out = sdb_querys(core->sdb, NULL, 0, "rop/const/*");
2487  if (out) {
2489  free(out);
2490  }
2491  } else if (!strcmp(input + 1, "arithm")) {
2492  out = sdb_querys(core->sdb, NULL, 0, "rop/arithm/*");
2493  if (out) {
2495  free(out);
2496  }
2497  } else if (!strcmp(input + 1, "arithm_ct")) {
2498  out = sdb_querys(core->sdb, NULL, 0, "rop/arithm_ct/*");
2499  if (out) {
2501  free(out);
2502  }
2503  } else {
2504  eprintf("Invalid ROP class\n");
2505  }
2506  break;
2507  default:
2508  out = sdb_querys(core->sdb, NULL, 0, "rop/***");
2509  if (out) {
2511  free(out);
2512  }
2513  break;
2514  }
2515 }
2516 
2517 static int memcmpdiff(const ut8 *a, const ut8 *b, int len) {
2518  int i, diff = 0;
2519  for (i = 0; i < len; i++) {
2520  if (a[i] == b[i] && a[i] == 0x00) {
2521  /* ignore nulls */
2522  } else if (a[i] != b[i]) {
2523  diff++;
2524  }
2525  }
2526  return diff;
2527 }
2528 
2530  ut64 addr = from;
2531  ut8 *block = calloc(core->blocksize, 1);
2532  if (!block) {
2533  return;
2534  }
2535  while (addr < to) {
2536  (void)rz_io_read_at(core->io, addr, block, core->blocksize);
2537  if (rz_cons_is_breaked()) {
2538  break;
2539  }
2540  int diff = memcmpdiff(core->block, block, core->blocksize);
2541  int equal = core->blocksize - diff;
2542  if (equal >= count) {
2543  int pc = (equal * 100) / core->blocksize;
2544  rz_cons_printf("0x%08" PFMT64x " %4d/%d %3d%% ", addr, equal, core->blocksize, pc);
2545  ut8 ptr[2] = {
2546  (ut8)(pc * 2.5), 0
2547  };
2548  rz_print_fill(core->print, ptr, 1, UT64_MAX, core->blocksize);
2549  }
2550  addr += core->blocksize;
2551  }
2552  free(block);
2553 }
2554 
2555 static void search_similar_pattern(RzCore *core, int count, struct search_parameters *param) {
2556  RzIOMap *p;
2557  RzListIter *iter;
2558 
2560  rz_list_foreach (param->boundaries, iter, p) {
2561  search_similar_pattern_in(core, count, p->itv.addr, rz_itv_end(p->itv));
2562  }
2564 }
2565 
2566 static bool isArm(RzCore *core) {
2567  RzAsm *as = core ? core->rasm : NULL;
2568  if (as && as->cur && as->cur->arch) {
2569  if (rz_str_startswith(as->cur->arch, "arm")) {
2570  if (as->cur->bits < 64) {
2571  return true;
2572  }
2573  }
2574  }
2575  return false;
2576 }
2577 
2578 void _CbInRangeSearchV(RzCore *core, ut64 from, ut64 to, int vsize, void *user) {
2579  struct search_parameters *param = user;
2580  bool isarm = isArm(core);
2581  // this is expensive operation that could be cached but is a callback
2582  // and for not messing adding a new param
2583  const char *prefix = rz_config_get(core->config, "search.prefix");
2584  if (isarm) {
2585  if (to & 1) {
2586  to--;
2587  }
2588  }
2589  if (param->outmode != RZ_MODE_JSON) {
2590  rz_cons_printf("0x%" PFMT64x ": 0x%" PFMT64x "\n", from, to);
2591  } else {
2592  pj_o(param->pj);
2593  pj_kN(param->pj, "offset", from);
2594  pj_kN(param->pj, "value", to);
2595  pj_end(param->pj);
2596  }
2597  rz_core_cmdf(core, "f %s.value.0x%08" PFMT64x " %d @ 0x%08" PFMT64x " \n", prefix, to, vsize, to); // flag at value of hit
2598  rz_core_cmdf(core, "f %s.offset.0x%08" PFMT64x " %d @ 0x%08" PFMT64x " \n", prefix, from, vsize, from); // flag at offset of hit
2599  const char *cmdHit = rz_config_get(core->config, "cmd.hit");
2600  if (cmdHit && *cmdHit) {
2601  ut64 addr = core->offset;
2602  rz_core_seek(core, from, true);
2603  rz_core_cmd(core, cmdHit, 0);
2604  rz_core_seek(core, addr, true);
2605  }
2606 }
2607 
2608 static ut8 *v_writebuf(RzCore *core, RzList *nums, int len, char ch, int bsize) {
2609  ut8 *ptr;
2610  ut64 n64;
2611  ut32 n32;
2612  ut16 n16;
2613  ut8 n8;
2614  int i = 0;
2615  ut8 *buf = calloc(1, bsize);
2616  if (!buf) {
2617  eprintf("Cannot allocate %d byte(s)\n", bsize);
2618  free(buf);
2619  return NULL;
2620  }
2621  ptr = buf;
2622  for (i = 0; i < len; i++) {
2623  switch (ch) {
2624  case '1':
2625  n8 = rz_num_math(core->num, rz_list_pop_head(nums));
2626  rz_write_le8(ptr, n8);
2627  ptr = (ut8 *)ptr + sizeof(ut8);
2628  break;
2629  case '2':
2630  n16 = rz_num_math(core->num, rz_list_pop_head(nums));
2631  rz_write_le16(ptr, n16);
2632  ptr = (ut8 *)ptr + sizeof(ut16);
2633  break;
2634  case '4':
2635  n32 = (ut32)rz_num_math(core->num, rz_list_pop_head(nums));
2636  rz_write_le32(ptr, n32);
2637  ptr = (ut8 *)ptr + sizeof(ut32);
2638  break;
2639  default:
2640  case '8':
2641  n64 = rz_num_math(core->num, rz_list_pop_head(nums));
2642  rz_write_le64(ptr, n64);
2643  ptr = (ut8 *)ptr + sizeof(ut64);
2644  break;
2645  }
2646  if (ptr > ptr + bsize) {
2647  free(buf);
2648  return NULL;
2649  }
2650  }
2651  return buf;
2652 }
2653 
2654 // maybe useful as in util/big.c .?
2655 static void incBuffer(ut8 *buf, int bufsz) {
2656  int i = 0;
2657  while (i < bufsz) {
2658  buf[i]++;
2659  if (!buf[i]) {
2660  i++;
2661  continue;
2662  }
2663  break;
2664  }
2665  // may overflow/hang/end/stop/whatever here
2666 }
2667 
2668 static void incPrintBuffer(ut8 *buf, int bufsz) {
2669  int i = 0;
2670  while (i < bufsz) {
2671  buf[i]++;
2672  if (!buf[i]) {
2673  i++;
2674  continue;
2675  }
2676  if (IS_PRINTABLE(buf[i])) {
2677  break;
2678  }
2679  }
2680 }
2681 
2682 static void incLowerBuffer(ut8 *buf, int bufsz) {
2683  int i = 0;
2684  while (i < bufsz) {
2685  buf[i]++;
2686  if (buf[i] && isalpha(buf[i]) && islower(buf[i])) {
2687  break;
2688  }
2689  if (!buf[i]) {
2690  i++;
2691  continue;
2692  }
2693  }
2694 }
2695 
2696 static void incUpperBuffer(ut8 *buf, int bufsz) {
2697  int i = 0;
2698  while (i < bufsz) {
2699  buf[i]++;
2700  if (buf[i] && isalpha(buf[i]) && isupper(buf[i])) {
2701  break;
2702  }
2703  if (!buf[i]) {
2704  i++;
2705  continue;
2706  }
2707  }
2708 }
2709 
2710 static void incAlphaBuffer(ut8 *buf, int bufsz) {
2711  int i = 0;
2712  while (i < bufsz) {
2713  buf[i]++;
2714  if (buf[i] && isalpha(buf[i])) {
2715  break;
2716  }
2717  if (!buf[i]) {
2718  i++;
2719  continue;
2720  }
2721  }
2722  // may overflow/hang/end/stop/whatever here
2723 }
2724 
2725 static void incDigitBuffer(ut8 *buf, int bufsz) {
2726  int i = 0;
2727  while (i < bufsz) {
2728  buf[i]++;
2729  if (buf[i] && isdigit(buf[i])) {
2730  break;
2731  }
2732  if (!buf[i]) {
2733  i++;
2734  continue;
2735  }
2736  }
2737  // may overflow/hang/end/stop/whatever here
2738 }
2739 
2740 static void search_collisions(RzCore *core, const char *hashName, const ut8 *hashValue, int hashLength, int mode) {
2741  ut8 RZ_ALIGNED(8) cmphash[128];
2742  const RzHashPlugin *crc32 = rz_hash_plugin_by_name(core->hash, "crc32");
2743  ut8 *digest = NULL;
2744 
2745  int i = 0;
2746  int bufsz = core->blocksize;
2747  ut8 *buf = calloc(1, bufsz);
2748  if (!buf) {
2749  return;
2750  }
2751  memcpy(buf, core->block, bufsz);
2752  if (hashLength > sizeof(cmphash)) {
2753  eprintf("Hashlength mismatch %d %d\n", hashLength, (int)sizeof(cmphash));
2754  free(buf);
2755  return;
2756  }
2757  memcpy(cmphash, hashValue, hashLength);
2758 
2759  if (hashLength != 4) {
2760  eprintf("Invalid hash size %d (expected 4)\n", hashLength);
2761  free(buf);
2762  return;
2763  }
2764 
2766  ut64 prev = rz_time_now_mono();
2767  ut64 inc = 0;
2768  int amount = 0;
2769  int mount = 0;
2770  while (!rz_cons_is_breaked()) {
2771  ut64 now = rz_time_now_mono();
2772  if (now < (prev + 1000000)) {
2773  amount++;
2774  } else {
2775  mount += amount;
2776  mount /= 2;
2777  amount = 0;
2778  prev = now;
2779  }
2780  switch (mode) {
2781  case 'p': // digits+alpha
2782  incPrintBuffer(buf, bufsz);
2783  break;
2784  case 'a': // lowercase alpha
2785  incLowerBuffer(buf, bufsz);
2786  break;
2787  case 'A': // uppercase alpha
2788  incUpperBuffer(buf, bufsz);
2789  break;
2790  case 'l': // letters
2791  incAlphaBuffer(buf, bufsz);
2792  break;
2793  case 'd': // digits
2794  incDigitBuffer(buf, bufsz);
2795  break;
2796  default: // binary
2797  incBuffer(buf, bufsz);
2798  break;
2799  }
2800 
2801  eprintf("0x%08" PFMT64x " input:", inc);
2802  for (i = 0; i < bufsz; i++) {
2803  eprintf("%02x", buf[i]);
2804  }
2805  if (mode) {
2806  eprintf(" \"%s\"", buf);
2807  }
2808 
2809  crc32->small_block(buf, bufsz, &digest, NULL);
2810 
2811  eprintf(" digest:");
2812  for (i = 0; i < hashLength; i++) {
2813  eprintf("%02x", digest[i]);
2814  }
2815  eprintf(" (%d h/s) \r", mount);
2816  if (!memcmp(hashValue, digest, hashLength)) {
2817  eprintf("\nCOLLISION FOUND!\n");
2818  rz_core_print_hexdump(core, core->offset, buf, bufsz, 0, 16, 0);
2819  rz_cons_flush();
2820  }
2821  RZ_FREE(digest);
2822  inc++;
2823  }
2825  free(buf);
2826 }
2827 
2828 static void __core_cmd_search_asm_infinite(RzCore *core, const char *arg) {
2829  const char *search_in = rz_config_get(core->config, "search.in");
2830  RzList *boundaries = rz_core_get_boundaries_prot(core, -1, search_in, "search");
2831  RzListIter *iter;
2832  RzIOMap *map;
2834  ut64 at;
2835  rz_list_foreach (boundaries, iter, map) {
2836  ut64 map_begin = map->itv.addr;
2837  ut64 map_size = map->itv.size;
2838  ut64 map_end = map_begin + map_size;
2839  ut8 *buf = calloc(map_end - map_begin, 1);
2840  if (!buf) {
2841  continue;
2842  }
2843  (void)rz_io_read_at(core->io, map_begin, buf, map_size);
2844  for (at = map->itv.addr; at + 24 < map_end; at += 1) {
2845  rz_analysis_op(core->analysis, &analop, at, buf + (at - map_begin), 24, RZ_ANALYSIS_OP_MASK_HINT);
2846  if (at == analop.jump) {
2847  rz_cons_printf("0x%08" PFMT64x "\n", at);
2848  }
2849  at += analop.size;
2851  }
2852  free(buf);
2853  }
2854 }
2855 
2857  RzAsmOp asmop;
2858  ut8 buf[32];
2859  int i;
2860  rz_io_read_at(core->io, 0, buf, sizeof(buf));
2861  if (nth < 0 || nth >= sizeof(buf) - 1) {
2862  return;
2863  }
2864  for (i = 0; i <= 0xff; i++) {
2865  buf[nth] = i;
2866  if (rz_asm_disassemble(core->rasm, &asmop, buf, sizeof(buf)) > 0) {
2867  const char *asmstr = rz_strbuf_get(&asmop.buf_asm);
2868  if (!strstr(asmstr, "invalid") && !strstr(asmstr, "unaligned")) {
2869  rz_cons_printf("%02x %s\n", i, asmstr);
2870  }
2871  }
2872  }
2873 }
2874 
2875 RZ_IPI int rz_cmd_search(void *data, const char *input) {
2876  bool dosearch = false;
2877  int ret = true;
2878  RzCore *core = (RzCore *)data;
2879  struct search_parameters param = {
2880  .core = core,
2881  .cmd_hit = rz_config_get(core->config, "cmd.hit"),
2882  .outmode = 0,
2883  .inverse = false,
2884  .aes_search = false,
2885  .privkey_search = false,
2886  };
2887  if (!param.cmd_hit) {
2888  param.cmd_hit = "";
2889  }
2890  RzSearch *search = core->search;
2891  int ignorecase = false;
2892  int param_offset = 2;
2893  char *inp;
2894  if (!core || !core->io) {
2895  eprintf("Can't search if we don't have an open file.\n");
2896  return false;
2897  }
2898  if (core->in_search) {
2899  eprintf("Can't search from within a search.\n");
2900  return false;
2901  }
2902  if (input[0] == '/') {
2903  if (core->lastsearch) {
2904  input = core->lastsearch;
2905  } else {
2906  eprintf("No previous search done\n");
2907  return false;
2908  }
2909  } else {
2910  free(core->lastsearch);
2912  }
2913 
2914  core->in_search = true;
2915  rz_flag_space_push(core->flags, "search");
2916  const ut64 search_from = rz_config_get_i(core->config, "search.from"),
2917  search_to = rz_config_get_i(core->config, "search.to");
2918  if (search_from > search_to && search_to) {
2919  eprintf("search.from > search.to is not supported\n");
2920  ret = false;
2921  goto beach;
2922  }
2923  // {.addr = UT64_MAX, .size = 0} means search range is unspecified
2924  RzInterval search_itv = { search_from, search_to - search_from };
2925  bool empty_search_itv = search_from == search_to && search_from != UT64_MAX;
2926  if (empty_search_itv) {
2927  eprintf("WARNING from == to?\n");
2928  ret = false;
2929  goto beach;
2930  }
2931  // TODO full address cannot be represented, shrink 1 byte to [0, UT64_MAX)
2932  if (search_from == UT64_MAX && search_to == UT64_MAX) {
2933  search_itv.addr = 0;
2934  search_itv.size = UT64_MAX;
2935  }
2936 
2937  c = 0;
2938 
2939  searchshow = rz_config_get_i(core->config, "search.show");
2940  param.mode = rz_config_get(core->config, "search.in");
2941  param.boundaries = rz_core_get_boundaries_prot(core, -1, param.mode, "search");
2942 
2943  /*
2944  this introduces a bug until we implement backwards search
2945  for all search types
2946  if (__to < __from) {
2947  eprintf ("Invalid search range. Check 'e search.{from|to}'\n");
2948  return false;
2949  }
2950  since the backward search will be implemented soon I'm not gonna stick
2951  checks for every case in switch // jjdredd
2952  remove when everything is done
2953  */
2954 
2955  core->search->align = rz_config_get_i(core->config, "search.align");
2956  searchflags = rz_config_get_i(core->config, "search.flags");
2957  core->search->maxhits = rz_config_get_i(core->config, "search.maxhits");
2958  searchprefix = rz_config_get(core->config, "search.prefix");
2959  core->search->overlap = rz_config_get_i(core->config, "search.overlap");
2960  core->search->bckwrds = false;
2961 
2962  /* Quick & dirty check for json output */
2963  if (input[0] && (input[1] == 'j') && (input[0] != ' ')) {
2964  param.outmode = RZ_MODE_JSON;
2965  param_offset++;
2966  }
2967  param.pj = pj_new();
2968 
2969 reread:
2970  switch (*input) {
2971  case '!':
2972  input++;
2973  param.inverse = true;
2974  goto reread;
2975  case 'b': // "/b" backward search
2976  if (*(++input) == '?') {
2977  eprintf("Usage: /b<command> [value] backward search, see '/?'\n");
2978  goto beach;
2979  }
2980  search->bckwrds = true;
2981  if (core->offset) {
2982  RzInterval itv = { 0, core->offset };
2983  if (!rz_itv_overlap(search_itv, itv)) {
2984  ret = false;
2985  goto beach;
2986  } else {
2987  search_itv = rz_itv_intersect(search_itv, itv);
2988  }
2989  }
2990  goto reread;
2991  case 'o': { // "/o" print the offset of the Previous opcode
2992  ut64 addr, n = input[param_offset - 1] ? rz_num_math(core->num, input + param_offset) : 1;
2993  n = RZ_ABS((st64)n);
2994  if (((st64)n) < 1) {
2995  n = 1;
2996  }
2997  if (!rz_core_prevop_addr(core, core->offset, n, &addr)) {
2998  addr = UT64_MAX;
2999  (void)rz_core_asm_bwdis_len(core, NULL, &addr, n);
3000  }
3001  if (param.outmode == RZ_MODE_JSON) {
3002  rz_cons_printf("[%" PFMT64u "]", addr);
3003  } else {
3004  rz_cons_printf("0x%08" PFMT64x "\n", addr);
3005  }
3006  break;
3007  }
3008  case 'O': { // "/O" alternative to "/o"
3009  ut64 addr, n = input[param_offset - 1] ? rz_num_math(core->num, input + param_offset) : 1;
3010  if (!n) {
3011  n = 1;
3012  }
3014  if (param.outmode == RZ_MODE_JSON) {
3015  rz_cons_printf("[%" PFMT64u "]", addr);
3016  } else {
3017  rz_cons_printf("0x%08" PFMT64x "\n", addr);
3018  }
3019  break;
3020  }
3021  case 'R': // "/R"
3022  if (input[1] == '?') {
3024  } else if (input[1] == '/') {
3025  rz_core_search_rop(core, search_itv, 0, input + 1, 1, &param);
3026  } else if (input[1] == 'k') {
3027  if (input[2] == '?') {
3029  } else {
3030  rop_kuery(core, input + 2, param.pj);
3031  }
3032  } else {
3033  Sdb *gadgetSdb = sdb_ns(core->sdb, "gadget_sdb", false);
3034 
3035  if (!gadgetSdb) {
3036  rz_core_search_rop(core, search_itv, 0, input + 1, 0, &param);
3037  } else {
3038  SdbKv *kv;
3039  SdbListIter *sdb_iter;
3040  SdbList *sdb_list = sdb_foreach_list(gadgetSdb, true);
3041 
3042  ls_foreach (sdb_list, sdb_iter, kv) {
3043  RzList *hitlist = rz_core_asm_hit_list_new();
3044  if (!hitlist) {
3045  goto beach;
3046  }
3047 
3048  char *s = sdbkv_value(kv);
3049  ut64 addr;
3050  int opsz;
3051  int mode = 0;
3052 
3053  // Options, like JSON, linear, ...
3054  if (input + 1) {
3055  mode = *(input + 1);
3056  }
3057 
3058  do {
3059  RzCoreAsmHit *hit = rz_core_asm_hit_new();
3060  if (!hit) {
3061  rz_list_free(hitlist);
3062  goto beach;
3063  }
3064  sscanf(s, "%" PFMT64x "(%" PFMT32d ")", &addr, &opsz);
3065  hit->addr = addr;
3066  hit->len = opsz;
3067  rz_list_append(hitlist, hit);
3068  } while (*(s = strchr(s, ')') + 1) != '\0');
3069 
3070  print_rop(core, hitlist, param.pj, mode);
3071  rz_list_free(hitlist);
3072  }
3073  }
3074  }
3075  goto beach;
3076  case 'r': // "/r"
3077  {
3078  ut64 n = (input[1] == ' ' || (input[1] && input[2] == ' '))
3079  ? rz_num_math(core->num, input + 2)
3080  : UT64_MAX;
3081  if (n == 0LL) {
3082  eprintf("Cannot find null references.\n");
3083  break;
3084  }
3085  switch (input[1]) {
3086  case 'c': // "/rc"
3087  {
3088  RzListIter *iter;
3089  RzIOMap *map;
3090  rz_list_foreach (param.boundaries, iter, map) {
3091  eprintf("-- 0x%" PFMT64x " 0x%" PFMT64x "\n", map->itv.addr, rz_itv_end(map->itv));
3092  rz_core_analysis_search(core, map->itv.addr, rz_itv_end(map->itv), n, 'c');
3093  }
3094  } break;
3095  case 'a': // "/ra"
3096  {
3097  RzListIter *iter;
3098  RzIOMap *map;
3099  rz_list_foreach (param.boundaries, iter, map) {
3100  eprintf("-- 0x%" PFMT64x " 0x%" PFMT64x "\n", map->itv.addr, rz_itv_end(map->itv));
3101  rz_core_analysis_search(core, map->itv.addr, rz_itv_end(map->itv), n, 0);
3102  }
3103  } break;
3104  case 'r': // "/rr" - read refs
3105  {
3106  RzListIter *iter;
3107  RzIOMap *map;
3108  rz_list_foreach (param.boundaries, iter, map) {
3109  eprintf("-- 0x%" PFMT64x " 0x%" PFMT64x "\n", map->itv.addr, rz_itv_end(map->itv));
3110  rz_core_analysis_search(core, map->itv.addr, rz_itv_end(map->itv), n, 'r');
3111  }
3112  } break;
3113  case 'w': // "/rw" - write refs
3114  {
3115  RzListIter *iter;
3116  RzIOMap *map;
3117  rz_list_foreach (param.boundaries, iter, map) {
3118  eprintf("-- 0x%" PFMT64x " 0x%" PFMT64x "\n", map->itv.addr, rz_itv_end(map->itv));
3119  rz_core_analysis_search(core, map->itv.addr, rz_itv_end(map->itv), n, 'w');
3120  }
3121  } break;
3122  case ' ': // "/r $$"
3123  case 0: // "/r"
3124  {
3125  RzListIter *iter;
3126  RzIOMap *map;
3127  rz_list_foreach (param.boundaries, iter, map) {
3128  ut64 from = map->itv.addr;
3129  ut64 to = rz_itv_end(map->itv);
3130  if (input[param_offset - 1] == ' ') {
3132  rz_num_math(core->num, input + 2), 0);
3133  do_ref_search(core, rz_num_math(core->num, input + 2), from, to, &param);
3134  } else {
3136  do_ref_search(core, core->offset, from, to, &param);
3137  }
3138  if (rz_cons_is_breaked()) {
3139  break;
3140  }
3141  }
3142  } break;
3143  case '?':
3145  break;
3146  }
3147  } break;
3148  case 'a': // "/a"
3149  if (input[1] == '?') {
3151  } else if (input[1] == 'd') { // "ad"
3152  dosearch = 0;
3153  do_asm_search(core, &param, input + 2, 0, search_itv);
3154  } else if (input[1] == 'e') { // "ae"
3155  dosearch = 0;
3156  do_asm_search(core, &param, input + 2, 'e', search_itv);
3157  } else if (input[1] == 'c') { // "/ac"
3158  dosearch = 0;
3159  do_asm_search(core, &param, input + 2, 'c', search_itv);
3160  } else if (input[1] == 'o') { // "/ao"
3161  dosearch = 0;
3162  do_asm_search(core, &param, input + 2, 'o', search_itv);
3163  } else if (input[1] == 'a') { // "/aa"
3164  dosearch = 0;
3165  do_asm_search(core, &param, input + 2, 'a', search_itv);
3166  } else if (input[1] == 'i') { // "/ai"
3167  do_asm_search(core, &param, input + 2, 'i', search_itv);
3168  } else if (input[1] == '1') { // "a1"
3170  } else if (input[1] == 'I') { // "/aI" - infinite
3172  } else if (input[1] == ' ') {
3173  if (input[param_offset - 1]) {
3174  char *kwd = rz_core_asm_search(core, input + param_offset);
3175  if (!kwd) {
3176  ret = false;
3177  goto beach;
3178  }
3179  dosearch = true;
3181  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3184  free(kwd);
3185  }
3186  } else if (input[1] == 's') {
3187  if (input[2] == 'l') { // "asl"
3188  rz_core_cmd0(core, "asl");
3189  } else { // "as"
3190  do_syscall_search(core, &param);
3191  }
3192  dosearch = false;
3193  } else {
3194  dosearch = do_analysis_search(core, &param, input + 1);
3195  }
3196  break;
3197  case 'c': { // "/c"
3198  dosearch = true;
3199  switch (input[1]) {
3200  case 'c': // "/cc"
3201  {
3202  ret = false;
3203  char *space = strchr(input, ' ');
3204  const char *arg = space ? rz_str_trim_head_ro(space + 1) : NULL;
3205  if (!arg || input[2] == '?') {
3206  eprintf("Usage: /cc[aAdlpb] [hashname] [hexpairhashvalue]\n");
3207  eprintf(" /cca - lowercase alphabet chars only\n");
3208  eprintf(" /ccA - uppercase alphabet chars only\n");
3209  eprintf(" /ccl - letters (lower + upper alphabet chars)\n");
3210  eprintf(" /ccd - digits (only numbers)\n");
3211  eprintf(" /ccp - printable (alpha + digit)\n");
3212  eprintf(" /ccb - binary (any number is valid)\n");
3213  goto beach;
3214  }
3215  char *s = strdup(arg);
3216  char *sp = strchr(s, ' ');
3217  int mode = input[2];
3218  if (sp) {
3219  *sp = 0;
3220  sp++;
3221  char *hashName = s;
3222  ut8 *hashValue = (ut8 *)strdup(sp);
3223  if (hashValue) {
3224  if (!rz_str_startswith((const char *)hashValue, "0x")) {
3225  // TODO: support bigger hashes
3226  int hashLength = 4;
3227  ut32 n = (ut32)rz_num_get(NULL, (const char *)hashValue);
3228  memcpy(hashValue, (const ut8 *)&n, sizeof(ut32));
3229  search_collisions(core, hashName, hashValue, hashLength, mode);
3230  } else {
3231  int hashLength = rz_hex_str2bin(sp, hashValue);
3232  if (hashLength > 0) {
3233  search_collisions(core, hashName, hashValue, hashLength, mode);
3234  } else {
3235  eprintf("Invalid expected hash hexpairs.\n");
3236  }
3237  }
3238  free(hashValue);
3239  } else {
3240  eprintf("Cannot allocate memory.\n");
3241  }
3242  ret = true;
3243  } else {
3244  eprintf("Usage: /cc [hashname] [hexpairhashvalue]\n");
3245  eprintf("Usage: /CC to search ascii collisions\n");
3246  }
3247  free(s);
3248  goto beach;
3249  } break;
3250  case 'd': // "cd"
3251  {
3252  RzSearchKeyword *kw;
3253  kw = rz_search_keyword_new_hex("308200003082", "ffff0000ffff", NULL);
3255  if (kw) {
3257  // eprintf ("Searching %d byte(s)...\n", kw->keyword_length);
3259  } else {
3260  eprintf("bad pointer\n");
3261  dosearch = false;
3262  }
3263  } break;
3264  case 'a': // "ca"
3265  {
3266  RzSearchKeyword *kw;
3267  kw = rz_search_keyword_new_hexmask("00", NULL);
3268  // AES search is done over 40 bytes
3271  rz_search_kw_add(search, kw);
3273  param.aes_search = true;
3274  break;
3275  }
3276  case 'r': // "cr"
3277  {
3278  RzSearchKeyword *kw;
3279  kw = rz_search_keyword_new_hexmask("00", NULL);
3280  // Private key search is at least 11 bytes
3283  rz_search_kw_add(search, kw);
3285  param.privkey_search = true;
3286  break;
3287  }
3288  default: {
3289  dosearch = false;
3291  }
3292  }
3293  } break;
3294  case 'm': // "/m"
3295  dosearch = false;
3296  if (input[1] == '?') { // "/m?"
3298  } else if (input[1] == 'b') { // "/mb"
3299  bool bin_verbose = rz_config_get_i(core->config, "bin.verbose");
3300  rz_config_set_i(core->config, "bin.verbose", false);
3301  // TODO : iter maps?
3302  cmd_search_bin(core, search_itv);
3303  rz_config_set_i(core->config, "bin.verbose", bin_verbose);
3304  } else if (input[1] == ' ' || input[1] == '\0' || param.outmode == RZ_MODE_JSON) {
3305  int ret;
3306  const char *file = input[param_offset - 1] ? input + param_offset : NULL;
3307  ut64 addr = search_itv.addr;
3308  RzListIter *iter;
3309  RzIOMap *map;
3310  if (param.outmode == RZ_MODE_JSON) {
3311  pj_a(param.pj);
3312  }
3314  int maxHits = rz_config_get_i(core->config, "search.maxhits");
3315  int hits = 0;
3316  rz_list_foreach (param.boundaries, iter, map) {
3317  if (param.outmode != RZ_MODE_JSON) {
3318  eprintf("-- %llx %llx\n", map->itv.addr, rz_itv_end(map->itv));
3319  }
3321  for (addr = map->itv.addr; addr < rz_itv_end(map->itv); addr++) {
3322  if (rz_cons_is_breaked()) {
3323  break;
3324  }
3325  ret = rz_core_magic_at(core, file, addr, 99, false, param.outmode == RZ_MODE_JSON ? param.pj : NULL, &hits);
3326  if (ret == -1) {
3327  // something went terribly wrong.
3328  break;
3329  }
3330  if (maxHits && hits >= maxHits) {
3331  break;
3332  }
3333  addr += ret - 1;
3334  }
3335  rz_cons_clear_line(1);
3337  }
3338  if (param.outmode == RZ_MODE_JSON) {
3339  pj_end(param.pj);
3340  }
3341  } else {
3342  eprintf("Usage: /m [file]\n");
3343  }
3344  rz_cons_clear_line(1);
3345  break;
3346  case 'p': // "/p"
3347  {
3348  if (input[param_offset - 1]) {
3349  int ps = atoi(input + param_offset);
3350  if (ps > 1) {
3351  RzListIter *iter;
3352  RzIOMap *map;
3353  rz_list_foreach (param.boundaries, iter, map) {
3354  eprintf("-- %llx %llx\n", map->itv.addr, rz_itv_end(map->itv));
3357  rz_search_pattern(core->search, map->itv.addr, rz_itv_end(map->itv));
3359  }
3360  break;
3361  }
3362  }
3363  eprintf("Invalid pattern size (must be > 0)\n");
3364  } break;
3365  case 'P': // "/P"
3366  search_similar_pattern(core, atoi(input + 1), &param);
3367  break;
3368  case 'V': // "/V"
3369  {
3370  if (input[2] == 'j') {
3371  param.outmode = RZ_MODE_JSON;
3372  param_offset++;
3373  } else if (strchr(input + 1, '*')) {
3374  param.outmode = RZ_MODE_RIZINCMD;
3375  }
3376  int err = 1, vsize = atoi(input + 1);
3377  const char *num_str = input + param_offset + 1;
3378  if (vsize && input[2] && num_str) {
3379  if (param.outmode == RZ_MODE_JSON) {
3380  pj_a(param.pj);
3381  }
3382  char *w = strchr(num_str, ' ');
3383  if (w) {
3384  *w++ = 0;
3385  ut64 vmin = rz_num_math(core->num, num_str);
3386  ut64 vmax = rz_num_math(core->num, w);
3387  if (vsize > 0) {
3388  RzIOMap *map;
3389  RzListIter *iter;
3390  rz_list_foreach (param.boundaries, iter, map) {
3391  err = 0;
3392  int hits = rz_core_search_value_in_range(core, map->itv,
3393  vmin, vmax, vsize,
3394  _CbInRangeSearchV, &param);
3395  if (param.outmode != RZ_MODE_JSON) {
3396  eprintf("hits: %d\n", hits);
3397  }
3398  }
3399  }
3400  }
3401  if (param.outmode == RZ_MODE_JSON) {
3402  pj_end(param.pj);
3403  }
3404  }
3405  if (err) {
3406  eprintf("Usage: /V[1|2|4|8] [minval] [maxval]\n");
3407  }
3408  }
3409  dosearch = false;
3410  break;
3411  case 'v': // "/v"
3412  if (input[1]) {
3413  if (input[1] == '?') {
3414  rz_cons_print("Usage: /v[1|2|4|8] [value]\n");
3415  break;
3416  }
3417  if (input[2] == 'j') {
3418  param.outmode = RZ_MODE_JSON;
3419  param_offset++;
3420  }
3421  }
3423  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3424  char *v_str = (char *)rz_str_trim_head_ro(input + param_offset);
3425  RzList *nums = rz_num_str_split_list(v_str);
3426  int len = rz_list_length(nums);
3427  int bsize = 0;
3428  ut8 *v_buf = NULL;
3429  switch (input[1]) {
3430  case '8':
3431  if (input[param_offset]) {
3432  bsize = sizeof(ut64) * len;
3433  v_buf = v_writebuf(core, nums, len, '8', bsize);
3434  } else {
3435  eprintf("Usage: /v8 value\n");
3436  }
3437  break;
3438  case '1':
3439  if (input[param_offset]) {
3440  bsize = sizeof(ut8) * len;
3441  v_buf = v_writebuf(core, nums, len, '1', bsize);
3442  } else {
3443  eprintf("Usage: /v1 value\n");
3444  }
3445  break;
3446  case '2':
3447  if (input[param_offset]) {
3448  bsize = sizeof(ut16) * len;
3449  v_buf = v_writebuf(core, nums, len, '2', bsize);
3450  } else {
3451  eprintf("Usage: /v2 value\n");
3452  }
3453  break;
3454  default: // default size
3455  case '4':
3456  if (input[param_offset - 1]) {
3457  if (input[param_offset]) {
3458  bsize = sizeof(ut32) * len;
3459  v_buf = v_writebuf(core, nums, len, '4', bsize);
3460  }
3461  } else {
3462  eprintf("Usage: /v4 value\n");
3463  }
3464  break;
3465  }
3466  if (v_buf) {
3468  rz_search_keyword_new((const ut8 *)v_buf, bsize, NULL, 0, NULL));
3469  free(v_buf);
3470  }
3472  dosearch = true;
3473  break;
3474  case 'w': // "/w" search wide string, includes ignorecase search functionality (/wi cmd)!
3475  if (input[2]) {
3476  if (input[1] == 'j' || input[2] == 'j') {
3477  param.outmode = RZ_MODE_JSON;
3478  }
3479  if (input[1] == 'i' || input[2] == 'i') {
3480  ignorecase = true;
3481  }
3482  } else {
3483  param.outmode = RZ_MODE_RIZINCMD;
3484  }
3485 
3486  size_t shift = 1 + ignorecase;
3487  if (param.outmode == RZ_MODE_JSON) {
3488  shift++;
3489  }
3490  size_t strstart;
3491  const char *p2;
3492  char *p;
3493  strstart = shift + 1;
3494  len = strlen(input + strstart);
3495  inp = calloc((len + 1), 2);
3496  for (p2 = input + strstart, p = inp; *p2; p += 2, p2++) {
3497  if (ignorecase) {
3498  p[0] = tolower((const ut8)*p2);
3499  } else {
3500  p[0] = *p2;
3501  }
3502  p[1] = 0;
3503  }
3505  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3506  RzSearchKeyword *skw;
3507  skw = rz_search_keyword_new((const ut8 *)inp, len * 2, NULL, 0, NULL);
3508  free(inp);
3509  if (skw) {
3510  skw->icase = ignorecase;
3511  rz_search_kw_add(core->search, skw);
3513  dosearch = true;
3514  } else {
3515  eprintf("Invalid keyword\n");
3516  break;
3517  }
3518  // fallthrough
3519  case 'i': // "/i"
3520  if (input[param_offset - 1] != ' ') {
3521  eprintf("Missing ' ' after /i\n");
3522  ret = false;
3523  goto beach;
3524  }
3525  ignorecase = true;
3526  // fallthrough
3527  case 'j': // "/j"
3528  if (input[0] == 'j' && input[1] == ' ') {
3529  param.outmode = RZ_MODE_JSON;
3530  }
3531  // fallthrough
3532  case ' ': // "/ " search string
3533  inp = strdup(input + 1 + ignorecase + (param.outmode == RZ_MODE_JSON ? 1 : 0));
3534  len = rz_str_unescape(inp);
3535 #if 0
3536  if (!json) {
3537  eprintf ("Searching %d byte(s) from 0x%08"PFMT64x " to 0x%08"PFMT64x ": ",
3538  len, search_itv.addr, rz_itv_end (search_itv));
3539  for (i = 0; i < len; i++) {
3540  eprintf ("%02x ", (ut8) inp[i]);
3541  }
3542  eprintf ("\n");
3543  }
3544 #endif
3546  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3547  {
3548  RzSearchKeyword *skw;
3549  skw = rz_search_keyword_new((const ut8 *)inp, len, NULL, 0, NULL);
3550  free(inp);
3551  if (skw) {
3552  skw->icase = ignorecase;
3554  rz_search_kw_add(core->search, skw);
3555  } else {
3556  eprintf("Invalid keyword\n");
3557  break;
3558  }
3559  }
3561  dosearch = true;
3562  break;
3563  case 'e': // "/e" match regexp
3564  if (input[1] == '?') {
3565  eprintf("Usage: /e /foo/i or /e/foo/i\n");
3566  } else if (input[1]) {
3567  RzSearchKeyword *kw;
3569  if (!kw) {
3570  eprintf("Invalid regexp specified\n");
3571  break;
3572  }
3574  // TODO distance is unused
3575  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3578  dosearch = true;
3579  } else {
3580  eprintf("Missing regex\n");
3581  }
3582  break;
3583  case 'E': // "/E"
3584  if (core->bin && core->bin->is_debugger) {
3586  }
3587  do_esil_search(core, &param, input);
3588  goto beach;
3589  case 'd': // "/d" search delta key
3590  if (input[1]) {
3593  rz_search_keyword_new_hexmask(input + param_offset, NULL));
3595  dosearch = true;
3596  } else {
3597  eprintf("Missing delta\n");
3598  }
3599  break;
3600  case 'h': // "/h"
3601  {
3602  char *p, *arg = rz_str_trim_dup(input + 1);
3603  p = strchr(arg, ' ');
3604  if (p) {
3605  *p++ = 0;
3606  if (*arg == '?') {
3607  eprintf("Usage: /h md5 [hash] [datalen]\n");
3608  } else {
3609  ut32 min = UT32_MAX;
3610  ut32 max = UT32_MAX;
3611  char *pmax, *pmin = strchr(p, ' ');
3612  if (pmin) {
3613  *pmin++ = 0;
3614  pmax = strchr(pmin, ' ');
3615  if (pmax) {
3616  *pmax++ = 0;
3617  max = rz_num_math(core->num, pmax);
3618  }
3619  min = rz_num_math(core->num, pmin);
3620  }
3621  search_hash(core, arg, p, min, max, &param);
3622  }
3623  } else {
3624  eprintf("Missing hash. See ph?\n");
3625  }
3626  free(arg);
3627  } break;
3628  case 'f': // "/f" forward search
3629  if (core->offset) {
3630  RzInterval itv = { core->offset, -core->offset };
3631  if (!rz_itv_overlap(search_itv, itv)) {
3632  ret = false;
3633  goto beach;
3634  } else {
3635  search_itv = rz_itv_intersect(search_itv, itv);
3636  }
3637  }
3638  break;
3639  case 'g': // "/g" graph search
3640  if (input[1] == '?') {
3641  rz_cons_printf("Usage: /g[g] [fromaddr] @ [toaddr]\n");
3642  rz_cons_printf("(find all graph paths A to B (/gg follow jumps, see search.count and analysis.depth)");
3643  } else {
3644  ut64 addr = UT64_MAX;
3645  if (input[1]) {
3646  addr = rz_num_math(core->num, input + 2);
3647  } else {
3649  if (fcn) {
3650  addr = fcn->addr;
3651  } else {
3652  addr = core->offset;
3653  }
3654  }
3655  const int depth = rz_config_get_i(core->config, "analysis.depth");
3656  // Va;ifate input length
3657  if (input[1] != '\0') {
3658  rz_core_analysis_paths(core, addr, core->offset, input[1] == 'g', depth, (input[1] == 'j' || input[2] == 'j'));
3659  }
3660  }
3661  break;
3662  case 'F': // "/F" search file /F [file] ([offset] ([sz]))
3663  if (input[param_offset - 1] == ' ') {
3664  int n_args;
3665  char **args = rz_str_argv(input + param_offset, &n_args);
3666  ut8 *buf = NULL;
3667  ut64 offset = 0;
3668  size_t size;
3669  buf = (ut8 *)rz_file_slurp(args[0], &size);
3670  if (!buf) {
3671  eprintf("Cannot open '%s'\n", args[0]);
3673  break;
3674  }
3675  if (n_args > 1) {
3676  offset = rz_num_math(core->num, args[1]);
3677  if (size <= offset) {
3678  eprintf("size <= offset\n");
3680  free(buf);
3681  break;
3682  }
3683  }
3684  if (n_args > 2) {
3685  len = rz_num_math(core->num, args[2]);
3686  if (len > size - offset) {
3687  eprintf("len too large\n");
3689  free(buf);
3690  break;
3691  }
3692  } else {
3693  len = size - offset;
3694  }
3695  RzSearchKeyword *kw;
3697  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3698  kw = rz_search_keyword_new(buf + offset, len, NULL, 0, NULL);
3699  if (kw) {
3701  // eprintf ("Searching %d byte(s)...\n", kw->keyword_length);
3703  dosearch = true;
3704  } else {
3705  eprintf("no keyword\n");
3706  }
3707 
3709  free(buf);
3710  } else {
3711  eprintf("Usage: /F[j] [file] ([offset] ([sz]))\n");
3712  }
3713  break;
3714  case 'x': // "/x" search hex
3715  if (input[1] == '?') {
3717  } else {
3718  RzSearchKeyword *kw;
3719  char *s, *p = strdup(input + param_offset);
3721  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3722  s = strchr(p, ':');
3723  if (s) {
3724  *s++ = 0;
3726  } else {
3728  }
3729  if (kw) {
3731  // eprintf ("Searching %d byte(s)...\n", kw->keyword_length);
3733  dosearch = true;
3734  } else {
3735  eprintf("no keyword\n");
3736  }
3737  free(p);
3738  }
3739  break;
3740  case 's': // "/s"
3741  do_section_search(core, &param, input + 1);
3742  break;
3743  case '+': // "/+"
3744  if (input[1] == ' ') {
3745  // TODO: support /+j
3746  char *buf = malloc(strlen(input) * 2);
3747  char *str = strdup(input + 2);
3748  int ochunksize;
3749  int i, len, chunksize = rz_config_get_i(core->config, "search.chunk");
3750  if (chunksize < 1) {
3751  chunksize = core->rasm->bits / 8;
3752  }
3753  len = rz_str_unescape(str);
3754  ochunksize = chunksize = RZ_MIN(len, chunksize);
3755  eprintf("Using chunksize: %d\n", chunksize);
3756  core->in_search = false;
3757  for (i = 0; i < len; i += chunksize) {
3758  chunksize = ochunksize;
3759  again:
3760  rz_hex_bin2str((ut8 *)str + i, RZ_MIN(chunksize, len - i), buf);
3761  eprintf("/x %s\n", buf);
3762  rz_core_cmdf(core, "/x %s", buf);
3763  if (core->num->value == 0) {
3764  chunksize--;
3765  if (chunksize < 1) {
3766  eprintf("Oops\n");
3767  free(buf);
3768  free(str);
3769  goto beach;
3770  }
3771  eprintf("Repeat with chunk size %d\n", chunksize);
3772  goto again;
3773  }
3774  }
3775  free(str);
3776  free(buf);
3777  } else {
3778  eprintf("Usage: /+ [string]\n");
3779  }
3780  break;
3781  case 'z': // "/z" search strings of min-max range
3782  {
3783  char *p;
3784  ut32 min, max;
3785  if (!input[1]) {
3786  eprintf("Usage: /z min max\n");
3787  break;
3788  }
3789  if ((p = strchr(input + 2, ' '))) {
3790  *p = 0;
3791  max = rz_num_math(core->num, p + 1);
3792  } else {
3793  eprintf("Usage: /z min max\n");
3794  break;
3795  }
3796  min = rz_num_math(core->num, input + 2);
3798  eprintf("Error: min must be lower than max\n");
3799  break;
3800  }
3802  rz_search_set_distance(core->search, (int)rz_config_get_i(core->config, "search.distance"));
3803  {
3806  rz_search_kw_add(search, kw);
3807  }
3809  dosearch = true;
3810  } break;
3811  case '?': // "/?"
3813  break;
3814  default:
3815  eprintf("See /? for help.\n");
3816  break;
3817  }
3818  rz_config_set_i(core->config, "search.kwidx", search->n_kws);
3819  if (dosearch) {
3820  do_string_search(core, search_itv, &param);
3821  }
3822 beach:
3823  core->num->value = search->nhits;
3824  core->in_search = false;
3825  rz_flag_space_pop(core->flags);
3826  if (param.outmode == RZ_MODE_JSON) {
3827  rz_cons_println(pj_string(param.pj));
3828  }
3829  pj_free(param.pj);
3830  rz_list_free(param.boundaries);
3832  return ret;
3833 }
size_t len
Definition: 6502dis.c:15
static void print_comment(const aarch64_inst *inst, struct disassemble_info *info)
Definition: aarch64-dis.c:3074
si
RZ_API RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
RZ_API ut64 rz_analysis_function_size_from_entry(RzAnalysisFunction *fcn)
Definition: function.c:333
RZ_API RzList * rz_analysis_preludes(RzAnalysis *analysis)
Definition: analysis.c:669
RZ_API int rz_analysis_archinfo(RzAnalysis *analysis, int query)
Definition: analysis.c:449
#define e(frag)
static int analop(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask)
#define mask()
#define RZ_IPI
Definition: analysis_wasm.c:11
RZ_API void rz_asm_op_fini(RzAsmOp *op)
Definition: aop.c:21
RZ_API char * rz_asm_op_get_hex(RzAsmOp *op)
Definition: aop.c:28
RZ_API char * rz_asm_op_get_asm(RzAsmOp *op)
Definition: aop.c:37
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
Definition: arm_il32.c:190
static bool err
Definition: armass.c:435
RZ_API RZ_OWN RzAsmParseParam * rz_asm_get_parse_param(RZ_NULLABLE const RzReg *reg, ut32 ana_op_type)
Does all kinds of NULL checks on the parameters and returns an initialized RzAsmParseParam or NULL on...
Definition: asm.c:1763
RZ_DEPRECATE RZ_API RZ_OWN RzStrBuf * rz_asm_colorize_asm_str(RZ_BORROW RzStrBuf *asm_str, RZ_BORROW RzPrint *p, RZ_NULLABLE const RzAsmParseParam *param, RZ_NULLABLE const RzAsmTokenString *toks)
Colors a given asm string and returns it. If toks is not NULL it uses the tokens to color the asm str...
Definition: asm.c:1741
RZ_API int rz_asm_set_pc(RzAsm *a, ut64 pc)
Definition: asm.c:533
RZ_API int rz_asm_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len)
Definition: asm.c:543
static ut8 bytes[32]
Definition: asm_arc.c:23
static int opstr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4054
RZ_API RzBinObject * rz_bin_cur_object(RzBin *bin)
Definition: bin.c:900
RZ_API RzBinPlugin * rz_bin_get_binplugin_by_buffer(RzBin *bin, RzBuffer *buf)
Definition: bin.c:349
RZ_API RzBinFile * rz_bin_open_io(RzBin *bin, RzBinOptions *opt)
Definition: bin.c:283
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
RZ_API int rz_search_pattern(RzSearch *s, ut64 from, ut64 to)
Definition: bytepat.c:61
void search()
Definition: cabinfo.c:91
RZ_API ut64 rz_core_analysis_address(RzCore *core, ut64 addr)
Definition: canalysis.c:168
RZ_API int rz_core_analysis_search(RzCore *core, ut64 from, ut64 to, ut64 ref, int mode)
Definition: canalysis.c:3071
RZ_API void rz_core_analysis_paths(RzCore *core, ut64 from, ut64 to, bool followCalls, int followDepth, bool is_json)
Definition: canalysis.c:5121
RZ_API int rz_core_analysis_fcn(RzCore *core, ut64 at, ut64 from, int reftype, int depth)
Definition: canalysis.c:2026
RZ_API int rz_core_search_value_in_range(RzCore *core, RzInterval search_itv, ut64 vmin, ut64 vmax, int vsize, inRangeCb cb, void *cb_user)
Definition: canalysis.c:4895
RZ_API char * rz_core_asm_search(RzCore *core, const char *input)
Definition: casm.c:56
RZ_API ut32 rz_core_asm_bwdis_len(RzCore *core, int *instr_len, ut64 *start_addr, ut32 nb)
Definition: casm.c:890
RZ_API RzList * rz_core_asm_strsearch(RzCore *core, const char *input, ut64 from, ut64 to, int maxhits, int regexp, int everyByte, int mode)
Definition: casm.c:185
RZ_API RzCoreAsmHit * rz_core_asm_hit_new(void)
Definition: casm.c:28
RZ_API RzList * rz_core_asm_hit_list_new(void)
Definition: casm.c:38
RZ_API void rz_core_analysis_esil_reinit(RZ_NONNULL RzCore *core)
Reinitialize ESIL.
Definition: cil.c:54
RZ_API int rz_core_cmd0(RzCore *core, const char *cmd)
Definition: cmd.c:5428
RZ_API void rz_core_cmd_help(const RzCore *core, const char *help[])
Definition: cmd.c:163
RZ_API int rz_core_cmd(RzCore *core, const char *cstr, int log)
Definition: cmd.c:5328
RZ_API int rz_core_cmdf(RzCore *core, const char *fmt,...)
Definition: cmd.c:5413
static const char * syscallNumber(int n)
RZ_API int rz_core_esil_step(RzCore *core, ut64 until_addr, const char *until_expr, ut64 *prev_addr, bool stepOver)
Definition: cmd_analysis.c:860
static int rz_core_magic_at(RzCore *core, const char *file, ut64 addr, int depth, int v, PJ *pj, int *hits)
Definition: cmd_magic.c:16
static void rz_core_magic_reset(RzCore *core)
Definition: cmd_magic.c:12
#define MAXINSTR
Definition: cmd_search.c:1705
static void do_string_search(RzCore *core, RzInterval search_itv, struct search_parameters *param)
Definition: cmd_search.c:2304
static bool is_end_gadget(const RzAnalysisOp *aop, const ut8 crop)
Definition: cmd_search.c:951
static const char * help_msg_slash[]
Definition: cmd_search.c:35
static void __core_cmd_search_asm_infinite(RzCore *core, const char *arg)
Definition: cmd_search.c:2828
static const char * help_msg_slash_m[]
Definition: cmd_search.c:28
static void do_asm_search(RzCore *core, struct search_parameters *param, const char *input, int mode, RzInterval search_itv)
Definition: cmd_search.c:2201
static int search_hash(RzCore *core, const char *hashname, const char *hashstr, ut32 minlen, ut32 maxlen, struct search_parameters *param)
Definition: cmd_search.c:176
static void incDigitBuffer(ut8 *buf, int bufsz)
Definition: cmd_search.c:2725
static ut8 * v_writebuf(RzCore *core, RzList *nums, int len, char ch, int bsize)
Definition: cmd_search.c:2608
static void incAlphaBuffer(ut8 *buf, int bufsz)
Definition: cmd_search.c:2710
RZ_IPI int rz_cmd_search(void *data, const char *input)
Definition: cmd_search.c:2875
static void do_esil_search(RzCore *core, struct search_parameters *param, const char *input)
Definition: cmd_search.c:1573
static bool isArm(RzCore *core)
Definition: cmd_search.c:2566
static int _cb_hit(RzSearchKeyword *kw, void *user, ut64 addr)
Definition: cmd_search.c:403
static char * getstring(char *b, int l)
Definition: cmd_search.c:388
static void incLowerBuffer(ut8 *buf, int bufsz)
Definition: cmd_search.c:2682
static void print_search_progress(ut64 at, ut64 to, int n, struct search_parameters *param)
Definition: cmd_search.c:522
static int c
Definition: cmd_search.c:520
static const char * searchprefix
Definition: cmd_search.c:157
static void do_syscall_search(RzCore *core, struct search_parameters *param)
Definition: cmd_search.c:1760
#define SUMARRAY(arr, size, res)
Definition: cmd_search.c:1706
static void print_rop(RzCore *core, RzList *hitlist, PJ *pj, int mode)
Definition: cmd_search.c:1124
static void search_similar_pattern(RzCore *core, int count, struct search_parameters *param)
Definition: cmd_search.c:2555
static const char * help_msg_slash_x[]
Definition: cmd_search.c:147
static const char * help_msg_slash_c[]
Definition: cmd_search.c:107
static void do_section_search(RzCore *core, struct search_parameters *param, const char *input)
Definition: cmd_search.c:2133
RZ_API RZ_OWN RzList * rz_core_get_boundaries_prot(RzCore *core, int perm, const char *mode, const char *prefix)
Definition: cmd_search.c:577
static const char * help_msg_slash_r[]
Definition: cmd_search.c:116
static const char * help_msg_slash_Rk[]
Definition: cmd_search.c:139
#define AES_SEARCH_LENGTH
Definition: cmd_search.c:16
static bool maskMatches(int perm, int mask, bool only)
Definition: cmd_search.c:567
static int __prelude_cb_hit(RzSearchKeyword *kw, void *user, ut64 addr)
Definition: cmd_search.c:283
void _CbInRangeSearchV(RzCore *core, ut64 from, ut64 to, int vsize, void *user)
Definition: cmd_search.c:2578
static bool do_analysis_search(RzCore *core, struct search_parameters *param, const char *input)
Definition: cmd_search.c:1949
static const char * help_msg_slash_a[]
Definition: cmd_search.c:86
static void __core_cmd_search_asm_byteswap(RzCore *core, int nth)
Definition: cmd_search.c:2856
static void incUpperBuffer(ut8 *buf, int bufsz)
Definition: cmd_search.c:2696
static RzList * construct_rop_gadget(RzCore *core, ut64 addr, ut8 *buf, int buflen, int idx, const char *grep, int regex, RzList *rx_list, struct endlist_pair *end_gadget, HtUU *badstart)
Definition: cmd_search.c:990
static void do_ref_search(RzCore *core, ut64 addr, ut64 from, ut64 to, struct search_parameters *param)
Definition: cmd_search.c:1904
static void incBuffer(ut8 *buf, int bufsz)
Definition: cmd_search.c:2655
static void search_similar_pattern_in(RzCore *core, int count, ut64 from, ut64 to)
Definition: cmd_search.c:2529
static const char * help_msg_slash_R[]
Definition: cmd_search.c:127
static bool esil_addrinfo(RzAnalysisEsil *esil)
Definition: cmd_search.c:1558
static void cmd_search_bin(RzCore *core, RzInterval itv)
Definition: cmd_search.c:246
#define PRIVATE_KEY_SEARCH_LENGTH
Definition: cmd_search.c:17
static int preludecnt
Definition: cmd_search.c:154
RZ_API int rz_core_search_preludes(RzCore *core, bool log)
Definition: cmd_search.c:330
static void incPrintBuffer(ut8 *buf, int bufsz)
Definition: cmd_search.c:2668
static int memcmpdiff(const ut8 *a, const ut8 *b, int len)
Definition: cmd_search.c:2517
RZ_API int rz_core_search_prelude(RzCore *core, ut64 from, ut64 to, const ut8 *buf, int blen, const ut8 *mask, int mlen)
Definition: cmd_search.c:292
static void append_bound(RzList *list, RzIO *io, RzInterval search_itv, ut64 from, ut64 size, int perms)
Definition: cmd_search.c:535
static void search_collisions(RzCore *core, const char *hashName, const ut8 *hashValue, int hashLength, int mode)
Definition: cmd_search.c:2740
static bool insert_into(void *user, const ut64 k, const ut64 v)
Definition: cmd_search.c:983
static int searchshow
Definition: cmd_search.c:156
static void rop_kuery(void *data, const char *input, PJ *pj)
Definition: cmd_search.c:2420
static const char * help_msg_search_esil[]
Definition: cmd_search.c:19
static int rz_core_search_rop(RzCore *core, RzInterval search_itv, int opt, const char *grep, int regexp, struct search_parameters *param)
Definition: cmd_search.c:1283
static int searchflags
Definition: cmd_search.c:155
static void rop_classify(RzCore *core, Sdb *db, RzList *ropList, const char *key, unsigned int size)
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API bool rz_config_get_b(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:142
RZ_API RzConfigNode * rz_config_set_i(RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i)
Definition: config.c:419
RZ_API RZ_BORROW const char * rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:75
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API void rz_cons_clear_line(int std_err)
Definition: cons.c:756
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_flush(void)
Definition: cons.c:959
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
#define RZ_API
RZ_IPI void rz_core_print_hexdump(RZ_NONNULL RzCore *core, ut64 addr, RZ_NONNULL const ut8 *buf, int len, int base, int step, size_t zoomsz)
Definition: cprint.c:161
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
#define w
Definition: crypto_rc6.c:13
cs_arch arch
Definition: cstool.c:13
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void nbytes
Definition: sflib.h:113
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
#define ut8
Definition: dcpu16.h:8
static int buf_size
Definition: debug_qnx.c:35
uint16_t ut16
uint32_t ut32
RZ_API bool rz_debug_map_sync(RzDebug *dbg)
Definition: dmap.c:33
RZ_API ut64 rz_debug_reg_get(RzDebug *dbg, const char *name)
Definition: dreg.c:99
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
struct tab * done
Definition: enough.c:233
int max
Definition: enough.c:225
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API void rz_analysis_esil_stack_free(RzAnalysisEsil *esil)
Definition: esil.c:3103
RZ_API RzAnalysisEsil * rz_analysis_esil_new(int stacksize, int iotrap, unsigned int addrsize)
Definition: esil.c:85
RZ_API int rz_analysis_esil_get_parm(RzAnalysisEsil *esil, const char *str, ut64 *num)
Definition: esil.c:483
RZ_API bool rz_analysis_esil_pushnum(RzAnalysisEsil *esil, ut64 num)
Definition: esil.c:408
RZ_API bool rz_analysis_esil_set_pc(RzAnalysisEsil *esil, ut64 addr)
Definition: esil.c:155
RZ_API bool rz_analysis_esil_set_op(RzAnalysisEsil *esil, const char *op, RzAnalysisEsilOpCb code, ut32 push, ut32 pop, ut32 type)
Definition: esil.c:110
RZ_API char * rz_analysis_esil_pop(RzAnalysisEsil *esil)
Definition: esil.c:422
RZ_API bool rz_analysis_esil_setup(RzAnalysisEsil *esil, RzAnalysis *analysis, int romem, int stats, int nonull)
Definition: esil.c:3298
RZ_API bool rz_analysis_esil_parse(RzAnalysisEsil *esil, const char *str)
Definition: esil.c:2998
RZ_API void rz_analysis_esil_free(RzAnalysisEsil *esil)
Definition: esil.c:163
RZ_DEPRECATE RZ_API RzAnalysisFunction * rz_analysis_get_fcn_in(RzAnalysis *analysis, ut64 addr, int type)
Definition: fcn.c:1687
RZ_API RzFlagItem * rz_flag_set(RzFlag *f, const char *name, ut64 off, ut32 size)
Definition: flag.c:521
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
unsigned short prefix[65536]
Definition: gun.c:163
RZ_API RZ_OWN char * rz_hash_cfg_calculate_small_block_string(RZ_NONNULL RzHash *rh, RZ_NONNULL const char *name, RZ_NONNULL const ut8 *buffer, ut64 bsize, RZ_NULLABLE ut32 *size, bool invert)
Definition: hash.c:545
RZ_API RZ_BORROW const RzHashPlugin * rz_hash_plugin_by_name(RZ_NONNULL RzHash *rh, RZ_NONNULL const char *name)
Definition: hash.c:120
RZ_API double rz_hash_entropy(RZ_NONNULL RzHash *rh, RZ_NONNULL const ut8 *data, ut64 len)
Definition: hash.c:32
RZ_API RzAnalysisHint * rz_analysis_hint_get(RzAnalysis *a, ut64 addr)
Definition: hint.c:506
RZ_API void rz_analysis_hint_free(RzAnalysisHint *h)
Definition: hint.c:371
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
a0
Definition: insn-good.s.cs:704
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
sprintf
Definition: kernel.h:365
RZ_API RzSearchKeyword * rz_search_keyword_new_hex(const char *kwstr, const char *bmstr, const char *data)
Definition: keyword.c:132
RZ_API RzSearchKeyword * rz_search_keyword_new_regexp(const char *str, const char *data)
Definition: keyword.c:196
RZ_API RzSearchKeyword * rz_search_keyword_new(const ut8 *kwbuf, int kwlen, const ut8 *bmbuf, int bmlen, const char *data)
Definition: keyword.c:16
RZ_API RzSearchKeyword * rz_search_keyword_new_hexmask(const char *kwstr, const char *data)
Definition: keyword.c:173
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API char * rz_core_op_str(RzCore *core, ut64 addr)
Definition: core.c:2869
static int hit(RzSearchKeyword *kw, void *user, ut64 addr)
Definition: rz-find.c:58
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API void rz_list_reverse(RZ_NONNULL RzList *list)
Reverses the list.
Definition: list.c:477
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_OWN void * rz_list_pop(RZ_NONNULL RzList *list)
Removes and returns the last element of the list.
Definition: list.c:376
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:77
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_OWN void * rz_list_pop_head(RZ_NONNULL RzList *list)
Removes and returns the first element of the list.
Definition: list.c:401
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
RZ_API char * sdb_querys(Sdb *r, char *buf, size_t len, const char *_cmd)
Definition: query.c:164
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static size_t max_count
Definition: malloc.c:67
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode dup
Definition: sflib.h:68
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
#define ls_foreach(list, it, pos)
Definition: ls.h:31
@ RZ_ABS
RZ_API const char * rz_meta_get_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr)
Definition: meta.c:146
int args
Definition: mipsasm.c:18
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
RZ_API bool rz_analysis_op_fini(RzAnalysisOp *op)
Definition: op.c:37
RZ_API const char * rz_analysis_optype_to_string(int type)
Definition: op.c:310
RZ_API bool rz_analysis_op_nonlinear(int t)
Definition: op.c:177
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: op.c:96
RZ_API const char * rz_analysis_op_family_to_string(int id)
Definition: op.c:560
RZ_API bool rz_parse_filter(RzParse *p, ut64 addr, RzFlag *f, RzAnalysisHint *hint, char *data, char *str, int len, bool big_endian)
filter the opcode in data into str by following the flags and hints information
Definition: filter.c:592
RZ_API void rz_print_fill(RzPrint *p, const ut8 *arr, int size, ut64 addr, int step)
Definition: print.c:1346
#define chunksize
#define min(a, b)
Definition: qsort.h:83
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API const char * rz_reg_64_to_32(RzReg *reg, const char *rreg64)
Definition: reg.c:44
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
RZ_API bool rz_reg_set_value(RzReg *reg, RzRegItem *item, ut64 value)
Definition: rvalue.c:186
@ RZ_ANALYSIS_FCN_TYPE_SYM
Definition: rz_analysis.h:195
@ RZ_ANALYSIS_FCN_TYPE_FCN
Definition: rz_analysis.h:193
@ RZ_ANALYSIS_XREF_TYPE_NULL
Definition: rz_analysis.h:899
@ RZ_ANALYSIS_OP_FAMILY_SECURITY
Definition: rz_analysis.h:320
@ RZ_ANALYSIS_ESIL_OP_TYPE_UNKNOWN
Definition: rz_analysis.h:1178
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
@ RZ_ANALYSIS_OP_MASK_DISASM
Definition: rz_analysis.h:445
@ RZ_ANALYSIS_OP_MASK_BASIC
Definition: rz_analysis.h:440
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
@ RZ_ANALYSIS_OP_MASK_HINT
Definition: rz_analysis.h:443
#define RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE
Definition: rz_analysis.h:98
@ RZ_ANALYSIS_OP_TYPE_ICALL
Definition: rz_analysis.h:381
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_UJMP
Definition: rz_analysis.h:369
@ RZ_ANALYSIS_OP_TYPE_IJMP
Definition: rz_analysis.h:371
@ RZ_ANALYSIS_OP_TYPE_UCCALL
Definition: rz_analysis.h:384
@ RZ_ANALYSIS_OP_TYPE_SWI
Definition: rz_analysis.h:393
@ RZ_ANALYSIS_OP_TYPE_TRAP
Definition: rz_analysis.h:392
@ RZ_ANALYSIS_OP_TYPE_CCALL
Definition: rz_analysis.h:383
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_CRET
Definition: rz_analysis.h:386
@ RZ_ANALYSIS_OP_TYPE_IRJMP
Definition: rz_analysis.h:372
@ RZ_ANALYSIS_OP_TYPE_RJMP
Definition: rz_analysis.h:370
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_UCJMP
Definition: rz_analysis.h:377
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_NOP
Definition: rz_analysis.h:389
@ RZ_ANALYSIS_OP_TYPE_RCALL
Definition: rz_analysis.h:380
@ RZ_ANALYSIS_OP_TYPE_IRCALL
Definition: rz_analysis.h:382
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_io_fd(RZ_NONNULL void *iob, int fd)
Creates a new buffer wrapping a file descriptor accessed through RzIOBind.
Definition: buf.c:490
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_slice(RzBuffer *b, ut64 offset, ut64 size)
Creates a new buffer from a slice of another buffer.
Definition: buf.c:364
#define Color_RESET
Definition: rz_cons.h:617
#define Color_YELLOW
Definition: rz_cons.h:631
static void rz_write_le32(void *dest, ut32 val)
Definition: rz_endian.h:256
static void rz_write_le16(void *dest, ut16 val)
Definition: rz_endian.h:222
static void rz_write_le64(void *dest, ut64 val)
Definition: rz_endian.h:277
static void rz_write_le8(void *dest, ut8 val)
Definition: rz_endian.h:198
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
RZ_API int rz_hex_bin2str(const ut8 *in, int len, char *out)
Definition: hex.c:382
RZ_API ut64 rz_io_fd_size(RzIO *io, int fd)
Definition: io_fd.c:42
RZ_API bool rz_io_read_at(RzIO *io, ut64 addr, ut8 *buf, int len)
Definition: io.c:300
RZ_API ut64 rz_io_size(RzIO *io)
Definition: io.c:399
RZ_API RzIOMap * rz_io_map_get(RzIO *io, ut64 addr)
Definition: io_map.c:176
RZ_API RZ_BORROW RzPVector * rz_io_maps(RzIO *io)
Returns the pointer to vector containing maps list.
Definition: io_map.c:435
RZ_API bool rz_io_is_valid_offset(RzIO *io, ut64 offset, int hasperm)
Definition: ioutils.c:20
RZ_API int rz_io_fd_get_current(RzIO *io)
Definition: io_fd.c:135
static ut64 rz_itv_begin(RzInterval itv)
Definition: rz_itv.h:34
static ut64 rz_itv_end(RzInterval itv)
Definition: rz_itv.h:42
static bool rz_itv_overlap(RzInterval itv, RzInterval x)
Definition: rz_itv.h:64
static RzInterval rz_itv_intersect(RzInterval itv, RzInterval x)
Definition: rz_itv.h:76
static ut64 rz_itv_size(RzInterval itv)
Definition: rz_itv.h:38
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API RzList * rz_num_str_split_list(char *str)
Definition: unum.c:905
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_ki(PJ *j, const char *k, int d)
Definition: pj.c:149
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
RZ_API PJ * pj_kN(PJ *j, const char *k, st64 n)
Definition: pj.c:128
#define RZ_PRINT_FLAGS_COLOR
Definition: rz_print.h:15
@ RZ_REG_NAME_SN
Definition: rz_reg.h:70
@ RZ_REG_NAME_PC
Definition: rz_reg.h:43
RZ_API int rz_regex_match(const char *pattern, const char *flags, const char *text)
Definition: regcomp.c:142
#define RZ_SEARCH_KEYWORD_TYPE_STRING
Definition: rz_search.h:32
@ RZ_SEARCH_REGEXP
Definition: rz_search.h:18
@ RZ_SEARCH_STRING
Definition: rz_search.h:20
@ RZ_SEARCH_AES
Definition: rz_search.h:22
@ RZ_SEARCH_DELTAKEY
Definition: rz_search.h:24
@ RZ_SEARCH_KEYWORD
Definition: rz_search.h:17
@ RZ_SEARCH_PRIV_KEY
Definition: rz_search.h:23
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
RZ_API int rz_str_rwx(const char *str)
Definition: str.c:318
RZ_API char * rz_str_trim_dup(const char *str)
Definition: str_trim.c:78
RZ_API char * rz_str_utf16_encode(const char *s, int len)
Definition: str.c:2993
RZ_API const char * rz_str_trim_head_ro(const char *str)
Definition: str_trim.c:86
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
RZ_API char ** rz_str_argv(const char *str, int *_argc)
Definition: str.c:2509
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API int rz_str_unescape(char *buf)
Definition: str.c:1300
RZ_API int rz_str_ncasecmp(const char *dst, const char *orig, size_t n)
Definition: str.c:129
RZ_API void rz_str_argv_free(char **argv)
Definition: str.c:2633
#define IS_PRINTABLE(x)
Definition: rz_str_util.h:10
#define RZ_STRBUF_SAFEGET(sb)
Definition: rz_strbuf.h:18
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API ut64 rz_time_now_mono(void)
Returns the current time in microseconds, using the monotonic clock.
Definition: time.c:102
#define PFMT64d
Definition: rz_types.h:394
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_W
Definition: rz_types.h:94
#define RZ_MODE_RIZINCMD
Definition: rz_types.h:26
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_MODE_JSON
Definition: rz_types.h:29
#define PFMT64u
Definition: rz_types.h:395
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define PFMT32d
Definition: rz_types.h:408
#define RZ_EMPTY
Definition: rz_types_base.h:68
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define RZ_MAX(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
#define RZ_BETWEEN(x, y, z)
typedef RZ_ALIGNED(1) ut16 uut16
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
Definition: rz_vector.h:88
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
#define islower(c)
Definition: safe-ctype.h:135
#define tolower(c)
Definition: safe-ctype.h:149
#define isalpha(c)
Definition: safe-ctype.h:125
#define isdigit(c)
Definition: safe-ctype.h:131
#define isupper(c)
Definition: safe-ctype.h:143
RZ_API SdbList * sdb_foreach_list(Sdb *s, bool sorted)
Definition: sdb.c:630
RZ_API int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas)
Definition: sdb.c:329
static char * sdbkv_key(const SdbKv *kv)
Definition: sdbht.h:21
static char * sdbkv_value(const SdbKv *kv)
Definition: sdbht.h:25
RZ_API void rz_search_string_prepare_backward(RzSearch *s)
Definition: search.c:516
RZ_API int rz_search_update(RzSearch *s, ut64 from, const ut8 *buf, long len)
Definition: search.c:470
RZ_API void rz_search_set_callback(RzSearch *s, RzSearchCallback(callback), void *user)
Definition: search.c:463
RZ_API int rz_search_begin(RzSearch *s)
Definition: search.c:96
RZ_API void rz_search_kw_reset(RzSearch *s)
Definition: search.c:544
RZ_API int rz_search_set_string_limits(RzSearch *s, ut32 min, ut32 max)
Definition: search.c:64
RZ_API void rz_search_reset(RzSearch *s, int mode)
Definition: search.c:537
RZ_API void rz_search_pattern_size(RzSearch *s, int size)
Definition: search.c:459
RZ_API int rz_search_kw_add(RzSearch *s, RzSearchKeyword *kw)
Definition: search.c:506
RZ_API void rz_search_set_distance(RzSearch *s, int dist)
Definition: search.c:449
RZ_API bool rz_core_seek(RzCore *core, ut64 addr, bool rb)
Seek to addr.
Definition: seek.c:116
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
static int
Definition: sfsocketcall.h:114
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define a(i)
Definition: sha256.c:41
_W64 signed int intptr_t
const char * name
Definition: sparc-opc.c:1838
int instr_offset
Definition: cmd_search.c:172
Definition: gzappend.c:170
Definition: heap-inl.h:40
Definition: gzlog.c:289
Definition: ls.h:17
Definition: ls.h:22
Definition: engine.c:71
Definition: rz_pj.h:12
RzAnalysisEsilCallbacks cb
Definition: rz_analysis.h:1078
RzAnalysisOpFamily family
Definition: rz_analysis.h:823
RzTypeCond cond
Definition: rz_analysis.h:818
RzAnalysisXRefType type
Definition: rz_analysis.h:909
struct rz_analysis_plugin_t * cur
Definition: rz_analysis.h:586
struct rz_analysis_esil_t * esil
Definition: rz_analysis.h:584
RzSyscall * syscall
Definition: rz_analysis.h:570
RzIOBind iob
Definition: rz_analysis.h:574
RzStrBuf buf_asm
Definition: rz_asm.h:72
RzAsmTokenString * asm_toks
Tokenized asm string.
Definition: rz_asm.h:74
int bits
Definition: rz_asm.h:100
_RzAsmPlugin * cur
Definition: rz_asm.h:106
RzList * sections
Definition: rz_bin.h:267
char * name
Definition: rz_bin.h:509
ut64(* size)(RzBinFile *bin)
Definition: rz_bin.h:516
RZ_DEPRECATE RzBinFile * cur
never use this in new code! Get a file from the binfiles list or track it yourself.
Definition: rz_bin.h:330
int is_debugger
Definition: rz_bin.h:350
RzSearch * search
Definition: rz_core.h:331
RzBin * bin
Definition: rz_core.h:298
ut64 offset
Definition: rz_core.h:301
RzAsm * rasm
Definition: rz_core.h:323
RzAnalysis * analysis
Definition: rz_core.h:322
RzDebug * dbg
Definition: rz_core.h:329
RzIO * io
Definition: rz_core.h:313
RzNum * num
Definition: rz_core.h:316
RzParse * parser
Definition: rz_core.h:326
bool tmpseek
Definition: rz_core.h:308
Sdb * sdb
Definition: rz_core.h:365
ut8 * block
Definition: rz_core.h:305
RzFlag * flags
Definition: rz_core.h:330
bool in_search
Definition: rz_core.h:359
RzPrint * print
Definition: rz_core.h:327
RzHash * hash
Definition: rz_core.h:389
char * lastsearch
Definition: rz_core.h:370
RzCoreFile * file
Definition: rz_core.h:314
ut32 blocksize
Definition: rz_core.h:303
RzConfig * config
Definition: rz_core.h:300
RzList * maps
Definition: rz_debug.h:306
RzReg * reg
Definition: rz_debug.h:286
ut64 addr
Definition: rz_itv.h:15
ut64 size
Definition: rz_itv.h:16
int perm
Definition: rz_io.h:147
ut64 delta
Definition: rz_io.h:150
RzInterval itv
Definition: rz_io.h:149
Definition: rz_io.h:59
RzSkyline map_skyline
Definition: rz_io.h:74
struct rz_io_desc_t * desc
Definition: rz_io.h:60
int va
Definition: rz_io.h:63
struct rz_list_iter_t * n
Definition: rz_list.h:15
void * data
Definition: rz_list.h:14
RzListIter * head
Definition: rz_list.h:19
ut64 value
Definition: rz_num.h:63
int big_endian
Definition: rz_print.h:124
int flags
Definition: rz_print.h:137
bool overlap
Definition: rz_search.h:68
char bckwrds
Definition: rz_search.h:74
ut64 maxhits
Definition: rz_search.h:64
RzList * kws
Definition: rz_search.h:72
int inverse
Definition: rz_search.h:67
ut64 nhits
Definition: rz_search.h:63
RzInterval itv
Definition: rz_skyline.h:8
RzVector v
Definition: rz_skyline.h:13
Definition: sdbht.h:14
Definition: sdb.h:88
char * name
Definition: sdb.h:89
Sdb * sdb
Definition: sdb.h:91
Definition: sdb.h:63
SdbList * ns
Definition: sdb.h:82
const char * mode
Definition: cmd_search.c:162
const char * cmd_hit
Definition: cmd_search.c:163
RzList * boundaries
Definition: cmd_search.c:161
Definition: z80asm.h:140
int pos
Definition: main.c:11
bool valid
Definition: core.c:77
ut64 maxlen
Definition: core.c:76
ut64 buflen
Definition: core.c:76
uint64_t blocks
Definition: list.c:104
RZ_API void rz_syscall_item_free(RzSyscallItem *si)
Definition: syscall.c:325
RZ_API RzSyscallItem * rz_syscall_get(RzSyscall *s, int num, int swi)
Definition: syscall.c:345
RZ_API RzList * rz_syscall_list(RzSyscall *s)
Definition: syscall.c:415
#define bool
Definition: sysdefs.h:146
#define fail(test)
Definition: tests.h:29
void error(const char *msg)
Definition: untgz.c:593
RZ_API bool rz_core_prevop_addr(RzCore *core, ut64 start_addr, int numinstrs, ut64 *prev_addr)
Definition: visual.c:1173
RZ_API ut64 rz_core_prevop_addr_force(RzCore *core, ut64 start_addr, int numinstrs)
Definition: visual.c:1195
static st64 delta
Definition: vmenus.c:2425
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
RZ_API RzList * rz_analysis_xrefs_get_to(RzAnalysis *analysis, ut64 addr)
Definition: xrefs.c:173
RZ_API const char * rz_analysis_xrefs_type_tostring(RzAnalysisXRefType type)
Definition: xrefs.c:216
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int sp
Definition: z80asm.c:91
static int addr
Definition: z80asm.c:58
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
static int add(char *argv[])
Definition: ziptool.c:84
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
Definition: crc32.c:1063