Use portable Format for Graph Metrics in Zignatures

This commit is contained in:
Florian Märkl 2021-02-01 15:33:18 +01:00 committed by Riccardo Schirone
parent c023766f50
commit 1907784363
5 changed files with 136 additions and 124 deletions

View file

@ -220,7 +220,7 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
}
// Deserialize key: zign|space|name
int n = rz_str_split(k2, '|');
size_t n = rz_str_split(k2, '|');
if (n != 3) {
eprintf("Warning: Skipping signature with invalid key (%s)\n", k);
success = false;
@ -271,15 +271,29 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
DBL_VAL_FAIL(it->comment, RZ_SIGN_COMMENT);
it->comment = strdup(token);
break;
case RZ_SIGN_GRAPH:
case RZ_SIGN_GRAPH: {
DBL_VAL_FAIL(it->graph, RZ_SIGN_GRAPH);
if (strlen(token) == 2 * sizeof(RzSignGraph)) {
it->graph = RZ_NEW0(RzSignGraph);
if (it->graph) {
rz_hex_str2bin(token, (ut8 *)it->graph);
}
char *s = strdup(token);
if (!s) {
break;
}
size_t gn = rz_str_split(s, ',');
if (gn == 5) {
it->graph = RZ_NEW0(RzSignGraph);
const char *t = s;
it->graph->cc = atoi(t);
t = rz_str_word_get_next0(t);
it->graph->nbbs = atoi(t);
t = rz_str_word_get_next0(t);
it->graph->edges = atoi(t);
t = rz_str_word_get_next0(t);
it->graph->ebbs = atoi(t);
t = rz_str_word_get_next0(t);
it->graph->bbsum = atoi(t);
}
free(s);
break;
}
case RZ_SIGN_OFFSET:
DBL_VAL_FAIL((it->addr != UT64_MAX), RZ_SIGN_OFFSET);
it->addr = atoll(token);
@ -389,125 +403,120 @@ static void serializeKeySpaceStr(RzAnalysis *a, const char *space, const char *n
static void serialize(RzAnalysis *a, RzSignItem *it, char *k, char *v) {
RzListIter *iter = NULL;
char *hexbytes = NULL, *hexmask = NULL, *hexgraph = NULL;
char *hexbytes = NULL, *hexmask = NULL;
char *refs = NULL, *xrefs = NULL, *ref = NULL, *var, *vars = NULL;
char *type, *types = NULL;
int i = 0, len = 0;
RzSignBytes *bytes = it->bytes;
RzSignGraph *graph = it->graph;
RzSignHash *hash = it->hash;
if (k) {
serializeKey(a, it->space, it->name, k);
}
if (v) {
if (bytes) {
len = bytes->size * 2 + 1;
hexbytes = calloc(1, len);
hexmask = calloc(1, len);
if (!hexbytes || !hexmask) {
free(hexbytes);
free(hexmask);
return;
}
if (!bytes->bytes) {
bytes->bytes = malloc((bytes->size + 1) * 3);
}
rz_hex_bin2str(bytes->bytes, bytes->size, hexbytes);
if (!bytes->mask) {
bytes->mask = malloc((bytes->size + 1) * 3);
}
rz_hex_bin2str(bytes->mask, bytes->size, hexmask);
}
if (graph) {
hexgraph = calloc(1, sizeof(RzSignGraph) * 2 + 1);
if (hexgraph) {
rz_hex_bin2str((ut8 *)graph, sizeof(RzSignGraph), hexgraph);
}
}
i = 0;
rz_list_foreach (it->refs, iter, ref) {
if (i > 0) {
refs = rz_str_appendch(refs, ',');
}
refs = rz_str_append(refs, ref);
i++;
}
i = 0;
rz_list_foreach (it->xrefs, iter, ref) {
if (i > 0) {
xrefs = rz_str_appendch(xrefs, ',');
}
xrefs = rz_str_append(xrefs, ref);
i++;
}
i = 0;
rz_list_foreach (it->vars, iter, var) {
if (i > 0) {
vars = rz_str_appendch(vars, ',');
}
vars = rz_str_append(vars, var);
i++;
}
i = 0;
rz_list_foreach (it->types, iter, type) {
if (i > 0) {
types = rz_str_appendch(types, ',');
}
types = rz_str_append(types, type);
i++;
}
RzStrBuf *sb = rz_strbuf_new("");
if (bytes) {
// TODO: do not hardcoded s,b,m here, use RzSignType enum
rz_strbuf_appendf(sb, "|s:%d|b:%s|m:%s", bytes->size, hexbytes, hexmask);
}
if (it->addr != UT64_MAX) {
rz_strbuf_appendf(sb, "|%c:%" PFMT64d, RZ_SIGN_OFFSET, it->addr);
}
if (graph) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_GRAPH, hexgraph);
}
if (refs) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_REFS, refs);
}
if (xrefs) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_XREFS, xrefs);
}
if (vars) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_VARS, vars);
}
if (types) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_TYPES, types);
}
if (it->comment) {
// b64 encoded
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_COMMENT, it->comment);
}
if (it->realname) {
// b64 encoded
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_NAME, it->realname);
}
if (hash && hash->bbhash) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_BBHASH, hash->bbhash);
}
if (rz_strbuf_length(sb) >= RZ_SIGN_VAL_MAXSZ) {
eprintf("Signature limit reached for 0x%08" PFMT64x " (%s)\n", it->addr, it->name);
}
char *res = rz_strbuf_drain(sb);
if (res) {
strncpy(v, res, RZ_SIGN_VAL_MAXSZ);
free(res);
}
free(hexbytes);
free(hexmask);
free(hexgraph);
free(refs);
free(vars);
free(xrefs);
free(types);
if (!v) {
return;
}
if (bytes) {
len = bytes->size * 2 + 1;
hexbytes = calloc(1, len);
hexmask = calloc(1, len);
if (!hexbytes || !hexmask) {
free(hexbytes);
free(hexmask);
return;
}
if (!bytes->bytes) {
bytes->bytes = malloc((bytes->size + 1) * 3);
}
rz_hex_bin2str(bytes->bytes, bytes->size, hexbytes);
if (!bytes->mask) {
bytes->mask = malloc((bytes->size + 1) * 3);
}
rz_hex_bin2str(bytes->mask, bytes->size, hexmask);
}
i = 0;
rz_list_foreach (it->refs, iter, ref) {
if (i > 0) {
refs = rz_str_appendch(refs, ',');
}
refs = rz_str_append(refs, ref);
i++;
}
i = 0;
rz_list_foreach (it->xrefs, iter, ref) {
if (i > 0) {
xrefs = rz_str_appendch(xrefs, ',');
}
xrefs = rz_str_append(xrefs, ref);
i++;
}
i = 0;
rz_list_foreach (it->vars, iter, var) {
if (i > 0) {
vars = rz_str_appendch(vars, ',');
}
vars = rz_str_append(vars, var);
i++;
}
i = 0;
rz_list_foreach (it->types, iter, type) {
if (i > 0) {
types = rz_str_appendch(types, ',');
}
types = rz_str_append(types, type);
i++;
}
RzStrBuf *sb = rz_strbuf_new("");
if (bytes) {
// TODO: do not hardcoded s,b,m here, use RzSignType enum
rz_strbuf_appendf(sb, "|s:%d|b:%s|m:%s", bytes->size, hexbytes, hexmask);
}
if (it->addr != UT64_MAX) {
rz_strbuf_appendf(sb, "|%c:%" PFMT64d, RZ_SIGN_OFFSET, it->addr);
}
if (it->graph) {
rz_strbuf_appendf(sb, "|%c:%d,%d,%d,%d,%d", RZ_SIGN_GRAPH,
it->graph->cc, it->graph->nbbs, it->graph->edges,
it->graph->ebbs, it->graph->bbsum);
}
if (refs) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_REFS, refs);
}
if (xrefs) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_XREFS, xrefs);
}
if (vars) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_VARS, vars);
}
if (types) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_TYPES, types);
}
if (it->comment) {
// b64 encoded
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_COMMENT, it->comment);
}
if (it->realname) {
// b64 encoded
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_NAME, it->realname);
}
if (hash && hash->bbhash) {
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_BBHASH, hash->bbhash);
}
if (rz_strbuf_length(sb) >= RZ_SIGN_VAL_MAXSZ) {
eprintf("Signature limit reached for 0x%08" PFMT64x " (%s)\n", it->addr, it->name);
}
char *res = rz_strbuf_drain(sb);
if (res) {
strncpy(v, res, RZ_SIGN_VAL_MAXSZ);
free(res);
}
free(hexbytes);
free(hexmask);
free(refs);
free(vars);
free(xrefs);
free(types);
}
static RzList *deserialize_sign_space(RzAnalysis *a, RzSpace *space) {

View file

@ -51,7 +51,7 @@ RZ_API char *rz_str_sanitize_sdb_key(const char *s);
RZ_API const char *rz_str_casestr(const char *a, const char *b);
RZ_API const char *rz_str_firstbut(const char *s, char ch, const char *but);
RZ_API const char *rz_str_lastbut(const char *s, char ch, const char *but);
RZ_API int rz_str_split(char *str, char ch);
RZ_API size_t rz_str_split(char *str, char ch);
RZ_API RzList *rz_str_split_list(char *str, const char *c, int n);
RZ_API RzList *rz_str_split_duplist(const char *str, const char *c, bool trim);
RZ_API RzList *rz_str_split_duplist_n(const char *str, const char *c, int n, bool trim);
@ -102,6 +102,9 @@ RZ_API int rz_str_char_count(const char *string, char ch);
RZ_API char *rz_str_word_get0set(char *stra, int stralen, int idx, const char *newstr, int *newlen);
RZ_API int rz_str_word_set0(char *str);
RZ_API int rz_str_word_set0_stack(char *str);
static inline const char *rz_str_word_get_next0(const char *str) {
return str + strlen(str) + 1;
}
RZ_API const char *rz_str_word_get0(const char *str, int idx);
RZ_API char *rz_str_word_get_first(const char *string);
RZ_API void rz_str_trim(char *str);

View file

@ -328,9 +328,9 @@ RZ_API int rz_str_delta(char *p, char a, char b) {
* Replaces all instances of \p ch in \p str with a NULL byte and it returns
* the number of split strings.
*/
RZ_API int rz_str_split(char *str, char ch) {
RZ_API size_t rz_str_split(char *str, char ch) {
rz_return_val_if_fail(str, 0);
int i;
size_t i;
char *p;
for (i = 1, p = str; *p; p++) {
if (*p == ch) {
@ -524,10 +524,10 @@ RZ_API const char *rz_str_word_get0(const char *str, int idx) {
int i;
const char *ptr = str;
if (!ptr || idx < 0 /* prevent crashes with negative index */) {
return (char *)nullstr;
return nullstr;
}
for (i = 0; i != idx; i++) {
ptr += strlen(ptr) + 1;
ptr = rz_str_word_get_next0(ptr);
}
return ptr;
}

View file

@ -1434,7 +1434,7 @@ Sdb *sign_ref_db() {
sdb_set(spaces, "name", "zs", 0);
Sdb *spaces_spaces = sdb_ns(spaces, "spaces", true);
sdb_set(spaces_spaces, "koridai", "s", 0);
sdb_set(db, "zign|*|sym.mahboi", "|s:4|b:deadbeef|m:c0ffee42|o:4919|g:7b0000000b0000000c0000000d0000002a000000|r:gwonam,link|x:king,ganon|v:r16,s42,b13|t:func.sym.mahboi.ret=char *,func.sym.mahboi.args=2,func.sym.mahboi.arg.0=\"int,arg0\",func.sym.mahboi.arg.1=\"uint32_t,die\"|c:This peace is what all true warriors strive for|n:sym.Mah.Boi|h:7bfa1358c427e26bc03c2384f41de7be6ebc01958a57e9a6deda5bdba9768851", 0);
sdb_set(db, "zign|*|sym.mahboi", "|s:4|b:deadbeef|m:c0ffee42|o:4919|g:123,11,12,13,42|r:gwonam,link|x:king,ganon|v:r16,s42,b13|t:func.sym.mahboi.ret=char *,func.sym.mahboi.args=2,func.sym.mahboi.arg.0=\"int,arg0\",func.sym.mahboi.arg.1=\"uint32_t,die\"|c:This peace is what all true warriors strive for|n:sym.Mah.Boi|h:7bfa1358c427e26bc03c2384f41de7be6ebc01958a57e9a6deda5bdba9768851", 0);
sdb_set(db, "zign|koridai|sym.boring", "|c:gee it sure is boring around here", 0);
return db;
}
@ -1836,4 +1836,4 @@ int all_tests() {
return tests_passed != tests_run;
}
mu_main(all_tests)
mu_main(all_tests)

View file

@ -149,7 +149,7 @@ bool test_rz_str_case(void) {
bool test_rz_str_split(void) {
char *hi = strdup("hello world");
int r = rz_str_split(hi, ' ');
size_t r = rz_str_split(hi, ' ');
mu_assert_eq(r, 2, "split on space");
char *hello = hi;
char *world = hi + 6;