[FLIRT] Refactoring and create rz_sign library (#1960)

This commit is contained in:
Giovanni 2021-11-11 20:29:59 +01:00 committed by GitHub
parent 92e1139f69
commit f41ea3c284
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 538 additions and 416 deletions

5
.github/labeler.yml vendored
View file

@ -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

View file

@ -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();

View file

@ -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',

View file

@ -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;

View file

@ -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
View 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;
}
}

View file

@ -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'

View file

@ -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

View file

@ -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
View 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 */

View file

@ -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);

View file

@ -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'
],

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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;
}
}

View 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
View 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);

View file

@ -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);
}

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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");