Implement the zc command ##signatures

Also add zcn, zcn! to compare only signatures with the same name.
This commit is contained in:
Francesco Tamagni 2019-05-17 16:50:39 +02:00 committed by radare
parent b4015791be
commit 0b880ed0b0
3 changed files with 278 additions and 5 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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