[FLIRT] Refactoring and create rz_sign library (#1960)
This commit is contained in:
parent
92e1139f69
commit
f41ea3c284
23 changed files with 538 additions and 416 deletions
5
.github/labeler.yml
vendored
5
.github/labeler.yml
vendored
|
|
@ -128,6 +128,11 @@ RZIL:
|
|||
- librz/il/**/*
|
||||
- librz/core/cil.c
|
||||
|
||||
FLIRT:
|
||||
- librz/signature/*
|
||||
- librz/include/rz_sign.h
|
||||
- librz/core/csign.c
|
||||
|
||||
infrastructure:
|
||||
- .appveyor.yml
|
||||
- .travis.yml
|
||||
|
|
|
|||
|
|
@ -41,28 +41,6 @@ static void meta_count_for(RzEvent *ev, int type, void *user, void *data) {
|
|||
se->res = rz_meta_space_count_for(analysis, se->data.count.space);
|
||||
}
|
||||
|
||||
static void zign_unset_for(RzEvent *ev, int type, void *user, void *data) {
|
||||
RzSpaces *s = (RzSpaces *)ev->user;
|
||||
RzAnalysis *analysis = container_of(s, RzAnalysis, zign_spaces);
|
||||
RzSpaceEvent *se = (RzSpaceEvent *)data;
|
||||
rz_sign_space_unset_for(analysis, se->data.unset.space);
|
||||
}
|
||||
|
||||
static void zign_count_for(RzEvent *ev, int type, void *user, void *data) {
|
||||
RzSpaces *s = (RzSpaces *)ev->user;
|
||||
RzAnalysis *analysis = container_of(s, RzAnalysis, zign_spaces);
|
||||
RzSpaceEvent *se = (RzSpaceEvent *)data;
|
||||
se->res = rz_sign_space_count_for(analysis, se->data.count.space);
|
||||
}
|
||||
|
||||
static void zign_rename_for(RzEvent *ev, int type, void *user, void *data) {
|
||||
RzSpaces *s = (RzSpaces *)ev->user;
|
||||
RzAnalysis *analysis = container_of(s, RzAnalysis, zign_spaces);
|
||||
RzSpaceEvent *se = (RzSpaceEvent *)data;
|
||||
rz_sign_space_rename_for(analysis, se->data.rename.space,
|
||||
se->data.rename.oldname, se->data.rename.newname);
|
||||
}
|
||||
|
||||
void rz_analysis_hint_storage_init(RzAnalysis *a);
|
||||
|
||||
void rz_analysis_hint_storage_fini(RzAnalysis *a);
|
||||
|
|
@ -110,10 +88,6 @@ RZ_API RzAnalysis *rz_analysis_new(void) {
|
|||
rz_event_hook(analysis->meta_spaces.event, RZ_SPACE_EVENT_UNSET, meta_unset_for, NULL);
|
||||
rz_event_hook(analysis->meta_spaces.event, RZ_SPACE_EVENT_COUNT, meta_count_for, NULL);
|
||||
|
||||
rz_spaces_init(&analysis->zign_spaces, "zs");
|
||||
rz_event_hook(analysis->zign_spaces.event, RZ_SPACE_EVENT_UNSET, zign_unset_for, NULL);
|
||||
rz_event_hook(analysis->zign_spaces.event, RZ_SPACE_EVENT_COUNT, zign_count_for, NULL);
|
||||
rz_event_hook(analysis->zign_spaces.event, RZ_SPACE_EVENT_RENAME, zign_rename_for, NULL);
|
||||
rz_analysis_hint_storage_init(analysis);
|
||||
rz_interval_tree_init(&analysis->meta, rz_meta_item_free);
|
||||
analysis->typedb = rz_type_db_new();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ rz_analysis_sources = [
|
|||
'rzil/rzil_trace.c',
|
||||
'rzil/rzil.c',
|
||||
'fcn.c',
|
||||
'flirt.c',
|
||||
'hint.c',
|
||||
'il_trace.c',
|
||||
'labels.c',
|
||||
|
|
@ -31,7 +30,6 @@ rz_analysis_sources = [
|
|||
'rtti.c',
|
||||
'rtti_msvc.c',
|
||||
'rtti_itanium.c',
|
||||
'sign.c',
|
||||
'switch.c',
|
||||
'dwarf_process.c',
|
||||
'value.c',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <rz_list.h>
|
||||
#include <rz_cons.h>
|
||||
#include <rz_util.h>
|
||||
#include <rz_flirt.h>
|
||||
|
||||
#include "../core_private.h"
|
||||
|
||||
|
|
@ -544,7 +545,7 @@ static int cmdFlirt(void *data, const char *input) {
|
|||
eprintf("Usage: zfd filename\n");
|
||||
return false;
|
||||
}
|
||||
rz_sign_flirt_dump(core->analysis, input + 2);
|
||||
rz_core_flirt_dump(input + 2);
|
||||
break;
|
||||
case 's':
|
||||
// TODO
|
||||
|
|
@ -557,7 +558,7 @@ static int cmdFlirt(void *data, const char *input) {
|
|||
RzListIter *iter;
|
||||
RzList *files = rz_file_globsearch(input + 2, depth);
|
||||
rz_list_foreach (files, iter, file) {
|
||||
rz_sign_flirt_scan(core->analysis, file);
|
||||
rz_sign_flirt_apply(core->analysis, file);
|
||||
}
|
||||
rz_list_free(files);
|
||||
break;
|
||||
|
|
@ -1417,7 +1418,7 @@ RZ_IPI RzCmdStatus rz_zign_save_sdb_handler(RzCore *core, int argc, const char *
|
|||
}
|
||||
|
||||
RZ_IPI RzCmdStatus rz_zign_flirt_dump_handler(RzCore *core, int argc, const char **argv) {
|
||||
rz_sign_flirt_dump(core->analysis, argv[1]);
|
||||
rz_core_flirt_dump(argv[1]);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1427,7 +1428,7 @@ RZ_IPI RzCmdStatus rz_zign_flirt_scan_handler(RzCore *core, int argc, const char
|
|||
RzListIter *iter;
|
||||
RzList *files = rz_file_globsearch(argv[1], depth);
|
||||
rz_list_foreach (files, iter, file) {
|
||||
rz_sign_flirt_scan(core->analysis, file);
|
||||
rz_sign_flirt_apply(core->analysis, file);
|
||||
}
|
||||
rz_list_free(files);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
|
|
|
|||
|
|
@ -302,6 +302,10 @@ static bool __syncDebugMaps(RzCore *core) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static const RzList *__flagsGet(RzCore *core, ut64 offset) {
|
||||
return rz_flag_get_list(core->flags, offset);
|
||||
}
|
||||
|
||||
RZ_API int rz_core_bind(RzCore *core, RzCoreBind *bnd) {
|
||||
bnd->core = core;
|
||||
bnd->bphit = (RzCoreDebugBpHit)rz_core_debug_breakpoint_hit;
|
||||
|
|
@ -320,6 +324,7 @@ RZ_API int rz_core_bind(RzCore *core, RzCoreBind *bnd) {
|
|||
bnd->numGet = (RzCoreNumGet)numget;
|
||||
bnd->isMapped = (RzCoreIsMapped)__isMapped;
|
||||
bnd->syncDebugMaps = (RzCoreDebugMapsSync)__syncDebugMaps;
|
||||
bnd->flagsGet = (RzCoreFlagsGet)__flagsGet;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2460,6 +2465,7 @@ RZ_API bool rz_core_init(RzCore *core) {
|
|||
core->rasm->num = core->num;
|
||||
core->rasm->core = core;
|
||||
core->analysis = rz_analysis_new();
|
||||
rz_sign_analysis_set_hooks(core->analysis);
|
||||
core->gadgets = rz_list_newf((RzListFree)rz_core_gadget_free);
|
||||
core->analysis->ev = core->ev;
|
||||
core->analysis->read_at = rz_core_analysis_read_at;
|
||||
|
|
|
|||
116
librz/core/csign.c
Normal file
116
librz/core/csign.c
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-FileCopyrightText: 2014-2016 jfrankowski <jody.frankowski@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_core.h>
|
||||
#include <rz_sign.h>
|
||||
#include <rz_flirt.h>
|
||||
|
||||
static void flirt_print_module(const RzFlirtModule *module) {
|
||||
RzListIter *pub_func_it, *ref_func_it, *tail_byte_it;
|
||||
RzFlirtFunction *func, *ref_func;
|
||||
RzFlirtTailByte *tail_byte;
|
||||
|
||||
rz_cons_printf("%02X %04X %04X ", module->crc_length, module->crc16, module->length);
|
||||
rz_list_foreach (module->public_functions, pub_func_it, func) {
|
||||
if (func->is_local || func->is_collision) {
|
||||
rz_cons_printf("(");
|
||||
if (func->is_local) {
|
||||
rz_cons_printf("l");
|
||||
}
|
||||
if (func->is_collision) {
|
||||
rz_cons_printf("!");
|
||||
}
|
||||
rz_cons_printf(")");
|
||||
}
|
||||
rz_cons_printf("%04X:%s", func->offset, func->name);
|
||||
if (pub_func_it->n) {
|
||||
rz_cons_printf(" ");
|
||||
}
|
||||
}
|
||||
if (module->tail_bytes) {
|
||||
rz_list_foreach (module->tail_bytes, tail_byte_it, tail_byte) {
|
||||
rz_cons_printf(" (%04X: %02X)", tail_byte->offset, tail_byte->value);
|
||||
}
|
||||
}
|
||||
if (module->referenced_functions) {
|
||||
rz_cons_printf(" (REF ");
|
||||
rz_list_foreach (module->referenced_functions, ref_func_it, ref_func) {
|
||||
rz_cons_printf("%04X: %s", ref_func->offset, ref_func->name);
|
||||
if (ref_func_it->n) {
|
||||
rz_cons_printf(" ");
|
||||
}
|
||||
}
|
||||
rz_cons_printf(")");
|
||||
}
|
||||
rz_cons_printf("\n");
|
||||
}
|
||||
|
||||
static void flirt_print_node_pattern(const RzFlirtNode *node) {
|
||||
for (ut32 i = 0; i < node->length; i++) {
|
||||
if (node->variant_bool_array[i]) {
|
||||
rz_cons_printf("..");
|
||||
} else {
|
||||
rz_cons_printf("%02X", node->pattern_bytes[i]);
|
||||
}
|
||||
}
|
||||
rz_cons_printf(":\n");
|
||||
}
|
||||
|
||||
static void flirt_print_indentation(int indent) {
|
||||
rz_cons_printf("%s", rz_str_pad(' ', indent));
|
||||
}
|
||||
|
||||
static void flirt_print_node(const RzFlirtNode *node, int indent) {
|
||||
/* Prints a signature node. The output is similar to dumpsig */
|
||||
RzListIter *child_it, *module_it;
|
||||
RzFlirtNode *child;
|
||||
RzFlirtModule *module;
|
||||
|
||||
if (node->pattern_bytes) { // avoid printing the root node
|
||||
flirt_print_indentation(indent);
|
||||
flirt_print_node_pattern(node);
|
||||
}
|
||||
if (node->child_list) {
|
||||
rz_list_foreach (node->child_list, child_it, child) {
|
||||
flirt_print_node(child, indent + 1);
|
||||
}
|
||||
} else if (node->module_list) {
|
||||
ut32 i = 0;
|
||||
rz_list_foreach (node->module_list, module_it, module) {
|
||||
flirt_print_indentation(indent + 1);
|
||||
rz_cons_printf("%d. ", i);
|
||||
flirt_print_module(module);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Dumps the contents of a FLIRT file
|
||||
*
|
||||
* \param flirt_file FLIRT file name to dump
|
||||
*/
|
||||
RZ_API void rz_core_flirt_dump(RZ_NONNULL const char *flirt_file) {
|
||||
rz_return_if_fail(RZ_STR_ISNOTEMPTY(flirt_file));
|
||||
|
||||
RzBuffer *buffer = NULL;
|
||||
RzFlirtNode *node = NULL;
|
||||
|
||||
if (!(buffer = rz_buf_new_slurp(flirt_file))) {
|
||||
RZ_LOG_ERROR("FLIRT: Can't open %s\n", flirt_file);
|
||||
return;
|
||||
}
|
||||
|
||||
node = rz_sign_flirt_parse_buffer(buffer);
|
||||
rz_buf_free(buffer);
|
||||
if (node) {
|
||||
flirt_print_node(node, -1);
|
||||
rz_sign_flirt_node_free(node);
|
||||
return;
|
||||
} else {
|
||||
RZ_LOG_ERROR("FLIRT: We encountered an error while parsing the file. Sorry.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +1,50 @@
|
|||
subdir('cmd_descs')
|
||||
|
||||
rz_core_sources = [
|
||||
'analysis_tp.c',
|
||||
'agraph.c',
|
||||
'analysis_objc.c',
|
||||
'casm.c',
|
||||
'analysis_tp.c',
|
||||
'cagraph.c',
|
||||
'canalysis.c',
|
||||
'ctypes.c',
|
||||
'cannotated_code.c',
|
||||
'carg.c',
|
||||
'casm.c',
|
||||
'cautocmpl.c',
|
||||
'cbin.c',
|
||||
'cconfig.c',
|
||||
'cdebug.c',
|
||||
'cdwarf.c',
|
||||
'cpdb.c',
|
||||
'cfile.c',
|
||||
'chash.c',
|
||||
'cheap.c',
|
||||
'cio.c',
|
||||
'cil.c',
|
||||
'cmeta.c',
|
||||
'cio.c',
|
||||
'clang.c',
|
||||
'cparser.c',
|
||||
'cmeta.c',
|
||||
'core.c',
|
||||
'disasm.c',
|
||||
'cfile.c',
|
||||
'cparser.c',
|
||||
'cpdb.c',
|
||||
'cplugin.c',
|
||||
'csign.c',
|
||||
'ctypes.c',
|
||||
'cvfile.c',
|
||||
'disasm.c',
|
||||
'fortune.c',
|
||||
'gdiff.c',
|
||||
'agraph.c',
|
||||
'hack.c',
|
||||
'libs.c',
|
||||
#'linux_heap_glibc.c',
|
||||
'cplugin.c',
|
||||
'project.c',
|
||||
'project_migrate.c',
|
||||
'rtr.c',
|
||||
#'rtr_http.c',
|
||||
#'rtr_shell.c',
|
||||
'seek.c',
|
||||
'serialize_core.c',
|
||||
'task.c',
|
||||
'vmarks.c',
|
||||
'yank.c',
|
||||
'p/core_java.c',
|
||||
'cannotated_code.c',
|
||||
'serialize_core.c',
|
||||
cmd_descs_ch,
|
||||
'cmd/cmd.c',
|
||||
#'cmd/cmd_analysis.c',
|
||||
|
|
@ -106,6 +107,7 @@ rz_core_deps = [
|
|||
rz_asm_dep,
|
||||
rz_egg_dep,
|
||||
rz_search_dep,
|
||||
rz_sign_dep,
|
||||
rz_il_dep,
|
||||
rz_analysis_dep,
|
||||
rz_type_dep,
|
||||
|
|
@ -166,6 +168,7 @@ pkgconfig_mod.generate(
|
|||
'rz_bin',
|
||||
'rz_asm',
|
||||
'rz_bp',
|
||||
'rz_sign',
|
||||
'rz_il'
|
||||
],
|
||||
description: 'rizin foundation libraries'
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@
|
|||
#ifndef RZ_BIND_H
|
||||
#define RZ_BIND_H
|
||||
|
||||
// TODO: move riobind here too?
|
||||
// TODO: move rprint here too
|
||||
#include <rz_list.h>
|
||||
|
||||
// TODO: These binds needs to be removed.
|
||||
|
||||
typedef int (*RzCoreCmd)(void *core, const char *cmd);
|
||||
typedef int (*RzCoreCmdF)(void *user, const char *fmt, ...);
|
||||
|
|
@ -23,6 +24,8 @@ typedef void (*RzCoreSeekArchBits)(void *core, ut64 addr);
|
|||
typedef int (*RzCoreConfigGetI)(void *core, const char *key);
|
||||
typedef const char *(*RzCoreConfigGet)(void *core, const char *key);
|
||||
typedef ut64 (*RzCoreNumGet)(void *core, const char *str);
|
||||
typedef const char *(*RzCoreConfigGet)(void *core, const char *key);
|
||||
typedef const RzList *(*RzCoreFlagsGet)(void *core, ut64 offset);
|
||||
|
||||
typedef struct rz_core_bind_t {
|
||||
void *core;
|
||||
|
|
@ -42,6 +45,7 @@ typedef struct rz_core_bind_t {
|
|||
RzCoreNumGet numGet;
|
||||
RzCoreIsMapped isMapped;
|
||||
RzCoreDebugMapsSync syncDebugMaps;
|
||||
RzCoreFlagsGet flagsGet;
|
||||
} RzCoreBind;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1117,6 +1117,8 @@ RZ_API RzCoreAutocomplete *rz_core_autocomplete_find(RzCoreAutocomplete *parent,
|
|||
RZ_API bool rz_core_autocomplete_remove(RzCoreAutocomplete *parent, const char *cmd);
|
||||
RZ_API void rz_core_analysis_propagate_noreturn(RzCore *core, ut64 addr);
|
||||
|
||||
RZ_API void rz_core_flirt_dump(RZ_NONNULL const char *flirt_file);
|
||||
|
||||
/* PLUGINS */
|
||||
extern RzCorePlugin rz_core_plugin_java;
|
||||
|
||||
|
|
|
|||
60
librz/include/rz_flirt.h
Normal file
60
librz/include/rz_flirt.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-FileCopyrightText: 2014-2016 jfrankowski <jody.frankowski@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef RZ_FLIRT_H
|
||||
#define RZ_FLIRT_H
|
||||
|
||||
#include <rz_list.h>
|
||||
#include <rz_analysis.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RZ_FLIRT_NAME_MAX 1024
|
||||
|
||||
typedef struct RzFlirtTailByte {
|
||||
ut16 offset; // from pattern_size + crc_length
|
||||
ut8 value;
|
||||
} RzFlirtTailByte;
|
||||
|
||||
typedef struct RzFlirtFunction {
|
||||
char name[RZ_FLIRT_NAME_MAX];
|
||||
ut16 offset; // function offset from the module start
|
||||
ut8 negative_offset; // true if offset is negative, for referenced functions
|
||||
ut8 is_local; // true if function is static
|
||||
ut8 is_collision; // true if was an unresolved collision
|
||||
} RzFlirtFunction;
|
||||
|
||||
typedef struct RzFlirtModule {
|
||||
ut32 crc_length;
|
||||
ut32 crc16; // crc16 of the module after the pattern bytes
|
||||
// until but not including the first variant byte
|
||||
// this is a custom crc16
|
||||
ut16 length; // total length of the module, should be < 0x8000
|
||||
RzList *public_functions;
|
||||
RzList *tail_bytes;
|
||||
RzList *referenced_functions;
|
||||
} RzFlirtModule;
|
||||
|
||||
typedef struct RzFlirtNode {
|
||||
RzList *child_list;
|
||||
RzList *module_list;
|
||||
ut32 length; // length of the pattern
|
||||
ut64 variant_mask; // this is the mask that will define variant bytes in ut8 *pattern_bytes
|
||||
ut8 *pattern_bytes; // holds the pattern bytes of the signature
|
||||
ut8 *variant_bool_array; // bool array, if true, byte in pattern_bytes is a variant byte
|
||||
} RzFlirtNode;
|
||||
|
||||
RZ_API RZ_OWN RzFlirtNode *rz_sign_flirt_parse_buffer(RZ_NONNULL RzBuffer *buffer);
|
||||
RZ_API void rz_sign_flirt_node_free(RZ_NULLABLE RzFlirtNode *node);
|
||||
RZ_API ut8 rz_sign_flirt_get_version(RZ_NONNULL RzBuffer *buffer);
|
||||
RZ_API void rz_sign_flirt_apply(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL const char *flirt_file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RZ_FLIRT_H */
|
||||
|
|
@ -104,6 +104,9 @@ typedef struct {
|
|||
} RzSignCloseMatch;
|
||||
|
||||
#ifdef RZ_API
|
||||
|
||||
RZ_API void rz_sign_analysis_set_hooks(RZ_NONNULL RzAnalysis *analysis);
|
||||
|
||||
RZ_API bool rz_sign_add_bytes(RzAnalysis *a, const char *name, ut64 size, const ut8 *bytes, const ut8 *mask);
|
||||
RZ_API bool rz_sign_add_analysis(RzAnalysis *a, const char *name, ut64 size, const ut8 *bytes, ut64 at);
|
||||
RZ_API bool rz_sign_add_graph(RzAnalysis *a, const char *name, RzSignGraph graph);
|
||||
|
|
@ -148,10 +151,6 @@ RZ_API RzList *rz_sign_fcn_xrefs_to(RzAnalysis *a, RzAnalysisFunction *fcn);
|
|||
RZ_API RzList *rz_sign_fcn_vars(RzAnalysis *a, RzAnalysisFunction *fcn);
|
||||
RZ_API RzList *rz_sign_fcn_types(RzAnalysis *a, RzAnalysisFunction *fcn);
|
||||
|
||||
RZ_API int rz_sign_is_flirt(RzBuffer *buf);
|
||||
RZ_API void rz_sign_flirt_dump(const RzAnalysis *analysis, const char *flirt_file);
|
||||
RZ_API void rz_sign_flirt_scan(RzAnalysis *analysis, const char *flirt_file);
|
||||
|
||||
RZ_API RzList *rz_sign_find_closest_sig(RzAnalysis *a, RzSignItem *it, int count, double score_threshold);
|
||||
RZ_API RzList *rz_sign_find_closest_fcn(RzAnalysis *a, RzSignItem *it, int count, double score_threshold);
|
||||
RZ_API void rz_sign_close_match_free(RzSignCloseMatch *match);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ rz_main_deps = [
|
|||
rz_debug_dep,
|
||||
rz_config_dep,
|
||||
rz_bin_dep,
|
||||
rz_sign_dep,
|
||||
rz_core_dep,
|
||||
rz_diff_dep,
|
||||
]
|
||||
|
|
@ -62,6 +63,7 @@ pkgconfig_mod.generate(rz_main,
|
|||
'rz_core',
|
||||
'rz_demangler',
|
||||
'rz_asm',
|
||||
'rz_sign',
|
||||
'rz_diff',
|
||||
'rz_syscall'
|
||||
],
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <rz_core.h>
|
||||
#include <rz_demangler.h>
|
||||
#include <rz_project.h>
|
||||
#include <rz_flirt.h>
|
||||
|
||||
static bool is_valid_gdb_file(RzCoreFile *fh) {
|
||||
RzIODesc *d = fh && fh->core ? rz_io_desc_get(fh->core->io, fh->fd) : NULL;
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ RZ_API int rz_main_rz_sign(int argc, const char **argv) {
|
|||
return -1;
|
||||
}
|
||||
core = opencore(NULL);
|
||||
rz_sign_flirt_dump(core->analysis, ifile);
|
||||
rz_core_flirt_dump(ifile);
|
||||
rz_cons_flush();
|
||||
rz_core_free(core);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -337,10 +337,9 @@ include_files =[
|
|||
'include/rz_analysis.h',
|
||||
'include/rz_arch.h',
|
||||
'include/rz_asm.h',
|
||||
'include/rz_bind.h',
|
||||
'include/rz_getopt.h',
|
||||
'include/rz_bin_dwarf.h',
|
||||
'include/rz_bin.h',
|
||||
'include/rz_bin_dwarf.h',
|
||||
'include/rz_bind.h',
|
||||
'include/rz_bp.h',
|
||||
'include/rz_cmd.h',
|
||||
'include/rz_config.h',
|
||||
|
|
@ -351,38 +350,40 @@ include_files =[
|
|||
'include/rz_demangler.h',
|
||||
'include/rz_diff.h',
|
||||
'include/rz_egg.h',
|
||||
'include/rz_main.h',
|
||||
'include/rz_endian.h',
|
||||
'include/rz_flag.h',
|
||||
'include/rz_msg_digest.h',
|
||||
'include/rz_flirt.h',
|
||||
'include/rz_getopt.h',
|
||||
'include/rz_heap_glibc.h',
|
||||
'include/rz_heap_jemalloc.h',
|
||||
'include/rz_il.h',
|
||||
'include/rz_io.h',
|
||||
'include/rz_lang.h',
|
||||
'include/rz_lib.h',
|
||||
'include/rz_list.h',
|
||||
'include/rz_magic.h',
|
||||
'include/rz_main.h',
|
||||
'include/rz_msg_digest.h',
|
||||
'include/rz_parse.h',
|
||||
'include/rz_pdb.h',
|
||||
'include/rz_project.h',
|
||||
'include/rz_qrcode.h',
|
||||
'include/rz_regex.h',
|
||||
'include/rz_reg.h',
|
||||
'include/rz_regex.h',
|
||||
'include/rz_search.h',
|
||||
'include/rz_sign.h',
|
||||
'include/rz_skiplist.h',
|
||||
'include/rz_skyline.h',
|
||||
'include/rz_socket.h',
|
||||
'include/rz_syscall.h',
|
||||
'include/rz_th.h',
|
||||
'include/rz_types_overflow.h',
|
||||
'include/rz_types_base.h',
|
||||
'include/rz_types.h',
|
||||
'include/rz_type.h',
|
||||
'include/rz_il.h',
|
||||
'include/rz_types.h',
|
||||
'include/rz_types_base.h',
|
||||
'include/rz_types_overflow.h',
|
||||
'include/rz_util.h',
|
||||
'include/rz_vector.h',
|
||||
'include/rz_windows_heap.h',
|
||||
'include/rz_skyline.h',
|
||||
]
|
||||
install_headers(include_files, install_dir: rizin_incdir)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-FileCopyrightText: 2014-2016 jfrankowski <jody.frankowski@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
/* credits to IDA for the flirt tech */
|
||||
|
|
@ -99,8 +101,7 @@
|
|||
*/
|
||||
|
||||
#include <rz_lib.h>
|
||||
#include <rz_sign.h>
|
||||
#include <rz_types.h>
|
||||
#include <rz_flirt.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define DEBUG 0
|
||||
|
|
@ -261,9 +262,14 @@ typedef struct idasig_v10_t {
|
|||
ut16 unknown;
|
||||
} idasig_v10_t;
|
||||
|
||||
#if DEBUG
|
||||
static int header_size = 0;
|
||||
#endif
|
||||
typedef struct parse_status_t {
|
||||
RzBuffer *buffer;
|
||||
bool eof;
|
||||
bool error;
|
||||
ut8 version;
|
||||
} ParseStatus;
|
||||
|
||||
#define is_status_err_or_eof(p) (p->eof || p->error)
|
||||
|
||||
/* newer header only add fields, that's why we'll always read a v5 header first */
|
||||
/*
|
||||
|
|
@ -281,44 +287,6 @@ static int header_size = 0;
|
|||
pattern_size : number of the leading pattern bytes
|
||||
*/
|
||||
|
||||
#define RZ_FLIRT_NAME_MAX 1024
|
||||
|
||||
typedef struct RzFlirtTailByte {
|
||||
ut16 offset; // from pattern_size + crc_length
|
||||
ut8 value;
|
||||
} RzFlirtTailByte;
|
||||
|
||||
typedef struct RzFlirtFunction {
|
||||
char name[RZ_FLIRT_NAME_MAX];
|
||||
ut16 offset; // function offset from the module start
|
||||
ut8 negative_offset; // true if offset is negative, for referenced functions
|
||||
ut8 is_local; // true if function is static
|
||||
ut8 is_collision; // true if was an unresolved collision
|
||||
} RzFlirtFunction;
|
||||
|
||||
typedef struct RzFlirtModule {
|
||||
ut32 crc_length;
|
||||
ut32 crc16; // crc16 of the module after the pattern bytes
|
||||
// until but not including the first variant byte
|
||||
// this is a custom crc16
|
||||
ut16 length; // total length of the module, should < 0x8000
|
||||
RzList *public_functions;
|
||||
RzList *tail_bytes;
|
||||
RzList *referenced_functions;
|
||||
} RzFlirtModule;
|
||||
|
||||
typedef struct RzFlirtNode {
|
||||
RzList *child_list;
|
||||
RzList *module_list;
|
||||
ut32 length; // length of the pattern
|
||||
ut64 variant_mask; // this is the mask that will define variant bytes in ut8 *pattern_bytes
|
||||
ut8 *pattern_bytes; // holds the pattern bytes of the signature
|
||||
ut8 *variant_bool_array; // bool array, if true, byte in pattern_bytes is a variant byte
|
||||
} RzFlirtNode;
|
||||
|
||||
static ut8 version; // version of the sig file being parsed
|
||||
// used in some cases to parse the right way
|
||||
|
||||
// This is from flair tools flair/crc16.cpp
|
||||
#define POLY 0x8408
|
||||
ut16 crc16(const unsigned char *data_p, size_t length) {
|
||||
|
|
@ -347,49 +315,45 @@ ut16 crc16(const unsigned char *data_p, size_t length) {
|
|||
return (ut16)(crc);
|
||||
}
|
||||
|
||||
// this is ugly, but we can't afford to change the return size of read_byte
|
||||
static bool buf_eof;
|
||||
static bool buf_err;
|
||||
|
||||
static ut8 read_byte(RzBuffer *b) {
|
||||
static ut8 read_byte(ParseStatus *b) {
|
||||
ut8 r = 0;
|
||||
int length;
|
||||
|
||||
if (buf_eof || buf_err) {
|
||||
if (b->eof || b->error) {
|
||||
return 0;
|
||||
}
|
||||
if ((length = rz_buf_read(b, &r, 1)) != 1) {
|
||||
if ((length = rz_buf_read(b->buffer, &r, 1)) != 1) {
|
||||
if (length == -1) {
|
||||
buf_err = true;
|
||||
b->error = true;
|
||||
}
|
||||
if (length == 0) {
|
||||
buf_eof = true;
|
||||
b->eof = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static ut16 read_short(RzBuffer *b) {
|
||||
static ut16 read_short(ParseStatus *b) {
|
||||
ut16 r = (read_byte(b) << 8);
|
||||
r += read_byte(b);
|
||||
return r;
|
||||
}
|
||||
|
||||
static ut32 read_word(RzBuffer *b) {
|
||||
static ut32 read_word(ParseStatus *b) {
|
||||
ut32 r = ((ut32)(read_short(b)) << 16);
|
||||
r += read_short(b);
|
||||
return r;
|
||||
}
|
||||
|
||||
static ut16 read_max_2_bytes(RzBuffer *b) {
|
||||
static ut16 read_max_2_bytes(ParseStatus *b) {
|
||||
ut16 r = read_byte(b);
|
||||
return (r & 0x80)
|
||||
? ((r & 0x7f) << 8) + read_byte(b)
|
||||
: r;
|
||||
}
|
||||
|
||||
static ut32 read_multiple_bytes(RzBuffer *b) {
|
||||
static ut32 read_multiple_bytes(ParseStatus *b) {
|
||||
ut32 r = read_byte(b);
|
||||
if ((r & 0x80) != 0x80) {
|
||||
return r;
|
||||
|
|
@ -409,120 +373,28 @@ static void module_free(RzFlirtModule *module) {
|
|||
if (!module) {
|
||||
return;
|
||||
}
|
||||
if (module->public_functions) {
|
||||
module->public_functions->free = (RzListFree)free;
|
||||
rz_list_free(module->public_functions);
|
||||
}
|
||||
if (module->tail_bytes) {
|
||||
module->tail_bytes->free = (RzListFree)free;
|
||||
rz_list_free(module->tail_bytes);
|
||||
}
|
||||
if (module->referenced_functions) {
|
||||
module->referenced_functions->free = (RzListFree)free;
|
||||
rz_list_free(module->referenced_functions);
|
||||
}
|
||||
rz_list_free(module->public_functions);
|
||||
rz_list_free(module->tail_bytes);
|
||||
rz_list_free(module->referenced_functions);
|
||||
free(module);
|
||||
}
|
||||
|
||||
static void node_free(RzFlirtNode *node) {
|
||||
/**
|
||||
* \brief Frees an RzFlirtNode struct
|
||||
*
|
||||
* \param RzFlirtNode The RzFlirtNode to be freed
|
||||
*/
|
||||
RZ_API void rz_sign_flirt_node_free(RZ_NULLABLE RzFlirtNode *node) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
free(node->variant_bool_array);
|
||||
free(node->pattern_bytes);
|
||||
if (node->module_list) {
|
||||
node->module_list->free = (RzListFree)module_free;
|
||||
rz_list_free(node->module_list);
|
||||
}
|
||||
if (node->child_list) {
|
||||
node->child_list->free = (RzListFree)node_free;
|
||||
rz_list_free(node->child_list);
|
||||
}
|
||||
rz_list_free(node->module_list);
|
||||
rz_list_free(node->child_list);
|
||||
free(node);
|
||||
}
|
||||
|
||||
static void print_module(const RzAnalysis *analysis, const RzFlirtModule *module) {
|
||||
RzListIter *pub_func_it, *ref_func_it, *tail_byte_it;
|
||||
RzFlirtFunction *func, *ref_func;
|
||||
RzFlirtTailByte *tail_byte;
|
||||
|
||||
analysis->cb_printf("%02X %04X %04X ", module->crc_length, module->crc16, module->length);
|
||||
rz_list_foreach (module->public_functions, pub_func_it, func) {
|
||||
if (func->is_local || func->is_collision) {
|
||||
analysis->cb_printf("(");
|
||||
if (func->is_local) {
|
||||
analysis->cb_printf("l");
|
||||
}
|
||||
if (func->is_collision) {
|
||||
analysis->cb_printf("!");
|
||||
}
|
||||
analysis->cb_printf(")");
|
||||
}
|
||||
analysis->cb_printf("%04X:%s", func->offset, func->name);
|
||||
if (pub_func_it->n) {
|
||||
analysis->cb_printf(" ");
|
||||
}
|
||||
}
|
||||
if (module->tail_bytes) {
|
||||
rz_list_foreach (module->tail_bytes, tail_byte_it, tail_byte) {
|
||||
analysis->cb_printf(" (%04X: %02X)", tail_byte->offset, tail_byte->value);
|
||||
}
|
||||
}
|
||||
if (module->referenced_functions) {
|
||||
analysis->cb_printf(" (REF ");
|
||||
rz_list_foreach (module->referenced_functions, ref_func_it, ref_func) {
|
||||
analysis->cb_printf("%04X: %s", ref_func->offset, ref_func->name);
|
||||
if (ref_func_it->n) {
|
||||
analysis->cb_printf(" ");
|
||||
}
|
||||
}
|
||||
analysis->cb_printf(")");
|
||||
}
|
||||
analysis->cb_printf("\n");
|
||||
}
|
||||
|
||||
static void print_node_pattern(const RzAnalysis *analysis, const RzFlirtNode *node) {
|
||||
int i;
|
||||
for (i = 0; i < node->length; i++) {
|
||||
if (node->variant_bool_array[i]) {
|
||||
analysis->cb_printf("..");
|
||||
} else {
|
||||
analysis->cb_printf("%02X", node->pattern_bytes[i]);
|
||||
}
|
||||
}
|
||||
analysis->cb_printf(":\n");
|
||||
}
|
||||
|
||||
static void print_indentation(const RzAnalysis *analysis, int indent) {
|
||||
analysis->cb_printf("%s", rz_str_pad(' ', indent));
|
||||
}
|
||||
|
||||
static void print_node(const RzAnalysis *analysis, const RzFlirtNode *node, int indent) {
|
||||
/*Prints a signature node. The output is similar to dumpsig*/
|
||||
int i;
|
||||
RzListIter *child_it, *module_it;
|
||||
RzFlirtNode *child;
|
||||
RzFlirtModule *module;
|
||||
|
||||
if (node->pattern_bytes) { // avoid printing the root node
|
||||
print_indentation(analysis, indent);
|
||||
print_node_pattern(analysis, node);
|
||||
}
|
||||
if (node->child_list) {
|
||||
rz_list_foreach (node->child_list, child_it, child) {
|
||||
print_node(analysis, child, indent + 1);
|
||||
}
|
||||
} else if (node->module_list) {
|
||||
i = 0;
|
||||
rz_list_foreach (node->module_list, module_it, module) {
|
||||
print_indentation(analysis, indent + 1);
|
||||
analysis->cb_printf("%d. ", i);
|
||||
print_module(analysis, module);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int module_match_buffer(RzAnalysis *analysis, const RzFlirtModule *module,
|
||||
ut8 *b, ut64 address, ut32 buf_size) {
|
||||
/* Returns true if module matches b, according to the signatures infos.
|
||||
|
|
@ -605,7 +477,7 @@ static int module_match_buffer(RzAnalysis *analysis, const RzFlirtModule *module
|
|||
next_module_function->name = rz_str_newf("flirt.%s", name);
|
||||
analysis->flb.set(analysis->flb.f, next_module_function->name,
|
||||
next_module_function->addr, next_module_function_size);
|
||||
analysis->cb_printf("Found %s\n", next_module_function->name);
|
||||
RZ_LOG_INFO("FLIRT: Found %s\n", next_module_function->name);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -653,14 +525,15 @@ static int node_match_buffer(RzAnalysis *analysis, const RzFlirtNode *node, ut8
|
|||
return false;
|
||||
}
|
||||
|
||||
static int node_match_functions(RzAnalysis *analysis, const RzFlirtNode *root_node) {
|
||||
/* Tries to find matching functions between the signature infos in root_node
|
||||
* and the analyzed functions in anal
|
||||
* Returns false on error. */
|
||||
/* Tries to find matching functions between the signature infos in root_node
|
||||
* and the analyzed functions in analysis
|
||||
* Returns false on error. */
|
||||
static bool node_match_functions(RzAnalysis *analysis, const RzFlirtNode *root_node) {
|
||||
bool ret = true;
|
||||
|
||||
if (rz_list_length(analysis->fcns) == 0) {
|
||||
analysis->cb_printf("There are no analyzed functions. Have you run 'aa'?\n");
|
||||
return true;
|
||||
RZ_LOG_ERROR("FLIRT: There are no analyzed functions. Have you run 'aa'?\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
analysis->flb.push_fs(analysis->flb.f, "flirt");
|
||||
|
|
@ -674,12 +547,14 @@ static int node_match_functions(RzAnalysis *analysis, const RzFlirtNode *root_no
|
|||
ut64 func_size = rz_analysis_function_linear_size(func);
|
||||
ut8 *func_buf = malloc(func_size);
|
||||
if (!func_buf) {
|
||||
continue;
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
if (!analysis->iob.read_at(analysis->iob.io, func->addr, func_buf, (int)func_size)) {
|
||||
eprintf("Couldn't read function %s at 0x%" PFMT64x "\n", func->name, func->addr);
|
||||
free(func_buf);
|
||||
continue;
|
||||
RZ_LOG_ERROR("FLIRT: Couldn't read function %s at 0x%" PFMT64x "\n", func->name, func->addr);
|
||||
RZ_FREE(func_buf);
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
RzListIter *node_child_it;
|
||||
RzFlirtNode *child;
|
||||
|
|
@ -688,14 +563,14 @@ static int node_match_functions(RzAnalysis *analysis, const RzFlirtNode *root_no
|
|||
break;
|
||||
}
|
||||
}
|
||||
free(func_buf);
|
||||
RZ_FREE(func_buf);
|
||||
}
|
||||
analysis->flb.pop_fs(analysis->flb.f);
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ut8 read_module_tail_bytes(RzFlirtModule *module, RzBuffer *b) {
|
||||
static ut8 read_module_tail_bytes(RzFlirtModule *module, ParseStatus *b) {
|
||||
/*parses a module tail bytes*/
|
||||
/*returns false on parsing error*/
|
||||
int i;
|
||||
|
|
@ -705,9 +580,9 @@ static ut8 read_module_tail_bytes(RzFlirtModule *module, RzBuffer *b) {
|
|||
goto err_exit;
|
||||
}
|
||||
|
||||
if (version >= 8) { // this counter was introduced in version 8
|
||||
if (b->version >= 8) { // this counter was introduced in version 8
|
||||
number_of_tail_bytes = read_byte(b); // XXX are we sure it's not read_multiple_bytes?
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
} else { // suppose there's only one
|
||||
|
|
@ -718,20 +593,20 @@ static ut8 read_module_tail_bytes(RzFlirtModule *module, RzBuffer *b) {
|
|||
if (!tail_byte) {
|
||||
return false;
|
||||
}
|
||||
if (version >= 9) {
|
||||
if (b->version >= 9) {
|
||||
/*/!\ XXX don't trust ./zipsig output because it will write a version 9 header, but keep the old version offsets*/
|
||||
tail_byte->offset = read_multiple_bytes(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
} else {
|
||||
tail_byte->offset = read_max_2_bytes(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
tail_byte->value = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
rz_list_append(module->tail_bytes, tail_byte);
|
||||
|
|
@ -748,7 +623,7 @@ err_exit:
|
|||
return false;
|
||||
}
|
||||
|
||||
static ut8 read_module_referenced_functions(RzFlirtModule *module, RzBuffer *b) {
|
||||
static ut8 read_module_referenced_functions(RzFlirtModule *module, ParseStatus *b) {
|
||||
/*parses a module referenced functions*/
|
||||
/*returns false on parsing error*/
|
||||
int i, j;
|
||||
|
|
@ -756,11 +631,11 @@ static ut8 read_module_referenced_functions(RzFlirtModule *module, RzBuffer *b)
|
|||
ut32 ref_function_name_length;
|
||||
RzFlirtFunction *ref_function = NULL;
|
||||
|
||||
module->referenced_functions = rz_list_new();
|
||||
module->referenced_functions = rz_list_newf((RzListFree)free);
|
||||
|
||||
if (version >= 8) { // this counter was introduced in version 8
|
||||
if (b->version >= 8) { // this counter was introduced in version 8
|
||||
number_of_referenced_functions = read_byte(b); // XXX are we sure it's not read_multiple_bytes?
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
} else { // suppose there's only one
|
||||
|
|
@ -772,25 +647,25 @@ static ut8 read_module_referenced_functions(RzFlirtModule *module, RzBuffer *b)
|
|||
if (!ref_function) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (version >= 9) {
|
||||
if (b->version >= 9) {
|
||||
ref_function->offset = read_multiple_bytes(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
} else {
|
||||
ref_function->offset = read_max_2_bytes(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
ref_function_name_length = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (!ref_function_name_length) {
|
||||
// not sure why it's not read_multiple_bytes() in the first place
|
||||
ref_function_name_length = read_multiple_bytes(b); // XXX might be read_max_2_bytes, need more data
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
|
@ -799,7 +674,7 @@ static ut8 read_module_referenced_functions(RzFlirtModule *module, RzBuffer *b)
|
|||
}
|
||||
for (j = 0; j < ref_function_name_length; j++) {
|
||||
ref_function->name[j] = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
|
@ -822,7 +697,7 @@ err_exit:
|
|||
return false;
|
||||
}
|
||||
|
||||
static ut8 read_module_public_functions(RzFlirtModule *module, RzBuffer *b, ut8 *flags) {
|
||||
static ut8 read_module_public_functions(RzFlirtModule *module, ParseStatus *b, ut8 *flags) {
|
||||
/* Reads and set the public functions names and offsets associated within a module */
|
||||
/*returns false on parsing error*/
|
||||
int i;
|
||||
|
|
@ -830,25 +705,25 @@ static ut8 read_module_public_functions(RzFlirtModule *module, RzBuffer *b, ut8
|
|||
ut8 current_byte;
|
||||
RzFlirtFunction *function = NULL;
|
||||
|
||||
module->public_functions = rz_list_new();
|
||||
module->public_functions = rz_list_newf((RzListFree)free);
|
||||
|
||||
do {
|
||||
function = RZ_NEW0(RzFlirtFunction);
|
||||
if (version >= 9) { // seems like version 9 introduced some larger offsets
|
||||
if (b->version >= 9) { // seems like version 9 introduced some larger offsets
|
||||
offset += read_multiple_bytes(b); // offsets are dependent of the previous ones
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
} else {
|
||||
offset += read_max_2_bytes(b); // offsets are dependent of the previous ones
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
function->offset = offset;
|
||||
|
||||
current_byte = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
if (current_byte < 0x20) {
|
||||
|
|
@ -859,15 +734,15 @@ static ut8 read_module_public_functions(RzFlirtModule *module, RzBuffer *b, ut8
|
|||
// unresolved collision (happens in *.exc while creating .sig from .pat)
|
||||
function->is_collision = true;
|
||||
}
|
||||
if (current_byte & 0x01 || current_byte & 0x04) { // appears as 'd' or '?' in dumpsig
|
||||
#if DEBUG
|
||||
if (current_byte & 0x01 || current_byte & 0x04) { // appears as 'd' or '?' in dumpsig
|
||||
// XXX investigate
|
||||
eprintf("INVESTIGATE PUBLIC NAME FLAG: %02X @ %04X\n", current_byte,
|
||||
rz_buf_tell(b) + header_size);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
current_byte = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
|
@ -875,7 +750,7 @@ static ut8 read_module_public_functions(RzFlirtModule *module, RzBuffer *b, ut8
|
|||
for (i = 0; current_byte >= 0x20 && i < RZ_FLIRT_NAME_MAX; i++) {
|
||||
function->name[i] = current_byte;
|
||||
current_byte = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
|
@ -904,22 +779,22 @@ err_exit:
|
|||
return false;
|
||||
}
|
||||
|
||||
static ut8 parse_leaf(const RzAnalysis *analysis, RzBuffer *b, RzFlirtNode *node) {
|
||||
static ut8 parse_leaf(ParseStatus *b, RzFlirtNode *node) {
|
||||
/*parses a signature leaf: modules with same leading pattern*/
|
||||
/*returns false on parsing error*/
|
||||
ut8 flags, crc_length;
|
||||
ut16 crc16;
|
||||
RzFlirtModule *module = NULL;
|
||||
|
||||
node->module_list = rz_list_new();
|
||||
node->module_list = rz_list_newf((RzListFree)module_free);
|
||||
do { // loop for all modules having the same prefix
|
||||
|
||||
crc_length = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
crc16 = read_short(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
#if DEBUG
|
||||
|
|
@ -939,15 +814,15 @@ static ut8 parse_leaf(const RzAnalysis *analysis, RzBuffer *b, RzFlirtNode *node
|
|||
module->crc_length = crc_length;
|
||||
module->crc16 = crc16;
|
||||
|
||||
if (version >= 9) { // seems like version 9 introduced some larger length
|
||||
if (b->version >= 9) { // seems like version 9 introduced some larger length
|
||||
/*/!\ XXX don't trust ./zipsig output because it will write a version 9 header, but keep the old version offsets*/
|
||||
module->length = read_multiple_bytes(b); // should be < 0x8000
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
} else {
|
||||
module->length = read_max_2_bytes(b); // should be < 0x8000
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
goto err_exit;
|
||||
}
|
||||
}
|
||||
|
|
@ -981,9 +856,9 @@ err_exit:
|
|||
return false;
|
||||
}
|
||||
|
||||
static ut8 read_node_length(RzFlirtNode *node, RzBuffer *b) {
|
||||
static ut8 read_node_length(RzFlirtNode *node, ParseStatus *b) {
|
||||
node->length = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
return false;
|
||||
}
|
||||
#if DEBUG
|
||||
|
|
@ -992,23 +867,23 @@ static ut8 read_node_length(RzFlirtNode *node, RzBuffer *b) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static ut8 read_node_variant_mask(RzFlirtNode *node, RzBuffer *b) {
|
||||
static ut8 read_node_variant_mask(RzFlirtNode *node, ParseStatus *b) {
|
||||
/*Reads and sets a node's variant bytes mask. This mask is then used to*/
|
||||
/*read the non-variant bytes following.*/
|
||||
/*returns false on parsing error*/
|
||||
if (node->length < 0x10) {
|
||||
node->variant_mask = read_max_2_bytes(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
return false;
|
||||
}
|
||||
} else if (node->length <= 0x20) {
|
||||
node->variant_mask = read_multiple_bytes(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
return false;
|
||||
}
|
||||
} else if (node->length <= 0x40) { // it shouldn't be more than 64 bytes
|
||||
node->variant_mask = ((ut64)read_multiple_bytes(b) << 32) + read_multiple_bytes(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1016,7 +891,7 @@ static ut8 read_node_variant_mask(RzFlirtNode *node, RzBuffer *b) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool read_node_bytes(RzFlirtNode *node, RzBuffer *b) {
|
||||
static bool read_node_bytes(RzFlirtNode *node, ParseStatus *b) {
|
||||
/*Reads the node bytes, and also sets the variant bytes in variant_bool_array*/
|
||||
/*returns false on parsing error*/
|
||||
int i;
|
||||
|
|
@ -1037,7 +912,7 @@ static bool read_node_bytes(RzFlirtNode *node, RzBuffer *b) {
|
|||
node->pattern_bytes[i] = 0x00;
|
||||
} else {
|
||||
node->pattern_bytes[i] = read_byte(b);
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1045,18 +920,18 @@ static bool read_node_bytes(RzFlirtNode *node, RzBuffer *b) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static ut8 parse_tree(const RzAnalysis *analysis, RzBuffer *b, RzFlirtNode *root_node) {
|
||||
static ut8 parse_tree(ParseStatus *b, RzFlirtNode *root_node) {
|
||||
/*parse a signature pattern tree or sub-tree*/
|
||||
/*returns false on parsing error*/
|
||||
RzFlirtNode *node = NULL;
|
||||
int i, tree_nodes = read_multiple_bytes(b); // confirmed it's not read_byte(), XXX could it be read_max_2_bytes() ???
|
||||
if (buf_eof || buf_err) {
|
||||
if (is_status_err_or_eof(b)) {
|
||||
return false;
|
||||
}
|
||||
if (tree_nodes == 0) { // if there's no tree nodes remaining, that means we are on the leaf
|
||||
return parse_leaf(analysis, b, root_node);
|
||||
return parse_leaf(b, root_node);
|
||||
}
|
||||
root_node->child_list = rz_list_new();
|
||||
root_node->child_list = rz_list_newf((RzListFree)rz_sign_flirt_node_free);
|
||||
|
||||
for (i = 0; i < tree_nodes; i++) {
|
||||
if (!(node = RZ_NEW0(RzFlirtNode))) {
|
||||
|
|
@ -1072,13 +947,13 @@ static ut8 parse_tree(const RzAnalysis *analysis, RzBuffer *b, RzFlirtNode *root
|
|||
goto err_exit;
|
||||
}
|
||||
rz_list_append(root_node->child_list, node);
|
||||
if (!parse_tree(analysis, b, node)) {
|
||||
if (!parse_tree(b, node)) {
|
||||
goto err_exit; // parse child nodes
|
||||
}
|
||||
}
|
||||
return true;
|
||||
err_exit:
|
||||
node_free(node);
|
||||
rz_sign_flirt_node_free(node);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1238,7 +1113,7 @@ static void print_header(idasig_v5_t *header) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static int parse_header(RzBuffer *buf, idasig_v5_t *header) {
|
||||
static int parse_v5_header(RzBuffer *buf, idasig_v5_t *header) {
|
||||
rz_buf_seek(buf, 0, RZ_BUF_SET);
|
||||
if (rz_buf_read(buf, header->magic, sizeof(header->magic)) != sizeof(header->magic)) {
|
||||
return false;
|
||||
|
|
@ -1304,7 +1179,15 @@ static int parse_v10_header(RzBuffer *buf, idasig_v10_t *header) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf) {
|
||||
/**
|
||||
* \brief Parses the RzBuffer containing a FLIRT structure and returns an RzFlirtNode
|
||||
*
|
||||
* \param flirt_buf The buffer to read
|
||||
* \return Parsed FLIRT node
|
||||
*/
|
||||
RZ_API RZ_OWN RzFlirtNode *rz_sign_flirt_parse_buffer(RZ_NONNULL RzBuffer *flirt_buf) {
|
||||
rz_return_val_if_fail(flirt_buf, NULL);
|
||||
|
||||
ut8 *name = NULL;
|
||||
ut8 *buf = NULL, *decompressed_buf = NULL;
|
||||
RzBuffer *rz_buf = NULL;
|
||||
|
|
@ -1316,15 +1199,14 @@ static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf)
|
|||
idasig_v8_v9_t *v8_v9 = NULL;
|
||||
idasig_v10_t *v10 = NULL;
|
||||
|
||||
buf_eof = false;
|
||||
buf_err = false;
|
||||
ParseStatus ps = { 0 };
|
||||
|
||||
if (!(version = rz_sign_is_flirt(flirt_buf))) {
|
||||
if (!(ps.version = rz_sign_flirt_get_version(flirt_buf))) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (version < 5 || version > 10) {
|
||||
eprintf("Unsupported flirt signature version\n");
|
||||
if (ps.version < 5 || ps.version > 10) {
|
||||
RZ_LOG_ERROR("FLIRT: Unsupported flirt signature version\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
@ -1332,9 +1214,9 @@ static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
parse_header(flirt_buf, header);
|
||||
parse_v5_header(flirt_buf, header);
|
||||
|
||||
if (version >= 6) {
|
||||
if (ps.version >= 6) {
|
||||
if (!(v6_v7 = RZ_NEW0(idasig_v6_v7_t))) {
|
||||
goto exit;
|
||||
}
|
||||
|
|
@ -1342,7 +1224,7 @@ static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (version >= 8) {
|
||||
if (ps.version >= 8) {
|
||||
if (!(v8_v9 = RZ_NEW0(idasig_v8_v9_t))) {
|
||||
goto exit;
|
||||
}
|
||||
|
|
@ -1350,7 +1232,7 @@ static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (version >= 10) {
|
||||
if (ps.version >= 10) {
|
||||
if (!(v10 = RZ_NEW0(idasig_v10_t))) {
|
||||
goto exit;
|
||||
}
|
||||
|
|
@ -1372,13 +1254,6 @@ static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf)
|
|||
|
||||
name[header->library_name_len] = '\0';
|
||||
|
||||
// analysis->cb_printf ("Loading: %s\n", name);
|
||||
#if DEBUG
|
||||
print_header(header);
|
||||
eprintf("%s\n", name);
|
||||
header_size = rz_buf_tell(flirt_buf);
|
||||
#endif
|
||||
|
||||
size = rz_buf_size(flirt_buf) - rz_buf_tell(flirt_buf);
|
||||
buf = malloc(size);
|
||||
if (rz_buf_read(flirt_buf, buf, size) != size) {
|
||||
|
|
@ -1386,20 +1261,18 @@ static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf)
|
|||
}
|
||||
|
||||
if (header->features & IDASIG__FEATURE__COMPRESSED) {
|
||||
if (version >= 5 && version < 7) {
|
||||
if (ps.version >= 5 && ps.version < 7) {
|
||||
if (!(decompressed_buf = rz_inflate_ignore_header(buf, size, NULL, &decompressed_size))) {
|
||||
eprintf("Decompressing failed.\n");
|
||||
RZ_LOG_ERROR("FLIRT: Failed to decompress buffer.\n");
|
||||
goto exit;
|
||||
}
|
||||
} else if (version >= 7) {
|
||||
} else if (ps.version >= 7) {
|
||||
if (!(decompressed_buf = rz_inflate(buf, size, NULL, &decompressed_size))) {
|
||||
eprintf("Decompressing failed.\n");
|
||||
RZ_LOG_ERROR("FLIRT: Failed to decompress buffer.\n");
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
eprintf("Sorry we do not support the signatures"
|
||||
" version %c compression.\n",
|
||||
version);
|
||||
RZ_LOG_ERROR("FLIRT: Sorry we do not support compressed signatures with version %d.\n", ps.version);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
@ -1407,19 +1280,22 @@ static RzFlirtNode *flirt_parse(const RzAnalysis *analysis, RzBuffer *flirt_buf)
|
|||
buf = decompressed_buf;
|
||||
size = decompressed_size;
|
||||
}
|
||||
rz_buf = rz_buf_new_with_pointers(buf, size, false);
|
||||
if (!rz_buf) {
|
||||
goto exit;
|
||||
}
|
||||
ps.buffer = rz_buf;
|
||||
|
||||
if (!(node = RZ_NEW0(RzFlirtNode))) {
|
||||
goto exit;
|
||||
}
|
||||
rz_buf = rz_buf_new_with_pointers(buf, size, false);
|
||||
#if DEBUG
|
||||
rz_file_dump("sig_dump", buf, size, false);
|
||||
#endif
|
||||
if (parse_tree(analysis, rz_buf, node)) {
|
||||
|
||||
if (parse_tree(&ps, node)) {
|
||||
ret = node;
|
||||
} else {
|
||||
free(node);
|
||||
}
|
||||
|
||||
exit:
|
||||
free(buf);
|
||||
rz_buf_free(rz_buf);
|
||||
|
|
@ -1431,12 +1307,23 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
RZ_API int rz_sign_is_flirt(RzBuffer *buf) {
|
||||
/*if buf is a flirt signature, returns signature version, otherwise returns false*/
|
||||
int ret = false;
|
||||
/**
|
||||
* \brief Returns the FLIRT file version read from the RzBuffer
|
||||
* This function returns the FLIRT file version, when it fails returns 0
|
||||
*
|
||||
* \param buffer The buffer to read
|
||||
* \return Parsed FLIRT version
|
||||
*/
|
||||
RZ_API ut8 rz_sign_flirt_get_version(RZ_NONNULL RzBuffer *buffer) {
|
||||
rz_return_val_if_fail(buffer, false);
|
||||
ut8 ret = 0;
|
||||
|
||||
idasig_v5_t *header = RZ_NEW0(idasig_v5_t);
|
||||
if (rz_buf_read(buf, header->magic, sizeof(header->magic)) != sizeof(header->magic)) {
|
||||
if (!header) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (rz_buf_read(buffer, header->magic, sizeof(header->magic)) != sizeof(header->magic)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
@ -1444,7 +1331,7 @@ RZ_API int rz_sign_is_flirt(RzBuffer *buf) {
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (rz_buf_read(buf, &header->version, sizeof(header->version)) != sizeof(header->version)) {
|
||||
if (rz_buf_read(buffer, &header->version, sizeof(header->version)) != sizeof(header->version)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
@ -1456,48 +1343,32 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
RZ_API void rz_sign_flirt_dump(const RzAnalysis *analysis, const char *flirt_file) {
|
||||
/*dump a flirt signature content on screen.*/
|
||||
RzBuffer *flirt_buf;
|
||||
RzFlirtNode *node;
|
||||
/**
|
||||
* \brief Parses the FLIRT file and applies the signatures
|
||||
*
|
||||
* \param analysis The RzAnalysis structure
|
||||
* \param flirt_file The FLIRT file to parse
|
||||
*/
|
||||
RZ_API void rz_sign_flirt_apply(RzAnalysis *analysis, const char *flirt_file) {
|
||||
rz_return_if_fail(analysis && RZ_STR_ISNOTEMPTY(flirt_file));
|
||||
RzBuffer *flirt_buf = NULL;
|
||||
RzFlirtNode *node = NULL;
|
||||
|
||||
if (!(flirt_buf = rz_buf_new_slurp(flirt_file))) {
|
||||
eprintf("Can't open %s\n", flirt_file);
|
||||
RZ_LOG_ERROR("FLIRT: Can't open %s\n", flirt_file);
|
||||
return;
|
||||
}
|
||||
|
||||
node = flirt_parse(analysis, flirt_buf);
|
||||
rz_buf_free(flirt_buf);
|
||||
if (node) {
|
||||
print_node(analysis, node, -1);
|
||||
node_free(node);
|
||||
return;
|
||||
} else {
|
||||
eprintf("We encountered an error while parsing the file. Sorry.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RZ_API void rz_sign_flirt_scan(RzAnalysis *analysis, const char *flirt_file) {
|
||||
/*parses a flirt signature file and scan the currently opened file against it.*/
|
||||
RzBuffer *flirt_buf;
|
||||
RzFlirtNode *node;
|
||||
|
||||
if (!(flirt_buf = rz_buf_new_slurp(flirt_file))) {
|
||||
eprintf("Can't open %s\n", flirt_file);
|
||||
return;
|
||||
}
|
||||
|
||||
node = flirt_parse(analysis, flirt_buf);
|
||||
node = rz_sign_flirt_parse_buffer(flirt_buf);
|
||||
rz_buf_free(flirt_buf);
|
||||
if (node) {
|
||||
if (!node_match_functions(analysis, node)) {
|
||||
eprintf("Error while scanning the file %s\n", flirt_file);
|
||||
RZ_LOG_ERROR("FLIRT: Error while scanning the file %s\n", flirt_file);
|
||||
}
|
||||
node_free(node);
|
||||
rz_sign_flirt_node_free(node);
|
||||
return;
|
||||
} else {
|
||||
eprintf("We encountered an error while parsing the file %s. Sorry.\n", flirt_file);
|
||||
RZ_LOG_ERROR("FLIRT: We encountered an error while parsing the file %s. Sorry.\n", flirt_file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
48
librz/signature/meson.build
Normal file
48
librz/signature/meson.build
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
rz_sign_sources = [
|
||||
'flirt.c',
|
||||
'zignature.c',
|
||||
'sign.c',
|
||||
]
|
||||
|
||||
rz_sign_inc = [
|
||||
platform_inc,
|
||||
]
|
||||
|
||||
rz_sign = library('rz_sign', rz_sign_sources,
|
||||
include_directories: rz_sign_inc,
|
||||
c_args: library_cflags,
|
||||
dependencies: [
|
||||
rz_util_dep,
|
||||
rz_analysis_dep,
|
||||
rz_diff_dep,
|
||||
rz_hash_dep,
|
||||
rz_type_dep,
|
||||
rz_search_dep,
|
||||
rz_flag_dep,
|
||||
],
|
||||
install: true,
|
||||
implicit_include_directories: false,
|
||||
install_rpath: rpath_lib,
|
||||
soversion: rizin_libversion
|
||||
)
|
||||
|
||||
rz_sign_dep = declare_dependency(link_with: rz_sign,
|
||||
include_directories: rz_sign_inc)
|
||||
|
||||
pkgconfig_mod.generate(rz_sign,
|
||||
subdirs: 'librz',
|
||||
version: rizin_version,
|
||||
name: 'rz_sign',
|
||||
filebase: 'rz_sign',
|
||||
libraries: pkgcfg_sanitize_libs,
|
||||
requires: [
|
||||
'rz_util',
|
||||
'rz_analysis',
|
||||
'rz_diff',
|
||||
'rz_hash',
|
||||
'rz_search',
|
||||
'rz_type',
|
||||
'rz_flag',
|
||||
],
|
||||
description: 'rizin foundation libraries'
|
||||
)
|
||||
7
librz/signature/sign.c
Normal file
7
librz/signature/sign.c
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
|
||||
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_sign.h>
|
||||
|
||||
RZ_LIB_VERSION(rz_sign);
|
||||
|
|
@ -5,19 +5,16 @@
|
|||
#include <rz_analysis.h>
|
||||
#include <rz_sign.h>
|
||||
#include <rz_search.h>
|
||||
#include <rz_core.h>
|
||||
#include <rz_msg_digest.h>
|
||||
|
||||
RZ_LIB_VERSION(rz_sign);
|
||||
|
||||
#define SIGN_DIFF_MATCH_BYTES_THRESHOLD 1.0
|
||||
#define SIGN_DIFF_MATCH_GRAPH_THRESHOLD 1.0
|
||||
|
||||
const char *getRealRef(RzCore *core, ut64 off) {
|
||||
const char *getRealRef(RzAnalysis *a, ut64 off) {
|
||||
RzFlagItem *item;
|
||||
RzListIter *iter;
|
||||
|
||||
const RzList *list = rz_flag_get_list(core->flags, off);
|
||||
const RzList *list = a->coreb.flagsGet(a->coreb.core, off);
|
||||
if (!list) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -38,21 +35,15 @@ const char *getRealRef(RzCore *core, ut64 off) {
|
|||
RZ_API RzList *rz_sign_fcn_vars(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
||||
rz_return_val_if_fail(a && fcn, NULL);
|
||||
|
||||
RzCore *core = a->coreb.core;
|
||||
|
||||
if (!core) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzListIter *iter;
|
||||
RzAnalysisVar *var;
|
||||
RzList *ret = rz_list_newf((RzListFree)free);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
RzList *reg_vars = rz_analysis_var_list(core->analysis, fcn, RZ_ANALYSIS_VAR_KIND_REG);
|
||||
RzList *spv_vars = rz_analysis_var_list(core->analysis, fcn, RZ_ANALYSIS_VAR_KIND_SPV);
|
||||
RzList *bpv_vars = rz_analysis_var_list(core->analysis, fcn, RZ_ANALYSIS_VAR_KIND_BPV);
|
||||
RzList *reg_vars = rz_analysis_var_list(a, fcn, RZ_ANALYSIS_VAR_KIND_REG);
|
||||
RzList *spv_vars = rz_analysis_var_list(a, fcn, RZ_ANALYSIS_VAR_KIND_SPV);
|
||||
RzList *bpv_vars = rz_analysis_var_list(a, fcn, RZ_ANALYSIS_VAR_KIND_BPV);
|
||||
rz_list_foreach (bpv_vars, iter, var) {
|
||||
rz_list_append(ret, rz_str_newf("b%d", var->delta));
|
||||
}
|
||||
|
|
@ -112,14 +103,11 @@ RZ_API RzList *rz_sign_fcn_types(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
|||
}
|
||||
|
||||
RZ_API RzList *rz_sign_fcn_xrefs_to(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
||||
RzListIter *iter = NULL;
|
||||
RzAnalysisXRef *xrefi = NULL;
|
||||
|
||||
rz_return_val_if_fail(a && fcn, NULL);
|
||||
|
||||
RzCore *core = a->coreb.core;
|
||||
|
||||
if (!core) {
|
||||
RzListIter *iter = NULL;
|
||||
RzAnalysisXRef *xrefi = NULL;
|
||||
if (!a->coreb.core) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +115,7 @@ RZ_API RzList *rz_sign_fcn_xrefs_to(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
|||
RzList *xrefs = rz_analysis_function_get_xrefs_to(fcn);
|
||||
rz_list_foreach (xrefs, iter, xrefi) {
|
||||
if (xrefi->type == RZ_ANALYSIS_REF_TYPE_CODE || xrefi->type == RZ_ANALYSIS_REF_TYPE_CALL) {
|
||||
const char *flag = getRealRef(core, xrefi->from);
|
||||
const char *flag = getRealRef(a, xrefi->from);
|
||||
if (flag) {
|
||||
rz_list_append(ret, rz_str_new(flag));
|
||||
}
|
||||
|
|
@ -138,14 +126,11 @@ RZ_API RzList *rz_sign_fcn_xrefs_to(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
|||
}
|
||||
|
||||
RZ_API RzList *rz_sign_fcn_xrefs_from(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
||||
rz_return_val_if_fail(a && fcn, NULL);
|
||||
RzListIter *iter = NULL;
|
||||
RzAnalysisXRef *xrefi = NULL;
|
||||
|
||||
rz_return_val_if_fail(a && fcn, NULL);
|
||||
|
||||
RzCore *core = a->coreb.core;
|
||||
|
||||
if (!core) {
|
||||
if (!a->coreb.core) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +138,7 @@ RZ_API RzList *rz_sign_fcn_xrefs_from(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
|||
RzList *xrefs = rz_analysis_function_get_xrefs_from(fcn);
|
||||
rz_list_foreach (xrefs, iter, xrefi) {
|
||||
if (xrefi->type == RZ_ANALYSIS_REF_TYPE_CODE || xrefi->type == RZ_ANALYSIS_REF_TYPE_CALL) {
|
||||
const char *flag = getRealRef(core, xrefi->to);
|
||||
const char *flag = getRealRef(a, xrefi->to);
|
||||
if (flag) {
|
||||
rz_list_append(ret, rz_str_new(flag));
|
||||
}
|
||||
|
|
@ -204,7 +189,7 @@ static RzList *do_reflike_sig(const char *token) {
|
|||
|
||||
#define DBL_VAL_FAIL(x, y) \
|
||||
if (x) { \
|
||||
eprintf("Warning: Skipping signature with multiple %c signatures (%s)\n", y, k); \
|
||||
RZ_LOG_WARN("zignature: Skipping signature with multiple %c signatures (%s)\n", y, k); \
|
||||
success = false; \
|
||||
goto out; \
|
||||
}
|
||||
|
|
@ -222,12 +207,12 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
|
|||
// Deserialize key: zign|space|name
|
||||
size_t n = rz_str_split(k2, '|');
|
||||
if (n != 3) {
|
||||
eprintf("Warning: Skipping signature with invalid key (%s)\n", k);
|
||||
RZ_LOG_WARN("zignature: Skipping signature with invalid key (%s)\n", k);
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(rz_str_word_get0(k2, 0), "zign")) {
|
||||
eprintf("Warning: Skipping signature with invalid value (%s)\n", k);
|
||||
RZ_LOG_WARN("zignature: Skipping signature with invalid value (%s)\n", k);
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -254,14 +239,14 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
|
|||
continue;
|
||||
}
|
||||
if (strlen(word) < 3 || word[1] != ':') {
|
||||
eprintf("Warning: Skipping signature with corrupted serialization (%s:%s)\n", k, word);
|
||||
RZ_LOG_WARN("zignature: Skipping signature with corrupted serialization (%s:%s)\n", k, word);
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
RzSignType st = (RzSignType)*word;
|
||||
switch (st) {
|
||||
case RZ_SIGN_ANALYSIS:
|
||||
eprintf("Unsupported\n");
|
||||
RZ_LOG_ERROR("zignature: Unsupported type (RZ_SIGN_ANALYSIS)\n");
|
||||
break;
|
||||
case RZ_SIGN_NAME:
|
||||
DBL_VAL_FAIL(it->realname, RZ_SIGN_NAME);
|
||||
|
|
@ -335,12 +320,12 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
|
|||
case RZ_SIGN_BYTES:
|
||||
// following two errors are not due to double entries
|
||||
if (!it->bytes) {
|
||||
eprintf("Warning: Skipping signature with no bytes size (%s)\n", k);
|
||||
RZ_LOG_WARN("zignature: Skipping signature with no bytes size (%s)\n", k);
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
if (strlen(token) != 2 * it->bytes->size) {
|
||||
eprintf("Warning: Skipping signature with invalid size (%s)\n", k);
|
||||
RZ_LOG_WARN("zignature: Skipping signature with invalid size (%s)\n", k);
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -353,12 +338,12 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
|
|||
case RZ_SIGN_BYTES_MASK:
|
||||
// following two errors are not due to double entries
|
||||
if (!it->bytes) {
|
||||
eprintf("Warning: Skipping signature with no mask size (%s)\n", k);
|
||||
RZ_LOG_WARN("zignature: Skipping signature with no mask size (%s)\n", k);
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
if (strlen(token) != 2 * it->bytes->size) {
|
||||
eprintf("Warning: Skipping signature invalid mask size (%s)\n", k);
|
||||
RZ_LOG_WARN("zignature: Skipping signature invalid mask size (%s)\n", k);
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -382,7 +367,7 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
|
|||
}
|
||||
break;
|
||||
default:
|
||||
eprintf("Unsupported (%s)\n", word);
|
||||
RZ_LOG_ERROR("zignature: Unsupported type (%s)\n", word);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -503,7 +488,7 @@ static void serialize(RzAnalysis *a, RzSignItem *it, char *k, char *v) {
|
|||
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);
|
||||
RZ_LOG_WARN("zignature: Signature limit reached for 0x%08" PFMT64x " (%s)\n", it->addr, it->name);
|
||||
}
|
||||
char *res = rz_strbuf_drain(sb);
|
||||
if (res) {
|
||||
|
|
@ -672,7 +657,7 @@ RZ_API bool rz_sign_add_item(RzAnalysis *a, RzSignItem *it) {
|
|||
curval = sdb_const_get(a->sdb_zigns, key, 0);
|
||||
if (curval) {
|
||||
if (!rz_sign_deserialize(a, curit, key, curval)) {
|
||||
eprintf("error: cannot deserialize zign\n");
|
||||
RZ_LOG_ERROR("zignature: cannot deserialize zign\n");
|
||||
retval = false;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -741,7 +726,7 @@ static bool addBytes(RzAnalysis *a, const char *name, ut64 size, const ut8 *byte
|
|||
bool retval = true;
|
||||
|
||||
if (rz_mem_is_zero(mask, size)) {
|
||||
eprintf("error: zero mask\n");
|
||||
RZ_LOG_ERROR("zignature: error: zero mask\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -786,12 +771,12 @@ fail:
|
|||
RZ_API bool rz_sign_add_hash(RzAnalysis *a, const char *name, int type, const char *val, int len) {
|
||||
rz_return_val_if_fail(a && name && type && val && len > 0, false);
|
||||
if (type != RZ_SIGN_BBHASH) {
|
||||
eprintf("error: hash type unknown");
|
||||
RZ_LOG_ERROR("zignature: hash type unknown");
|
||||
return false;
|
||||
}
|
||||
int digestsize = ZIGN_HASH_SIZE * 2;
|
||||
if (len != digestsize) {
|
||||
eprintf("error: invalid hash size: %d (%s digest size is %d)\n", len, ZIGN_HASH, digestsize);
|
||||
RZ_LOG_ERROR("zignature: invalid hash size: %d (%s digest size is %d)\n", len, ZIGN_HASH, digestsize);
|
||||
return false;
|
||||
}
|
||||
return addHash(a, name, type, val);
|
||||
|
|
@ -869,7 +854,7 @@ static RzSignBytes *rz_sign_fcn_bytes(RzAnalysis *a, RzAnalysisFunction *fcn) {
|
|||
|
||||
// fill in bytes
|
||||
if (!a->iob.read_at(a->iob.io, ea, sig->bytes, size)) {
|
||||
eprintf("error: failed to read at 0x%08" PFMT64x "\n", ea);
|
||||
RZ_LOG_ERROR("zignature: failed to read at 0x%08" PFMT64x "\n", ea);
|
||||
goto bytes_failed;
|
||||
}
|
||||
|
||||
|
|
@ -948,7 +933,7 @@ RZ_API bool rz_sign_addto_item(RzAnalysis *a, RzSignItem *it, RzAnalysisFunction
|
|||
}
|
||||
break;
|
||||
default:
|
||||
eprintf("Error: %s Can not handle type %c\n", __FUNCTION__, type);
|
||||
RZ_LOG_ERROR("zignature: %s Can not handle type %c\n", __FUNCTION__, type);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -1468,7 +1453,7 @@ RZ_API bool rz_sign_diff(RzAnalysis *a, RzSignOptions *options, const char *othe
|
|||
return false;
|
||||
}
|
||||
|
||||
eprintf("Diff %d %d\n", (int)ls_length(la), (int)ls_length(lb));
|
||||
RZ_LOG_INFO("zignature: Diff %d %d\n", (int)ls_length(la), (int)ls_length(lb));
|
||||
|
||||
RzListIter *itr;
|
||||
RzListIter *itr2;
|
||||
|
|
@ -1526,7 +1511,7 @@ RZ_API bool rz_sign_diff_by_name(RzAnalysis *a, RzSignOptions *options, const ch
|
|||
return false;
|
||||
}
|
||||
|
||||
eprintf("Diff by name %d %d (%s)\n", (int)ls_length(la), (int)ls_length(lb), not_matching ? "not matching" : "matching");
|
||||
RZ_LOG_INFO("zignature: Diff by name %d %d (%s)\n", (int)ls_length(la), (int)ls_length(lb), not_matching ? "not matching" : "matching");
|
||||
|
||||
RzListIter *itr;
|
||||
RzListIter *itr2;
|
||||
|
|
@ -1929,7 +1914,7 @@ static bool listCB(void *user, const char *k, const char *v) {
|
|||
RzAnalysis *a = ctx->analysis;
|
||||
|
||||
if (!rz_sign_deserialize(a, it, k, v)) {
|
||||
eprintf("error: cannot deserialize zign\n");
|
||||
RZ_LOG_ERROR("zignature: cannot deserialize zign\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -2147,7 +2132,7 @@ static bool countForCB(void *user, const char *k, const char *v) {
|
|||
ctx->count++;
|
||||
}
|
||||
} else {
|
||||
eprintf("error: cannot deserialize zign\n");
|
||||
RZ_LOG_ERROR("zignature: cannot deserialize zign\n");
|
||||
}
|
||||
rz_sign_item_free(it);
|
||||
|
||||
|
|
@ -2179,7 +2164,7 @@ static bool unsetForCB(void *user, const char *k, const char *v) {
|
|||
sdb_set(db, nk, nv, 0);
|
||||
}
|
||||
} else {
|
||||
eprintf("error: cannot deserialize zign\n");
|
||||
RZ_LOG_ERROR("zignature: cannot deserialize zign\n");
|
||||
}
|
||||
rz_sign_item_free(it);
|
||||
return true;
|
||||
|
|
@ -2239,7 +2224,7 @@ static bool foreachCB(void *user, const char *k, const char *v) {
|
|||
ctx->cb(it, ctx->user);
|
||||
}
|
||||
} else {
|
||||
eprintf("error: cannot deserialize zign\n");
|
||||
RZ_LOG_ERROR("zignature: cannot deserialize zign\n");
|
||||
}
|
||||
if (ctx->freeit) {
|
||||
rz_sign_item_free(it);
|
||||
|
|
@ -2293,7 +2278,7 @@ static int addSearchKwCB(RzSignItem *it, void *user) {
|
|||
RzSignBytes *bytes = it->bytes;
|
||||
|
||||
if (!bytes) {
|
||||
eprintf("Cannot find bytes for this signature: %s\n", it->name);
|
||||
RZ_LOG_ERROR("zignature: Cannot find bytes for this signature: %s\n", it->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -2504,7 +2489,7 @@ static int match_metrics(RzSignItem *it, void *user) {
|
|||
found = vars_match(it, &ctx->vars, sm);
|
||||
break;
|
||||
default:
|
||||
eprintf("Invalid type: %c\n", type);
|
||||
RZ_LOG_ERROR("zignature: Invalid type: %c\n", type);
|
||||
}
|
||||
if (found) {
|
||||
sm->cb(it, sm->fcn, type, (count > 1), sm->user);
|
||||
|
|
@ -2575,7 +2560,7 @@ static bool loadCB(void *user, const char *k, const char *v) {
|
|||
serialize(a, it, nk, nv);
|
||||
sdb_set(a->sdb_zigns, nk, nv, 0);
|
||||
} else {
|
||||
eprintf("error: cannot deserialize zign\n");
|
||||
RZ_LOG_ERROR("zignature: cannot deserialize zign\n");
|
||||
}
|
||||
rz_sign_item_free(it);
|
||||
return true;
|
||||
|
|
@ -2623,7 +2608,7 @@ RZ_API bool rz_sign_load(RzAnalysis *a, const char *file) {
|
|||
}
|
||||
char *path = rz_sign_path(a, file);
|
||||
if (!rz_file_exists(path)) {
|
||||
eprintf("error: file %s does not exist\n", file);
|
||||
RZ_LOG_ERROR("zignature: file %s does not exist\n", file);
|
||||
free(path);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2647,37 +2632,37 @@ RZ_API bool rz_sign_load_gz(RzAnalysis *a, const char *filename) {
|
|||
|
||||
char *path = rz_sign_path(a, filename);
|
||||
if (!rz_file_exists(path)) {
|
||||
eprintf("error: file %s does not exist\n", filename);
|
||||
RZ_LOG_ERROR("zignature: file %s does not exist\n", filename);
|
||||
retval = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(buf = rz_file_gzslurp(path, &size, 0))) {
|
||||
eprintf("error: cannot decompress file\n");
|
||||
RZ_LOG_ERROR("zignature: cannot decompress file\n");
|
||||
retval = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(tmpfile = rz_file_temp("r2zign"))) {
|
||||
eprintf("error: cannot create temp file\n");
|
||||
RZ_LOG_ERROR("zignature: cannot create temp file\n");
|
||||
retval = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!rz_file_dump(tmpfile, buf, size, 0)) {
|
||||
eprintf("error: cannot dump file\n");
|
||||
RZ_LOG_ERROR("zignature: cannot dump file\n");
|
||||
retval = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!rz_sign_load(a, tmpfile)) {
|
||||
eprintf("error: cannot load file\n");
|
||||
RZ_LOG_ERROR("zignature: cannot load file\n");
|
||||
retval = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!rz_file_rm(tmpfile)) {
|
||||
eprintf("error: cannot delete temp file\n");
|
||||
RZ_LOG_ERROR("zignature: cannot delete temp file\n");
|
||||
retval = false;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2694,7 +2679,7 @@ RZ_API bool rz_sign_save(RzAnalysis *a, const char *file) {
|
|||
rz_return_val_if_fail(a && file, false);
|
||||
|
||||
if (sdb_isempty(a->sdb_zigns)) {
|
||||
eprintf("WARNING: no zignatures to save\n");
|
||||
RZ_LOG_WARN("zignature: no zignatures to save\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2738,3 +2723,40 @@ RZ_API RzSignOptions *rz_sign_options_new(const char *bytes_thresh, const char *
|
|||
RZ_API void rz_sign_options_free(RzSignOptions *options) {
|
||||
RZ_FREE(options);
|
||||
}
|
||||
|
||||
static void zign_unset_for(RzEvent *ev, int type, void *user, void *data) {
|
||||
RzSpaces *s = (RzSpaces *)ev->user;
|
||||
RzAnalysis *analysis = container_of(s, RzAnalysis, zign_spaces);
|
||||
RzSpaceEvent *se = (RzSpaceEvent *)data;
|
||||
rz_sign_space_unset_for(analysis, se->data.unset.space);
|
||||
}
|
||||
|
||||
static void zign_count_for(RzEvent *ev, int type, void *user, void *data) {
|
||||
RzSpaces *s = (RzSpaces *)ev->user;
|
||||
RzAnalysis *analysis = container_of(s, RzAnalysis, zign_spaces);
|
||||
RzSpaceEvent *se = (RzSpaceEvent *)data;
|
||||
se->res = rz_sign_space_count_for(analysis, se->data.count.space);
|
||||
}
|
||||
|
||||
static void zign_rename_for(RzEvent *ev, int type, void *user, void *data) {
|
||||
RzSpaces *s = (RzSpaces *)ev->user;
|
||||
RzAnalysis *analysis = container_of(s, RzAnalysis, zign_spaces);
|
||||
RzSpaceEvent *se = (RzSpaceEvent *)data;
|
||||
rz_sign_space_rename_for(analysis, se->data.rename.space,
|
||||
se->data.rename.oldname, se->data.rename.newname);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize the event RzSpaces for zignatures
|
||||
* Initialize the RzSpaces for zignatures events (the event space is already cleaned by rz_analysis_free)
|
||||
* This adds the hooks for unset, count and rename
|
||||
* \param RzAnalysis The RzAnalysis structure to initialize
|
||||
*/
|
||||
RZ_API void rz_sign_analysis_set_hooks(RZ_NONNULL RzAnalysis *analysis) {
|
||||
rz_return_if_fail(analysis);
|
||||
|
||||
rz_spaces_init(&analysis->zign_spaces, "zs");
|
||||
rz_event_hook(analysis->zign_spaces.event, RZ_SPACE_EVENT_UNSET, zign_unset_for, NULL);
|
||||
rz_event_hook(analysis->zign_spaces.event, RZ_SPACE_EVENT_COUNT, zign_count_for, NULL);
|
||||
rz_event_hook(analysis->zign_spaces.event, RZ_SPACE_EVENT_RENAME, zign_rename_for, NULL);
|
||||
}
|
||||
|
|
@ -576,6 +576,7 @@ if host_machine.system() == 'windows'
|
|||
build_root / 'librz' / 'bp',
|
||||
build_root / 'librz' / 'config',
|
||||
build_root / 'librz' / 'cons',
|
||||
build_root / 'librz' / 'signature',
|
||||
build_root / 'librz' / 'core',
|
||||
build_root / 'librz' / 'demangler',
|
||||
build_root / 'librz' / 'diff',
|
||||
|
|
@ -623,6 +624,7 @@ subdir('librz/lang')
|
|||
subdir('librz/asm')
|
||||
subdir('librz/il')
|
||||
subdir('librz/analysis')
|
||||
subdir('librz/signature')
|
||||
subdir('librz/egg')
|
||||
subdir('librz/debug')
|
||||
subdir('librz/core')
|
||||
|
|
@ -690,6 +692,7 @@ if meson.is_subproject()
|
|||
rz_socket_dep,
|
||||
rz_syscall_dep,
|
||||
rz_il_dep,
|
||||
rz_sign_dep,
|
||||
rz_type_dep,
|
||||
rz_diff_dep,
|
||||
rz_demangler_dep,
|
||||
|
|
|
|||
|
|
@ -692,7 +692,6 @@ NAME=aa ; zfs libc-v7.sig
|
|||
FILE=bins/elf/analysis/pid_stripped
|
||||
CMDS=aa ; zfs bins/other/sigs/libc-v7.sig
|
||||
EXPECT=<<EOF
|
||||
Found flirt.__libc_start_main
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
@ -710,7 +709,6 @@ ARGS=-ecfg.oldshell=false
|
|||
FILE=bins/elf/analysis/pid_stripped
|
||||
CMDS=s 0x4e2420 ; af ; s 0x4e25c7 ; af ; zfs bins/other/sigs/libc-v7.sig ; afl ~4e2420
|
||||
EXPECT=<<EOF
|
||||
Found flirt.__libc_start_main
|
||||
0x004e2420 40 664 flirt.__libc_start_main
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -726,7 +724,6 @@ zfs bins/other/sigs/libc-v7.sig
|
|||
afl~4e2420
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
Found flirt.__libc_start_main
|
||||
0x004e2420 40 664 flirt.__libc_start_main
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -735,7 +732,6 @@ NAME=aa ; zfs libc-v10.sig
|
|||
FILE=bins/elf/analysis/pid_stripped
|
||||
CMDS=aa ; zfs bins/other/sigs/libc-v10.sig
|
||||
EXPECT=<<EOF
|
||||
Found flirt.__libc_start_main
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
@ -753,7 +749,6 @@ ARGS=-ecfg.oldshell=false
|
|||
FILE=bins/elf/analysis/pid_stripped
|
||||
CMDS=s 0x4e2420 ; af ; s 0x4e25c7 ; af ; zfs bins/other/sigs/libc-v10.sig ; afl ~4e2420
|
||||
EXPECT=<<EOF
|
||||
Found flirt.__libc_start_main
|
||||
0x004e2420 40 664 flirt.__libc_start_main
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -769,7 +764,6 @@ zfs bins/other/sigs/libc-v10.sig
|
|||
afl~4e2420
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
Found flirt.__libc_start_main
|
||||
0x004e2420 40 664 flirt.__libc_start_main
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -1344,6 +1344,7 @@ Sdb *sign_ref_db() {
|
|||
|
||||
bool test_analysis_sign_save() {
|
||||
RzAnalysis *analysis = rz_analysis_new();
|
||||
rz_sign_analysis_set_hooks(analysis);
|
||||
|
||||
RzSignItem *item = rz_sign_item_new();
|
||||
item->name = strdup("sym.mahboi");
|
||||
|
|
@ -1405,6 +1406,8 @@ bool test_analysis_sign_save() {
|
|||
|
||||
bool test_analysis_sign_load() {
|
||||
RzAnalysis *analysis = rz_analysis_new();
|
||||
rz_sign_analysis_set_hooks(analysis);
|
||||
|
||||
Sdb *db = sign_ref_db();
|
||||
bool succ = rz_serialize_analysis_sign_load(db, analysis, NULL);
|
||||
sdb_free(db);
|
||||
|
|
@ -1579,6 +1582,7 @@ Sdb *analysis_ref_db() {
|
|||
|
||||
bool test_analysis_save() {
|
||||
RzAnalysis *analysis = rz_analysis_new();
|
||||
rz_sign_analysis_set_hooks(analysis);
|
||||
|
||||
RzAnalysisBlock *ba = rz_analysis_create_block(analysis, 1337, 42);
|
||||
RzAnalysisBlock *bb = rz_analysis_create_block(analysis, 1234, 32);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
static bool test_analysis_sign_get_set(void) {
|
||||
RzAnalysis *analysis = rz_analysis_new();
|
||||
rz_sign_analysis_set_hooks(analysis);
|
||||
|
||||
RzSignItem *item = rz_sign_item_new();
|
||||
item->name = strdup("sym.mahboi");
|
||||
|
|
|
|||
Loading…
Reference in a new issue