Rizin
unix-like reverse engineering framework and cli tools
sigdb.c File Reference
#include <rz_flirt.h>

Go to the source code of this file.

Classes

struct  sigdb_move_data_t
 

Macros

#define field_cmp(fname, cmpfunction)
 

Functions

RZ_API void rz_sign_sigdb_signature_free (RZ_NULLABLE RzSigDBEntry *entry)
 Frees a RzSigDBEntry structure. More...
 
static int sigdb_signature_cmp (const RzSigDBEntry *a, const RzSigDBEntry *b)
 
static bool sigdb_signature_resolve_details (RzSigDBEntry *entry, size_t path_len, bool with_details)
 
RZ_API RZ_OWN RzSigDbrz_sign_sigdb_load_database (RZ_NONNULL const char *sigdb_path, bool with_details)
 Returns a database of signatures loaded from the signature database path. More...
 
RZ_API bool rz_sign_sigdb_add_entry (RZ_NONNULL RzSigDb *db, RZ_NONNULL const RzSigDBEntry *entry)
 Add a new signature entry to a database. More...
 
static bool sigdb_move_entry (void *user, const void *k, const ut64 v)
 
RZ_API bool rz_sign_sigdb_merge (RZ_NONNULL RzSigDb *db, RZ_NONNULL RzSigDb *db2)
 Merge the signatures from db2 into db. More...
 
static int ut32cmp (int a, int b)
 
static int strcmp_null (const char *a, const char *b)
 
static int sigdb_entry_cmp (const void *a, const void *b)
 
static ut32 sigdb_entry_hash (const void *k)
 
static void ht_pu_sigdb_freekv (HtPUKv *kv)
 
RZ_API RZ_OWN RzSigDbrz_sign_sigdb_new (void)
 Create a new empty RzSigDb instance. More...
 
RZ_API void rz_sign_sigdb_free (RzSigDb *db)
 
static bool sigdb_to_list (void *user, const void *k, const ut64 v)
 
RZ_API RZ_OWN RzListrz_sign_sigdb_list (RZ_NONNULL const RzSigDb *db)
 Return the signature database as a list of entries. More...
 

Macro Definition Documentation

◆ field_cmp

#define field_cmp (   fname,
  cmpfunction 
)
Value:
do { \
int r = cmpfunction(sa->fname, sb->fname); \
if (r != 0) { \
return r; \
} \
} while (0)
static SblHeader sb
Definition: bin_mbn.c:26
#define r
Definition: crypto_rc6.c:12

Function Documentation

◆ ht_pu_sigdb_freekv()

static void ht_pu_sigdb_freekv ( HtPUKv *  kv)
static

Definition at line 250 of file sigdb.c.

250  {
251  if (!kv) {
252  return;
253  }
255 }
RZ_API void rz_sign_sigdb_signature_free(RZ_NULLABLE RzSigDBEntry *entry)
Frees a RzSigDBEntry structure.
Definition: sigdb.c:12

References rz_sign_sigdb_signature_free().

Referenced by rz_sign_sigdb_new().

◆ rz_sign_sigdb_add_entry()

RZ_API bool rz_sign_sigdb_add_entry ( RZ_NONNULL RzSigDb db,
RZ_NONNULL const RzSigDBEntry entry 
)

Add a new signature entry to a database.

Parameters
dbDatabase of signatures
entrySingle signature entry to add to the database
Returns
true if the signature entry was correctly added to the database, false otherwise

Definition at line 158 of file sigdb.c.

158  {
160  return ht_pu_insert(db->entries, entry, 1);
161 }
#define NULL
Definition: cris-opc.c:27
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
Definition: zipcmp.c:77

References NULL, and rz_return_val_if_fail.

Referenced by rz_sign_sigdb_load_database(), and sigdb_move_entry().

◆ rz_sign_sigdb_free()

RZ_API void rz_sign_sigdb_free ( RzSigDb db)

Definition at line 277 of file sigdb.c.

