diff --git a/libr/anal/sign.c b/libr/anal/sign.c index f100a4094d..c4ffa4e94b 100644 --- a/libr/anal/sign.c +++ b/libr/anal/sign.c @@ -162,7 +162,7 @@ R_API bool r_sign_deserialize(RAnal *a, RSignItem *it, const char *k, const char token = word + 2; if (!strcmp (word, "*")) { continue; - } + } if (strlen (word) < 3 || word[1] != ':') { eprintf ("Corrupted zignatures database (%s)\n", word); break; @@ -837,6 +837,229 @@ R_API bool r_sign_delete(RAnal *a, const char *name) { return sdb_remove (a->sdb_zigns, k, 0); } +static bool matchBytes(RSignItem *a, RSignItem *b) { + if (a->bytes && b->bytes) { + if (a->bytes->size == b->bytes->size) { + return !memcmp (a->bytes->bytes, b->bytes->bytes, b->bytes->size); + } + } + return false; +} + +static bool matchGraph(RSignItem *a, RSignItem *b) { + if (a->graph && b->graph) { + if (a->graph->cc != b->graph->cc) { + return false; + } + if (a->graph->nbbs != b->graph->nbbs) { + return false; + } + if (a->graph->ebbs != b->graph->ebbs) { + return false; + } + if (a->graph->edges != b->graph->edges) { + return false; + } + if (a->graph->bbsum!= b->graph->bbsum) { + return false; + } + return true; + } + return false; +} + +R_API bool r_sign_diff(RAnal *a, const char *other_space_name) { + char k[R_SIGN_KEY_MAXSZ]; + + r_return_val_if_fail (a && other_space_name, false); + + RSpace *current_space = r_spaces_current (&a->zign_spaces); + if (!current_space) { + return false; + } + RSpace *other_space = r_spaces_get (&a->zign_spaces, other_space_name); + if (!other_space) { + return false; + } + + serializeKey (a, current_space, "", k); + SdbList *current_zigns = sdb_foreach_match (a->sdb_zigns, k, false); + + serializeKey (a, other_space, "", k); + SdbList *other_zigns = sdb_foreach_match (a->sdb_zigns, k, false); + + eprintf ("Diff %d %d\n", (int)ls_length (current_zigns), (int)ls_length (other_zigns)); + + SdbListIter *iter; + SdbKv *kv; + RList *lb = NULL; + RList *la = r_list_new (); + if (!la) { + goto beach; + } + ls_foreach (current_zigns, iter, kv) { + RSignItem *it = r_sign_item_new (); + if (!it) { + goto beach; + } + if (r_sign_deserialize (a, it, kv->base.key, kv->base.value)) { + r_list_append (la, it); + } else { + r_sign_item_free (it); + } + } + lb = r_list_new (); + if (!lb) { + goto beach; + } + ls_foreach (other_zigns, iter, kv) { + RSignItem *it = r_sign_item_new (); + if (!it) { + goto beach; + } + if (r_sign_deserialize (a, it, kv->base.key, kv->base.value)) { + r_list_append (lb, it); + } else { + r_sign_item_free (it); + } + } + + ls_free (current_zigns); + ls_free (other_zigns); + + RListIter *itr; + RListIter *itr2; + RSignItem *si; + RSignItem *si2; + + // do the sign diff here + r_list_foreach (la, itr, si) { + if (strstr (si->name, "imp.")) { + continue; + } + r_list_foreach (lb, itr2, si2) { + if (strstr (si2->name, "imp.")) { + continue; + } + if (matchBytes (si, si2)) { + a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" B %s\n", si->addr, si2->addr, si->name); + } + if (matchGraph (si, si2)) { + a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" G %s\n", si->addr, si2->addr, si->name); + } + } + } + + r_list_free (la); + r_list_free (lb); + + return true; +beach: + ls_free (current_zigns); + ls_free (other_zigns); + r_list_free (la); + r_list_free (lb); + + return false; +} + +R_API bool r_sign_diff_by_name(RAnal *a, const char *other_space_name, bool not_matching) { + char k[R_SIGN_KEY_MAXSZ]; + + r_return_val_if_fail (a && other_space_name, false); + + RSpace *current_space = r_spaces_current (&a->zign_spaces); + if (!current_space) { + return false; + } + RSpace *other_space = r_spaces_get (&a->zign_spaces, other_space_name); + if (!other_space) { + return false; + } + + serializeKey (a, current_space, "", k); + SdbList *current_zigns = sdb_foreach_match (a->sdb_zigns, k, false); + + serializeKey (a, other_space, "", k); + SdbList *other_zigns = sdb_foreach_match (a->sdb_zigns, k, false); + + eprintf ("Diff by name %d %d (%s)\n", (int)ls_length (current_zigns), (int)ls_length (other_zigns), not_matching ? "not maching" : "matching"); + + SdbListIter *iter; + SdbKv *kv; + RList *lb = NULL; + RList *la = r_list_new (); + if (!la) { + goto beach; + } + ls_foreach (current_zigns, iter, kv) { + RSignItem *it = r_sign_item_new (); + if (!it) { + goto beach; + } + if (r_sign_deserialize (a, it, kv->base.key, kv->base.value)) { + r_list_append (la, it); + } else { + r_sign_item_free (it); + } + } + lb = r_list_new (); + if (!la) { + goto beach; + } + ls_foreach (other_zigns, iter, kv) { + RSignItem *it = r_sign_item_new (); + if (!it) { + goto beach; + } + if (r_sign_deserialize (a, it, kv->base.key, kv->base.value)) { + r_list_append (lb, it); + } else { + r_sign_item_free (it); + } + } + + ls_free (current_zigns); + ls_free (other_zigns); + + RListIter *itr; + RListIter *itr2; + RSignItem *si; + RSignItem *si2; + size_t current_space_name_len = strlen (current_space->name); + size_t other_space_name_len = strlen (other_space->name); + + r_list_foreach (la, itr, si) { + if (strstr (si->name, "imp.")) { + continue; + } + r_list_foreach (lb, itr2, si2) { + if (strcmp (si->name + current_space_name_len + 1, si2->name + other_space_name_len + 1)) { + continue; + } + bool bytesMatch = matchBytes (si, si2); + bool graphMatch = matchGraph (si, si2); + if ((bytesMatch && !not_matching) || (!bytesMatch && not_matching)) { + a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" B %s\n", si->addr, si2->addr, si->name); + } + if ((graphMatch && !not_matching) || (!graphMatch && not_matching)) { + a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" G %s\n", si->addr, si2->addr, si->name); + } + } + } + + r_list_free (la); + r_list_free (lb); + + return true; +beach: + ls_free (current_zigns); + ls_free (other_zigns); + r_list_free (la); + r_list_free (lb); + + return false; +} struct ctxListCB { RAnal *anal; int idx; diff --git a/libr/core/cmd_zign.c b/libr/core/cmd_zign.c index 6797ac2dc9..31ee5773b2 100644 --- a/libr/core/cmd_zign.c +++ b/libr/core/cmd_zign.c @@ -22,7 +22,7 @@ static const char *help_msg_z[] = { "zo", "[?]", "manage zignature files", "zf", "[?]", "manage FLIRT signatures", "z/", "[?]", "search zignatures", - "zc", " [zspace]", "compare current zignspace zignatures with others", + "zc", "[?]", "compare current zignspace zignatures with another one", "zs", "[?]", "manage zignspaces", "zi", "", "show zignatures matching information", NULL @@ -74,6 +74,14 @@ static const char *help_msg_zs[] = { NULL }; +static const char *help_msg_zc[] = { + "Usage:", "zc[n!] other_space ", "# Compare zignspaces", + "zc", " other_space", "compare all current space with other_space", + "zcn", " other_space", "compare current space with zigns with same name on other_space", + "zcn!", " other_space", "same as above but show the ones not matching", + NULL +}; + static void cmd_zign_init(RCore *core) { DEFINE_CMD_DESCRIPTOR (core, z); DEFINE_CMD_DESCRIPTOR_SPECIAL (core, z/, z_slash); @@ -81,6 +89,7 @@ static void cmd_zign_init(RCore *core) { DEFINE_CMD_DESCRIPTOR (core, zf); DEFINE_CMD_DESCRIPTOR (core, zo); DEFINE_CMD_DESCRIPTOR (core, zs); + DEFINE_CMD_DESCRIPTOR (core, zc); } static bool addFcnHash(RCore *core, RAnalFunction *fcn, const char *name) { @@ -158,7 +167,7 @@ static char *getFcnComments(RCore *core, RAnalFunction *fcn) { if (r && *r) { return r; } - // + // return NULL; } #endif @@ -820,8 +829,46 @@ TODO: add useXRefs, useName } static int cmdCompare(void *data, const char *input) { - eprintf ("TODO\n"); - return 0; + RCore *core = (RCore *) data; + + switch (*input) { + case ' ': + if (!input[1]) { + eprintf ("usage: zc other_space\n"); + return false; + } + return r_sign_diff (core->anal, input + 1); + break; + case 'n': + switch (input[1]) { + case ' ': + if (!input[2]) { + eprintf ("usage: zcn other_space\n"); + return false; + } + return r_sign_diff_by_name (core->anal, input + 2, false); + break; + case '!': + if (input[2] != ' ' || !input[3]) { + eprintf ("usage: zcn! other_space\n"); + return false; + } + return r_sign_diff_by_name (core->anal, input + 3, true); + break; + default: + eprintf ("usage: zcn! other_space\n"); + return false; + } + break; + case '?': + r_core_cmd_help (core, help_msg_zc); + break; + default: + eprintf ("usage: zc[?n!] other_space\n"); + return false; + } + + return true; } static int cmdCheck(void *data, const char *input) { diff --git a/libr/include/r_sign.h b/libr/include/r_sign.h index 8d033089ec..272493b197 100644 --- a/libr/include/r_sign.h +++ b/libr/include/r_sign.h @@ -126,6 +126,9 @@ R_API RList *r_sign_fcn_vars(RAnal *a, RAnalFunction *fcn); R_API int r_sign_is_flirt(RBuffer *buf); R_API void r_sign_flirt_dump(const RAnal *anal, const char *flirt_file); R_API void r_sign_flirt_scan(RAnal *anal, const char *flirt_file); + +R_API bool r_sign_diff(RAnal *a, const char *other_space_name); +R_API bool r_sign_diff_by_name(RAnal *a, const char *other_space_name, bool not_matching); #endif #ifdef __cplusplus