Add byte signature diff zd ##diff ##signatures (#18620)

This commit is contained in:
Dennis Goodlett 2021-04-24 03:26:13 -04:00 committed by GitHub
parent 9a14c294fc
commit f550986e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 224 additions and 1 deletions

View File

@ -12,6 +12,7 @@ static const char *help_msg_z[] = {
"z", "", "show zignatures",
"z.", "", "find matching zignatures in current offset",
"zb", "[?][n=5]", "search for best match",
"zd", "zignature", "diff current function and signature",
"z*", "", "show zignatures in radare format",
"zq", "", "show zignatures in quiet mode",
"zj", "", "show zignatures in json format",
@ -1096,9 +1097,198 @@ static bool bestmatch(void *data, const char *input) {
}
}
static bool _sig_bytediff_cb(RLevBuf *va, RLevBuf *vb, ut32 ia, ut32 ib) {
RSignBytes *a = (RSignBytes *)va->buf;
RSignBytes *b = (RSignBytes *)vb->buf;
if ((a->bytes[ia] & a->mask[ia]) == (b->bytes[ib] & b->mask[ib])) {
return false;
}
return true;
}
#define lines_addbytesmask(l, sig, index, add, col) \
if (col) { \
l.bytes = r_str_appendf (l.bytes, " %s%s%02x\x1b[0m", col, add, sig->bytes[index]); \
l.mask = r_str_appendf (l.mask, " %s%s%02x\x1b[0m", col, add, sig->mask[index]); \
l.land = r_str_appendf (l.land, " %s%s%02x\x1b[0m", col, add, sig->bytes[index] & sig->mask[index]); \
} else { \
l.bytes = r_str_appendf (l.bytes, " %s%02x", add, sig->bytes[index]); \
l.mask = r_str_appendf (l.mask, " %s%02x", add, sig->mask[index]); \
l.land = r_str_appendf (l.land, " %s%02x", add, sig->bytes[index] & sig->mask[index]); \
} \
index++;
#define lines_addblnk(l) \
l.bytes = r_str_append (l.bytes, " "); \
l.mask = r_str_append (l.mask, " "); \
l.land = r_str_append (l.land, " ");
#define freelines(x) \
free (x.bytes); \
free (x.mask); \
free (x.land); \
memset (&x, 0, sizeof (x));
static void print_zig_diff(RCore *c, RSignBytes *ab, RSignBytes *bb, RLevOp *ops) {
struct lines {
char *mask, *bytes, *land;
} al, bl;
memset (&al, 0, sizeof (al));
memset (&bl, 0, sizeof (bl));
char *colsub, *coladd, *coldel;
colsub = coladd = coldel = NULL;
if (r_config_get_b (c->config, "scr.color")) {
coldel = "\x1b[1;31m";
coladd = "\x1b[1;32m";
colsub = "\x1b[1;33m";
}
int i, ia, ib, iastart, ibstart;
ia = ib = iastart = ibstart = 0;
bool printb = false;
for (i = 0; ops[i] != LEVEND; i++) {
switch (ops[i]) {
case LEVNOP:
// lines_addbytesmask macro does ia++ so test must before
if (!printb && (ab->bytes[ia] != bb->bytes[ib] || ab->mask[ia] != bb->mask[ib])) {
printb = true;
}
lines_addbytesmask (al, ab, ia, " ", (char *)NULL);
lines_addbytesmask (bl, bb, ib, " ", (char *)NULL);
break;
case LEVSUB:
lines_addbytesmask (al, ab, ia, " ", colsub);
lines_addbytesmask (bl, bb, ib, "^", colsub);
printb = true;
break;
case LEVADD:
lines_addblnk (al);
lines_addbytesmask (bl, bb, ib, "+", coladd);
printb = true;
break;
case LEVDEL:
lines_addbytesmask (al, ab, ia, "-", coldel);
lines_addblnk (bl);
printb = true;
break;
default:
r_warn_if_reached ();
freelines (al);
freelines (bl);
return;
}
// when alloc fails
if (!(al.bytes && al.mask && al.land && bl.bytes && bl.mask && bl.land)) {
freelines (al);
freelines (bl);
return;
}
if (i % 16 == 15 || ops[i + 1] == LEVEND) {
if (i > 16) {
r_cons_printf ("\n");
}
r_cons_printf ("Fnc cmp 0x%04x %s\n", iastart, al.land);
if (printb) {
r_cons_printf ("Sig cmp 0x%04x %s\n", ibstart, bl.land);
}
r_cons_printf ("Fnc Mask 0x%04x %s\n", iastart, al.mask);
if (printb) {
r_cons_printf ("Sig Mask 0x%04x %s\n", ibstart, bl.mask);
}
r_cons_printf ("Fnc Bytes 0x%04x %s\n", iastart, al.bytes);
if (printb) {
r_cons_printf ("Sig Bytes 0x%04x %s\n", ibstart, bl.bytes);
} else {
r_cons_printf ("== Signature was same ==\n");
}
freelines (al);
freelines (bl);
iastart = ia;
ibstart = ib;
printb = false;
}
}
}
#undef lines_addbytesmask
#undef lines_addblnk
#undef freelines
static bool diff_zig(void *data, const char *input) {
r_return_val_if_fail (data && input, false);
RCore *core = (RCore *)data;
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
if (!fcn) {
eprintf ("No function at 0x%08" PFMT64x "\n", core->offset);
return false;
}
char *argv = r_str_new (input);
if (!argv) {
return false;
}
char *zigname = strtok (argv, " ");
if (!zigname) {
eprintf ("Need a signature\n");
free (argv);
return false;
}
if (strtok (NULL, " ")) {
eprintf ("too many arguments");
free (argv);
return false;
}
RSignItem *it = item_frm_signame (core->anal, zigname);
if (!it) {
eprintf ("Couldn't get signature for %s\n", zigname);
free (argv);
return false;
}
free (argv);
if (!it->bytes) {
eprintf ("Signature %s missing bytes\n", it->name);
return false;
}
RLevBuf b;
b.buf = it->bytes;
b.len = it->bytes->size;
RSignItem *fit = r_sign_item_new ();
if (!fit) {
r_sign_item_free (it);
return false;
}
r_sign_addto_item (core->anal, fit, fcn, R_SIGN_BYTES);
RLevBuf a;
a.buf = fit->bytes;
a.len = fit->bytes->size;
RLevOp *ops = NULL;
if (r_diff_levenshtein_path (&a, &b, UT32_MAX, _sig_bytediff_cb, &ops) < 0) {
eprintf ("Diff failed\n");
} else {
print_zig_diff (core, fit->bytes, it->bytes, ops);
}
free (ops);
r_sign_item_free (fit);
r_sign_item_free (it);
return false;
}
static int cmdCompare(void *data, const char *input) {
int result = true;
RCore *core = (RCore *) data;
RCore *core = (RCore *)data;
const char *raw_bytes_thresh = r_config_get (core->config, "zign.diff.bthresh");
const char *raw_graph_thresh = r_config_get (core->config, "zign.diff.gthresh");
RSignOptions *options = r_sign_options_new (raw_bytes_thresh, raw_graph_thresh);
@ -1279,6 +1469,8 @@ static int cmd_zign(void *data, const char *input) {
return cmdCheck (data, arg);
case 'b': // "zb"
return bestmatch (data, arg);
case 'd': // "zb"
return diff_zig (data, arg);
case 'o': // "zo"
return cmdOpen (data, arg);
case 'g': // "zg"

View File

@ -1784,3 +1784,34 @@ int sym.new_function_name (int NEWARGC, char **NEWARGV);
sym.new_function_name
EOF
RUN
NAME=zd basic
FILE=bins/elf/static-glibc-2.27
CMDS=<<EOF
s 0x00410210
e zign.maxsz = 32
af
za sym.test b ff41554154498afc555383ec08e89e02ffff488b2d77952a004889c38b450045:ffffffffffffffffffffffffffff00000000ff000000000000ffffffffffffff
zd sym.test
EOF
EXPECT=<<EOF
Fnc cmp 0x0000 41 55 41 54 49 89 fc 55 53 -48 83 ec 08 e8 00
Sig cmp 0x0000 +ff 41 55 41 54 49 ^8a fc 55 53 83 ec 08 e8 00
Fnc Mask 0x0000 ff ff ff ff ff ff ff ff ff -ff ff ff ff ff 00
Sig Mask 0x0000 +ff ff ff ff ff ff ^ff ff ff ff ff ff ff ff 00
Fnc Bytes 0x0000 41 55 41 54 49 89 fc 55 53 -48 83 ec 08 e8 9e
Sig Bytes 0x0000 +ff 41 55 41 54 49 ^8a fc 55 53 83 ec 08 e8 9e
Fnc cmp 0x000f 00 00 00 48 00 00 00 00 00 00 48 89 c3 8b 45 00
Fnc Mask 0x000f 00 00 00 ff 00 00 00 00 00 00 ff ff ff ff ff ff
Fnc Bytes 0x000f 02 ff ff 48 8b 2d 77 95 2a 00 48 89 c3 8b 45 00
== Signature was same ==
Fnc cmp 0x001f 48
Sig cmp 0x001f ^45
Fnc Mask 0x001f ff
Sig Mask 0x001f ^ff
Fnc Bytes 0x001f 48
Sig Bytes 0x001f ^45
EOF
RUN