Rizin
unix-like reverse engineering framework and cli tools
cmd_search_rop.c File Reference
#include <stddef.h>
#include "rz_core.h"
#include "rz_io.h"
#include "rz_list.h"
#include "rz_types_base.h"

Go to the source code of this file.

Macros

#define FREE_ROP
 

Functions

static RzListparse_list (const char *str)
 
static RzListget_constants (const char *str)
 
static bool isFlag (RzRegItem *reg)
 
static bool simulate_op (const char *op, ut64 src1, ut64 src2, ut64 old_src1, ut64 old_src2, ut64 *result, int size)
 
static void fillRegisterValues (RzCore *core)
 
static void esil_split_flg (char *esil_str, char **esil_main, char **esil_flg)
 
static char * rop_classify_constant (RzCore *core, RzList *ropList)
 
static char * rop_classify_mov (RzCore *core, RzList *ropList)
 
static char * rop_classify_arithmetic (RzCore *core, RzList *ropList)
 
static char * rop_classify_arithmetic_const (RzCore *core, RzList *ropList)
 
static int rop_classify_nops (RzCore *core, RzList *ropList)
 
static void rop_classify (RzCore *core, Sdb *db, RzList *ropList, const char *key, unsigned int size)
 

Macro Definition Documentation

◆ FREE_ROP

#define FREE_ROP
Value:
{ \
RZ_FREE(out); \
RZ_FREE(esil_flg); \
RZ_FREE(esil_main); \
rz_list_free(ops_list); \
ops_list = NULL; \
rz_list_free(flg_read); \
flg_read = NULL; \
rz_list_free(flg_write); \
flg_write = NULL; \
rz_list_free(reg_read); \
reg_read = NULL; \
rz_list_free(reg_write); \
reg_write = NULL; \
rz_list_free(mem_read); \
mem_read = NULL; \
rz_list_free(mem_write); \
mem_write = NULL; \
}
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static int mem_read(struct mem_file *fh, void *buffer, int bytes)
Definition: cabd_memory.c:59
static int mem_write(struct mem_file *fh, void *buffer, int bytes)
Definition: cabd_memory.c:68
#define NULL
Definition: cris-opc.c:27

Definition at line 193 of file cmd_search_rop.c.

Function Documentation

◆ esil_split_flg()

static void esil_split_flg ( char *  esil_str,
char **  esil_main,
char **  esil_flg 
)
static

Definition at line 176 of file cmd_search_rop.c.

176  {
177  char *split = strstr(esil_str, "f,=");
178  const int kCommaHits = 2;
179  int hits = 0;
180 
181  if (split) {
182  while (hits != kCommaHits) {
183  --split;
184  if (*split == ',') {
185  hits++;
186  }
187  }
188  *esil_flg = strdup(++split);
189  *esil_main = rz_str_ndup(esil_str, strlen(esil_str) - strlen(*esil_flg) - 1);
190  }
191 }
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")
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

References rz_str_ndup(), and strdup().

Referenced by rop_classify_arithmetic(), rop_classify_arithmetic_const(), rop_classify_constant(), and rop_classify_mov().

◆ fillRegisterValues()

static void fillRegisterValues ( RzCore core)
static

Definition at line 156 of file cmd_search_rop.c.

156  {
157  RzListIter *iter_reg;
158  RzRegItem *reg_item;
159  int nr = 10;
160 
162  if (!regs) {
163  return;
164  }
165  rz_list_foreach (regs, iter_reg, reg_item) {
166  rz_reg_arena_pop(core->analysis->reg);
167  rz_reg_set_value(core->analysis->reg, reg_item, nr);
169  nr += 3;
170  }
171 }
static char * regs[]
Definition: analysis_sh.c:203
RZ_API int rz_reg_arena_push(RzReg *reg)
Definition: arena.c:236
RZ_API void rz_reg_arena_pop(RzReg *reg)
Definition: arena.c:216
RZ_API const RzList * rz_reg_get_list(RzReg *reg, int type)
Definition: reg.c:389
RZ_API bool rz_reg_set_value(RzReg *reg, RzRegItem *item, ut64 value)
Definition: rvalue.c:186
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
RzAnalysis * analysis
Definition: rz_core.h:322

References rz_core_t::analysis, rz_analysis_t::reg, regs, rz_reg_arena_pop(), rz_reg_arena_push(), rz_reg_get_list(), rz_reg_set_value(), and RZ_REG_TYPE_GPR.

Referenced by rop_classify_arithmetic(), rop_classify_arithmetic_const(), rop_classify_constant(), rop_classify_mov(), and rop_classify_nops().

◆ get_constants()

static RzList* get_constants ( const char *  str)
static

Definition at line 27 of file cmd_search_rop.c.