277  {
278  if (!db) {
279  return;
280  }
281  ht_pu_free(db->entries);
282  free(db);
283 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References rz_signature_db_t::entries, and free().

Referenced by analysis_sigdb_add(), and rz_sign_sigdb_load_database().

◆ rz_sign_sigdb_list()

RZ_API RZ_OWN RzList* rz_sign_sigdb_list ( RZ_NONNULL const RzSigDb db)

Return the signature database as a list of entries.

Definition at line 294 of file sigdb.c.

294  {
296 
297  RzList *res = rz_list_new();
298  if (!res) {
299  return NULL;
300  }
301  ht_pu_foreach(db->entries, sigdb_to_list, res);
303  return res;
304 }
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
static int sigdb_signature_cmp(const RzSigDBEntry *a, const RzSigDBEntry *b)
Definition: sigdb.c:24
static bool sigdb_to_list(void *user, const void *k, const ut64 v)
Definition: sigdb.c:285

References NULL, rz_list_new(), rz_list_sort(), rz_return_val_if_fail, sigdb_signature_cmp(), and sigdb_to_list().

Referenced by rz_core_analysis_sigdb_list().

◆ rz_sign_sigdb_load_database()

RZ_API RZ_OWN RzSigDb* rz_sign_sigdb_load_database ( RZ_NONNULL const char *  sigdb_path,
bool  with_details 
)

Returns a database of signatures loaded from the signature database path.

Parameters
sigdb_pathThe signature database path/location
with_detailsWhen true, opens each signature within the db for extra details
Returns
List of entries

Definition at line 105 of file sigdb.c.

105  {
107  char glob[1024];
108  if (!rz_file_is_directory(sigdb_path)) {
109  RZ_LOG_ERROR("sigdb path is unknown or invalid (path: %s)\n", sigdb_path);
110  return NULL;
111  }
112  size_t path_len = strlen(sigdb_path) + 1; // ignoring also the filesystem separator
113  RzSigDb *sigs = rz_sign_sigdb_new();
114  if (!sigs) {
115  RZ_LOG_ERROR("cannot allocate signature database\n");
116  return NULL;
117  }
118 
119  rz_strf(glob, RZ_JOIN_2_PATHS("%s", "**"), sigdb_path);
120  RzList *files = rz_file_globsearch(glob, 10);
121  char *file = NULL;
122  RzListIter *iter = NULL;
123  RzSigDBEntry *sig = NULL;
124 
125  rz_list_foreach (files, iter, file) {
126  if (!rz_str_endswith(file, ".pat") && !rz_str_endswith(file, ".sig")) {
127  continue;
128  }
129 
130  sig = RZ_NEW0(RzSigDBEntry);
131  if (!sig) {
132  goto fail;
133  }
134 
135  sig->file_path = strdup(file);
136  if (!sig->file_path || !sigdb_signature_resolve_details(sig, path_len, with_details)) {
138  goto fail;
139  }
140  rz_sign_sigdb_add_entry(sigs, sig);
141  }
143  return sigs;
144 
145 fail:
147  rz_sign_sigdb_free(sigs);
148  return NULL;
149 }
checking print the parsed form of the magic use in n conjunction with m to debug a new magic file n before installing it n output MIME type special files
Definition: file_opts.h:46
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API bool rz_file_is_directory(const char *str)
Definition: file.c:167
RZ_API RzList * rz_file_globsearch(const char *globbed_path, int maxdepth)
Definition: file.c:1263
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_JOIN_2_PATHS(p1, p2)
Definition: rz_types.h:224
RZ_API RZ_OWN RzSigDb * rz_sign_sigdb_new(void)
Create a new empty RzSigDb instance.
Definition: sigdb.c:260
RZ_API void rz_sign_sigdb_free(RzSigDb *db)
Definition: sigdb.c:277
static bool sigdb_signature_resolve_details(RzSigDBEntry *entry, size_t path_len, bool with_details)
Definition: sigdb.c:28
RZ_API bool rz_sign_sigdb_add_entry(RZ_NONNULL RzSigDb *db, RZ_NONNULL const RzSigDBEntry *entry)
Add a new signature entry to a database.
Definition: sigdb.c:158
Definition: gzappend.c:170
Definition: rz_flirt.h:240
char * file_path
full path to the signature file
Definition: rz_flirt.h:246
#define fail(test)
Definition: tests.h:29

References fail, rz_signature_database_entry_t::file_path, files, NULL, rz_file_globsearch(), rz_file_is_directory(), RZ_JOIN_2_PATHS, rz_list_free(), RZ_LOG_ERROR, RZ_NEW0, rz_return_val_if_fail, rz_sign_sigdb_add_entry(), rz_sign_sigdb_free(), rz_sign_sigdb_new(), rz_sign_sigdb_signature_free(), rz_str_endswith(), RZ_STR_ISNOTEMPTY, rz_strf, sigdb_signature_resolve_details(), and strdup().

Referenced by analysis_sigdb_add().

◆ rz_sign_sigdb_merge()

RZ_API bool rz_sign_sigdb_merge ( RZ_NONNULL RzSigDb db,
RZ_NONNULL RzSigDb db2 
)

Merge the signatures from db2 into db.

Data within db2 is moved into db, making it empty.

Parameters
dbDatabase of signatures to extend
db2Database of signatures that need to be merged into db
Returns
true if the databases were correctly merged, false otherwise

Definition at line 184 of file sigdb.c.

184  {
185  rz_return_val_if_fail(db && db2, NULL);
186  struct sigdb_move_data_t opt = {
187  .src = db2,
188  .dst = db,
189  };
190  db2->entries->opt.freefn = NULL;
191  ht_pu_foreach(db2->entries, sigdb_move_entry, &opt);
192  return true;
193 }
static bool sigdb_move_entry(void *user, const void *k, const ut64 v)
Definition: sigdb.c:168
RzSigDb * src
Definition: sigdb.c:164

References rz_signature_db_t::entries, NULL, rz_return_val_if_fail, sigdb_move_entry(), and sigdb_move_data_t::src.

Referenced by analysis_sigdb_add().

◆ rz_sign_sigdb_new()

RZ_API RZ_OWN RzSigDb* rz_sign_sigdb_new ( void  )

Create a new empty RzSigDb instance.

Definition at line 260 of file sigdb.c.

260  {
261  RzSigDb *db = RZ_NEW0(RzSigDb);
262  if (!db) {
263  return NULL;
264  }
265  HtPUOptions opt = { 0 };
266  opt.cmp = sigdb_entry_cmp,
267  opt.hashfn = sigdb_entry_hash,
268  opt.freefn = ht_pu_sigdb_freekv;
269  db->entries = ht_pu_new_opt(&opt);
270  if (!db->entries) {
271  free(db);
272  return NULL;
273  }
274  return db;
275 }
static void ht_pu_sigdb_freekv(HtPUKv *kv)
Definition: sigdb.c:250
static int sigdb_entry_cmp(const void *a, const void *b)
Definition: sigdb.c:218
static ut32 sigdb_entry_hash(const void *k)
Definition: sigdb.c:241

References rz_signature_db_t::entries, free(), ht_pu_sigdb_freekv(), NULL, RZ_NEW0, sigdb_entry_cmp(), and sigdb_entry_hash().

Referenced by rz_core_analysis_sigdb_list(), and rz_sign_sigdb_load_database().

◆ rz_sign_sigdb_signature_free()

RZ_API void rz_sign_sigdb_signature_free ( RZ_NULLABLE RzSigDBEntry entry)

Frees a RzSigDBEntry structure.

Parameters
[in]entryThe RzSigDBEntry to free

Definition at line 12 of file sigdb.c.

12  {
13  if (!entry) {
14  return;
15  }
16  // base_name points to file_path, so there is no need to call free
17  // short_path points to file_path, so there is no need to call free
18  free(entry->bin_name);
19  free(entry->arch_name);
20  free(entry->file_path);
21  free(entry);
22 }

References free().

Referenced by ht_pu_sigdb_freekv(), and rz_sign_sigdb_load_database().

◆ sigdb_entry_cmp()

static int sigdb_entry_cmp ( const void *  a,
const void *  b 
)
static

Definition at line 218 of file sigdb.c.

218  {
219 #define field_cmp(fname, cmpfunction) \
220  do { \
221  int r = cmpfunction(sa->fname, sb->fname); \
222  if (r != 0) { \
223  return r; \
224  } \
225  } while (0)
226 
227  const RzSigDBEntry *sa = (const RzSigDBEntry *)a;
228  const RzSigDBEntry *sb = (const RzSigDBEntry *)b;
229  field_cmp(bin_name, strcmp_null);
230  field_cmp(arch_name, strcmp_null);
231  field_cmp(arch_bits, ut32cmp);
232  field_cmp(base_name, strcmp_null);
233  field_cmp(short_path, strcmp_null);
234  field_cmp(file_path, strcmp_null);
235  field_cmp(details, strcmp_null);
236  field_cmp(n_modules, ut32cmp);
237  return 0;
238 #undef field_cmp
239 }
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
static int ut32cmp(int a, int b)
Definition: sigdb.c:195
static int strcmp_null(const char *a, const char *b)
Definition: sigdb.c:205
#define field_cmp(fname, cmpfunction)

References a, b, field_cmp, sb, strcmp_null(), and ut32cmp().

Referenced by rz_sign_sigdb_new().

◆ sigdb_entry_hash()

static ut32 sigdb_entry_hash ( const void *  k)
static

Definition at line 241 of file sigdb.c.

241  {
242  const RzSigDBEntry *s = (const RzSigDBEntry *)k;
243  ut32 r = sdb_hash(s->bin_name);
244  r ^= sdb_hash(s->arch_name);
245  r ^= s->arch_bits;
246  r ^= sdb_hash(s->short_path);
247  return r;
248 }
uint32_t ut32
const char * k
Definition: dsignal.c:11
static RzSocket * s
Definition: rtr.c:28
RZ_API ut32 sdb_hash(const char *key)
Definition: util.c:22

References k, r, s, and sdb_hash().

Referenced by rz_sign_sigdb_new().

◆ sigdb_move_entry()

static bool sigdb_move_entry ( void *  user,
const void *  k,
const ut64  v 
)
static

Definition at line 168 of file sigdb.c.

168  {
169  struct sigdb_move_data_t *move_data = (struct sigdb_move_data_t *)user;
170  rz_sign_sigdb_add_entry(move_data->dst, k);
171  ht_pu_delete(move_data->src->entries, k);
172  return true;
173 }
RzSigDb * dst
Definition: sigdb.c:165

References sigdb_move_data_t::dst, rz_signature_db_t::entries, k, rz_sign_sigdb_add_entry(), and sigdb_move_data_t::src.

Referenced by rz_sign_sigdb_merge().

◆ sigdb_signature_cmp()

static int sigdb_signature_cmp ( const RzSigDBEntry a,
const RzSigDBEntry b 
)
static

Definition at line 24 of file sigdb.c.

24  {
25  return strcmp(a->short_path, b->short_path);
26 }

References a, and b.

Referenced by rz_sign_sigdb_list().

◆ sigdb_signature_resolve_details()

static bool sigdb_signature_resolve_details ( RzSigDBEntry entry,
size_t  path_len,
bool  with_details 
)
static

Definition at line 28 of file sigdb.c.

28  {
29  char *bin_end = NULL;
30  char *arch_end = NULL;
31  char *bits_end = NULL;
32  char copy_path[1024] = { 0 };
33  RzFlirtNode *node = NULL;
34  RzFlirtInfo info = { 0 };
35  RzBuffer *buffer = NULL;
36 
37 #if __WINDOWS__
38  rz_str_replace_char(entry->file_path, '/', '\\');
39 #endif
40  // expected path elf/x86/64/signature.sig/.pat
41  strncpy(copy_path, entry->file_path + path_len, sizeof(copy_path) - 1);
42  entry->base_name = rz_file_basename(entry->file_path);
43  entry->short_path = entry->file_path + path_len;
44 
45  if (!(bin_end = strstr(copy_path, RZ_SYS_DIR))) {
46  RZ_LOG_WARN("sigdb: folder structure is invalid (missing bin name).\n");
47  return false;
48  } else if (!(arch_end = strstr(bin_end + strlen(RZ_SYS_DIR), RZ_SYS_DIR))) {
49  RZ_LOG_WARN("sigdb: folder structure is invalid (missing arch name).\n");
50  return false;
51  } else if (!(bits_end = strstr(arch_end + strlen(RZ_SYS_DIR), RZ_SYS_DIR))) {
52  RZ_LOG_WARN("sigdb: folder structure is invalid (missing arch bits).\n");
53  return false;
54  }
55 
56  if (!with_details) {
57  goto skip_details;
58  }
59 
60  buffer = rz_buf_new_file(entry->file_path, O_RDONLY, 0);
61  if (!buffer) {
62  RZ_LOG_WARN("sigdb: cannot open signature file '%s'.\n", entry->file_path);
63  return false;
64  }
65 
66  if (rz_str_endswith(entry->base_name, ".sig")) {
69  if (!success) {
70  return false;
71  }
72 
73  entry->details = RZ_STR_DUP(info.u.sig.name);
74  entry->n_modules = info.u.sig.n_modules;
75  } else {
78  if (!node) {
79  return false;
80  }
81 
82  entry->n_modules = info.u.pat.n_modules;
83  }
86 
87 skip_details:
88  bin_end[0] = 0;
89  entry->bin_name = strdup(copy_path);
90  arch_end[0] = 0;
91  entry->arch_name = strdup(bin_end + strlen(RZ_SYS_DIR));
92  bits_end[0] = 0;
93  entry->arch_bits = rz_get_input_num_value(NULL, arch_end + strlen(RZ_SYS_DIR));
94 
95  return true;
96 }
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_file(const char *file, int perm, int mode)
Creates a new buffer from a file.
Definition: buf.c:317
RZ_API const char * rz_file_basename(const char *path)
Definition: file.c:83
RZ_API RZ_OWN RzFlirtNode * rz_sign_flirt_parse_string_pattern_from_buffer(RZ_NONNULL RzBuffer *flirt_buf, ut32 optimization, RZ_NULLABLE RzFlirtInfo *info)
Parses the RzBuffer containing a FLIRT signature in string format and returns an RzFlirtNode.
Definition: pat.c:356
RZ_API void rz_sign_flirt_node_free(RZ_NULLABLE RzFlirtNode *node)
Frees an RzFlirtNode struct.
Definition: flirt.c:299
RZ_API RZ_OWN bool rz_sign_flirt_parse_header_compressed_pattern_from_buffer(RZ_NONNULL RzBuffer *flirt_buf, RZ_NONNULL RzFlirtInfo *info)
Parses the RzBuffer containing a FLIRT structure and returns an RzFlirtInfo.
Definition: flirt.c:1062
RZ_API void rz_sign_flirt_info_fini(RZ_NULLABLE RzFlirtInfo *info)
Frees an RzFlirtInfo struct elements without freeing the pointer.
Definition: flirt.c:315
@ RZ_FLIRT_NODE_OPTIMIZE_NONE
keeps the structure flattened (keep the tail bytes)
Definition: rz_flirt.h:186
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
RZ_API ut64 rz_get_input_num_value(RzNum *num, const char *input_value)
Definition: unum.c:743
RZ_API int rz_str_replace_char(char *s, int a, int b)
Definition: str.c:169
#define RZ_STR_DUP(x)
Definition: rz_str.h:69
#define RZ_SYS_DIR
Definition: rz_types.h:218
#define O_RDONLY
Definition: sftypes.h:486
Definition: buffer.h:15

References info(), NULL, O_RDONLY, rz_buf_free(), rz_buf_new_file(), rz_file_basename(), RZ_FLIRT_NODE_OPTIMIZE_NONE, rz_get_input_num_value(), RZ_LOG_WARN, rz_sign_flirt_info_fini(), rz_sign_flirt_node_free(), rz_sign_flirt_parse_header_compressed_pattern_from_buffer(), rz_sign_flirt_parse_string_pattern_from_buffer(), RZ_STR_DUP, rz_str_endswith(), rz_str_replace_char(), RZ_SYS_DIR, and strdup().

Referenced by rz_sign_sigdb_load_database().

◆ sigdb_to_list()

static bool sigdb_to_list ( void *  user,
const void *  k,
const ut64  v 
)
static

Definition at line 285 of file sigdb.c.

285  {
286  RzList *l = (RzList *)user;
287  rz_list_append(l, (void *)k);
288  return true;
289 }
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288

References k, and rz_list_append().

Referenced by rz_sign_sigdb_list().

◆ strcmp_null()

static int strcmp_null ( const char *  a,
const char *  b 
)
static

Definition at line 205 of file sigdb.c.

205  {
206  if (!a && !b) {
207  return 0;
208  }
209  if (!a && b) {
210  return -1;
211  }
212  if (a && !b) {
213  return 1;
214  }
215  return strcmp(a, b);
216 }

References a, and b.

Referenced by sigdb_entry_cmp().

◆ ut32cmp()

static int ut32cmp ( int  a,
int  b 
)
static

Definition at line 195 of file sigdb.c.

195  {
196  if (a < b) {
197  return -1;
198  }
199  if (a > b) {
200  return 1;
201  }
202  return 0;
203 }

References a, and b.

Referenced by sigdb_entry_cmp().