Apply types on matching zignature data ##signatures (#15746)
* Implement new zignature types format * Adapt zignature types deserialization to new format * Integrate fcn types when zignatures match
This commit is contained in:
parent
3c788a4967
commit
0efbb81c91
|
@ -67,6 +67,40 @@ R_API RList *r_sign_fcn_vars(RAnal *a, RAnalFunction *fcn) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
R_API RList *r_sign_fcn_types(RAnal *a, RAnalFunction *fcn) {
|
||||
|
||||
// From anal/types/*:
|
||||
// Get key-value types from sdb matching "func.%s", fcn->name
|
||||
// Get func.%s.args (number of args)
|
||||
// Get type,name pairs
|
||||
// Put everything in RList following the next format:
|
||||
// types: main.ret=%type%, main.args=%num%, main.arg.0="int,argc", ...
|
||||
|
||||
r_return_val_if_fail (a && fcn, NULL);
|
||||
|
||||
RList *ret = r_list_newf ((RListFree) free);
|
||||
char *args_expr = r_str_newf ("func.%s.args", fcn->name), *arg = NULL;
|
||||
const char *ret_type = sdb_const_get (a->sdb_types, r_str_newf ("func.%s.ret", fcn->name), 0);
|
||||
const char *fcntypes = sdb_const_get (a->sdb_types, args_expr, 0);
|
||||
int argc = 0;
|
||||
|
||||
if (fcntypes) {
|
||||
if (ret_type) {
|
||||
r_list_append (ret, r_str_newf ("func.%s.ret=%s", fcn->name, ret_type));
|
||||
}
|
||||
argc = atoi (fcntypes);
|
||||
r_list_append (ret, r_str_newf ("func.%s.args=%d", fcn->name, argc));
|
||||
for (int i = 0; i < argc; i++) {
|
||||
arg = sdb_get (a->sdb_types, r_str_newf ("func.%s.arg.%d", fcn->name, i), 0);
|
||||
r_list_append (ret, r_str_newf ("func.%s.arg.%d=\"%s\"", fcn->name, i, arg));
|
||||
}
|
||||
}
|
||||
|
||||
free (arg);
|
||||
free (args_expr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API RList *r_sign_fcn_xrefs(RAnal *a, RAnalFunction *fcn) {
|
||||
RListIter *iter = NULL;
|
||||
RAnalRef *refi = NULL;
|
||||
|
@ -119,12 +153,35 @@ R_API RList *r_sign_fcn_refs(RAnal *a, RAnalFunction *fcn) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static RList *zign_types_to_list(RAnal *a, char *types) {
|
||||
RList *ret = r_list_newf ((RListFree) free);
|
||||
unsigned int i = 0, prev = 0, len = strlen (types);
|
||||
bool quoted = false;
|
||||
char *token = NULL;
|
||||
|
||||
for (i = 0; i <= len; i++) {
|
||||
if (types[i] == '"') {
|
||||
quoted = !quoted;
|
||||
}
|
||||
else if ((types[i] == ',' && !quoted) || types[i] == '\0') {
|
||||
token = r_str_ndup (types + prev, i - prev);
|
||||
if (token) {
|
||||
prev = i + 1;
|
||||
r_list_append (ret, strdup (token));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (token);
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API bool r_sign_deserialize(RAnal *a, RSignItem *it, const char *k, const char *v) {
|
||||
char *refs = NULL;
|
||||
char *vars = NULL;
|
||||
char *types = NULL;
|
||||
const char *token = NULL;
|
||||
int i = 0, n = 0, nrefs = 0, nvars = 0, ntypes = 0, size = 0, w = 0;
|
||||
int i = 0, n = 0, nrefs = 0, nvars = 0, size = 0, w = 0;
|
||||
|
||||
r_return_val_if_fail (a && it && k && v, false);
|
||||
|
||||
|
@ -225,13 +282,7 @@ R_API bool r_sign_deserialize(RAnal *a, RSignItem *it, const char *k, const char
|
|||
break;
|
||||
case R_SIGN_TYPES:
|
||||
types = r_str_new (token);
|
||||
ntypes = r_str_split (types, ',');
|
||||
if (ntypes > 0) {
|
||||
it->types = r_list_newf ((RListFree) free);
|
||||
for (i = 0; i < ntypes; i++) {
|
||||
r_list_append (it->types, r_str_newf (r_str_word_get0 (types, i)));
|
||||
}
|
||||
}
|
||||
it->types = zign_types_to_list (a, types);
|
||||
break;
|
||||
case R_SIGN_BBHASH:
|
||||
if (token[0] != 0) {
|
||||
|
@ -2081,7 +2132,7 @@ static int typesMatchCB(RSignItem *it, void *user) {
|
|||
return 1;
|
||||
}
|
||||
// TODO(nibble | oxcabe): slow operation, add cache
|
||||
types = r_anal_types_from_fcn (ctx->anal, ctx->fcn);
|
||||
types = r_sign_fcn_types (ctx->anal, ctx->fcn);
|
||||
if (!types) {
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -833,6 +833,11 @@ static void __add_vars_sdb(RCore *core, RAnalFunction *fcn) {
|
|||
arg_count++;
|
||||
}
|
||||
}
|
||||
if (arg_count > 0) {
|
||||
char *query = r_str_newf ("anal/types/func.%s.args=%d", fcn->name, arg_count);
|
||||
sdb_querys (core->sdb, NULL, 0, query);
|
||||
free (query);
|
||||
}
|
||||
}
|
||||
|
||||
static bool cmd_anal_aaft(RCore *core) {
|
||||
|
|
|
@ -161,7 +161,7 @@ static bool addFcnVars(RCore *core, RAnalFunction *fcn, const char *name) {
|
|||
}
|
||||
|
||||
static bool addFcnTypes(RCore *core, RAnalFunction *fcn, const char *name) {
|
||||
RList *types = r_anal_types_from_fcn (core->anal, fcn);
|
||||
RList *types = r_sign_fcn_types (core->anal, fcn);
|
||||
if (!types) {
|
||||
return false;
|
||||
}
|
||||
|
@ -731,21 +731,116 @@ struct ctxSearchCB {
|
|||
const char *prefix;
|
||||
};
|
||||
|
||||
static void addFlag(RCore *core, RSignItem *it, ut64 addr, int size, int count, const char* prefix, bool rad) {
|
||||
const char *zign_prefix = r_config_get (core->config, "zign.prefix");
|
||||
char *name = r_str_newf ("%s.%s.%s_%d", zign_prefix, prefix, it->name, count);
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
if (rad) {
|
||||
r_cons_printf ("f %s %d @ 0x%08"PFMT64x"\n", name, size, addr);
|
||||
if (it->realname) {
|
||||
r_cons_printf ("\"afn %s @ 0x%08"PFMT64x"\"\n", it->realname, addr); // XXX command injection
|
||||
static bool __fcnstrValidField(char *field, int i) {
|
||||
char *arg_number = r_str_newf ("%d", i);
|
||||
int is_ret = strcmp (field, "ret");
|
||||
int is_args = strcmp (field, "args");
|
||||
int is_arg = strcmp (field, "arg");
|
||||
int is_arg_number = strcmp (field, arg_number);
|
||||
|
||||
free (arg_number);
|
||||
|
||||
return !(is_ret && is_args && is_arg && is_arg_number);
|
||||
}
|
||||
|
||||
static const char *types_list_to_fcnstr(RList *types) {
|
||||
char *type_kv = NULL, *k = NULL, *v = NULL;
|
||||
char *field = NULL, *name = NULL, *rettype = NULL;
|
||||
char *arg = NULL, *ret = NULL;
|
||||
int nargs = 0, i = 0, j = 0;
|
||||
RList *args = r_list_new ();
|
||||
RListIter *iter;
|
||||
|
||||
r_list_foreach (types, iter, type_kv) {
|
||||
k = strtok (type_kv, "=");
|
||||
v = strtok (NULL, "\0");
|
||||
|
||||
strtok (k, ".");
|
||||
name = strtok (NULL, ".");
|
||||
field = strtok (NULL, ".");
|
||||
|
||||
while (!__fcnstrValidField (field, i) && field) {
|
||||
name = field;
|
||||
field = strtok (NULL, ".");
|
||||
}
|
||||
|
||||
if (!strcmp (field, "args")) {
|
||||
nargs = atoi (v);
|
||||
} else if (!strcmp (field, "ret")) {
|
||||
rettype = v;
|
||||
} else {
|
||||
if (i < nargs) {
|
||||
arg = strdup (v);
|
||||
for (j = 0; j < strlen (arg); j++) {
|
||||
if (arg[j] == ',') {
|
||||
arg[j] = ' ';
|
||||
}
|
||||
}
|
||||
r_list_append (args, r_str_ndup (arg + 1,
|
||||
strlen (arg) - 2));
|
||||
free (arg);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
r_flag_set (core->flags, name, addr, size);
|
||||
}
|
||||
free (name);
|
||||
|
||||
if (!rettype) {
|
||||
rettype = strdup ("void"); // workaround for "afs" bug
|
||||
}
|
||||
|
||||
ret = r_str_newf ("%s %s(", rettype, name);
|
||||
|
||||
r_list_foreach (args, iter, arg) {
|
||||
if (iter != r_list_tail (args)) {
|
||||
ret = r_str_newf ("%s%s, ", ret, arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (r_list_length (args) > 0) {
|
||||
ret = r_str_newf ("%s%s);", ret, (char *)r_list_get_top (args));
|
||||
} else {
|
||||
ret = r_str_newf ("%s);", ret);
|
||||
}
|
||||
|
||||
r_list_free (args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void addFlag(RCore *core, RSignItem *it, ut64 addr, int size, int count, const char* prefix, bool rad) {
|
||||
RAnalFunction *fcn = NULL;
|
||||
const char *zign_prefix = r_config_get (core->config, "zign.prefix");
|
||||
char *name = NULL;
|
||||
|
||||
if (it->types) {
|
||||
const char *fcnstr = types_list_to_fcnstr (it->types);
|
||||
char *fcnstr_copy = strdup (fcnstr);
|
||||
fcn = r_anal_get_fcn_in (core->anal, it->addr, 0);
|
||||
if (fcn) {
|
||||
const char *fcn_name = strrchr (r_str_trim_tail (strtok (fcnstr_copy, "(")), ' ');
|
||||
// __setFunctionName() ; cmd_anal.c:2535 ; Expand into R_API function
|
||||
free (fcn->name);
|
||||
fcn->name = strdup (fcn_name + 1);
|
||||
if (core->anal->cb.on_fcn_rename) {
|
||||
core->anal->cb.on_fcn_rename (core->anal, core->anal->user, fcn, fcn->name);
|
||||
}
|
||||
r_anal_str_to_fcn (core->anal, fcn, fcnstr);
|
||||
}
|
||||
if (fcnstr_copy) {
|
||||
free (fcnstr_copy);
|
||||
}
|
||||
}
|
||||
name = r_name_filter2 (r_str_newf ("%s.%s.%s_%d", zign_prefix, prefix, it->name, count));
|
||||
if (name) {
|
||||
if (rad) {
|
||||
r_cons_printf ("f %s %d @ 0x%08"PFMT64x"\n", name, size, addr);
|
||||
if (it->realname) {
|
||||
r_cons_printf ("\"afn %s @ 0x%08"PFMT64x"\"\n", it->realname, addr); // XXX command injection
|
||||
}
|
||||
} else {
|
||||
r_flag_set (core->flags, name, addr, size);
|
||||
}
|
||||
free (name);
|
||||
}
|
||||
}
|
||||
|
||||
static int searchHitCB(RSignItem *it, RSearchKeyword *kw, ut64 addr, void *user) {
|
||||
|
@ -884,7 +979,7 @@ static bool search(RCore *core, bool rad, bool only_func) {
|
|||
}
|
||||
|
||||
// Function search
|
||||
// TODO (oxcabe): This big conditionals should be refactored into a variable
|
||||
// TODO (oxcabe): Refactor big conditional
|
||||
if (useGraph || useOffset || useRefs || useHash || (useBytes && only_func) || useTypes) {
|
||||
eprintf ("[+] searching function metrics\n");
|
||||
r_cons_break_push (NULL, NULL);
|
||||
|
@ -943,7 +1038,7 @@ TODO: add useXRefs, useName
|
|||
}
|
||||
|
||||
hits = bytes_search_ctx.count + graph_match_ctx.count +
|
||||
offset_match_ctx.count + refs_match_ctx.count + hash_match_ctx.count;
|
||||
offset_match_ctx.count + refs_match_ctx.count + hash_match_ctx.count + types_match_ctx.count;
|
||||
eprintf ("hits: %d\n", hits);
|
||||
|
||||
return retval;
|
||||
|
|
|
@ -2083,7 +2083,6 @@ R_API void r_anal_class_list(RAnal *anal, int mode);
|
|||
R_API void r_anal_class_list_bases(RAnal *anal, const char *class_name);
|
||||
R_API void r_anal_class_list_vtables(RAnal *anal, const char *class_name);
|
||||
|
||||
R_API RList *r_anal_types_from_fcn(RAnal *anal, RAnalFunction *fcn);
|
||||
R_API RAnalEsilCFG *r_anal_esil_cfg_expr(RAnalEsilCFG *cfg, RAnal *anal, const ut64 off, char *expr);
|
||||
R_API RAnalEsilCFG *r_anal_esil_cfg_op(RAnalEsilCFG *cfg, RAnal *anal, RAnalOp *op);
|
||||
R_API void r_anal_esil_cfg_merge_blocks(RAnalEsilCFG *cfg);
|
||||
|
|
|
@ -132,6 +132,7 @@ R_API void r_sign_item_free(RSignItem *item);
|
|||
R_API RList *r_sign_fcn_refs(RAnal *a, RAnalFunction *fcn);
|
||||
R_API RList *r_sign_fcn_xrefs(RAnal *a, RAnalFunction *fcn);
|
||||
R_API RList *r_sign_fcn_vars(RAnal *a, RAnalFunction *fcn);
|
||||
R_API RList *r_sign_fcn_types(RAnal *a, RAnalFunction *fcn);
|
||||
|
||||
R_API int r_sign_is_flirt(RBuffer *buf);
|
||||
R_API void r_sign_flirt_dump(const RAnal *anal, const char *flirt_file);
|
||||
|
|
|
@ -424,7 +424,7 @@ zigs:main:
|
|||
realname: main
|
||||
refs: sym.print
|
||||
vars: b-4, b-16, r110, r114
|
||||
types: int, char **, int64_t
|
||||
types: func.main.ret=int, func.main.args=2, func.main.arg.0="int,argc", func.main.arg.1="char **,argv"
|
||||
bbhash: 9890426532f35eb3a80fe773d887714fe27d13ea125ad7e90beab16a51b74496
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
|
@ -447,7 +447,7 @@ zigs:main:
|
|||
realname: main
|
||||
refs: sym.print
|
||||
vars: b-4, b-16, r110, r114
|
||||
types: int, char **, int64_t
|
||||
types: func.main.ret=int, func.main.args=2, func.main.arg.0="int,argc", func.main.arg.1="char **,argv"
|
||||
bbhash: 9890426532f35eb3a80fe773d887714fe27d13ea125ad7e90beab16a51b74496
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
|
@ -469,7 +469,7 @@ main:
|
|||
addr: 0x0040055b
|
||||
refs: sym.print
|
||||
vars: b-4, b-16, r110, r114
|
||||
types: int, char **, int64_t
|
||||
types: func.main.ret=int, func.main.args=2, func.main.arg.0="int,argc", func.main.arg.1="char **,argv"
|
||||
bbhash: 9890426532f35eb3a80fe773d887714fe27d13ea125ad7e90beab16a51b74496
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
|
@ -491,7 +491,7 @@ foobar:
|
|||
realname: main
|
||||
refs: sym.print
|
||||
vars: b-4, b-16, r110, r114
|
||||
types: int, char **, int64_t
|
||||
types: func.main.ret=int, func.main.args=2, func.main.arg.0="int,argc", func.main.arg.1="char **,argv"
|
||||
bbhash: 9890426532f35eb3a80fe773d887714fe27d13ea125ad7e90beab16a51b74496
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
|
@ -514,7 +514,7 @@ foobar:
|
|||
realname: main
|
||||
refs: sym.print
|
||||
vars: b-4, b-16, r110, r114
|
||||
types: int, char **, int64_t
|
||||
types: func.main.ret=int, func.main.args=2, func.main.arg.0="int,argc", func.main.arg.1="char **,argv"
|
||||
bbhash: 9890426532f35eb3a80fe773d887714fe27d13ea125ad7e90beab16a51b74496
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
|
|
Loading…
Reference in New Issue