1 /* radare - LGPL - Copyright 2009-2020 - pancake, nibble */
2
3 #include <r_anal.h>
4 #include <r_sign.h>
5 #include <r_search.h>
6 #include <r_core.h>
7
8 R_LIB_VERSION (r_sign);
9
10 #define SIGN_DIFF_MATCH_BYTES_THRESHOLD 1.0
11 #define SIGN_DIFF_MATCH_GRAPH_THRESHOLD 1.0
12
getRealRef(RCore * core,ut64 off)13 const char *getRealRef(RCore *core, ut64 off) {
14 RFlagItem *item;
15 RListIter *iter;
16
17 const RList *list = r_flag_get_list (core->flags, off);
18 if (!list) {
19 return NULL;
20 }
21
22 r_list_foreach (list, iter, item) {
23 if (!item->name) {
24 continue;
25 }
26 if (strncmp (item->name, "sym.", 4)) {
27 continue;
28 }
29 return item->name;
30 }
31
32 return NULL;
33 }
34
r_sign_fcn_vars(RAnal * a,RAnalFunction * fcn)35 R_API RList *r_sign_fcn_vars(RAnal *a, RAnalFunction *fcn) {
36 r_return_val_if_fail (a && fcn, NULL);
37
38 RCore *core = a->coreb.core;
39
40 if (!core) {
41 return NULL;
42 }
43
44 RListIter *iter;
45 RAnalVar *var;
46 RList *ret = r_list_newf ((RListFree) free);
47 if (!ret) {
48 return NULL;
49 }
50 RList *reg_vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_REG);
51 RList *spv_vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_SPV);
52 RList *bpv_vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_BPV);
53 r_list_foreach (bpv_vars, iter, var) {
54 r_list_append (ret, r_str_newf ("b%d", var->delta));
55 }
56 r_list_foreach (spv_vars, iter, var) {
57 r_list_append (ret, r_str_newf ("s%d", var->delta));
58 }
59 r_list_foreach (reg_vars, iter, var) {
60 r_list_append (ret, r_str_newf ("r%d", var->delta));
61 }
62 r_list_free (reg_vars);
63 r_list_free (bpv_vars);
64 r_list_free (spv_vars);
65 return ret;
66 }
67
r_sign_fcn_types(RAnal * a,RAnalFunction * fcn)68 R_API RList *r_sign_fcn_types(RAnal *a, RAnalFunction *fcn) {
69
70 // From anal/types/*:
71 // Get key-value types from sdb matching "func.%s", fcn->name
72 // Get func.%s.args (number of args)
73 // Get type,name pairs
74 // Put everything in RList following the next format:
75 // types: main.ret=%type%, main.args=%num%, main.arg.0="int,argc", ...
76
77 r_return_val_if_fail (a && fcn, NULL);
78
79 RList *ret = r_list_newf ((RListFree) free);
80 if (!ret) {
81 return NULL;
82 }
83
84 char *scratch = r_str_newf ("func.%s.args", fcn->name);
85 if (!scratch) {
86 return NULL;
87 }
88 const char *fcntypes = sdb_const_get (a->sdb_types, scratch, 0);
89 free (scratch);
90
91 scratch = r_str_newf ("func.%s.ret", fcn->name);
92 if (!scratch) {
93 return NULL;
94 }
95 const char *ret_type = sdb_const_get (a->sdb_types, scratch, 0);
96 free (scratch);
97
98 if (fcntypes) {
99 if (ret_type) {
100 r_list_append (ret, r_str_newf ("func.%s.ret=%s", fcn->name, ret_type));
101 }
102 int argc = atoi (fcntypes);
103 r_list_append (ret, r_str_newf ("func.%s.args=%d", fcn->name, argc));
104 int i;
105 for (i = 0; i < argc; i++) {
106 const char *arg = sdb_const_get (a->sdb_types, r_str_newf ("func.%s.arg.%d", fcn->name, i), 0);
107 r_list_append (ret, r_str_newf ("func.%s.arg.%d=\"%s\"", fcn->name, i, arg));
108 }
109 }
110
111 return ret;
112 }
113
r_sign_fcn_xrefs(RAnal * a,RAnalFunction * fcn)114 R_API RList *r_sign_fcn_xrefs(RAnal *a, RAnalFunction *fcn) {
115 RListIter *iter = NULL;
116 RAnalRef *refi = NULL;
117
118 r_return_val_if_fail (a && fcn, NULL);
119
120 RCore *core = a->coreb.core;
121
122 if (!core) {
123 return NULL;
124 }
125
126 RList *ret = r_list_newf ((RListFree) free);
127 RList *xrefs = r_anal_function_get_xrefs (fcn);
128 r_list_foreach (xrefs, iter, refi) {
129 if (refi->type == R_ANAL_REF_TYPE_CODE || refi->type == R_ANAL_REF_TYPE_CALL) {
130 const char *flag = getRealRef (core, refi->addr);
131 if (flag) {
132 r_list_append (ret, r_str_new (flag));
133 }
134 }
135 }
136 r_list_free (xrefs);
137 return ret;
138 }
139
r_sign_fcn_refs(RAnal * a,RAnalFunction * fcn)140 R_API RList *r_sign_fcn_refs(RAnal *a, RAnalFunction *fcn) {
141 RListIter *iter = NULL;
142 RAnalRef *refi = NULL;
143
144 r_return_val_if_fail (a && fcn, NULL);
145
146 RCore *core = a->coreb.core;
147
148 if (!core) {
149 return NULL;
150 }
151
152 RList *ret = r_list_newf ((RListFree) free);
153 RList *refs = r_anal_function_get_refs (fcn);
154 r_list_foreach (refs, iter, refi) {
155 if (refi->type == R_ANAL_REF_TYPE_CODE || refi->type == R_ANAL_REF_TYPE_CALL) {
156 const char *flag = getRealRef (core, refi->addr);
157 if (flag) {
158 r_list_append (ret, r_str_new (flag));
159 }
160 }
161 }
162 r_list_free (refs);
163 return ret;
164 }
165
zign_types_to_list(RAnal * a,const char * types)166 static RList *zign_types_to_list(RAnal *a, const char *types) {
167 RList *ret = r_list_newf ((RListFree)free);
168 if (!ret) {
169 return NULL;
170 }
171
172 unsigned int i = 0, prev = 0, len = strlen (types);
173 bool quoted = false;
174 char *token = NULL;
175 for (i = 0; i <= len; i++) {
176 if (types[i] == '"') {
177 quoted = !quoted;
178 } else if ((types[i] == ',' && !quoted) || types[i] == '\0') {
179 token = r_str_ndup (types + prev, i - prev);
180 if (token) {
181 prev = i + 1;
182 r_list_append (ret, token);
183 token = NULL;
184 }
185 }
186 }
187
188 return ret;
189 }
190
do_reflike_sig(const char * token)191 static RList *do_reflike_sig(const char *token) {
192 RList *list = NULL;
193 char *scratch = r_str_new (token);
194 int cnt = r_str_split (scratch, ',');
195 if (cnt > 0 && (list = r_list_newf ((RListFree)free))) {
196 int i;
197 for (i = 0; i < cnt; i++) {
198 r_list_append (list, r_str_new (r_str_word_get0 (scratch, i)));
199 }
200 }
201 free (scratch);
202 return list;
203 }
204
205 #define DBL_VAL_FAIL(x,y) \
206 if (x) { \
207 eprintf ("Warning: Skipping signature with multiple %c signatures (%s)\n", y, k); \
208 success = false; \
209 goto out; \
210 }
r_sign_deserialize(RAnal * a,RSignItem * it,const char * k,const char * v)211 R_API bool r_sign_deserialize(RAnal *a, RSignItem *it, const char *k, const char *v) {
212 r_return_val_if_fail (a && it && k && v, false);
213
214 bool success = true;
215 char *k2 = r_str_new (k);
216 char *v2 = r_str_new (v);
217 if (!k2 || !v2) {
218 success = false;
219 goto out;
220 }
221
222 // Deserialize key: zign|space|name
223 int n = r_str_split (k2, '|');
224 if (n != 3) {
225 eprintf ("Warning: Skipping signature with invalid key (%s)\n", k);
226 success = false;
227 goto out;
228 }
229 if (strcmp (r_str_word_get0 (k2, 0), "zign")) {
230 eprintf ("Warning: Skipping signature with invalid value (%s)\n", k);
231 success = false;
232 goto out;
233 }
234
235 it->space = r_spaces_add (&a->zign_spaces, r_str_word_get0 (k2, 1));
236 it->name = r_str_new (r_str_word_get0 (k2, 2));
237
238 // remove newline at end
239 strtok (v2, "\n");
240 // Deserialize value: |k:v|k:v|k:v|...
241 n = r_str_split (v2, '|');
242 const char *token = NULL;
243 int w, size;
244 for (w = 0; w < n; w++) {
245 const char *word = r_str_word_get0 (v2, w);
246 if (!word) {
247 break;
248 }
249 if (!*word) {
250 continue;
251 }
252 token = word + 2;
253 if (!strcmp (word, "*")) {
254 continue;
255 }
256 if (strlen (word) < 3 || word[1] != ':') {
257 eprintf ("Warning: Skipping signature with corrupted serialization (%s:%s)\n", k, word);
258 success = false;
259 goto out;
260 }
261 RSignType st = (RSignType)*word;
262 switch (st) {
263 case R_SIGN_ANAL:
264 eprintf ("Unsupported\n");
265 break;
266 case R_SIGN_NAME:
267 DBL_VAL_FAIL (it->realname, R_SIGN_NAME);
268 it->realname = strdup (token);
269 break;
270 case R_SIGN_COMMENT:
271 DBL_VAL_FAIL (it->comment, R_SIGN_COMMENT);
272 it->comment = strdup (token);
273 break;
274 case R_SIGN_GRAPH:
275 DBL_VAL_FAIL (it->graph, R_SIGN_GRAPH);
276 if (strlen (token) == 2 * sizeof (RSignGraph)) {
277 it->graph = R_NEW0 (RSignGraph);
278 if (it->graph) {
279 r_hex_str2bin (token, (ut8 *)it->graph);
280 }
281 }
282 break;
283 case R_SIGN_OFFSET:
284 DBL_VAL_FAIL ((it->addr != UT64_MAX), R_SIGN_OFFSET);
285 it->addr = atoll (token);
286 break;
287 case R_SIGN_REFS:
288 DBL_VAL_FAIL (it->refs, R_SIGN_REFS);
289 if (!(it->refs = do_reflike_sig (token))) {
290 success = false;
291 goto out;
292 }
293 break;
294 case R_SIGN_XREFS:
295 DBL_VAL_FAIL (it->xrefs, R_SIGN_XREFS);
296 if (!(it->xrefs = do_reflike_sig (token))) {
297 success = false;
298 goto out;
299 }
300 break;
301 case R_SIGN_VARS:
302 DBL_VAL_FAIL (it->vars, R_SIGN_VARS);
303 if (!(it->vars = do_reflike_sig (token))) {
304 success = false;
305 goto out;
306 }
307 break;
308 case R_SIGN_TYPES:
309 DBL_VAL_FAIL (it->types, R_SIGN_TYPES);
310 it->types = zign_types_to_list (a, token);
311 break;
312 case R_SIGN_BBHASH:
313 DBL_VAL_FAIL (it->hash, R_SIGN_BBHASH);
314 if (token[0] != 0) {
315 it->hash = R_NEW0 (RSignHash);
316 if (it->hash) {
317 it->hash->bbhash = r_str_new (token);
318 }
319 }
320 break;
321 case R_SIGN_BYTES:
322 // following two errors are not due to double entries
323 if (!it->bytes) {
324 eprintf ("Warning: Skipping signature with no bytes size (%s)\n", k);
325 success = false;
326 goto out;
327 }
328 if (strlen (token) != 2 * it->bytes->size) {
329 eprintf ("Warning: Skipping signature with invalid size (%s)\n", k);
330 success = false;
331 goto out;
332 }
333 DBL_VAL_FAIL (it->bytes->bytes, R_SIGN_BYTES);
334 it->bytes->bytes = malloc (it->bytes->size);
335 if (it->bytes->bytes) {
336 r_hex_str2bin (token, it->bytes->bytes);
337 }
338 break;
339 case R_SIGN_BYTES_MASK:
340 // following two errors are not due to double entries
341 if (!it->bytes) {
342 eprintf ("Warning: Skipping signature with no mask size (%s)\n", k);
343 success = false;
344 goto out;
345 }
346 if (strlen (token) != 2 * it->bytes->size) {
347 eprintf ("Warning: Skipping signature invalid mask size (%s)\n", k);
348 success = false;
349 goto out;
350 }
351 DBL_VAL_FAIL (it->bytes->mask, R_SIGN_BYTES);
352 it->bytes->mask = malloc (it->bytes->size);
353 if (!it->bytes->mask) {
354 goto out;
355 }
356 r_hex_str2bin (token, it->bytes->mask);
357 break;
358 case R_SIGN_BYTES_SIZE:
359 // allocate
360 size = atoi (token);
361 if (size > 0) {
362 DBL_VAL_FAIL (it->bytes, R_SIGN_BYTES_SIZE);
363 it->bytes = R_NEW0 (RSignBytes);
364 if (!it->bytes) {
365 goto out;
366 }
367 it->bytes->size = size;
368 }
369 break;
370 default:
371 eprintf ("Unsupported (%s)\n", word);
372 break;
373 }
374 }
375 out:
376 free (k2);
377 free (v2);
378 return success;
379 }
380 #undef DBL_VAL_FAIL
381
serializeKey(RAnal * a,const RSpace * space,const char * name,char * k)382 static void serializeKey(RAnal *a, const RSpace *space, const char* name, char *k) {
383 snprintf (k, R_SIGN_KEY_MAXSZ, "zign|%s|%s", space? space->name: "*", name);
384 }
385
serializeKeySpaceStr(RAnal * a,const char * space,const char * name,char * k)386 static void serializeKeySpaceStr(RAnal *a, const char *space, const char* name, char *k) {
387 snprintf (k, R_SIGN_KEY_MAXSZ, "zign|%s|%s", space, name);
388 }
389
serialize(RAnal * a,RSignItem * it,char * k,char * v)390 static void serialize(RAnal *a, RSignItem *it, char *k, char *v) {
391 RListIter *iter = NULL;
392 char *hexbytes = NULL, *hexmask = NULL, *hexgraph = NULL;
393 char *refs = NULL, *xrefs = NULL, *ref = NULL, *var, *vars = NULL;
394 char *type, *types = NULL;
395 int i = 0, len = 0;
396 RSignBytes *bytes = it->bytes;
397 RSignGraph *graph = it->graph;
398 RSignHash *hash = it->hash;
399
400 if (k) {
401 serializeKey (a, it->space, it->name, k);
402 }
403 if (v) {
404 if (bytes) {
405 len = bytes->size * 2 + 1;
406 hexbytes = calloc (1, len);
407 hexmask = calloc (1, len);
408 if (!hexbytes || !hexmask) {
409 free (hexbytes);
410 free (hexmask);
411 return;
412 }
413 if (!bytes->bytes) {
414 bytes->bytes = malloc ((bytes->size + 1) * 3);
415 }
416 r_hex_bin2str (bytes->bytes, bytes->size, hexbytes);
417 if (!bytes->mask) {
418 bytes->mask = malloc ((bytes->size + 1) * 3);
419 }
420 r_hex_bin2str (bytes->mask, bytes->size, hexmask);
421 }
422 if (graph) {
423 hexgraph = calloc (1, sizeof (RSignGraph) * 2 + 1);
424 if (hexgraph) {
425 r_hex_bin2str ((ut8 *) graph, sizeof (RSignGraph), hexgraph);
426 }
427 }
428 i = 0;
429 r_list_foreach (it->refs, iter, ref) {
430 if (i > 0) {
431 refs = r_str_appendch (refs, ',');
432 }
433 refs = r_str_append (refs, ref);
434 i++;
435 }
436 i = 0;
437 r_list_foreach (it->xrefs, iter, ref) {
438 if (i > 0) {
439 xrefs = r_str_appendch (xrefs, ',');
440 }
441 xrefs = r_str_append (xrefs, ref);
442 i++;
443 }
444 i = 0;
445 r_list_foreach (it->vars, iter, var) {
446 if (i > 0) {
447 vars = r_str_appendch (vars, ',');
448 }
449 vars = r_str_append (vars, var);
450 i++;
451 }
452 i = 0;
453 r_list_foreach (it->types, iter, type) {
454 if (i > 0) {
455 types = r_str_appendch (types, ',');
456 }
457 types = r_str_append (types, type);
458 i++;
459 }
460 RStrBuf *sb = r_strbuf_new ("");
461 if (bytes) {
462 // TODO: do not hardcoded s,b,m here, use RSignType enum
463 r_strbuf_appendf (sb, "|s:%d|b:%s|m:%s", bytes->size, hexbytes, hexmask);
464 }
465 if (it->addr != UT64_MAX) {
466 r_strbuf_appendf (sb, "|%c:%"PFMT64d, R_SIGN_OFFSET, it->addr);
467 }
468 if (graph) {
469 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_GRAPH, hexgraph);
470 }
471 if (refs) {
472 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_REFS, refs);
473 }
474 if (xrefs) {
475 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_XREFS, xrefs);
476 }
477 if (vars) {
478 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_VARS, vars);
479 }
480 if (types) {
481 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_TYPES, types);
482 }
483 if (it->comment) {
484 // b64 encoded
485 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_COMMENT, it->comment);
486 }
487 if (it->realname) {
488 // b64 encoded
489 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_NAME, it->realname);
490 }
491 if (hash && hash->bbhash) {
492 r_strbuf_appendf (sb, "|%c:%s", R_SIGN_BBHASH, hash->bbhash);
493 }
494 if (r_strbuf_length (sb) >= R_SIGN_VAL_MAXSZ) {
495 eprintf ("Signature limit reached for 0x%08"PFMT64x" (%s)\n", it->addr, it->name);
496 }
497 char *res = r_strbuf_drain (sb);
498 if (res) {
499 strncpy (v, res, R_SIGN_VAL_MAXSZ);
500 free (res);
501 }
502
503 free (hexbytes);
504 free (hexmask);
505 free (hexgraph);
506 free (refs);
507 free (vars);
508 free (xrefs);
509 free (types);
510 }
511 }
512
deserialize_sign_space(RAnal * a,RSpace * space)513 static RList *deserialize_sign_space(RAnal *a, RSpace *space) {
514 r_return_val_if_fail (a && space, NULL);
515
516 char k[R_SIGN_KEY_MAXSZ];
517 serializeKey (a, space, "", k);
518 SdbList *zigns = sdb_foreach_match (a->sdb_zigns, k, false);
519
520 SdbListIter *iter;
521 SdbKv *kv;
522 RList *ret = r_list_newf ((RListFree)r_sign_item_free);
523 if (!ret) {
524 goto beach;
525 }
526 ls_foreach (zigns, iter, kv) {
527 RSignItem *it = r_sign_item_new ();
528 if (!it) {
529 goto beach;
530 }
531 if (r_sign_deserialize (a, it, kv->base.key, kv->base.value)) {
532 r_list_append (ret, it);
533 } else {
534 r_sign_item_free (it);
535 }
536 }
537
538 ls_free (zigns);
539 return ret;
540
541 beach:
542 ls_free (zigns);
543 r_list_free (ret);
544 return NULL;
545 }
546
mergeItem(RSignItem * dst,RSignItem * src)547 static void mergeItem(RSignItem *dst, RSignItem *src) {
548 RListIter *iter = NULL;
549 char *ref, *var, *type;
550
551 if (src->bytes) {
552 r_sign_bytes_free (dst->bytes);
553 dst->bytes = R_NEW0 (RSignBytes);
554 if (!dst->bytes) {
555 return;
556 }
557 dst->space = src->space;
558 dst->bytes->size = src->bytes->size;
559 dst->bytes->bytes = malloc (src->bytes->size);
560 if (!dst->bytes->bytes) {
561 r_sign_bytes_free (dst->bytes);
562 return;
563 }
564 memcpy (dst->bytes->bytes, src->bytes->bytes, src->bytes->size);
565 dst->bytes->mask = malloc (src->bytes->size);
566 if (!dst->bytes->mask) {
567 r_sign_bytes_free (dst->bytes);
568 return;
569 }
570 memcpy (dst->bytes->mask, src->bytes->mask, src->bytes->size);
571 }
572
573 if (src->graph) {
574 free (dst->graph);
575 dst->graph = R_NEW0 (RSignGraph);
576 if (!dst->graph) {
577 return;
578 }
579 *dst->graph = *src->graph;
580 }
581
582 if (src->comment) {
583 dst->comment = strdup (src->comment);
584 }
585
586 if (src->realname) {
587 dst->realname = strdup (src->realname);
588 }
589
590 if (src->addr != UT64_MAX) {
591 dst->addr = src->addr;
592 }
593
594 if (src->refs) {
595 r_list_free (dst->refs);
596
597 dst->refs = r_list_newf ((RListFree)free);
598 r_list_foreach (src->refs, iter, ref) {
599 r_list_append (dst->refs, r_str_new (ref));
600 }
601 }
602
603 if (src->vars) {
604 r_list_free (dst->vars);
605
606 dst->vars = r_list_newf ((RListFree)free);
607 r_list_foreach (src->vars, iter, var) {
608 r_list_append (dst->vars, r_str_new (var));
609 }
610 }
611
612 if (src->types) {
613 r_list_free (dst->types);
614
615 dst->types = r_list_newf ((RListFree)free);
616 r_list_foreach (src->types, iter, type) {
617 r_list_append (dst->types, r_str_new (type));
618 }
619 }
620
621 if (src->hash) {
622 if (!dst->hash) {
623 dst->hash = R_NEW0 (RSignHash);
624 if (!dst->hash) {
625 return;
626 }
627 }
628 if (src->hash->bbhash) {
629 dst->hash->bbhash = strdup (src->hash->bbhash);
630 }
631 }
632 }
633
r_sign_get_item(RAnal * a,const char * name)634 R_API RSignItem *r_sign_get_item(RAnal *a, const char *name) {
635 char k[R_SIGN_KEY_MAXSZ];
636 serializeKey (a, r_spaces_current (&a->zign_spaces), name, k);
637
638 const char *v = sdb_const_get (a->sdb_zigns, k, 0);
639 if (!v) {
640 return NULL;
641 }
642 RSignItem *it = r_sign_item_new ();
643 if (!it) {
644 return NULL;
645 }
646 if (!r_sign_deserialize (a, it, k, v)) {
647 r_sign_item_free (it);
648 return NULL;
649 }
650 return it;
651 }
652
r_sign_add_item(RAnal * a,RSignItem * it)653 R_API bool r_sign_add_item(RAnal *a, RSignItem *it) {
654 char key[R_SIGN_KEY_MAXSZ], val[R_SIGN_VAL_MAXSZ];
655 const char *curval = NULL;
656 bool retval = true;
657 RSignItem *curit = r_sign_item_new ();
658 if (!curit) {
659 return false;
660 }
661
662 serialize (a, it, key, val);
663 curval = sdb_const_get (a->sdb_zigns, key, 0);
664 if (curval) {
665 if (!r_sign_deserialize (a, curit, key, curval)) {
666 eprintf ("error: cannot deserialize zign\n");
667 retval = false;
668 goto out;
669 }
670 mergeItem (curit, it);
671 serialize (a, curit, key, val);
672 }
673 sdb_set (a->sdb_zigns, key, val, 0);
674
675 out:
676 r_sign_item_free (curit);
677
678 return retval;
679 }
680
addHash(RAnal * a,const char * name,int type,const char * val)681 static bool addHash(RAnal *a, const char *name, int type, const char *val) {
682 RSignItem *it = r_sign_item_new ();
683 if (!it) {
684 r_sign_item_free (it);
685 return false;
686 }
687 it->name = r_str_new (name);
688 if (!it->name) {
689 r_sign_item_free (it);
690 return false;
691 }
692 it->hash = R_NEW0 (RSignHash);
693 if (!it->hash) {
694 r_sign_item_free (it);
695 return false;
696 }
697 it->space = r_spaces_current (&a->zign_spaces);
698
699 bool retval = false;
700 switch (type) {
701 case R_SIGN_BBHASH:
702 it->hash->bbhash = strdup (val);
703 retval = r_sign_add_item (a, it);
704 r_sign_item_free (it);
705 break;
706 }
707
708 return retval;
709 }
710
addBBHash(RAnal * a,RAnalFunction * fcn,const char * name)711 static bool addBBHash(RAnal *a, RAnalFunction *fcn, const char *name) {
712 bool retval = false;
713 RSignItem *it = r_sign_item_new ();
714 if (!it) {
715 goto beach;
716 }
717 it->name = r_str_new (name);
718 if (!it->name) {
719 goto beach;
720 }
721 it->space = r_spaces_current (&a->zign_spaces);
722
723 if (r_sign_addto_item (a, it, fcn, R_SIGN_BBHASH)) {
724 retval = r_sign_add_item (a, it);
725 }
726 beach:
727 r_sign_item_free (it);
728 return retval;
729 }
730
addBytes(RAnal * a,const char * name,ut64 size,const ut8 * bytes,const ut8 * mask)731 static bool addBytes(RAnal *a, const char *name, ut64 size, const ut8 *bytes, const ut8 *mask) {
732 bool retval = true;
733
734 if (r_mem_is_zero (mask, size)) {
735 eprintf ("error: zero mask\n");
736 return false;
737 }
738
739 RSignItem *it = r_sign_item_new ();
740 if (!it) {
741 return false;
742 }
743
744 it->name = r_str_new (name);
745 if (!it->name) {
746 free (it);
747 return false;
748 }
749 it->space = r_spaces_current (&a->zign_spaces);
750 it->bytes = R_NEW0 (RSignBytes);
751 if (!it->bytes) {
752 goto fail;
753 }
754 it->bytes->size = size;
755 it->bytes->bytes = malloc (size);
756 if (!it->bytes->bytes) {
757 goto fail;
758 }
759 memcpy (it->bytes->bytes, bytes, size);
760 it->bytes->mask = malloc (size);
761 if (!it->bytes->mask) {
762 goto fail;
763 }
764 memcpy (it->bytes->mask, mask, size);
765 retval = r_sign_add_item (a, it);
766 r_sign_item_free (it);
767 return retval;
768 fail:
769 if (it) {
770 free (it->name);
771 r_sign_bytes_free (it->bytes);
772 }
773 free (it);
774 return false;
775 }
776
r_sign_add_hash(RAnal * a,const char * name,int type,const char * val,int len)777 R_API bool r_sign_add_hash(RAnal *a, const char *name, int type, const char *val, int len) {
778 r_return_val_if_fail (a && name && type && val && len > 0, false);
779 if (type != R_SIGN_BBHASH) {
780 eprintf ("error: hash type unknown");
781 return false;
782 }
783 int digestsize = r_hash_size (R_ZIGN_HASH) * 2;
784 if (len != digestsize) {
785 eprintf ("error: invalid hash size: %d (%s digest size is %d)\n", len, ZIGN_HASH, digestsize);
786 return false;
787 }
788 return addHash (a, name, type, val);
789 }
790
r_sign_add_bb_hash(RAnal * a,RAnalFunction * fcn,const char * name)791 R_API bool r_sign_add_bb_hash(RAnal *a, RAnalFunction *fcn, const char *name) {
792 r_return_val_if_fail (a && fcn && name, false);
793 return addBBHash (a, fcn, name);
794 }
795
r_sign_add_bytes(RAnal * a,const char * name,ut64 size,const ut8 * bytes,const ut8 * mask)796 R_API bool r_sign_add_bytes(RAnal *a, const char *name, ut64 size, const ut8 *bytes, const ut8 *mask) {
797 r_return_val_if_fail (a && name && size > 0 && bytes && mask, false);
798 return addBytes (a, name, size, bytes, mask);
799 }
800
r_sign_add_anal(RAnal * a,const char * name,ut64 size,const ut8 * bytes,ut64 at)801 R_API bool r_sign_add_anal(RAnal *a, const char *name, ut64 size, const ut8 *bytes, ut64 at) {
802 bool retval = false;
803 r_return_val_if_fail (a && name && size > 0 && bytes, false);
804 ut8 *mask = r_anal_mask (a, size, bytes, at);
805 if (mask) {
806 retval = addBytes (a, name, size, bytes, mask);
807 free (mask);
808 }
809 return retval;
810 }
811
r_sign_fcn_graph(RAnalFunction * fcn)812 static RSignGraph *r_sign_fcn_graph(RAnalFunction *fcn) {
813 r_return_val_if_fail (fcn, false);
814 RSignGraph *graph = R_NEW0 (RSignGraph);
815 if (graph) {
816 graph->cc = r_anal_function_complexity (fcn),
817 graph->nbbs = r_list_length (fcn->bbs);
818 graph->edges = r_anal_function_count_edges (fcn, &graph->ebbs);
819 graph->bbsum = r_anal_function_realsize (fcn);
820 }
821 return graph;
822 }
823
bb_sort_by_addr(const void * x,const void * y)824 static int bb_sort_by_addr(const void *x, const void *y) {
825 RAnalBlock *a = (RAnalBlock *)x;
826 RAnalBlock *b = (RAnalBlock *)y;
827 if (a->addr > b->addr) {
828 return 1;
829 }
830 if (a->addr < b->addr) {
831 return -1;
832 }
833 return 0;
834 }
835
r_sign_fcn_bytes(RAnal * a,RAnalFunction * fcn)836 static RSignBytes *r_sign_fcn_bytes(RAnal *a, RAnalFunction *fcn) {
837 r_return_val_if_fail (a && fcn && fcn->bbs && fcn->bbs->head, false);
838
839 // get size
840 RCore *core = a->coreb.core;
841 int maxsz = a->coreb.cfggeti (core, "zign.maxsz");
842 r_list_sort (fcn->bbs, &bb_sort_by_addr);
843 ut64 ea = fcn->addr;
844 RAnalBlock *bb = (RAnalBlock *)fcn->bbs->tail->data;
845 int size = R_MIN (bb->addr + bb->size - ea, maxsz);
846
847 // alloc space for signature
848 RSignBytes *sig = R_NEW0 (RSignBytes);
849 if (!sig) {
850 goto bytes_failed;
851 }
852 if (!(sig->bytes = malloc (size))) {
853 goto bytes_failed;
854 }
855 if (!(sig->mask = malloc (size))) {
856 goto bytes_failed;
857 }
858 memset (sig->mask, 0, size);
859 sig->size = size;
860
861 // fill in bytes
862 if (!a->iob.read_at (a->iob.io, ea, sig->bytes, size)) {
863 eprintf ("error: failed to read at 0x%08" PFMT64x "\n", ea);
864 goto bytes_failed;
865 }
866
867 ut8 *tmpmask = NULL;
868 RListIter *iter;
869 r_list_foreach (fcn->bbs, iter, bb) {
870 if (bb->addr >= ea) {
871 size_t delta = bb->addr - ea;
872 size_t rsize = bb->size;
873
874 // bounds check
875 if (delta > size) {
876 break;
877 }
878 if (size - delta < rsize) {
879 rsize = size - delta;
880 }
881
882 // get mask for block
883 if (!(tmpmask = r_anal_mask (a, rsize, sig->bytes + delta, ea))) {
884 goto bytes_failed;
885 }
886 if (rsize > 0) {
887 memcpy (sig->mask + delta, tmpmask, rsize);
888 }
889 free (tmpmask);
890 }
891 }
892
893 return sig;
894 bytes_failed:
895 r_sign_bytes_free (sig);
896 return NULL;
897 }
898
r_sign_fcn_bbhash(RAnal * a,RAnalFunction * fcn)899 static RSignHash *r_sign_fcn_bbhash(RAnal *a, RAnalFunction *fcn) {
900 r_return_val_if_fail (a && fcn, NULL);
901 RSignHash *hash = R_NEW0 (RSignHash);
902 if (!hash) {
903 return NULL;
904 }
905
906 char *digest_hex = r_sign_calc_bbhash (a, fcn);
907 if (!digest_hex) {
908 free (hash);
909 return NULL;
910 }
911 hash->bbhash = digest_hex;
912 return hash;
913 }
914
r_sign_addto_item(RAnal * a,RSignItem * it,RAnalFunction * fcn,RSignType type)915 R_API bool r_sign_addto_item(RAnal *a, RSignItem *it, RAnalFunction *fcn, RSignType type) {
916 r_return_val_if_fail (a && it && fcn, false);
917 switch (type) {
918 case R_SIGN_GRAPH:
919 return !it->graph && (it->graph = r_sign_fcn_graph (fcn));
920 case R_SIGN_BYTES:
921 return !it->bytes && (it->bytes = r_sign_fcn_bytes (a, fcn));
922 case R_SIGN_XREFS:
923 return !it->xrefs && (it->xrefs = r_sign_fcn_xrefs (a, fcn));
924 case R_SIGN_REFS:
925 return !it->refs && (it->refs = r_sign_fcn_refs (a, fcn));
926 case R_SIGN_VARS:
927 return !it->vars && (it->vars = r_sign_fcn_vars (a, fcn));
928 case R_SIGN_TYPES:
929 return !it->types && (it->types = r_sign_fcn_types (a, fcn));
930 case R_SIGN_BBHASH:
931 return !it->hash && (it->hash = r_sign_fcn_bbhash (a, fcn));
932 case R_SIGN_OFFSET:
933 it->addr = fcn->addr;
934 return true;
935 case R_SIGN_NAME:
936 if (!it->realname && it->name) {
937 if (strcmp (it->name, fcn->name)) {
938 it->realname = strdup (fcn->name);
939 }
940 return true;
941 }
942 break;
943 default:
944 eprintf ("Error: %s Can not handle type %c\n", __FUNCTION__, type);
945 }
946
947 return false;
948 }
949
r_sign_add_graph(RAnal * a,const char * name,RSignGraph graph)950 R_API bool r_sign_add_graph(RAnal *a, const char *name, RSignGraph graph) {
951 r_return_val_if_fail (a && !R_STR_ISEMPTY (name), false);
952 bool retval = true;
953 RSignItem *it = r_sign_item_new ();
954 if (!it) {
955 return false;
956 }
957 it->name = r_str_new (name);
958 if (!it->name) {
959 free (it);
960 return false;
961 }
962 it->space = r_spaces_current (&a->zign_spaces);
963 it->graph = R_NEW0 (RSignGraph);
964 if (!it->graph) {
965 free (it->name);
966 free (it);
967 return false;
968 }
969 *it->graph = graph;
970 retval = r_sign_add_item (a, it);
971 r_sign_item_free (it);
972
973 return retval;
974 }
975
r_sign_add_comment(RAnal * a,const char * name,const char * comment)976 R_API bool r_sign_add_comment(RAnal *a, const char *name, const char *comment) {
977 r_return_val_if_fail (a && name && comment, false);
978
979 RSignItem *it = r_sign_item_new ();
980 if (!it) {
981 return false;
982 }
983 it->name = r_str_new (name);
984 it->space = r_spaces_current (&a->zign_spaces);
985 it->comment = strdup (comment);
986 bool retval = r_sign_add_item (a, it);
987 r_sign_item_free (it);
988 return retval;
989 }
990
r_sign_add_name(RAnal * a,const char * name,const char * realname)991 R_API bool r_sign_add_name(RAnal *a, const char *name, const char *realname) {
992 r_return_val_if_fail (a && name && realname, false);
993 RSignItem *it = r_sign_item_new ();
994 if (it) {
995 it->name = r_str_new (name);
996 it->realname = strdup (realname);
997 it->space = r_spaces_current (&a->zign_spaces);
998 bool retval = r_sign_add_item (a, it);
999 r_sign_item_free (it);
1000 return retval;
1001 }
1002 return false;
1003 }
1004
r_sign_add_addr(RAnal * a,const char * name,ut64 addr)1005 R_API bool r_sign_add_addr(RAnal *a, const char *name, ut64 addr) {
1006 r_return_val_if_fail (a && name && addr != UT64_MAX, false);
1007
1008 RSignItem *it = r_sign_item_new ();
1009 if (!it) {
1010 return NULL;
1011 }
1012 it->name = r_str_new (name);
1013 it->space = r_spaces_current (&a->zign_spaces);
1014 it->addr = addr;
1015
1016 bool retval = r_sign_add_item (a, it);
1017
1018 r_sign_item_free (it);
1019
1020 return retval;
1021 }
1022
r_sign_add_vars(RAnal * a,const char * name,RList * vars)1023 R_API bool r_sign_add_vars(RAnal *a, const char *name, RList *vars) {
1024 r_return_val_if_fail (a && name && vars, false);
1025
1026 RListIter *iter;
1027 char *var;
1028
1029 RSignItem *it = r_sign_item_new ();
1030 if (!it) {
1031 return false;
1032 }
1033 it->name = r_str_new (name);
1034 if (!it->name) {
1035 r_sign_item_free (it);
1036 return false;
1037 }
1038 it->space = r_spaces_current (&a->zign_spaces);
1039 it->vars = r_list_newf ((RListFree)free);
1040 r_list_foreach (vars, iter, var) {
1041 r_list_append (it->vars, strdup (var));
1042 }
1043 bool retval = r_sign_add_item (a, it);
1044 r_sign_item_free (it);
1045
1046 return retval;
1047 }
1048
r_sign_add_types(RAnal * a,const char * name,RList * types)1049 R_API bool r_sign_add_types(RAnal *a, const char *name, RList *types) {
1050 r_return_val_if_fail (a && name && types, false);
1051
1052 RListIter *iter;
1053 char *type;
1054
1055 RSignItem *it = r_sign_item_new ();
1056 if (!it) {
1057 return false;
1058 }
1059 it->name = r_str_new (name);
1060 if (!it->name) {
1061 r_sign_item_free (it);
1062 return false;
1063 }
1064 it->space = r_spaces_current (&a->zign_spaces);
1065 it->types = r_list_newf ((RListFree) free);
1066 r_list_foreach (types, iter, type) {
1067 r_list_append (it->types, strdup (type));
1068 }
1069 bool retval = r_sign_add_item (a, it);
1070 r_sign_item_free (it);
1071
1072 return retval;
1073 }
1074
r_sign_add_refs(RAnal * a,const char * name,RList * refs)1075 R_API bool r_sign_add_refs(RAnal *a, const char *name, RList *refs) {
1076 r_return_val_if_fail (a && name && refs, false);
1077
1078 char *ref;
1079 RListIter *iter;
1080 RSignItem *it = r_sign_item_new ();
1081 if (!it) {
1082 return false;
1083 }
1084 it->name = r_str_new (name);
1085 if (!it->name) {
1086 free (it);
1087 return false;
1088 }
1089 it->space = r_spaces_current (&a->zign_spaces);
1090 it->refs = r_list_newf ((RListFree) free);
1091 r_list_foreach (refs, iter, ref) {
1092 r_list_append (it->refs, strdup (ref));
1093 }
1094 bool retval = r_sign_add_item (a, it);
1095 r_sign_item_free (it);
1096
1097 return retval;
1098 }
1099
r_sign_add_xrefs(RAnal * a,const char * name,RList * xrefs)1100 R_API bool r_sign_add_xrefs(RAnal *a, const char *name, RList *xrefs) {
1101 r_return_val_if_fail (a && name && xrefs, false);
1102
1103 RListIter *iter = NULL;
1104 char *ref = NULL;
1105 RSignItem *it = r_sign_item_new ();
1106 if (!it) {
1107 return false;
1108 }
1109 it->name = r_str_new (name);
1110 if (!it->name) {
1111 free (it);
1112 return false;
1113 }
1114 it->space = r_spaces_current (&a->zign_spaces);
1115 it->xrefs = r_list_newf ((RListFree) free);
1116 r_list_foreach (xrefs, iter, ref) {
1117 r_list_append (it->xrefs, strdup (ref));
1118 }
1119 bool retval = r_sign_add_item (a, it);
1120 r_sign_item_free (it);
1121
1122 return retval;
1123 }
1124
1125 struct ctxDeleteCB {
1126 RAnal *anal;
1127 char buf[R_SIGN_KEY_MAXSZ];
1128 };
1129
deleteBySpaceCB(void * user,const char * k,const char * v)1130 static bool deleteBySpaceCB(void *user, const char *k, const char *v) {
1131 struct ctxDeleteCB *ctx = (struct ctxDeleteCB *) user;
1132 if (!strncmp (k, ctx->buf, strlen (ctx->buf))) {
1133 sdb_remove (ctx->anal->sdb_zigns, k, 0);
1134 }
1135 return true;
1136 }
1137
r_sign_delete(RAnal * a,const char * name)1138 R_API bool r_sign_delete(RAnal *a, const char *name) {
1139 struct ctxDeleteCB ctx = {0};
1140 char k[R_SIGN_KEY_MAXSZ];
1141
1142 if (!a || !name) {
1143 return false;
1144 }
1145 // Remove all zigns
1146 if (*name == '*') {
1147 if (!r_spaces_current (&a->zign_spaces)) {
1148 sdb_reset (a->sdb_zigns);
1149 return true;
1150 }
1151 ctx.anal = a;
1152 serializeKey (a, r_spaces_current (&a->zign_spaces), "", ctx.buf);
1153 sdb_foreach (a->sdb_zigns, deleteBySpaceCB, &ctx);
1154 return true;
1155 }
1156 // Remove specific zign
1157 serializeKey (a, r_spaces_current (&a->zign_spaces), name, k);
1158 return sdb_remove (a->sdb_zigns, k, 0);
1159 }
1160
build_combined_bytes(RSignBytes * bsig)1161 static ut8 * build_combined_bytes(RSignBytes *bsig) {
1162 r_return_val_if_fail (bsig && bsig->bytes && bsig->mask, NULL);
1163 ut8 *buf = (ut8 *)malloc (bsig->size);
1164 if (buf) {
1165 size_t i;
1166 for (i = 0; i < bsig->size; i++) {
1167 buf[i] = bsig->bytes[i] & bsig->mask[i];
1168 }
1169 }
1170 return buf;
1171 }
1172
cmp_bytesig_to_buff(RSignBytes * sig,ut8 * buf,int len)1173 static double cmp_bytesig_to_buff(RSignBytes *sig, ut8 *buf, int len) {
1174 r_return_val_if_fail (sig && buf && len >= 0, (double)-1.0);
1175 ut8 *sigbuf = build_combined_bytes (sig);
1176 double sim = -1.0;
1177 if (sigbuf) {
1178 r_diff_buffers_distance (NULL, sigbuf, sig->size, buf, len, NULL, &sim);
1179 free (sigbuf);
1180 }
1181 return sim;
1182 }
1183
matchBytes(RSignItem * a,RSignItem * b)1184 static double matchBytes(RSignItem *a, RSignItem *b) {
1185 double result = 0.0;
1186
1187 if (!a->bytes || !b->bytes) {
1188 return result;
1189 }
1190
1191 size_t min_size = R_MIN ((size_t)a->bytes->size, (size_t)b->bytes->size);
1192 if (!min_size) {
1193 return result;
1194 }
1195
1196 ut8 *combined_mask = NULL;
1197 if (a->bytes->mask || b->bytes->mask) {
1198 combined_mask = (ut8*)malloc (min_size);
1199 if (!combined_mask) {
1200 return result;
1201 }
1202 memcpy (combined_mask, a->bytes->mask, min_size);
1203 if (b->bytes->mask) {
1204 int i;
1205 for (i = 0; i != min_size; i++) {
1206 combined_mask[i] &= b->bytes->mask[i];
1207 }
1208 }
1209 }
1210
1211 if ((combined_mask && !r_mem_cmp_mask (a->bytes->bytes, b->bytes->bytes, combined_mask, min_size)) ||
1212 (!combined_mask && !memcmp (a->bytes->bytes, b->bytes->bytes, min_size))) {
1213 result = (double)min_size / (double)R_MAX (a->bytes->size, b->bytes->size);
1214 }
1215
1216 free (combined_mask);
1217
1218 return result;
1219 }
1220
1221 #define SIMILARITY(a, b) \
1222 ((a) == (b)? 1.0: (R_MAX ((a), (b)) == 0.0? 0.0: (double)R_MIN ((a), (b)) / (double)R_MAX ((a), (b))))
1223
matchGraph(RSignItem * a,RSignItem * b)1224 static double matchGraph(RSignItem *a, RSignItem *b) {
1225 if (!a->graph || !b->graph) {
1226 return 0.0;
1227 }
1228
1229 double total = 0.0;
1230
1231 total += SIMILARITY (a->graph->cc, b->graph->cc);
1232 total += SIMILARITY (a->graph->nbbs, b->graph->nbbs);
1233 total += SIMILARITY (a->graph->ebbs, b->graph->ebbs);
1234 total += SIMILARITY (a->graph->edges, b->graph->edges);
1235 total += SIMILARITY (a->graph->bbsum, b->graph->bbsum);
1236
1237 return total / 5.0;
1238 }
1239
score_cmpr(const void * a,const void * b)1240 static int score_cmpr(const void *a, const void *b) {
1241 double sa = ((RSignCloseMatch *)a)->score;
1242 double sb = ((RSignCloseMatch *)b)->score;
1243
1244 if (sa < sb) {
1245 return 1;
1246 }
1247 if (sa > sb) {
1248 return -1;
1249 }
1250 return 0;
1251 }
1252
1253 typedef struct {
1254 RSignItem *test;
1255 RList *output;
1256 size_t count;
1257 double score_threshold;
1258 ut8 *bytes_combined;
1259
1260 // greatest lower bound. Thanks lattice theory for helping name variables
1261 double infimum;
1262 } ClosestMatchData;
1263
closest_match_update(ClosestMatchData * data,RSignItem * it)1264 static bool closest_match_update(ClosestMatchData *data, RSignItem *it) {
1265 // quantify how close the signature matches
1266 int div = 0;
1267 double score = 0.0;
1268 double gscore = -1.0;
1269 if (it->graph && data->test->graph) {
1270 gscore = matchGraph (it, data->test);
1271 score += gscore;
1272 div++;
1273 }
1274 double bscore = -1.0;
1275 bool list_full = (r_list_length (data->output) == data->count);
1276
1277 // value to beat to enter the list
1278 double pivot = data->score_threshold;
1279 if (list_full) {
1280 pivot = R_MAX (pivot, data->infimum);
1281 }
1282
1283 if (it->bytes && data->bytes_combined) {
1284 int sizea = it->bytes->size;
1285 int sizeb = data->test->bytes->size;
1286 if (pivot > 0.0) {
1287 // bytes distance is slow. To avoid it, we can do quick maths to
1288 // see if the highest possible score would be good enough to change
1289 // results
1290 double maxscore = R_MIN (sizea, sizeb) / R_MAX (sizea, sizeb);
1291 if (div > 0) {
1292 maxscore = (maxscore + score) / div;
1293 }
1294 if (maxscore < pivot) {
1295 r_sign_item_free (it);
1296 return true;
1297 }
1298 }
1299
1300 // get true byte score
1301 bscore = cmp_bytesig_to_buff (it->bytes, data->bytes_combined, sizeb);
1302 score += bscore;
1303 div++;
1304 }
1305 if (div == 0) {
1306 r_sign_item_free (it);
1307 return true;
1308 }
1309 score /= div;
1310
1311 // score is too low, don't bother doing any more work
1312 if (score < pivot) {
1313 r_sign_item_free (it);
1314 return true;
1315 }
1316
1317 // add new element
1318 RSignCloseMatch *row = R_NEW (RSignCloseMatch);
1319 if (!row) {
1320 r_sign_item_free (it);
1321 return false;
1322 }
1323 row->score = score;
1324 row->gscore = gscore;
1325 row->bscore = bscore;
1326 row->item = it;
1327 r_list_add_sorted (data->output, (void *)row, &score_cmpr);
1328
1329 if (list_full) {
1330 // remove smallest element
1331 r_sign_close_match_free (r_list_pop (data->output));
1332
1333 // get new infimum
1334 row = r_list_get_top (data->output);
1335 data->infimum = row->score;
1336 }
1337 return true;
1338 }
1339
closest_match_callback(void * a,const char * name,const char * value)1340 static bool closest_match_callback(void *a, const char *name, const char *value) {
1341 ClosestMatchData *data = (ClosestMatchData *)a;
1342
1343 // get signature in usable format
1344 RSignItem *it = r_sign_item_new ();
1345 if (!it) {
1346 return false;
1347 }
1348 if (!r_sign_deserialize (a, it, name, value)) {
1349 r_sign_item_free (it);
1350 return false;
1351 }
1352
1353 return closest_match_update (data, it);
1354 }
1355
r_sign_close_match_free(RSignCloseMatch * match)1356 R_API void r_sign_close_match_free(RSignCloseMatch *match) {
1357 if (match) {
1358 r_sign_item_free (match->item);
1359 free (match);
1360 }
1361 }
1362
r_sign_find_closest_sig(RAnal * a,RSignItem * it,int count,double score_threshold)1363 R_API RList *r_sign_find_closest_sig(RAnal *a, RSignItem *it, int count, double score_threshold) {
1364 r_return_val_if_fail (a && it && count > 0 && score_threshold >= 0 && score_threshold <= 1, NULL);
1365
1366 // need at least one acceptable signature type
1367 r_return_val_if_fail (it->bytes || it->graph, NULL);
1368
1369 ClosestMatchData data;
1370 RList *output = r_list_newf ((RListFree)r_sign_close_match_free);
1371 if (!output) {
1372 return NULL;
1373 }
1374
1375 data.output = output;
1376 data.count = count;
1377 data.score_threshold = score_threshold;
1378 data.infimum = 0.0;
1379 data.test = it;
1380 if (it->bytes) {
1381 data.bytes_combined = build_combined_bytes (it->bytes);
1382 } else {
1383 data.bytes_combined = NULL;
1384 }
1385
1386 // TODO: handle sign spaces
1387 if (!sdb_foreach (a->sdb_zigns, &closest_match_callback, (void *)&data)) {
1388 r_list_free (output);
1389 output = NULL;
1390 }
1391
1392 free (data.bytes_combined);
1393 return output;
1394 }
1395
r_sign_find_closest_fcn(RAnal * a,RSignItem * it,int count,double score_threshold)1396 R_API RList *r_sign_find_closest_fcn(RAnal *a, RSignItem *it, int count, double score_threshold) {
1397 r_return_val_if_fail (a && it && count > 0 && score_threshold >= 0 && score_threshold <= 1, NULL);
1398 r_return_val_if_fail (it->bytes || it->graph, NULL);
1399
1400 RList *output = r_list_newf ((RListFree)r_sign_close_match_free);
1401 if (!output) {
1402 return NULL;
1403 }
1404
1405 ClosestMatchData data;
1406 data.output = output;
1407 data.count = count;
1408 data.score_threshold = score_threshold;
1409 data.infimum = 0.0;
1410 data.test = it;
1411 if (it->bytes) {
1412 data.bytes_combined = build_combined_bytes (it->bytes);
1413 } else {
1414 data.bytes_combined = NULL;
1415 }
1416
1417 RAnalFunction *fcn;
1418 RListIter *iter;
1419 r_list_foreach (a->fcns, iter, fcn) {
1420 // turn function into signature item
1421 RSignItem *fsig = r_sign_item_new ();
1422 if (!fsig) {
1423 r_list_free (output);
1424 return NULL;
1425 }
1426 if (data.bytes_combined) {
1427 r_sign_addto_item (a, fsig, fcn, R_SIGN_BYTES);
1428 }
1429 if (it->graph) {
1430 r_sign_addto_item (a, fsig, fcn, R_SIGN_GRAPH);
1431 }
1432 r_sign_addto_item (a, fsig, fcn, R_SIGN_OFFSET);
1433 fsig->name = r_str_new (fcn->name);
1434
1435 // maybe add signature item to output list
1436 closest_match_update (&data, fsig);
1437 }
1438 free (data.bytes_combined);
1439 return output;
1440 }
1441
r_sign_diff(RAnal * a,RSignOptions * options,const char * other_space_name)1442 R_API bool r_sign_diff(RAnal *a, RSignOptions *options, const char *other_space_name) {
1443 r_return_val_if_fail (a && other_space_name, false);
1444
1445 RSpace *current_space = r_spaces_current (&a->zign_spaces);
1446 if (!current_space) {
1447 return false;
1448 }
1449 RSpace *other_space = r_spaces_get (&a->zign_spaces, other_space_name);
1450 if (!other_space) {
1451 return false;
1452 }
1453
1454 RList *la = deserialize_sign_space (a, current_space);
1455 if (!la) {
1456 return false;
1457 }
1458 RList *lb = deserialize_sign_space (a, other_space);
1459 if (!lb) {
1460 r_list_free (la);
1461 return false;
1462 }
1463
1464 eprintf ("Diff %d %d\n", (int)ls_length (la), (int)ls_length (lb));
1465
1466 RListIter *itr;
1467 RListIter *itr2;
1468 RSignItem *si;
1469 RSignItem *si2;
1470
1471 // do the sign diff here
1472 r_list_foreach (la, itr, si) {
1473 if (strstr (si->name, "imp.")) {
1474 continue;
1475 }
1476 r_list_foreach (lb, itr2, si2) {
1477 if (strstr (si2->name, "imp.")) {
1478 continue;
1479 }
1480 double bytesScore = matchBytes (si, si2);
1481 double graphScore = matchGraph (si, si2);
1482 bool bytesMatch = bytesScore >= (options ? options->bytes_diff_threshold : SIGN_DIFF_MATCH_BYTES_THRESHOLD);
1483 bool graphMatch = graphScore >= (options ? options->graph_diff_threshold : SIGN_DIFF_MATCH_GRAPH_THRESHOLD);
1484
1485 if (bytesMatch) {
1486 a->cb_printf ("0x%08" PFMT64x " 0x%08"PFMT64x " %02.5lf B %s\n", si->addr, si2->addr, bytesScore, si->name);
1487 }
1488
1489 if (graphMatch) {
1490 a->cb_printf ("0x%08" PFMT64x " 0x%08"PFMT64x" %02.5lf G %s\n", si->addr, si2->addr, graphScore, si->name);
1491 }
1492 }
1493 }
1494
1495 r_list_free (la);
1496 r_list_free (lb);
1497 return true;
1498 }
1499
r_sign_diff_by_name(RAnal * a,RSignOptions * options,const char * other_space_name,bool not_matching)1500 R_API bool r_sign_diff_by_name(RAnal *a, RSignOptions *options, const char *other_space_name, bool not_matching) {
1501 r_return_val_if_fail (a && other_space_name, false);
1502
1503 RSpace *current_space = r_spaces_current (&a->zign_spaces);
1504 if (!current_space) {
1505 return false;
1506 }
1507 RSpace *other_space = r_spaces_get (&a->zign_spaces, other_space_name);
1508 if (!other_space) {
1509 return false;
1510 }
1511
1512 RList *la = deserialize_sign_space (a, current_space);
1513 if (!la) {
1514 return false;
1515 }
1516 RList *lb = deserialize_sign_space (a, other_space);
1517 if (!lb) {
1518 return false;
1519 }
1520
1521 eprintf ("Diff by name %d %d (%s)\n", (int)ls_length (la), (int)ls_length (lb), not_matching? "not matching" : "matching");
1522
1523 RListIter *itr;
1524 RListIter *itr2;
1525 RSignItem *si;
1526 RSignItem *si2;
1527 size_t current_space_name_len = strlen (current_space->name);
1528 size_t other_space_name_len = strlen (other_space->name);
1529
1530 r_list_foreach (la, itr, si) {
1531 if (strstr (si->name, "imp.")) {
1532 continue;
1533 }
1534 r_list_foreach (lb, itr2, si2) {
1535 if (strcmp (si->name + current_space_name_len + 1, si2->name + other_space_name_len + 1)) {
1536 continue;
1537 }
1538 // TODO: add config variable for threshold
1539 double bytesScore = matchBytes (si, si2);
1540 double graphScore = matchGraph (si, si2);
1541 bool bytesMatch = bytesScore >= (options ? options->bytes_diff_threshold : SIGN_DIFF_MATCH_BYTES_THRESHOLD);
1542 bool graphMatch = graphScore >= (options ? options->graph_diff_threshold : SIGN_DIFF_MATCH_GRAPH_THRESHOLD);
1543 if ((bytesMatch && !not_matching) || (!bytesMatch && not_matching)) {
1544 a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %02.5f B %s\n", si->addr, si2->addr, bytesScore, si->name);
1545 }
1546 if ((graphMatch && !not_matching) || (!graphMatch && not_matching)) {
1547 a->cb_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %02.5f G %s\n", si->addr, si2->addr, graphScore, si->name);
1548 }
1549 }
1550 }
1551
1552 r_list_free (la);
1553 r_list_free (lb);
1554
1555 return true;
1556 }
1557
1558 struct ctxListCB {
1559 RAnal *anal;
1560 int idx;
1561 int format;
1562 PJ *pj;
1563 };
1564
1565 struct ctxGetListCB {
1566 RAnal *anal;
1567 RList *list;
1568 };
1569
listBytes(RAnal * a,RSignItem * it,PJ * pj,int format)1570 static void listBytes(RAnal *a, RSignItem *it, PJ *pj, int format) {
1571 RSignBytes *bytes = it->bytes;
1572
1573 if (!bytes->bytes) {
1574 return;
1575 }
1576
1577 int masked = 0, i = 0;
1578 for (i = 0; i < bytes->size; i++) {
1579 masked += bytes->mask[i] == 0xff;
1580 }
1581
1582 char * strbytes = r_hex_bin2strdup (bytes->bytes, bytes->size);
1583 if (!strbytes) {
1584 return;
1585 }
1586 char * strmask = r_hex_bin2strdup (bytes->mask, bytes->size);
1587 if (!strmask) {
1588 free (strbytes);
1589 return;
1590 }
1591
1592 if (format == '*') {
1593 if (masked == bytes->size) {
1594 a->cb_printf ("za %s b %s\n", it->name, strbytes);
1595 } else {
1596 a->cb_printf ("za %s b %s:%s\n", it->name, strbytes, strmask);
1597 }
1598 } else if (format == 'q') {
1599 a->cb_printf (" b(%d/%d)", masked, bytes->size);
1600 } else if (format == 'j') {
1601 pj_ks (pj, "bytes", strbytes);
1602 pj_ks (pj, "mask", strmask);
1603 } else {
1604 a->cb_printf (" bytes: %s\n", strbytes);
1605 a->cb_printf (" mask: %s\n", strmask);
1606 }
1607
1608 free (strbytes);
1609 free (strmask);
1610 }
1611
listGraph(RAnal * a,RSignItem * it,PJ * pj,int format)1612 static void listGraph(RAnal *a, RSignItem *it, PJ *pj, int format) {
1613 RSignGraph *graph = it->graph;
1614
1615 if (format == 'q') {
1616 a->cb_printf (" g(cc=%d,nb=%d,e=%d,eb=%d,h=%d)",
1617 graph->cc, graph->nbbs, graph->edges, graph->ebbs, graph->bbsum);
1618 } else if (format == '*') {
1619 a->cb_printf ("za %s g cc=%d nbbs=%d edges=%d ebbs=%d bbsum=%d\n",
1620 it->name, graph->cc, graph->nbbs, graph->edges, graph->ebbs, graph->bbsum);
1621 } else if (format == 'j') {
1622 pj_ko (pj, "graph");
1623 pj_kN (pj, "cc", graph->cc);
1624 pj_kN (pj, "nbbs", graph->nbbs);
1625 pj_kN (pj, "edges", graph->edges);
1626 pj_kN (pj, "ebbs", graph->ebbs);
1627 pj_kN (pj, "bbsum", graph->bbsum);
1628 pj_end (pj);
1629 } else {
1630 a->cb_printf (" graph: cc=%d nbbs=%d edges=%d ebbs=%d bbsum=%d\n",
1631 graph->cc, graph->nbbs, graph->edges, graph->ebbs, graph->bbsum);
1632 }
1633 }
1634
listComment(RAnal * a,RSignItem * it,PJ * pj,int format)1635 static void listComment(RAnal *a, RSignItem *it, PJ *pj, int format) {
1636 if (it->comment) {
1637 if (format == 'q') {
1638 // a->cb_printf (" addr(0x%08"PFMT64x")", it->addr);
1639 a->cb_printf ("\n ; %s\n", it->comment);
1640 } else if (format == '*') {
1641 a->cb_printf ("%s\n", it->comment); // comment injection via CCu..
1642 } else if (format == 'j') {
1643 pj_ks (pj, "comments", it->comment);
1644 } else {
1645 a->cb_printf (" comment: 0x%08" PFMT64x "\n", it->addr);
1646 }
1647 }
1648 }
1649
listRealname(RAnal * a,RSignItem * it,PJ * pj,int format)1650 static void listRealname(RAnal *a, RSignItem *it, PJ *pj, int format) {
1651 if (it->realname) {
1652 if (format == 'q') {
1653 // a->cb_printf (" addr(0x%08"PFMT64x")", it->addr);
1654 } else if (format == '*') {
1655 a->cb_printf ("za %s n %s\n", it->name, it->realname);
1656 a->cb_printf ("afn %s @ 0x%08"PFMT64x"\n", it->realname, it->addr);
1657 } else if (format == 'j') {
1658 pj_ks (pj, "realname", it->realname);
1659 } else {
1660 a->cb_printf (" realname: %s\n", it->realname);
1661 }
1662 }
1663 }
1664
listOffset(RAnal * a,RSignItem * it,PJ * pj,int format)1665 static void listOffset(RAnal *a, RSignItem *it, PJ *pj, int format) {
1666 if (format == 'q') {
1667 // a->cb_printf (" addr(0x%08"PFMT64x")", it->addr);
1668 } else if (format == '*') {
1669 a->cb_printf ("za %s o 0x%08"PFMT64x"\n", it->name, it->addr);
1670 } else if (format == 'j') {
1671 pj_kN (pj, "addr", it->addr);
1672 } else {
1673 a->cb_printf (" addr: 0x%08"PFMT64x"\n", it->addr);
1674 }
1675 }
1676
listVars(RAnal * a,RSignItem * it,PJ * pj,int format)1677 static void listVars(RAnal *a, RSignItem *it, PJ *pj, int format) {
1678 RListIter *iter = NULL;
1679 char *var = NULL;
1680 int i = 0;
1681
1682 if (format == '*') {
1683 a->cb_printf ("za %s v ", it->name);
1684 } else if (format == 'q') {
1685 a->cb_printf (" vars(%d)", r_list_length (it->vars));
1686 return;
1687 } else if (format == 'j') {
1688 pj_ka (pj, "vars");
1689 } else {
1690 a->cb_printf (" vars: ");
1691 }
1692
1693 r_list_foreach (it->vars, iter, var) {
1694 if (i > 0) {
1695 if (format == '*') {
1696 a->cb_printf (" ");
1697 } else if (format != 'j') {
1698 a->cb_printf (", ");
1699 }
1700 }
1701 if (format == 'j') {
1702 pj_s (pj, var);
1703 } else {
1704 a->cb_printf ("%s", var);
1705 }
1706 i++;
1707 }
1708
1709 if (format == 'j') {
1710 pj_end (pj);
1711 } else {
1712 a->cb_printf ("\n");
1713 }
1714 }
1715
print_list_type_header(RAnal * a,RSignItem * it,PJ * pj,int format)1716 static void print_list_type_header(RAnal *a, RSignItem *it, PJ *pj, int format) {
1717 if (format == '*') {
1718 a->cb_printf ("za %s t ", it->name);
1719 } else if (format == 'q') {
1720 a->cb_printf (" types(%d)", r_list_length (it->types));
1721 return;
1722 } else if (format == 'j') {
1723 pj_ka (pj, "types");
1724 } else {
1725 a->cb_printf (" types: ");
1726 }
1727 }
1728
print_function_args_json(RAnal * a,PJ * pj,char * arg_type)1729 static void print_function_args_json(RAnal *a, PJ *pj, char *arg_type) {
1730 char *arg_name = strchr (arg_type, ',');
1731
1732 if (arg_name == NULL) {
1733 return;
1734 }
1735
1736 *arg_name = '\0';
1737 ++arg_name;
1738
1739 size_t len_arg_name = strlen (arg_name);
1740 arg_name[len_arg_name - 1] = '\0';
1741
1742 pj_o (pj);
1743 pj_ks (pj, "name", arg_name);
1744 pj_ks (pj, "type", arg_type + 1);
1745 pj_end (pj);
1746 }
1747
print_type_json(RAnal * a,char * type,PJ * pj,size_t pos)1748 static void print_type_json(RAnal *a, char *type, PJ *pj, size_t pos) {
1749 if (pos == 0) {
1750 return;
1751 }
1752
1753 char *str_type = strchr (type, '=');
1754
1755 if (str_type == NULL) {
1756 return;
1757 }
1758
1759 *str_type = '\0';
1760 ++str_type;
1761
1762 print_function_args_json (a, pj, str_type);
1763 }
1764
print_list_separator(RAnal * a,RSignItem * it,PJ * pj,int format,int pos)1765 static void print_list_separator(RAnal *a, RSignItem *it, PJ *pj, int format, int pos) {
1766 if (pos == 0 || format == 'j') {
1767 return;
1768 }
1769 if (format == '*') {
1770 a->cb_printf (" ");
1771 } else {
1772 a->cb_printf (", ");
1773 }
1774 }
1775
print_list_type_body(RAnal * a,RSignItem * it,PJ * pj,int format)1776 static void print_list_type_body(RAnal *a, RSignItem *it, PJ *pj, int format) {
1777 int i = 0;
1778 char *type = NULL;
1779 RListIter *iter = NULL;
1780
1781 r_list_foreach (it->types, iter, type) {
1782 print_list_separator (a, it, pj, format, i);
1783
1784 if (format == 'j') {
1785 char *t = strdup (type);
1786 print_type_json (a, t, pj, i);
1787 free (t);
1788 } else {
1789 a->cb_printf ("%s", type);
1790 }
1791 i++;
1792 }
1793 }
1794
listTypes(RAnal * a,RSignItem * it,PJ * pj,int format)1795 static void listTypes(RAnal *a, RSignItem *it, PJ *pj, int format) {
1796 print_list_type_header (a, it, pj, format);
1797 print_list_type_body (a, it, pj, format);
1798
1799 if (format == 'j') {
1800 pj_end (pj);
1801 } else {
1802 a->cb_printf ("\n");
1803 }
1804 }
1805
listXRefs(RAnal * a,RSignItem * it,PJ * pj,int format)1806 static void listXRefs(RAnal *a, RSignItem *it, PJ *pj, int format) {
1807 RListIter *iter = NULL;
1808 char *ref = NULL;
1809 int i = 0;
1810
1811 if (format == '*') {
1812 a->cb_printf ("za %s x ", it->name);
1813 } else if (format == 'q') {
1814 a->cb_printf (" xrefs(%d)", r_list_length (it->xrefs));
1815 return;
1816 } else if (format == 'j') {
1817 pj_ka (pj, "xrefs");
1818 } else {
1819 if (it->xrefs && !r_list_empty (it->xrefs)) {
1820 a->cb_printf (" xrefs: ");
1821 }
1822 }
1823
1824 r_list_foreach (it->xrefs, iter, ref) {
1825 if (i > 0) {
1826 if (format == '*') {
1827 a->cb_printf (" ");
1828 } else if (format != 'j') {
1829 a->cb_printf (", ");
1830 }
1831 }
1832 if (format == 'j') {
1833 pj_s (pj, ref);
1834 } else {
1835 a->cb_printf ("%s", ref);
1836 }
1837 i++;
1838 }
1839
1840 if (format == 'j') {
1841 pj_end (pj);
1842 } else {
1843 a->cb_printf ("\n");
1844 }
1845 }
1846
listRefs(RAnal * a,RSignItem * it,PJ * pj,int format)1847 static void listRefs(RAnal *a, RSignItem *it, PJ *pj, int format) {
1848 RListIter *iter = NULL;
1849 char *ref = NULL;
1850 int i = 0;
1851
1852 if (format == '*') {
1853 a->cb_printf ("za %s r ", it->name);
1854 } else if (format == 'q') {
1855 a->cb_printf (" refs(%d)", r_list_length (it->refs));
1856 return;
1857 } else if (format == 'j') {
1858 pj_ka (pj, "refs");
1859 } else {
1860 if (it->refs && !r_list_empty (it->refs)) {
1861 a->cb_printf (" refs: ");
1862 }
1863 }
1864
1865 r_list_foreach (it->refs, iter, ref) {
1866 if (i > 0) {
1867 if (format == '*') {
1868 a->cb_printf (" ");
1869 } else if (format != 'j') {
1870 a->cb_printf (", ");
1871 }
1872 }
1873 if (format == 'j') {
1874 pj_s (pj, ref);
1875 } else {
1876 a->cb_printf ("%s", ref);
1877 }
1878 i++;
1879 }
1880
1881 if (format == 'j') {
1882 pj_end (pj);
1883 } else {
1884 a->cb_printf ("\n");
1885 }
1886 }
1887
listHash(RAnal * a,RSignItem * it,PJ * pj,int format)1888 static void listHash(RAnal *a, RSignItem *it, PJ *pj, int format) {
1889 if (!it->hash) {
1890 return;
1891 }
1892 switch (format) {
1893 case 'q':
1894 if (it->hash->bbhash) {
1895 a->cb_printf (" h(%08x)", r_str_hash (it->hash->bbhash));
1896 }
1897 break;
1898 case '*':
1899 if (it->hash->bbhash) {
1900 a->cb_printf ("za %s h %s\n", it->name, it->hash->bbhash);
1901 }
1902 break;
1903 case 'j':
1904 pj_ko (pj, "hash");
1905 if (it->hash->bbhash) {
1906 pj_ks (pj, "bbhash", it->hash->bbhash);
1907 }
1908 pj_end (pj);
1909 break;
1910 default:
1911 if (it->hash->bbhash) {
1912 a->cb_printf (" bbhash: %s\n", it->hash->bbhash);
1913 }
1914 break;
1915 }
1916 }
1917
listCB(void * user,const char * k,const char * v)1918 static bool listCB(void *user, const char *k, const char *v) {
1919 struct ctxListCB *ctx = (struct ctxListCB *)user;
1920 RSignItem *it = r_sign_item_new ();
1921 RAnal *a = ctx->anal;
1922
1923 if (!r_sign_deserialize (a, it, k, v)) {
1924 eprintf ("error: cannot deserialize zign\n");
1925 goto out;
1926 }
1927
1928 RSpace *cur = r_spaces_current (&a->zign_spaces);
1929 if (cur != it->space && cur) {
1930 goto out;
1931 }
1932
1933 // Start item
1934 if (ctx->format == 'j') {
1935 pj_o (ctx->pj);
1936 }
1937
1938 // Zignspace and name (except for radare format)
1939 if (ctx->format == '*') {
1940 if (it->space) {
1941 a->cb_printf ("zs %s\n", it->space->name);
1942 } else {
1943 a->cb_printf ("zs *\n");
1944 }
1945 } else if (ctx->format == 'q') {
1946 a->cb_printf ("0x%08" PFMT64x " ", it->addr);
1947 const char *pad = r_str_pad (' ', 30 - strlen (it->name));
1948 a->cb_printf ("%s:%s", it->name, pad);
1949 } else if (ctx->format == 'j') {
1950 if (it->space) {
1951 pj_ks (ctx->pj, "zignspace", it->space->name);
1952 }
1953 pj_ks (ctx->pj, "name", it->name);
1954 } else {
1955 if (!r_spaces_current (&a->zign_spaces) && it->space) {
1956 a->cb_printf ("(%s) ", it->space->name);
1957 }
1958 a->cb_printf ("%s:\n", it->name);
1959 }
1960
1961 // Bytes pattern
1962 if (it->bytes) {
1963 listBytes (a, it, ctx->pj, ctx->format);
1964 } else if (ctx->format == 'j') {
1965 pj_ks (ctx->pj, "bytes", "");
1966 }
1967
1968 // Graph metrics
1969 if (it->graph) {
1970 listGraph (a, it, ctx->pj, ctx->format);
1971 } else if (ctx->format == 'j') {
1972 pj_ko (ctx->pj, "graph");
1973 pj_end (ctx->pj);
1974 }
1975
1976 // Offset
1977 if (it->addr != UT64_MAX) {
1978 listOffset (a, it, ctx->pj, ctx->format);
1979 } else if (ctx->format == 'j') {
1980 pj_kN (ctx->pj, "addr", -1);
1981 }
1982 // Name
1983 if (it->realname) {
1984 listRealname (a, it, ctx->pj, ctx->format);
1985 }
1986 if (it->comment) {
1987 listComment (a, it, ctx->pj, ctx->format);
1988 }
1989 // References
1990 if (it->refs) {
1991 listRefs (a, it, ctx->pj, ctx->format);
1992 } else if (ctx->format == 'j') {
1993 pj_ka (ctx->pj, "refs");
1994 pj_end (ctx->pj);
1995 }
1996 // XReferences
1997 if (it->xrefs) {
1998 listXRefs (a, it, ctx->pj, ctx->format);
1999 } else if (ctx->format == 'j') {
2000 pj_ka (ctx->pj, "xrefs");
2001 pj_end (ctx->pj);
2002 }
2003 // Vars
2004 if (it->vars) {
2005 listVars (a, it, ctx->pj, ctx->format);
2006 } else if (ctx->format == 'j') {
2007 pj_ka (ctx->pj, "vars");
2008 pj_end (ctx->pj);
2009 }
2010 if (it->types) {
2011 listTypes (a, it, ctx->pj, ctx->format);
2012 } else if (ctx->format == 'j') {
2013 pj_ka (ctx->pj, "types");
2014 pj_end (ctx->pj);
2015 }
2016 // Hash
2017 if (it->hash) {
2018 listHash (a, it, ctx->pj, ctx->format);
2019 } else if (ctx->format == 'j') {
2020 pj_ko (ctx->pj, "hash");
2021 pj_end (ctx->pj);
2022 }
2023
2024 // End item
2025 if (ctx->format == 'j') {
2026 pj_end (ctx->pj);
2027 }
2028 if (ctx->format == 'q') {
2029 a->cb_printf ("\n");
2030 }
2031
2032 ctx->idx++;
2033
2034 out:
2035 r_sign_item_free (it);
2036
2037 return true;
2038 }
2039
r_sign_list(RAnal * a,int format)2040 R_API void r_sign_list(RAnal *a, int format) {
2041 r_return_if_fail (a);
2042 PJ *pj = NULL;
2043
2044 if (format == 'j') {
2045 pj = a->coreb.pjWithEncoding (a->coreb.core);
2046 pj_a (pj);
2047 }
2048
2049 struct ctxListCB ctx = { a, 0, format, pj };
2050 sdb_foreach (a->sdb_zigns, listCB, &ctx);
2051
2052 if (format == 'j') {
2053 pj_end (pj);
2054 a->cb_printf ("%s\n", pj_string (pj));
2055 pj_free (pj);
2056 }
2057 }
2058
listGetCB(void * user,const char * key,const char * val)2059 static bool listGetCB(void *user, const char *key, const char *val) {
2060 struct ctxGetListCB *ctx = user;
2061 RSignItem *item = r_sign_item_new ();
2062 if (!item) {
2063 return false;
2064 }
2065 if (!r_sign_deserialize (ctx->anal, item, key, val)) {
2066 r_sign_item_free (item);
2067 return false;
2068 }
2069 r_list_append (ctx->list, item);
2070 return true;
2071 }
2072
r_sign_get_list(RAnal * a)2073 R_API RList *r_sign_get_list(RAnal *a) {
2074 r_return_val_if_fail (a, NULL);
2075 struct ctxGetListCB ctx = { a, r_list_newf ((RListFree)r_sign_item_free) };
2076 sdb_foreach (a->sdb_zigns, listGetCB, &ctx);
2077 return ctx.list;
2078 }
2079
cmpaddr(const void * _a,const void * _b)2080 static int cmpaddr(const void *_a, const void *_b) {
2081 const RAnalBlock *a = _a, *b = _b;
2082 return (a->addr - b->addr);
2083 }
2084
r_sign_calc_bbhash(RAnal * a,RAnalFunction * fcn)2085 R_API char *r_sign_calc_bbhash(RAnal *a, RAnalFunction *fcn) {
2086 RListIter *iter = NULL;
2087 RAnalBlock *bbi = NULL;
2088 char *digest_hex = NULL;
2089 RHash *ctx = r_hash_new (true, R_ZIGN_HASH);
2090 if (!ctx) {
2091 goto beach;
2092 }
2093 r_list_sort (fcn->bbs, &cmpaddr);
2094 r_hash_do_begin (ctx, R_ZIGN_HASH);
2095 r_list_foreach (fcn->bbs, iter, bbi) {
2096 ut8 *buf = malloc (bbi->size);
2097 if (!buf) {
2098 goto beach;
2099 }
2100 if (!a->iob.read_at (a->iob.io, bbi->addr, buf, bbi->size)) {
2101 goto beach;
2102 }
2103 if (!r_hash_do_sha256 (ctx, buf, bbi->size)) {
2104 goto beach;
2105 }
2106 free (buf);
2107 }
2108 r_hash_do_end (ctx, R_ZIGN_HASH);
2109
2110 digest_hex = r_hex_bin2strdup (ctx->digest, r_hash_size (R_ZIGN_HASH));
2111 beach:
2112 free (ctx);
2113 return digest_hex;
2114 }
2115
2116 struct ctxCountForCB {
2117 RAnal *anal;
2118 const RSpace *space;
2119 int count;
2120 };
2121
countForCB(void * user,const char * k,const char * v)2122 static bool countForCB(void *user, const char *k, const char *v) {
2123 struct ctxCountForCB *ctx = (struct ctxCountForCB *) user;
2124 RSignItem *it = r_sign_item_new ();
2125
2126 if (r_sign_deserialize (ctx->anal, it, k, v)) {
2127 if (it->space == ctx->space) {
2128 ctx->count++;
2129 }
2130 } else {
2131 eprintf ("error: cannot deserialize zign\n");
2132 }
2133 r_sign_item_free (it);
2134
2135 return true;
2136 }
2137
r_sign_space_count_for(RAnal * a,const RSpace * space)2138 R_API int r_sign_space_count_for(RAnal *a, const RSpace *space) {
2139 struct ctxCountForCB ctx = { a, space, 0 };
2140 r_return_val_if_fail (a, 0);
2141 sdb_foreach (a->sdb_zigns, countForCB, &ctx);
2142 return ctx.count;
2143 }
2144
2145 struct ctxUnsetForCB {
2146 RAnal *anal;
2147 const RSpace *space;
2148 };
2149
unsetForCB(void * user,const char * k,const char * v)2150 static bool unsetForCB(void *user, const char *k, const char *v) {
2151 struct ctxUnsetForCB *ctx = (struct ctxUnsetForCB *) user;
2152 char nk[R_SIGN_KEY_MAXSZ], nv[R_SIGN_VAL_MAXSZ];
2153 RSignItem *it = r_sign_item_new ();
2154 Sdb *db = ctx->anal->sdb_zigns;
2155 if (r_sign_deserialize (ctx->anal, it, k, v)) {
2156 if (it->space && it->space == ctx->space) {
2157 it->space = NULL;
2158 serialize (ctx->anal, it, nk, nv);
2159 sdb_remove (db, k, 0);
2160 sdb_set (db, nk, nv, 0);
2161 }
2162 } else {
2163 eprintf ("error: cannot deserialize zign\n");
2164 }
2165 r_sign_item_free (it);
2166 return true;
2167 }
2168
r_sign_space_unset_for(RAnal * a,const RSpace * space)2169 R_API void r_sign_space_unset_for(RAnal *a, const RSpace *space) {
2170 r_return_if_fail (a);
2171 struct ctxUnsetForCB ctx = { a, space };
2172 sdb_foreach (a->sdb_zigns, unsetForCB, &ctx);
2173 }
2174
2175 struct ctxRenameForCB {
2176 RAnal *anal;
2177 char oprefix[R_SIGN_KEY_MAXSZ];
2178 char nprefix[R_SIGN_KEY_MAXSZ];
2179 };
2180
renameForCB(void * user,const char * k,const char * v)2181 static bool renameForCB(void *user, const char *k, const char *v) {
2182 struct ctxRenameForCB *ctx = (struct ctxRenameForCB *) user;
2183 char nk[R_SIGN_KEY_MAXSZ], nv[R_SIGN_VAL_MAXSZ];
2184 const char *zigname = NULL;
2185 Sdb *db = ctx->anal->sdb_zigns;
2186
2187 if (!strncmp (k, ctx->oprefix, strlen (ctx->oprefix))) {
2188 zigname = k + strlen (ctx->oprefix);
2189 snprintf (nk, R_SIGN_KEY_MAXSZ, "%s%s", ctx->nprefix, zigname);
2190 snprintf (nv, R_SIGN_VAL_MAXSZ, "%s", v);
2191 sdb_remove (db, k, 0);
2192 sdb_set (db, nk, nv, 0);
2193 }
2194 return true;
2195 }
2196
r_sign_space_rename_for(RAnal * a,const RSpace * space,const char * oname,const char * nname)2197 R_API void r_sign_space_rename_for(RAnal *a, const RSpace *space, const char *oname, const char *nname) {
2198 r_return_if_fail (a && space && oname && nname);
2199 struct ctxRenameForCB ctx = {.anal = a};
2200 serializeKeySpaceStr (a, oname, "", ctx.oprefix);
2201 serializeKeySpaceStr (a, nname, "", ctx.nprefix);
2202 sdb_foreach (a->sdb_zigns, renameForCB, &ctx);
2203 }
2204
2205 struct ctxForeachCB {
2206 RAnal *anal;
2207 RSignForeachCallback cb;
2208 bool freeit;
2209 void *user;
2210 };
2211
foreachCB(void * user,const char * k,const char * v)2212 static bool foreachCB(void *user, const char *k, const char *v) {
2213 struct ctxForeachCB *ctx = (struct ctxForeachCB *) user;
2214 RSignItem *it = r_sign_item_new ();
2215 RAnal *a = ctx->anal;
2216
2217 if (r_sign_deserialize (a, it, k, v)) {
2218 RSpace *cur = r_spaces_current (&a->zign_spaces);
2219 if (ctx->cb && cur == it->space) {
2220 ctx->cb (it, ctx->user);
2221 }
2222 } else {
2223 eprintf ("error: cannot deserialize zign\n");
2224 }
2225 if (ctx->freeit) {
2226 r_sign_item_free (it);
2227 }
2228 return true;
2229 }
2230
r_sign_foreach_nofree(RAnal * a,RSignForeachCallback cb,void * user)2231 static bool r_sign_foreach_nofree(RAnal *a, RSignForeachCallback cb, void *user) {
2232 r_return_val_if_fail (a && cb, false);
2233 struct ctxForeachCB ctx = { a, cb, false, user };
2234 return sdb_foreach (a->sdb_zigns, foreachCB, &ctx);
2235 }
2236
r_sign_foreach(RAnal * a,RSignForeachCallback cb,void * user)2237 R_API bool r_sign_foreach(RAnal *a, RSignForeachCallback cb, void *user) {
2238 r_return_val_if_fail (a && cb, false);
2239 struct ctxForeachCB ctx = { a, cb, true, user };
2240 return sdb_foreach (a->sdb_zigns, foreachCB, &ctx);
2241 }
2242
r_sign_search_new(void)2243 R_API RSignSearch *r_sign_search_new(void) {
2244 RSignSearch *ret = R_NEW0 (RSignSearch);
2245 if (ret) {
2246 ret->search = r_search_new (R_SEARCH_KEYWORD);
2247 ret->items = r_list_newf ((RListFree) r_sign_item_free);
2248 }
2249 return ret;
2250 }
2251
r_sign_search_free(RSignSearch * ss)2252 R_API void r_sign_search_free(RSignSearch *ss) {
2253 if (!ss) {
2254 return;
2255 }
2256 r_search_free (ss->search);
2257 r_list_free (ss->items);
2258 free (ss);
2259 }
2260
searchHitCB(RSearchKeyword * kw,void * user,ut64 addr)2261 static int searchHitCB(RSearchKeyword *kw, void *user, ut64 addr) {
2262 RSignSearch *ss = (RSignSearch *) user;
2263 return ss->cb? ss->cb ((RSignItem *) kw->data, kw, addr, ss->user): 1;
2264 }
2265
2266 struct ctxAddSearchKwCB {
2267 RSignSearch *ss;
2268 int minsz;
2269 };
2270
addSearchKwCB(RSignItem * it,void * user)2271 static int addSearchKwCB(RSignItem *it, void *user) {
2272 struct ctxAddSearchKwCB *ctx = (struct ctxAddSearchKwCB *) user;
2273 RSignSearch *ss = ctx->ss;
2274 RSignBytes *bytes = it->bytes;
2275
2276 if (!bytes) {
2277 eprintf ("Cannot find bytes for this signature: %s\n", it->name);
2278 return 1;
2279 }
2280
2281 if (ctx->minsz && bytes->size < ctx->minsz) {
2282 return 1;
2283 }
2284 r_list_append (ss->items, it);
2285 // TODO(nibble): change arg data in r_search_keyword_new to void*
2286 RSearchKeyword *kw = r_search_keyword_new (bytes->bytes, bytes->size, bytes->mask, bytes->size, (const char *)it);
2287 r_search_kw_add (ss->search, kw);
2288 return 1;
2289 }
2290
r_sign_search_init(RAnal * a,RSignSearch * ss,int minsz,RSignSearchCallback cb,void * user)2291 R_API void r_sign_search_init(RAnal *a, RSignSearch *ss, int minsz, RSignSearchCallback cb, void *user) {
2292 struct ctxAddSearchKwCB ctx = { ss, minsz };
2293 r_return_if_fail (a && ss && cb);
2294 ss->cb = cb;
2295 ss->user = user;
2296 r_list_purge (ss->items);
2297 r_search_reset (ss->search, R_SEARCH_KEYWORD);
2298 r_sign_foreach_nofree (a, addSearchKwCB, &ctx);
2299 r_search_begin (ss->search);
2300 r_search_set_callback (ss->search, searchHitCB, ss);
2301 }
2302
r_sign_search_update(RAnal * a,RSignSearch * ss,ut64 * at,const ut8 * buf,int len)2303 R_API int r_sign_search_update(RAnal *a, RSignSearch *ss, ut64 *at, const ut8 *buf, int len) {
2304 r_return_val_if_fail (a && ss && buf && len > 0, 0);
2305 return r_search_update (ss->search, *at, buf, len);
2306 }
2307
2308 // allow ~10% of margin error
matchCount(int a,int b)2309 static int matchCount(int a, int b) {
2310 int c = a - b;
2311 int m = a / 10;
2312 return R_ABS (c) < m;
2313 }
2314
fcnMetricsCmp(RSignItem * it,RAnalFunction * fcn)2315 static bool fcnMetricsCmp(RSignItem *it, RAnalFunction *fcn) {
2316 RSignGraph *graph = it->graph;
2317 int ebbs = -1;
2318
2319 if (graph->cc != -1 && graph->cc != r_anal_function_complexity (fcn)) {
2320 return false;
2321 }
2322 if (graph->nbbs != -1 && graph->nbbs != r_list_length (fcn->bbs)) {
2323 return false;
2324 }
2325 if (graph->edges != -1 && graph->edges != r_anal_function_count_edges (fcn, &ebbs)) {
2326 return false;
2327 }
2328 if (graph->ebbs != -1 && graph->ebbs != ebbs) {
2329 return false;
2330 }
2331 if (graph->bbsum > 0 && matchCount (graph->bbsum, r_anal_function_linear_size (fcn))) {
2332 return false;
2333 }
2334 return true;
2335 }
2336
graph_match(RSignItem * it,RSignSearchMetrics * sm)2337 static bool graph_match(RSignItem *it, RSignSearchMetrics *sm) {
2338 RSignGraph *graph = it->graph;
2339
2340 if (!graph) {
2341 return false;
2342 }
2343
2344 if (graph->cc < sm->mincc) {
2345 return false;
2346 }
2347
2348 if (!fcnMetricsCmp (it, sm->fcn)) {
2349 return false;
2350 }
2351
2352 return true;
2353 }
2354
addr_match(RSignItem * it,RSignSearchMetrics * sm)2355 static bool addr_match(RSignItem *it, RSignSearchMetrics *sm) {
2356 if (it->addr != sm->fcn->addr || it->addr == UT64_MAX) {
2357 return false;
2358 }
2359 return true;
2360 }
2361
hash_match(RSignItem * it,char ** digest_hex,RSignSearchMetrics * sm)2362 static bool hash_match(RSignItem *it, char **digest_hex, RSignSearchMetrics *sm) {
2363 RSignHash *hash = it->hash;
2364 if (!hash || !hash->bbhash || hash->bbhash[0] == 0) {
2365 return false;
2366 }
2367
2368 if (!*digest_hex) {
2369 *digest_hex = r_sign_calc_bbhash (sm->anal, sm->fcn);
2370 }
2371 if (strcmp (hash->bbhash, *digest_hex)) {
2372 return false;
2373 }
2374 return true;
2375 }
2376
str_list_equals(RList * la,RList * lb)2377 static bool str_list_equals(RList *la, RList *lb) {
2378 r_return_val_if_fail (la && lb, false);
2379 size_t len = r_list_length (la);
2380 if (len != r_list_length (lb)) {
2381 return false;
2382 }
2383 size_t i;
2384 for (i = 0; i < len; i++) {
2385 const char *a = r_list_get_n (la, i);
2386 const char *b = r_list_get_n (lb, i);
2387 if (strcmp (a, b)) {
2388 return false;
2389 }
2390 }
2391 return true;
2392 }
2393
vars_match(RSignItem * it,RList ** vars,RSignSearchMetrics * sm)2394 static bool vars_match(RSignItem *it, RList **vars, RSignSearchMetrics *sm) {
2395 r_return_val_if_fail (vars && sm, false);
2396 if (!it->vars) {
2397 return false;
2398 }
2399
2400 if (!*vars) {
2401 *vars = r_sign_fcn_vars (sm->anal, sm->fcn);
2402 if (!*vars) {
2403 return false;
2404 }
2405 }
2406
2407 if (str_list_equals (*vars, it->vars)) {
2408 return true;
2409 }
2410 return false;
2411 }
2412
refs_match(RSignItem * it,RList ** refs,RSignSearchMetrics * sm)2413 static bool refs_match(RSignItem *it, RList **refs, RSignSearchMetrics *sm) {
2414 r_return_val_if_fail (refs && sm, false);
2415 if (!it->refs) {
2416 return false;
2417 }
2418
2419 if (!*refs) {
2420 *refs = r_sign_fcn_refs (sm->anal, sm->fcn);
2421 if (!*refs) {
2422 return false;
2423 }
2424 }
2425
2426 if (str_list_equals (*refs, it->refs)) {
2427 return true;
2428 }
2429 return false;
2430 }
2431
types_match(RSignItem * it,RList ** types,RSignSearchMetrics * sm)2432 static bool types_match(RSignItem *it, RList **types, RSignSearchMetrics *sm) {
2433 r_return_val_if_fail (types && sm, false);
2434 if (!it->types) {
2435 return false;
2436 }
2437
2438 if (!*types) {
2439 *types = r_sign_fcn_types (sm->anal, sm->fcn);
2440 if (!*types) {
2441 return false;
2442 }
2443 }
2444
2445 if (str_list_equals (*types, it->types)) {
2446 return true;
2447 }
2448 return false;
2449 }
2450
2451 struct metric_ctx {
2452 int matched;
2453 RSignSearchMetrics *sm;
2454 RList *refs;
2455 RList *types;
2456 RList *vars;
2457 char *digest_hex;
2458 };
2459
match_metrics(RSignItem * it,void * user)2460 static int match_metrics(RSignItem *it, void *user) {
2461 struct metric_ctx *ctx = (struct metric_ctx *)user;
2462 RSignSearchMetrics *sm = ctx->sm;
2463 RSignType type;
2464 int count = 0;
2465 int i = 0;
2466 while ((type = sm->types[i++])) {
2467 bool found = false;
2468 switch (type) {
2469 case R_SIGN_GRAPH:
2470 found = graph_match (it, sm);
2471 break;
2472 case R_SIGN_OFFSET:
2473 found = addr_match (it, sm);
2474 break;
2475 case R_SIGN_BBHASH:
2476 found = hash_match (it, &ctx->digest_hex, sm);
2477 break;
2478 case R_SIGN_REFS:
2479 found = refs_match (it, &ctx->refs, sm);
2480 break;
2481 case R_SIGN_TYPES:
2482 found = vars_match (it, &ctx->vars, sm);
2483 break;
2484 case R_SIGN_VARS:
2485 found = types_match (it, &ctx->types, sm);
2486 break;
2487 default:
2488 eprintf ("Invalid type: %c\n", type);
2489 }
2490 if (found) {
2491 sm->cb (it, sm->fcn, type, (count > 1), sm->user);
2492 count++;
2493 }
2494 }
2495 ctx->matched += count;
2496 return count? 0: 1;
2497 }
2498
r_sign_fcn_match_metrics(RSignSearchMetrics * sm)2499 R_API int r_sign_fcn_match_metrics(RSignSearchMetrics *sm) {
2500 r_return_val_if_fail (sm && sm->mincc >= 0 && sm->anal && sm->fcn, false);
2501 struct metric_ctx ctx = { 0, sm, NULL, NULL, NULL, NULL };
2502 r_sign_foreach (sm->anal, match_metrics, (void *)&ctx);
2503 r_list_free (ctx.refs);
2504 r_list_free (ctx.types);
2505 r_list_free (ctx.vars);
2506 free (ctx.digest_hex);
2507 return ctx.matched;
2508 }
2509
r_sign_item_new(void)2510 R_API RSignItem *r_sign_item_new(void) {
2511 RSignItem *ret = R_NEW0 (RSignItem);
2512 if (ret) {
2513 ret->addr = UT64_MAX;
2514 ret->space = NULL;
2515 }
2516 return ret;
2517 }
2518
r_sign_item_free(RSignItem * item)2519 R_API void r_sign_item_free(RSignItem *item) {
2520 if (!item) {
2521 return;
2522 }
2523 free (item->name);
2524 r_sign_bytes_free (item->bytes);
2525 if (item->hash) {
2526 free (item->hash->bbhash);
2527 free (item->hash);
2528 }
2529 r_sign_graph_free (item->graph);
2530 free (item->comment);
2531 free (item->realname);
2532 r_list_free (item->refs);
2533 r_list_free (item->vars);
2534 r_list_free (item->xrefs);
2535 r_list_free (item->types);
2536 free (item);
2537 }
2538
r_sign_graph_free(RSignGraph * graph)2539 R_API void r_sign_graph_free(RSignGraph *graph) {
2540 free (graph);
2541 }
2542
r_sign_bytes_free(RSignBytes * bytes)2543 R_API void r_sign_bytes_free(RSignBytes *bytes) {
2544 if (bytes) {
2545 free (bytes->bytes);
2546 free (bytes->mask);
2547 free (bytes);
2548 }
2549 }
2550
loadCB(void * user,const char * k,const char * v)2551 static bool loadCB(void *user, const char *k, const char *v) {
2552 RAnal *a = (RAnal *) user;
2553 char nk[R_SIGN_KEY_MAXSZ], nv[R_SIGN_VAL_MAXSZ];
2554 RSignItem *it = r_sign_item_new ();
2555 if (it && r_sign_deserialize (a, it, k, v)) {
2556 serialize (a, it, nk, nv);
2557 sdb_set (a->sdb_zigns, nk, nv, 0);
2558 } else {
2559 eprintf ("error: cannot deserialize zign\n");
2560 }
2561 r_sign_item_free (it);
2562 return true;
2563 }
2564
r_sign_path(RAnal * a,const char * file)2565 R_API char *r_sign_path(RAnal *a, const char *file) {
2566 char *abs = r_file_abspath (file);
2567 if (abs) {
2568 if (r_file_is_regular (abs)) {
2569 return abs;
2570 }
2571 free (abs);
2572 }
2573
2574 if (a->zign_path) {
2575 char *path = r_str_newf ("%s%s%s", a->zign_path, R_SYS_DIR, file);
2576 abs = r_file_abspath (path);
2577 free (path);
2578 if (r_file_is_regular (abs)) {
2579 return abs;
2580 }
2581 free (abs);
2582 } else {
2583 char *home = r_str_home (R2_HOME_ZIGNS);
2584 abs = r_str_newf ("%s%s%s", home, R_SYS_DIR, file);
2585 free (home);
2586 if (r_file_is_regular (abs)) {
2587 return abs;
2588 }
2589 free (abs);
2590 }
2591
2592 abs = r_str_newf (R_JOIN_3_PATHS ("%s", R2_ZIGNS, "%s"), r_sys_prefix (NULL), file);
2593 if (r_file_is_regular (abs)) {
2594 return abs;
2595 }
2596 free (abs);
2597
2598 return NULL;
2599 }
2600
r_sign_load(RAnal * a,const char * file)2601 R_API bool r_sign_load(RAnal *a, const char *file) {
2602 if (!a || !file) {
2603 return false;
2604 }
2605 char *path = r_sign_path (a, file);
2606 if (!r_file_exists (path)) {
2607 eprintf ("error: file %s does not exist\n", file);
2608 free (path);
2609 return false;
2610 }
2611 Sdb *db = sdb_new (NULL, path, 0);
2612 if (!db) {
2613 free (path);
2614 return false;
2615 }
2616 sdb_foreach (db, loadCB, a);
2617 sdb_close (db);
2618 sdb_free (db);
2619 free (path);
2620 return true;
2621 }
2622
r_sign_load_gz(RAnal * a,const char * filename)2623 R_API bool r_sign_load_gz(RAnal *a, const char *filename) {
2624 ut8 *buf = NULL;
2625 int size = 0;
2626 char *tmpfile = NULL;
2627 bool retval = true;
2628
2629 char *path = r_sign_path (a, filename);
2630 if (!r_file_exists (path)) {
2631 eprintf ("error: file %s does not exist\n", filename);
2632 retval = false;
2633 goto out;
2634 }
2635
2636 if (!(buf = r_file_gzslurp (path, &size, 0))) {
2637 eprintf ("error: cannot decompress file\n");
2638 retval = false;
2639 goto out;
2640 }
2641
2642 if (!(tmpfile = r_file_temp ("r2zign"))) {
2643 eprintf ("error: cannot create temp file\n");
2644 retval = false;
2645 goto out;
2646 }
2647
2648 if (!r_file_dump (tmpfile, buf, size, 0)) {
2649 eprintf ("error: cannot dump file\n");
2650 retval = false;
2651 goto out;
2652 }
2653
2654 if (!r_sign_load (a, tmpfile)) {
2655 eprintf ("error: cannot load file\n");
2656 retval = false;
2657 goto out;
2658 }
2659
2660 if (!r_file_rm (tmpfile)) {
2661 eprintf ("error: cannot delete temp file\n");
2662 retval = false;
2663 goto out;
2664 }
2665
2666 out:
2667 free (buf);
2668 free (tmpfile);
2669 free (path);
2670
2671 return retval;
2672 }
2673
r_sign_save(RAnal * a,const char * file)2674 R_API bool r_sign_save(RAnal *a, const char *file) {
2675 r_return_val_if_fail (a && file, false);
2676
2677 if (sdb_isempty (a->sdb_zigns)) {
2678 eprintf ("WARNING: no zignatures to save\n");
2679 return false;
2680 }
2681
2682 Sdb *db = sdb_new (NULL, file, 0);
2683 if (!db) {
2684 return false;
2685 }
2686 sdb_merge (db, a->sdb_zigns);
2687 bool retval = sdb_sync (db);
2688 sdb_close (db);
2689 sdb_free (db);
2690
2691 return retval;
2692 }
2693
r_sign_options_new(const char * bytes_thresh,const char * graph_thresh)2694 R_API RSignOptions *r_sign_options_new(const char *bytes_thresh, const char *graph_thresh) {
2695 RSignOptions *options = R_NEW0 (RSignOptions);
2696 if (!options) {
2697 return NULL;
2698 }
2699
2700 options->bytes_diff_threshold = r_num_get_float (NULL, bytes_thresh);
2701 options->graph_diff_threshold = r_num_get_float (NULL, graph_thresh);
2702
2703 if (options->bytes_diff_threshold > 1.0) {
2704 options->bytes_diff_threshold = 1.0;
2705 }
2706 if (options->bytes_diff_threshold < 0) {
2707 options->bytes_diff_threshold = 0.0;
2708 }
2709 if (options->graph_diff_threshold > 1.0) {
2710 options->graph_diff_threshold = 1.0;
2711 }
2712 if (options->graph_diff_threshold < 0) {
2713 options->graph_diff_threshold = 0.0;
2714 }
2715
2716 return options;
2717 }
2718
r_sign_options_free(RSignOptions * options)2719 R_API void r_sign_options_free(RSignOptions *options) {
2720 R_FREE (options);
2721 }
2722