27  {
28  RzList *list;
29  char *p, *data;
30  if (!str) {
31  return NULL;
32  }
33 
34  data = strdup(str);
36  p = strtok(data, ",");
37  while (p) {
38  if (strtol(p, NULL, 0)) {
39  rz_list_append(list, (void *)strdup(p));
40  }
41  p = strtok(NULL, ",");
42  }
43  free(data);
44  return list;
45 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
void * p
Definition: libc.cpp:67
static void list(RzEgg *egg)
Definition: rz-gg.c:52
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_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

References free(), list(), NULL, p, rz_list_append(), rz_list_newf(), cmd_descs_generate::str, and strdup().

Referenced by rop_classify_arithmetic_const(), and rop_classify_constant().

◆ isFlag()

static bool isFlag ( RzRegItem reg)
static

Definition at line 47 of file cmd_search_rop.c.

47  {
48  const char *type = rz_reg_get_type(reg->type);
49 
50  if (!strcmp(type, "flg"))
51  return true;
52  return false;
53 }
#define reg(n)
int type
Definition: mipsasm.c:17
RZ_API const char * rz_reg_get_type(int idx)
Definition: reg.c:68

References reg, rz_reg_get_type(), and type.

Referenced by rop_classify_arithmetic(), rop_classify_arithmetic_const(), and rop_classify_mov().

◆ parse_list()

static RzList* parse_list ( const char *  str)
static

Definition at line 11 of file cmd_search_rop.c.

11  {
12  char *line, *data, *str_n;
13 
14  if (!str) {
15  return NULL;
16  }
17  str_n = strdup(str);
18  line = strtok(str_n, "\n");
19  data = strchr(line, '=');
20 
21  RzList *list = rz_str_split_duplist(data + 1, ",", false);
22 
23  free(str_n);
24  return list;
25 }
line
Definition: setup.py:34
RZ_API RzList * rz_str_split_duplist(const char *str, const char *c, bool trim)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3464

References free(), setup::line, list(), NULL, rz_str_split_duplist(), cmd_descs_generate::str, and strdup().

Referenced by rop_classify_arithmetic(), rop_classify_arithmetic_const(), rop_classify_constant(), and rop_classify_mov().

◆ rop_classify()

static void rop_classify ( RzCore core,
Sdb db,
RzList ropList,
const char *  key,
unsigned int  size 
)
static

Definition at line 676 of file cmd_search_rop.c.

676  {
677  int nop = 0;
678  rop_classify_nops(core, ropList);
679  char *mov, *ct, *arithm, *arithm_ct, *str;
680  Sdb *db_nop = sdb_ns(db, "nop", true);
681  Sdb *db_mov = sdb_ns(db, "mov", true);
682  Sdb *db_ct = sdb_ns(db, "const", true);
683  Sdb *db_aritm = sdb_ns(db, "arithm", true);
684  Sdb *db_aritm_ct = sdb_ns(db, "arithm_ct", true);
685 
686  if (!db_nop || !db_mov || !db_ct || !db_aritm || !db_aritm_ct) {
687  eprintf("Error: Could not create SDB 'rop' sub-namespaces\n");
688  return;
689  }
690  nop = rop_classify_nops(core, ropList);
691  mov = rop_classify_mov(core, ropList);
692  ct = rop_classify_constant(core, ropList);
693  arithm = rop_classify_arithmetic(core, ropList);
694  arithm_ct = rop_classify_arithmetic_const(core, ropList);
695  str = rz_str_newf("0x%u", size);
696 
697  if (nop == 1) {
698  char *str_nop = rz_str_newf("%s NOP", str);
699  sdb_set(db_nop, key, str_nop, 0);
700  free(str_nop);
701  } else {
702  if (mov) {
703  char *str_mov = rz_str_newf("%s MOV { %s }", str, mov);
704  sdb_set(db_mov, key, str_mov, 0);
705  free(str_mov);
706  free(mov);
707  }
708  if (ct) {
709  char *str_ct = rz_str_newf("%s LOAD_CONST { %s }", str, ct);
710  sdb_set(db_ct, key, str_ct, 0);
711  free(str_ct);
712  free(ct);
713  }
714  if (arithm) {
715  char *str_arithm = rz_str_newf("%s ARITHMETIC { %s }", str, arithm);
716  sdb_set(db_aritm, key, str_arithm, 0);
717  free(str_arithm);
718  free(arithm);
719  }
720  if (arithm_ct) {
721  char *str_arithm_ct = rz_str_newf("%s ARITHMETIC_CONST { %s }", str, arithm_ct);
722  sdb_set(db_aritm_ct, key, str_arithm_ct, 0);
723  free(str_arithm_ct);
724  free(arithm_ct);
725  }
726  }
727 
728  free(str);
729 }
static RzILOpEffect * mov(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:351
static char * rop_classify_mov(RzCore *core, RzList *ropList)
static char * rop_classify_arithmetic(RzCore *core, RzList *ropList)
static char * rop_classify_constant(RzCore *core, RzList *ropList)
static char * rop_classify_arithmetic_const(RzCore *core, RzList *ropList)
static int rop_classify_nops(RzCore *core, RzList *ropList)
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
voidpf void uLong size
Definition: ioapi.h:138
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
Definition: sdb.h:63

References eprintf, free(), key, mov(), rop_classify_arithmetic(), rop_classify_arithmetic_const(), rop_classify_constant(), rop_classify_mov(), rop_classify_nops(), rz_str_newf(), sdb_ns(), sdb_set(), and cmd_descs_generate::str.

Referenced by print_rop().

◆ rop_classify_arithmetic()

static char* rop_classify_arithmetic ( RzCore core,
RzList ropList 
)
static

Definition at line 394 of file cmd_search_rop.c.

394  {
395  char *esil_str, *op;
396  char *arithmetic = NULL, *esil_flg = NULL, *esil_main = NULL,
397  *out = NULL;
398  RzListIter *iter_src1, *iter_src2, *iter_r, *iter_dst, *iter_ops;
399  RzRegItem *item_src1, *item_src2, *item_dst;
400  const RzList *head;
401  RzList *ops_list = NULL, *flg_read = NULL, *flg_write = NULL,
402  *reg_read = NULL, *reg_write = NULL, *mem_read = NULL,
403  *mem_write = NULL;
404  const bool romem = rz_config_get_i(core->config, "esil.romem");
405  const bool stats = rz_config_get_i(core->config, "esil.stats");
406  ut64 *op_result = RZ_NEW0(ut64);
407  ut64 *op_result_r = RZ_NEW0(ut64);
408 
409  if (!romem || !stats) {
410  // eprintf ("Error: esil.romem and esil.stats must be set TRUE");
411  free(op_result);
412  free(op_result_r);
413  return NULL;
414  }
415 
416  rz_list_foreach (ropList, iter_r, esil_str) {
417  // init regs with known values
418  fillRegisterValues(core);
420  if (!head) {
421  goto out_error;
422  }
423  esil_split_flg(esil_str, &esil_main, &esil_flg);
424  if (esil_main) {
425  cmd_analysis_esil(core, esil_main);
426  } else {
427  cmd_analysis_esil(core, esil_str);
428  }
429  out = sdb_querys(core->analysis->esil->stats, NULL, 0, "*");
430  // rz_cons_println (out);
431  if (!out) {
432  goto continue_error;
433  }
434  ops_list = parse_list(strstr(out, "ops.list"));
435  flg_read = parse_list(strstr(out, "flg.read"));
436  flg_write = parse_list(strstr(out, "flg.write"));
437  reg_read = parse_list(strstr(out, "reg.read"));
438  reg_write = parse_list(strstr(out, "reg.write"));
439  mem_read = parse_list(strstr(out, "mem.read"));
440  mem_write = parse_list(strstr(out, "mem.write"));
441 
442  rz_list_foreach (ops_list, iter_ops, op) {
443  rz_list_foreach (head, iter_src1, item_src1) {
444  ut64 value_src1, diff_src1;
445 
446  value_src1 = rz_reg_get_value(core->analysis->reg, item_src1);
447  rz_reg_arena_swap(core->analysis->reg, false);
448  diff_src1 = rz_reg_get_value(core->analysis->reg, item_src1);
449  rz_reg_arena_swap(core->analysis->reg, false);
450  if (!rz_list_find(reg_read, item_src1->name,
451  (RzListComparator)strcmp)) {
452  continue;
453  }
454 
455  rz_list_foreach (head, iter_src2, item_src2) {
456  ut64 value_src2, diff_src2;
457  value_src2 = rz_reg_get_value(core->analysis->reg, item_src2);
458  rz_reg_arena_swap(core->analysis->reg, false);
459  diff_src2 = rz_reg_get_value(core->analysis->reg, item_src2);
460 
461  if (!rz_list_find(reg_read, item_src2->name,
462  (RzListComparator)strcmp)) {
463  continue;
464  }
465  // TODO check condition
466  if (iter_src1 == iter_src2) {
467  continue;
468  }
469 
470  rz_list_foreach (head, iter_dst, item_dst) {
471  ut64 value_dst;
472  bool redundant = false, simulate, simulate_r;
473 
474  value_dst = rz_reg_get_value(core->analysis->reg, item_dst);
475  rz_reg_arena_swap(core->analysis->reg, false);
476  if (!rz_list_find(reg_write, item_dst->name,
477  (RzListComparator)strcmp)) {
478  continue;
479  }
480  // don't check flags for arithmetic
481  if (isFlag(item_dst)) {
482  continue;
483  }
484  simulate = simulate_op(op, value_src1, value_src2, diff_src1, diff_src2, op_result, item_dst->size);
485  simulate_r = simulate_op(op, value_src2, value_src1, diff_src2, diff_src1, op_result_r, item_dst->size);
486  if (/*value_src1 != 0 && value_src2 != 0 && */ simulate && value_dst == *op_result) {
487  // rz_cons_println ("Debug: FOUND ONE !");
488  char *tmp = rz_str_newf("%s <-- %s %s %s;", item_dst->name, item_src1->name, op, item_src2->name);
489  if (arithmetic && !strstr(arithmetic, tmp)) {
491  } else if (!arithmetic) {
493  }
494  free(tmp);
495  } else if (!redundant /*&& value_src1 != 0 && value_src2 != 0*/ && simulate_r && value_dst == *op_result_r) {
496  // rz_cons_println ("Debug: FOUND ONE reversed!");
497  char *tmp = rz_str_newf("%s <-- %s %s %s;", item_dst->name, item_src2->name, op, item_src1->name);
498  if (arithmetic && !strstr(arithmetic, tmp)) {
500  } else if (!arithmetic) {
502  }
503  free(tmp);
504  }
505  }
506  }
507  }
508  }
509  continue_error:
510  FREE_ROP;
511  }
512  free(op_result);
513  free(op_result_r);
514  return arithmetic;
515 out_error:
516  FREE_ROP;
517  free(op_result);
518  free(op_result_r);
519  return NULL;
520 }
ut8 op
Definition: 6502dis.c:13
RZ_API void rz_reg_arena_swap(RzReg *reg, int copy)
Definition: arena.c:196
static ut32 arithmetic(ArmOp *op, int k)
Definition: armass64.c:933
static void cmd_analysis_esil(RzCore *core, const char *input)
#define FREE_ROP
static bool isFlag(RzRegItem *reg)
static void fillRegisterValues(RzCore *core)
static void esil_split_flg(char *esil_str, char **esil_main, char **esil_flg)
static bool simulate_op(const char *op, ut64 src1, ut64 src2, ut64 old_src1, ut64 old_src2, ut64 *result, int size)
static RzList * parse_list(const char *str)
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
RZ_API char * sdb_querys(Sdb *r, char *buf, size_t len, const char *_cmd)
Definition: query.c:164
RZ_API ut64 rz_reg_get_value(RzReg *reg, RzRegItem *item)
Definition: rvalue.c:114
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
#define RZ_NEW0(x)
Definition: rz_types.h:284
struct rz_analysis_esil_t * esil
Definition: rz_analysis.h:584
RzConfig * config
Definition: rz_core.h:300
int size
in bits> 8,16,32,64 ... 128/256
Definition: rz_reg.h:120
char * name
Definition: rz_reg.h:118
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References rz_core_t::analysis, arithmetic(), cmd_analysis_esil(), rz_core_t::config, rz_analysis_t::esil, esil_split_flg(), fillRegisterValues(), free(), FREE_ROP, test-lz4-versions::head, isFlag(), mem_read(), mem_write(), rz_reg_item_t::name, NULL, op, out, parse_list(), rz_analysis_t::reg, rz_config_get_i(), rz_list_find(), RZ_NEW0, rz_reg_arena_swap(), rz_reg_get_list(), rz_reg_get_value(), RZ_REG_TYPE_GPR, rz_str_append(), rz_str_newf(), sdb_querys(), simulate_op(), rz_reg_item_t::size, rz_analysis_esil_t::stats, autogen_x86imm::tmp, and ut64().

Referenced by rop_classify().

◆ rop_classify_arithmetic_const()

static char* rop_classify_arithmetic_const ( RzCore core,
RzList ropList 
)
static

Definition at line 522 of file cmd_search_rop.c.

522  {
523  char *esil_str, *op, *constant;
524  char *arithmetic = NULL, *esil_flg = NULL, *esil_main = NULL;
525  RzListIter *iter_src1, *iter_r, *iter_dst, *iter_ops, *iter_const;
526  RzRegItem *item_src1, *item_dst;
527  const RzList *head;
528  RzList *constants;
529  RzList *ops_list = NULL, *flg_read = NULL, *flg_write = NULL, *reg_read = NULL,
530  *reg_write = NULL, *mem_read = NULL, *mem_write = NULL;
531  const bool romem = rz_config_get_i(core->config, "esil.romem");
532  const bool stats = rz_config_get_i(core->config, "esil.stats");
533  ut64 *op_result = RZ_NEW0(ut64);
534  ut64 *op_result_r = RZ_NEW0(ut64);
535 
536  if (!romem || !stats) {
537  // eprintf ("Error: esil.romem and esil.stats must be set TRUE");
538  RZ_FREE(op_result);
539  RZ_FREE(op_result_r);
540  return NULL;
541  }
542 
543  rz_list_foreach (ropList, iter_r, esil_str) {
544  constants = get_constants(esil_str);
545  // if there are no constants in the instruction continue
546  if (rz_list_empty(constants)) {
547  continue;
548  }
549  // init regs with known values
550  fillRegisterValues(core);
552  if (!head) {
553  arithmetic = NULL;
554  continue;
555  }
556  esil_split_flg(esil_str, &esil_main, &esil_flg);
557  if (esil_main) {
558  cmd_analysis_esil(core, esil_main);
559  } else {
560  cmd_analysis_esil(core, esil_str);
561  }
562  char *out = sdb_querys(core->analysis->esil->stats, NULL, 0, "*");
563  // rz_cons_println (out);
564  if (out) {
565  ops_list = parse_list(strstr(out, "ops.list"));
566  flg_read = parse_list(strstr(out, "flg.read"));
567  flg_write = parse_list(strstr(out, "flg.write"));
568  reg_read = parse_list(strstr(out, "reg.read"));
569  reg_write = parse_list(strstr(out, "reg.write"));
570  mem_read = parse_list(strstr(out, "mem.read"));
571  mem_write = parse_list(strstr(out, "mem.write"));
572  } else {
573  RZ_FREE(op_result);
574  RZ_FREE(op_result_r);
575  goto continue_error;
576  }
577 
578  rz_list_foreach (ops_list, iter_ops, op) {
579  rz_list_foreach (head, iter_src1, item_src1) {
580  ut64 value_src1, diff_src1;
581  value_src1 = rz_reg_get_value(core->analysis->reg, item_src1);
582  rz_reg_arena_swap(core->analysis->reg, false);
583  diff_src1 = rz_reg_get_value(core->analysis->reg, item_src1);
584  rz_reg_arena_swap(core->analysis->reg, false);
585 
586  if (!rz_list_find(reg_read, item_src1->name,
587  (RzListComparator)strcmp)) {
588  continue;
589  }
590  rz_list_foreach (head, iter_dst, item_dst) {
591  ut64 value_dst, diff_dst;
592  bool redundant = false, simulate, simulate_r;
593  value_dst = rz_reg_get_value(core->analysis->reg, item_dst);
594  rz_reg_arena_swap(core->analysis->reg, false);
595  diff_dst = rz_reg_get_value(core->analysis->reg, item_dst);
596  rz_reg_arena_swap(core->analysis->reg, false);
597  if (!rz_list_find(reg_write, item_dst->name,
598  (RzListComparator)strcmp)) {
599  continue;
600  }
601  // don't check flags for arithmetic
602  if (isFlag(item_dst)) {
603  continue;
604  }
605  if (value_dst != diff_dst) {
606  rz_list_foreach (constants, iter_const, constant) {
607  ut64 value_ct = rz_num_get(NULL, constant);
608  simulate = simulate_op(op, value_src1, value_ct,
609  diff_src1, value_ct, op_result,
610  item_dst->size);
611  simulate_r = simulate_op(op, value_ct, value_src1,
612  value_ct, diff_src1, op_result_r,
613  item_dst->size);
614  if (simulate && op_result && value_dst == *op_result) {
615  char *tmp = rz_str_newf("%s <-- %s %s %s;", item_dst->name, item_src1->name, op, constant);
616  if (arithmetic && !strstr(arithmetic, tmp)) {
618  } else if (!arithmetic) {
620  }
621  free(tmp);
622  redundant = true;
623  } else if (!redundant && simulate_r && value_dst == *op_result_r) {
624  char *tmp = rz_str_newf("%s <-- %s %s %s;", item_dst->name, constant, op, item_src1->name);
625  if (arithmetic && !strstr(arithmetic, tmp)) {
627  } else if (!arithmetic) {
629  }
630  free(tmp);
631  }
632  }
633  }
634  }
635  }
636  }
637  continue_error:
638  FREE_ROP;
639  rz_list_free(constants);
640  }
641  free(op_result);
642  free(op_result_r);
643  return arithmetic;
644 }
static RzList * get_constants(const char *str)
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
#define RZ_FREE(x)
Definition: rz_types.h:369

References rz_core_t::analysis, arithmetic(), cmd_analysis_esil(), rz_core_t::config, rz_analysis_t::esil, esil_split_flg(), fillRegisterValues(), free(), FREE_ROP, get_constants(), test-lz4-versions::head, isFlag(), mem_read(), mem_write(), rz_reg_item_t::name, NULL, op, out, parse_list(), rz_analysis_t::reg, rz_config_get_i(), RZ_FREE, rz_list_find(), rz_list_free(), RZ_NEW0, rz_num_get(), rz_reg_arena_swap(), rz_reg_get_list(), rz_reg_get_value(), RZ_REG_TYPE_GPR, rz_str_append(), rz_str_newf(), sdb_querys(), simulate_op(), rz_reg_item_t::size, rz_analysis_esil_t::stats, autogen_x86imm::tmp, and ut64().

Referenced by rop_classify().

◆ rop_classify_constant()

static char* rop_classify_constant ( RzCore core,
RzList ropList 
)
static

Definition at line 214 of file cmd_search_rop.c.

214  {
215  char *esil_str, *constant;
216  char *ct = NULL, *esil_main = NULL, *esil_flg = NULL, *out = NULL;
217  RzListIter *iter_r, *iter_dst, *iter_const;
218  RzRegItem *item_dst;
219  const RzList *head;
220  RzList *constants;
221  RzList *ops_list = NULL, *flg_read = NULL, *flg_write = NULL,
222  *reg_read = NULL, *reg_write = NULL, *mem_read = NULL,
223  *mem_write = NULL;
224  const bool romem = rz_config_get_i(core->config, "esil.romem");
225  const bool stats = rz_config_get_i(core->config, "esil.stats");
226 
227  if (!romem || !stats) {
228  // eprintf ("Error: esil.romem and esil.stats must be set TRUE");
229  return NULL;
230  }
231 
232  rz_list_foreach (ropList, iter_r, esil_str) {
233  constants = get_constants(esil_str);
234  // if there are no constants in the instruction continue
235  if (rz_list_empty(constants)) {
236  continue;
237  }
238  // init regs with known values
239  fillRegisterValues(core);
241  if (!head) {
242  ct = NULL;
243  goto continue_error;
244  }
245  esil_split_flg(esil_str, &esil_main, &esil_flg);
246  cmd_analysis_esil(core, esil_main ? esil_main : esil_str);
247  out = sdb_querys(core->analysis->esil->stats, NULL, 0, "*");
248  if (!out) {
249  goto continue_error;
250  }
251  ops_list = parse_list(strstr(out, "ops.list"));
252  flg_read = parse_list(strstr(out, "flg.read"));
253  flg_write = parse_list(strstr(out, "flg.write"));
254  reg_read = parse_list(strstr(out, "reg.read"));
255  reg_write = parse_list(strstr(out, "reg.write"));
256  mem_read = parse_list(strstr(out, "mem.read"));
257  mem_write = parse_list(strstr(out, "mem.write"));
258  if (!rz_list_find(ops_list, "=", (RzListComparator)strcmp)) {
259  goto continue_error;
260  }
262  if (!head) {
263  goto out_error;
264  }
265  rz_list_foreach (head, iter_dst, item_dst) {
266  ut64 diff_dst, value_dst;
267  if (!rz_list_find(reg_write, item_dst->name,
268  (RzListComparator)strcmp)) {
269  continue;
270  }
271 
272  value_dst = rz_reg_get_value(core->analysis->reg, item_dst);
273  rz_reg_arena_swap(core->analysis->reg, false);
274  diff_dst = rz_reg_get_value(core->analysis->reg, item_dst);
275  rz_reg_arena_swap(core->analysis->reg, false);
276  // restore initial value
277  rz_reg_set_value(core->analysis->reg, item_dst, diff_dst);
278 
279  if (value_dst != diff_dst) {
280  rz_list_foreach (constants, iter_const, constant) {
281  if (value_dst == rz_num_get(NULL, constant)) {
282  ct = rz_str_appendf(ct, "%s <-- 0x%" PFMT64x ";", item_dst->name, value_dst);
283  }
284  }
285  }
286  }
287  continue_error:
288  // coverity may complain here but as long as the pointer is set back to
289  // NULL is safe that is why is used RZ_FREE
290  FREE_ROP;
291  rz_list_free(constants);
292  }
293  return ct;
294 out_error:
295  FREE_ROP;
296  rz_list_free(constants);
297  return NULL;
298 }
RZ_API char * rz_str_appendf(char *ptr, const char *fmt,...) RZ_PRINTF_CHECK(2
#define PFMT64x
Definition: rz_types.h:393

References rz_core_t::analysis, cmd_analysis_esil(), rz_core_t::config, rz_analysis_t::esil, esil_split_flg(), fillRegisterValues(), FREE_ROP, get_constants(), test-lz4-versions::head, mem_read(), mem_write(), rz_reg_item_t::name, NULL, out, parse_list(), PFMT64x, rz_analysis_t::reg, rz_config_get_i(), rz_list_find(), rz_list_free(), rz_num_get(), rz_reg_arena_swap(), rz_reg_get_list(), rz_reg_get_value(), rz_reg_set_value(), RZ_REG_TYPE_GPR, rz_str_appendf(), sdb_querys(), rz_analysis_esil_t::stats, and ut64().

Referenced by rop_classify().

◆ rop_classify_mov()

static char* rop_classify_mov ( RzCore core,
RzList ropList 
)
static

Definition at line 300 of file cmd_search_rop.c.

300  {
301  char *esil_str;
302  char *mov = NULL, *esil_main = NULL, *esil_flg = NULL, *out = NULL;
303  RzListIter *iter_src, *iter_r, *iter_dst;
304  RzRegItem *item_src, *item_dst;
305  const RzList *head;
306  RzList *ops_list = NULL, *flg_read = NULL, *flg_write = NULL,
307  *reg_read = NULL, *reg_write = NULL, *mem_read = NULL,
308  *mem_write = NULL;
309  const bool romem = rz_config_get_i(core->config, "esil.romem");
310  const bool stats = rz_config_get_i(core->config, "esil.stats");
311 
312  if (!romem || !stats) {
313  // eprintf ("Error: esil.romem and esil.stats must be set TRUE");
314  return NULL;
315  }
316 
317  rz_list_foreach (ropList, iter_r, esil_str) {
318  // init regs with known values
319  fillRegisterValues(core);
321  if (!head) {
322  goto out_error;
323  }
324  esil_split_flg(esil_str, &esil_main, &esil_flg);
325  cmd_analysis_esil(core, esil_main ? esil_main : esil_str);
326  out = sdb_querys(core->analysis->esil->stats, NULL, 0, "*");
327  if (out) {
328  ops_list = parse_list(strstr(out, "ops.list"));
329  flg_read = parse_list(strstr(out, "flg.read"));
330  flg_write = parse_list(strstr(out, "flg.write"));
331  reg_read = parse_list(strstr(out, "reg.read"));
332  reg_write = parse_list(strstr(out, "reg.write"));
333  mem_read = parse_list(strstr(out, "mem.read"));
334  mem_write = parse_list(strstr(out, "mem.write"));
335  } else {
336  goto continue_error;
337  }
338 
339  if (!rz_list_find(ops_list, "=", (RzListComparator)strcmp)) {
340  goto continue_error;
341  }
342 
344  if (!head) {
345  goto out_error;
346  }
347  rz_list_foreach (head, iter_dst, item_dst) {
348  ut64 diff_dst, value_dst;
349  if (!rz_list_find(reg_write, item_dst->name,
350  (RzListComparator)strcmp)) {
351  continue;
352  }
353 
354  // you never mov into flags
355  if (isFlag(item_dst)) {
356  continue;
357  }
358 
359  value_dst = rz_reg_get_value(core->analysis->reg, item_dst);
360  rz_reg_arena_swap(core->analysis->reg, false);
361  diff_dst = rz_reg_get_value(core->analysis->reg, item_dst);
362  rz_reg_arena_swap(core->analysis->reg, false);
363  rz_list_foreach (head, iter_src, item_src) {
364  ut64 diff_src, value_src;
365  if (!rz_list_find(reg_read, item_src->name,
366  (RzListComparator)strcmp)) {
367  continue;
368  }
369  // you never mov from flags
370  if (item_src == item_dst || isFlag(item_src)) {
371  continue;
372  }
373  value_src = rz_reg_get_value(core->analysis->reg, item_src);
374  rz_reg_arena_swap(core->analysis->reg, false);
375  diff_src = rz_reg_get_value(core->analysis->reg, item_src);
376  rz_reg_arena_swap(core->analysis->reg, false);
377  // restore initial value
378  rz_reg_set_value(core->analysis->reg, item_src, diff_src);
379  if (value_dst == value_src && value_dst != diff_dst) {
380  mov = rz_str_appendf(mov, "%s <-- %s;",
381  item_dst->name, item_src->name);
382  }
383  }
384  }
385  continue_error:
386  FREE_ROP;
387  }
388  return mov;
389 out_error:
390  FREE_ROP;
391  return NULL;
392 }

References rz_core_t::analysis, cmd_analysis_esil(), rz_core_t::config, rz_analysis_t::esil, esil_split_flg(), fillRegisterValues(), FREE_ROP, test-lz4-versions::head, isFlag(), mem_read(), mem_write(), mov(), rz_reg_item_t::name, NULL, out, parse_list(), rz_analysis_t::reg, rz_config_get_i(), rz_list_find(), rz_reg_arena_swap(), rz_reg_get_list(), rz_reg_get_value(), rz_reg_set_value(), RZ_REG_TYPE_GPR, rz_str_appendf(), sdb_querys(), rz_analysis_esil_t::stats, and ut64().

Referenced by rop_classify().

◆ rop_classify_nops()

static int rop_classify_nops ( RzCore core,
RzList ropList 
)
static

Definition at line 646 of file cmd_search_rop.c.

646  {
647  char *esil_str;
648  int changes = 1;
649  RzListIter *iter_r;
650  const bool romem = rz_config_get_i(core->config, "esil.romem");
651  const bool stats = rz_config_get_i(core->config, "esil.stats");
652 
653  if (!romem || !stats) {
654  // eprintf ("Error: esil.romem and esil.stats must be set TRUE\n");
655  return -2;
656  }
657 
658  rz_list_foreach (ropList, iter_r, esil_str) {
659  fillRegisterValues(core);
660 
661  // rz_cons_printf ("Emulating nop:%s\n", esil_str);
662  cmd_analysis_esil(core, esil_str);
663  char *out = sdb_querys(core->analysis->esil->stats, NULL, 0, "*");
664  // rz_cons_println (out);
665  if (out) {
666  free(out);
667  return 0;
668  }
669  // directly say NOP
670  continue;
671  }
672 
673  return changes;
674 }

References rz_core_t::analysis, cmd_analysis_esil(), rz_core_t::config, rz_analysis_t::esil, fillRegisterValues(), free(), NULL, out, rz_config_get_i(), sdb_querys(), and rz_analysis_esil_t::stats.

Referenced by rop_classify().

◆ simulate_op()

static bool simulate_op ( const char *  op,
ut64  src1,
ut64  src2,
ut64  old_src1,
ut64  old_src2,
ut64 result,
int  size 
)
static

Definition at line 56 of file cmd_search_rop.c.

56  {
57  ut64 limit;
58  if (size == 64) {
59  limit = UT64_MAX;
60  } else {
61  limit = 1ULL << size;
62  }
63 
64  if (!strcmp(op, "^")) {
65  *result = src1 ^ src2;
66  return true;
67  }
68  if (!strcmp(op, "+")) {
69  *result = src1 + src2;
70  return true;
71  }
72  if (!strcmp(op, "-")) {
73  if (src2 > src1) {
74  *result = limit + (src1 - src2);
75  } else {
76  *result = src1 - src2;
77  }
78  return true;
79  }
80  if (!strcmp(op, "*")) {
81  *result = src1 * src2;
82  return true;
83  }
84  if (!strcmp(op, "|")) {
85  *result = src1 | src2;
86  return true;
87  }
88  if (!strcmp(op, "/")) {
89  *result = src1 / src2;
90  return true;
91  }
92  if (!strcmp(op, "%")) {
93  *result = src1 % src2;
94  return true;
95  }
96  if (!strcmp(op, "<<")) {
97  *result = src1 << src2;
98  return true;
99  }
100  if (!strcmp(op, ">>")) {
101  *result = src1 >> src2;
102  return true;
103  }
104  if (!strcmp(op, "&")) {
105  *result = src1 & src2;
106  return true;
107  }
108  if (!strcmp(op, "+=")) {
109  *result = old_src1 + src2;
110  return true;
111  }
112  if (!strcmp(op, "-=")) {
113  if (src2 > old_src1) {
114  *result = limit + (old_src1 - src2);
115  } else {
116  *result = old_src1 - src2;
117  }
118  return true;
119  }
120  if (!strcmp(op, "*=")) {
121  *result = old_src1 * src2;
122  return true;
123  }
124  if (!strcmp(op, "/=")) {
125  *result = old_src1 / src2;
126  return true;
127  }
128  if (!strcmp(op, "%=")) {
129  *result = old_src1 % src2;
130  return true;
131  }
132  if (!strcmp(op, "<<")) {
133  *result = src1 << src2;
134  return true;
135  }
136  if (!strcmp(op, ">>")) {
137  *result = src1 >> src2;
138  return true;
139  }
140  if (!strcmp(op, "&=")) {
141  *result = src1 & src2;
142  return true;
143  }
144  if (!strcmp(op, "^=")) {
145  *result = src1 ^ src2;
146  return true;
147  }
148  if (!strcmp(op, "|=")) {
149  *result = src1 | src2;
150  return true;
151  }
152  return false;
153 }
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
#define UT64_MAX
Definition: rz_types_base.h:86

References limit, ut64(), and UT64_MAX.

Referenced by rop_classify_arithmetic(), and rop_classify_arithmetic_const().