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

Go to the source code of this file.

Classes

struct  idasig_v5_t
 
struct  idasig_v6_v7_t
 
struct  idasig_v8_v9_t
 
struct  idasig_v10_t
 
struct  parse_status_t
 

Macros

#define MAX_WBITS   15
 
#define sig_dbg(...)
 
#define sig_dbg_buffer(n, b, s)
 
#define rz_buf_append_le_bits(buffer, tmp, value, bits)
 
#define rz_buf_append_be_bits(buffer, tmp, value, bits)
 
#define IDASIG_FEATURE_NONE   0x00
 
#define IDASIG_FEATURE_STARTUP   0x01
 
#define IDASIG_FEATURE_CTYPE_CRC   0x02
 
#define IDASIG_FEATURE_2BYTE_CTYPE   0x04
 
#define IDASIG_FEATURE_ALT_CTYPE_CRC   0x08
 
#define IDASIG_FEATURE_COMPRESSED   0x10
 
#define IDASIG_PARSE_MORE_PUBLIC_NAMES   0x01
 
#define IDASIG_PARSE_READ_TAIL_BYTES   0x02
 
#define IDASIG_PARSE_READ_REFERENCED_FUNCTIONS   0x04
 
#define IDASIG_PARSE_MORE_MODULES_WITH_SAME_CRC   0x08
 
#define IDASIG_PARSE_MORE_MODULES   0x10
 
#define IDASIG_FUNCTION_LOCAL   0x02
 
#define IDASIG_FUNCTION_UNRESOLVED_COLLISION   0x08
 
#define is_status_err_or_eof(p)   (p->eof || p->error)
 
#define POLY   0x8408
 

Typedefs

typedef struct idasig_v5_t idasig_v5_t
 
typedef struct idasig_v6_v7_t idasig_v6_v7_t
 
typedef struct idasig_v8_v9_t idasig_v8_v9_t
 
typedef struct idasig_v10_t idasig_v10_t
 
typedef struct parse_status_t ParseStatus
 

Functions

ut16 flirt_crc16 (const ut8 *data_p, size_t length)
 
static ut8 read_byte (ParseStatus *b)
 
static ut16 read_short (ParseStatus *b)
 
static ut32 read_word (ParseStatus *b)
 
static ut16 read_max_2_bytes (ParseStatus *b)
 
static ut32 read_multiple_bytes (ParseStatus *b)
 
void module_free (RzFlirtModule *module)
 
RZ_API void rz_sign_flirt_node_free (RZ_NULLABLE RzFlirtNode *node)
 Frees an RzFlirtNode struct. More...
 
RZ_API void rz_sign_flirt_info_fini (RZ_NULLABLE RzFlirtInfo *info)
 Frees an RzFlirtInfo struct elements without freeing the pointer. More...
 
static bool is_pattern_matching (ut32 p_size, const ut8 *pattern, const ut8 *mask, const ut8 *b, ut32 b_size)
 Checks if a pattern does match the buffer data. More...
 
static int module_match_buffer (RzAnalysis *analysis, const RzFlirtModule *module, ut8 *b, ut64 address, ut32 buf_size)
 Checks if the module matches the buffer and renames the matched functions. More...
 
static int node_match_buffer (RzAnalysis *analysis, const RzFlirtNode *node, ut8 *b, ut64 address, ut32 buf_size, ut32 buf_idx)
 
static bool 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 analysis. More...
 
static ut8 read_module_tail_bytes (RzFlirtModule *module, ParseStatus *b)
 
static ut8 read_module_referenced_functions (RzFlirtModule *module, ParseStatus *b)
 
static ut8 read_module_public_functions (RzFlirtModule *module, ParseStatus *b, ut8 *flags)
 
static ut8 parse_leaf (ParseStatus *b, RzFlirtNode *node)
 
static bool read_node_length (RzFlirtNode *node, ParseStatus *b)
 
static bool read_node_variant_mask (RzFlirtNode *node, ParseStatus *b)
 
static bool read_node_bytes (RzFlirtNode *node, ParseStatus *b)
 
static ut8 parse_tree (ParseStatus *b, RzFlirtNode *root_node)
 
static bool parse_v5_header (RzBuffer *buf, idasig_v5_t *header)
 
static int parse_v6_v7_header (RzBuffer *buf, idasig_v6_v7_t *header)
 
static int parse_v8_v9_header (RzBuffer *buf, idasig_v8_v9_t *header)
 
static int parse_v10_header (RzBuffer *buf, idasig_v10_t *header)
 
static ut8 flirt_parse_version (RzBuffer *buffer)
 Returns the FLIRT file version read from the RzBuffer This function returns the FLIRT file version, when it fails returns 0. More...
 
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. More...
 
RZ_API RZ_OWN RzFlirtNoderz_sign_flirt_parse_compressed_pattern_from_buffer (RZ_NONNULL RzBuffer *flirt_buf, ut8 expected_arch, RZ_NULLABLE RzFlirtInfo *info)
 Parses the RzBuffer containing a FLIRT structure and returns an RzFlirtNode. More...
 
RZ_API bool rz_sign_flirt_apply (RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL const char *flirt_file, ut8 expected_arch)
 Parses the FLIRT file and applies the signatures. More...
 
RZ_API ut32 rz_sign_flirt_node_count_nodes (RZ_NONNULL const RzFlirtNode *node)
 Counts the number of FLIRT signatures in the node. More...
 
static bool rz_write_vle16 (RzBuffer *buffer, ut16 val)
 
static bool rz_write_vle32 (RzBuffer *buffer, ut32 val)
 
static bool rz_write_vle64 (RzBuffer *buffer, ut64 val)
 
static bool flirt_has_references (RZ_NONNULL const RzFlirtModule *module)
 
static bool rz_write_versioned_vle (RzBuffer *buffer, ut32 value, ut8 version)
 
static bool flirt_write_module (RZ_NONNULL const RzFlirtModule *module, RZ_NONNULL RzBuffer *buffer, ut8 flags, ut8 version, bool first)
 
static bool flirt_write_node (RZ_NONNULL const RzFlirtNode *node, RZ_NONNULL RzBuffer *buffer, ut8 version)
 
RZ_API bool rz_sign_flirt_write_compressed_pattern_to_buffer (RZ_NONNULL const RzFlirtNode *node, RZ_NONNULL RzBuffer *buffer, RzFlirtCompressedOptions *options)
 Writes in the the RzBuffer the FLIRT signatures in compressed format. More...
 

Macro Definition Documentation

◆ IDASIG_FEATURE_2BYTE_CTYPE

#define IDASIG_FEATURE_2BYTE_CTYPE   0x04

Definition at line 133 of file flirt.c.

◆ IDASIG_FEATURE_ALT_CTYPE_CRC

#define IDASIG_FEATURE_ALT_CTYPE_CRC   0x08

Definition at line 134 of file flirt.c.

◆ IDASIG_FEATURE_COMPRESSED

#define IDASIG_FEATURE_COMPRESSED   0x10

Definition at line 135 of file flirt.c.

◆ IDASIG_FEATURE_CTYPE_CRC

#define IDASIG_FEATURE_CTYPE_CRC   0x02

Definition at line 132 of file flirt.c.

◆ IDASIG_FEATURE_NONE

#define IDASIG_FEATURE_NONE   0x00

Definition at line 130 of file flirt.c.

◆ IDASIG_FEATURE_STARTUP

#define IDASIG_FEATURE_STARTUP   0x01

Definition at line 131 of file flirt.c.

◆ IDASIG_FUNCTION_LOCAL

#define IDASIG_FUNCTION_LOCAL   0x02

Definition at line 145 of file flirt.c.

◆ IDASIG_FUNCTION_UNRESOLVED_COLLISION

#define IDASIG_FUNCTION_UNRESOLVED_COLLISION   0x08

Definition at line 146 of file flirt.c.

◆ IDASIG_PARSE_MORE_MODULES

#define IDASIG_PARSE_MORE_MODULES   0x10

Definition at line 142 of file flirt.c.

◆ IDASIG_PARSE_MORE_MODULES_WITH_SAME_CRC

#define IDASIG_PARSE_MORE_MODULES_WITH_SAME_CRC   0x08

Definition at line 141 of file flirt.c.

◆ IDASIG_PARSE_MORE_PUBLIC_NAMES

#define IDASIG_PARSE_MORE_PUBLIC_NAMES   0x01

Definition at line 138 of file flirt.c.

◆ IDASIG_PARSE_READ_REFERENCED_FUNCTIONS

#define IDASIG_PARSE_READ_REFERENCED_FUNCTIONS   0x04

Definition at line 140 of file flirt.c.

◆ IDASIG_PARSE_READ_TAIL_BYTES

#define IDASIG_PARSE_READ_TAIL_BYTES   0x02

Definition at line 139 of file flirt.c.

◆ is_status_err_or_eof

#define is_status_err_or_eof (   p)    (p->eof || p->error)

Definition at line 183 of file flirt.c.

◆ MAX_WBITS

#define MAX_WBITS   15

Definition at line 105 of file flirt.c.

◆ POLY

#define POLY   0x8408

Definition at line 203 of file flirt.c.

◆ rz_buf_append_be_bits

#define rz_buf_append_be_bits (   buffer,
  tmp,
  value,
  bits 
)
Value:
rz_write_be##bits(tmp, value); \
rz_buf_append_bytes(buffer, tmp, sizeof(ut##bits))
int bits(struct state *s, int need)
Definition: blast.c:72
static int value
Definition: cmd_api.c:93
Definition: buffer.h:15

Definition at line 125 of file flirt.c.

◆ rz_buf_append_le_bits

#define rz_buf_append_le_bits (   buffer,
  tmp,
  value,
  bits 
)
Value:
rz_write_le##bits(tmp, value); \
rz_buf_append_bytes(buffer, tmp, sizeof(ut##bits))

Definition at line 121 of file flirt.c.

◆ sig_dbg

#define sig_dbg (   ...)

Definition at line 117 of file flirt.c.

◆ sig_dbg_buffer

#define sig_dbg_buffer (   n,
  b,
  s 
)

Definition at line 118 of file flirt.c.

Typedef Documentation

◆ idasig_v10_t

typedef struct idasig_v10_t idasig_v10_t

◆ idasig_v5_t

typedef struct idasig_v5_t idasig_v5_t

◆ idasig_v6_v7_t

◆ idasig_v8_v9_t

◆ ParseStatus

typedef struct parse_status_t ParseStatus

Function Documentation

◆ flirt_crc16()

ut16 flirt_crc16 ( const ut8 data_p,
size_t  length 
)

Definition at line 204 of file flirt.c.

204  {
205  ut8 i;
206  ut32 data;
207  ut32 crc = 0xFFFF;
208 
209  if (length == 0) {
210  return 0;
211  }
212  do {
213  data = *data_p++;
214  for (i = 0; i < 8; i++) {
215  if ((crc ^ data) & 1) {
216  crc = (crc >> 1) ^ POLY;
217  } else {
218  crc >>= 1;
219  }
220  data >>= 1;
221  }
222  } while (--length > 0);
223 
224  crc = ~crc;
225  data = crc;
226  crc = (crc << 8) | ((data >> 8) & 0xff);
227  return (ut16)(crc);
228 }
lzma_index ** i
Definition: index.h:629
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
uint16_t ut16
uint32_t ut32
#define POLY
Definition: flirt.c:203
uint8_t ut8
Definition: lh5801.h:11

References i, length, and POLY.

Referenced by flirt_module_new(), and module_match_buffer().

◆ flirt_has_references()

static bool flirt_has_references ( RZ_NONNULL const RzFlirtModule module)
static

Definition at line 1402 of file flirt.c.

1402  {
1403  return module->referenced_functions && rz_list_length(module->referenced_functions) > 0;
1404 }
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
Definition: sftypes.h:77

References rz_list_length().

Referenced by flirt_write_module().

◆ flirt_parse_version()

static ut8 flirt_parse_version ( RzBuffer buffer)
static

Returns the FLIRT file version read from the RzBuffer This function returns the FLIRT file version, when it fails returns 0.

Parameters
bufferThe buffer to read
Returns
Parsed FLIRT version

Definition at line 1021 of file flirt.c.

1021  {
1022  ut8 ret = 0;
1023 
1025  if (!header) {
1026  goto exit;
1027  }
1028 
1029  if (rz_buf_read(buffer, header->magic, sizeof(header->magic)) != sizeof(header->magic)) {
1030  RZ_LOG_ERROR("FLIRT: invalid sig file (EOF in v5 header magic).\n");
1031  goto exit;
1032  }
1033 
1034  if (memcmp((const char *)header->magic, "IDASGN", 6)) {
1035  RZ_LOG_ERROR("FLIRT: invalid sig magic.\n");
1036  goto exit;
1037  }
1038 
1039  if (rz_buf_read(buffer, &header->version, sizeof(header->version)) != sizeof(header->version)) {
1040  RZ_LOG_ERROR("FLIRT: invalid sig file (EOF in v5 header version).\n");
1041  goto exit;
1042  }
1043 
1044  ret = header->version;
1045 
1046 exit:
1047  free(header);
1048  return ret;
1049 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
#define header(is_bt, len_min, ret_op)
RZ_API st64 rz_buf_read(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_NEW0(x)
Definition: rz_types.h:284

References test-lz4-list::exit, free(), header, rz_buf_read(), RZ_LOG_ERROR, and RZ_NEW0.

Referenced by rz_sign_flirt_parse_compressed_pattern_from_buffer().

◆ flirt_write_module()

static bool flirt_write_module ( RZ_NONNULL const RzFlirtModule module,
RZ_NONNULL RzBuffer buffer,
ut8  flags,
ut8  version,
bool  first 
)
static

Definition at line 1413 of file flirt.c.

1413  {
1414  ut8 tmp[4];
1415  size_t value = 0;
1416  ut32 base_offset = 0;
1417  RzListIter *it;
1418  RzFlirtFunction *func;
1419  RzFlirtTailByte *byte;
1420  bool has_ref = flirt_has_references(module);
1421 
1422  if (first) {
1423  rz_buf_append_le_bits(buffer, tmp, module->crc_length, 8);
1424 
1425  rz_buf_append_be_bits(buffer, tmp, module->crc16, 16);
1426  }
1427  rz_write_vle32(buffer, module->length);
1428 
1429  if (has_ref) {
1431  }
1432  if (rz_list_length(module->tail_bytes) > 0) {
1434  }
1435 
1436  rz_list_foreach (module->public_functions, it, func) {
1437  if (value > 0) {
1440  }
1441  rz_write_vle32(buffer, func->offset - base_offset);
1442  base_offset = func->offset;
1443  tmp[0] = 0;
1444  if (func->is_local) {
1445  tmp[0] |= IDASIG_FUNCTION_LOCAL;
1446  }
1447  if (func->is_collision) {
1449  }
1450  if (tmp[0]) {
1452  }
1454  value++;
1455  }
1456 
1457  if (value > 0) {
1459  }
1460 
1461  value = rz_list_length(module->tail_bytes);
1462  if (value) {
1463  if (version >= 8) {
1464  // n of tail bytes.
1466  }
1467  value = 0;
1468  rz_list_foreach (module->tail_bytes, it, byte) {
1469  if (version < 8 && value > 1) {
1470  RZ_LOG_WARN("FLIRT: the number of tail bytes (%u) is > 1 when version %u does allow only 1\n", rz_list_length(module->tail_bytes), version);
1471  break;
1472  }
1473  value++;
1474 
1476  rz_buf_append_le_bits(buffer, tmp, byte->value, 8);
1477  }
1478  }
1479 
1480  if (has_ref) {
1481  // on sig files, it is not allowed to have multiple references.
1482  tmp[0] = 1;
1484 
1485  value = 0;
1486  rz_list_foreach (module->referenced_functions, it, func) {
1487  if (value > 0) {
1488  break;
1489  }
1490  value++;
1491 
1493 
1494  ut32 length = strlen(func->name);
1495  if (length > 0x7F) {
1496  tmp[0] = 0; // when name length is > 0x7F the length is preceeded by a 0x00
1498  }
1501  }
1502  }
1503 
1504  return true;
1505 }
static bool rz_write_vle16(RzBuffer *buffer, ut16 val)
Definition: flirt.c:1348
#define IDASIG_FUNCTION_UNRESOLVED_COLLISION
Definition: flirt.c:146
static bool rz_write_versioned_vle(RzBuffer *buffer, ut32 value, ut8 version)
Definition: flirt.c:1406
static bool flirt_has_references(RZ_NONNULL const RzFlirtModule *module)
Definition: flirt.c:1402
#define rz_buf_append_le_bits(buffer, tmp, value, bits)
Definition: flirt.c:121
#define rz_buf_append_be_bits(buffer, tmp, value, bits)
Definition: flirt.c:125
static bool rz_write_vle32(RzBuffer *buffer, ut32 val)
Definition: flirt.c:1368
#define IDASIG_PARSE_READ_REFERENCED_FUNCTIONS
Definition: flirt.c:140
#define IDASIG_FUNCTION_LOCAL
Definition: flirt.c:145
#define IDASIG_PARSE_READ_TAIL_BYTES
Definition: flirt.c:139
#define IDASIG_PARSE_MORE_PUBLIC_NAMES
Definition: flirt.c:138
RZ_API bool rz_buf_append_bytes(RZ_NONNULL RzBuffer *b, RZ_NONNULL const ut8 *buf, ut64 len)
Append an array of bytes to the buffer.
Definition: buf.c:732
RZ_API st64 rz_buf_append_string(RZ_NONNULL RzBuffer *b, RZ_NONNULL const char *str)
Append a string to the buffer.
Definition: buf.c:962
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
char name[RZ_FLIRT_NAME_MAX]
Definition: rz_flirt.h:158

References flags, flirt_has_references(), IDASIG_FUNCTION_LOCAL, IDASIG_FUNCTION_UNRESOLVED_COLLISION, IDASIG_PARSE_MORE_PUBLIC_NAMES, IDASIG_PARSE_READ_REFERENCED_FUNCTIONS, IDASIG_PARSE_READ_TAIL_BYTES, rz_flirt_function_t::is_collision, rz_flirt_function_t::is_local, length, rz_flirt_function_t::name, rz_flirt_tail_byte_t::offset, rz_flirt_function_t::offset, rz_buf_append_be_bits, rz_buf_append_bytes(), rz_buf_append_le_bits, rz_buf_append_string(), rz_list_length(), RZ_LOG_WARN, rz_write_versioned_vle(), rz_write_vle16(), rz_write_vle32(), autogen_x86imm::tmp, value, and rz_flirt_tail_byte_t::value.

Referenced by flirt_write_node().

◆ flirt_write_node()

static bool flirt_write_node ( RZ_NONNULL const RzFlirtNode node,
RZ_NONNULL RzBuffer buffer,
ut8  version 
)
static

Definition at line 1507 of file flirt.c.

1507  {
1508  if (node->length > 64) {
1509  RZ_LOG_ERROR("FLIRT: pattern mask size is > 64.\n");
1510  return false;
1511  }
1512 
1513  RzListIter *it;
1514  RzFlirtNode *child;
1516 
1517  ut32 n_childs = rz_list_length(node->child_list);
1518  rz_write_vle32(buffer, n_childs);
1519 
1520  if (n_childs < 1) {
1521  // leaf
1522  ut8 flags = 0;
1523 
1524  RzFlirtModule *last = rz_list_last(node->module_list);
1525  rz_list_foreach (node->module_list, it, module) {
1526  bool already_found = !(flags & IDASIG_PARSE_MORE_MODULES_WITH_SAME_CRC);
1527  if (last != module) {
1529  if (next && next->crc16 == module->crc16) {
1531  } else {
1533  }
1534  } else {
1535  flags = 0;
1536  }
1537  if (!flirt_write_module(module, buffer, flags, version, already_found)) {
1538  return false;
1539  }
1540  }
1541  return true;
1542  }
1543 
1544  // tree
1545  rz_list_foreach (node->child_list, it, child) {
1546  // pattern mask size
1547  ut8 plen = child->length;
1548  rz_buf_append_bytes(buffer, &plen, 1);
1549  if (child->length < 0x10) {
1551  } else if (child->length <= 0x20) {
1553  } else if (child->length <= 0x40) {
1555  } else {
1556  RZ_LOG_ERROR("FLIRT: pattern mask size cannot be > 64 bits\n");
1557  return false;
1558  }
1559  for (ut32 i = 0; i < child->length; i++) {
1560  if (child->pattern_mask[i] != 0xFF) {
1561  continue;
1562  }
1563  rz_buf_append_bytes(buffer, &child->pattern_bytes[i], 1);
1564  }
1565  if (!flirt_write_node(child, buffer, version)) {
1566  return false;
1567  }
1568  }
1569 
1570  return true;
1571 }
static bool rz_write_vle64(RzBuffer *buffer, ut64 val)
Definition: flirt.c:1398
#define IDASIG_PARSE_MORE_MODULES
Definition: flirt.c:142
static bool flirt_write_module(RZ_NONNULL const RzFlirtModule *module, RZ_NONNULL RzBuffer *buffer, ut8 flags, ut8 version, bool first)
Definition: flirt.c:1413
static bool flirt_write_node(RZ_NONNULL const RzFlirtNode *node, RZ_NONNULL RzBuffer *buffer, ut8 version)
Definition: flirt.c:1507
#define IDASIG_PARSE_MORE_MODULES_WITH_SAME_CRC
Definition: flirt.c:141
RZ_API RZ_BORROW void * rz_list_iter_get_next_data(RzListIter *list)
returns the value stored in the next RzList iterator
Definition: list.c:29
RZ_API RZ_BORROW void * rz_list_last(RZ_NONNULL const RzList *list)
Returns the last element of the list.
Definition: list.c:86
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT16_MAX
ut8 * pattern_mask
Definition: rz_flirt.h:182
ut8 * pattern_bytes
Definition: rz_flirt.h:181
ut64 variant_mask
Definition: rz_flirt.h:180

References rz_flirt_module_t::crc16, flags, flirt_write_module(), i, IDASIG_PARSE_MORE_MODULES, IDASIG_PARSE_MORE_MODULES_WITH_SAME_CRC, rz_flirt_node_t::length, rz_flirt_node_t::pattern_bytes, rz_flirt_node_t::pattern_mask, rz_buf_append_bytes(), rz_list_iter_get_next_data(), rz_list_last(), rz_list_length(), RZ_LOG_ERROR, rz_write_vle16(), rz_write_vle32(), rz_write_vle64(), UT16_MAX, UT32_MAX, and rz_flirt_node_t::variant_mask.

Referenced by rz_sign_flirt_write_compressed_pattern_to_buffer().

◆ is_pattern_matching()

static bool is_pattern_matching ( ut32  p_size,
const ut8 pattern,
const ut8 mask,
const ut8 b,
ut32  b_size 
)
static

Checks if a pattern does match the buffer data.

Parameters
p_sizeThe pattern size
patternThe pattern to check agains
maskThe pattern mask
bBuffer to check
b_sizeSize of the buffer to check
Returns
True if pattern does match, false otherwise.

Definition at line 336 of file flirt.c.

336  {
337  if (b_size < p_size) {
338  return false;
339  }
340  for (ut32 i = 0; i < p_size; i++) {
341  if (mask[i] == 0xFF && pattern[i] != b[i]) {
342  return false;
343  }
344  }
345  return true;
346 }
#define mask()
#define b(i)
Definition: sha256.c:42

References b, i, and mask.

Referenced by node_match_buffer().

◆ module_free()

void module_free ( RzFlirtModule module)

Definition at line 284 of file flirt.c.

284  {
285  if (!module) {
286  return;
287  }
288  rz_list_free(module->public_functions);
289  rz_list_free(module->tail_bytes);
290  rz_list_free(module->referenced_functions);
291  free(module);
292 }
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137

References free(), and rz_list_free().

Referenced by flirt_create_child(), flirt_create_child_from_analysis(), flirt_module_new(), flirt_pat_parse_line(), and parse_leaf().

◆ module_match_buffer()

static int module_match_buffer ( RzAnalysis analysis,
const RzFlirtModule module,
ut8 b,
ut64  address,
ut32  buf_size 
)
static

Checks if the module matches the buffer and renames the matched functions.

Parameters
analysisThe RzAnalysis struct from where to fetch and modify the functions
moduleThe FLIRT module to match against the buffer
bBuffer to check
addressFunction address
buf_sizeSize of the buffer to check
Returns
True if pattern does match, false otherwise.

Definition at line 359 of file flirt.c.

359  {
360  RzFlirtFunction *flirt_func;
361  RzAnalysisFunction *next_module_function;
362  RzListIter *tail_byte_it, *flirt_func_it;
363  RzFlirtTailByte *tail_byte;
364  ut32 name_index = 0;
365 
366  if (32 + module->crc_length < buf_size &&
367  module->crc16 != flirt_crc16(b + 32, module->crc_length)) {
368  return false;
369  }
370  if (module->tail_bytes) {
371  rz_list_foreach (module->tail_bytes, tail_byte_it, tail_byte) {
372  if (32 + module->crc_length + tail_byte->offset < buf_size &&
373  b[32 + module->crc_length + tail_byte->offset] != tail_byte->value) {
374  return false;
375  }
376  }
377  }
378 
379  rz_list_foreach (module->public_functions, flirt_func_it, flirt_func) {
380  // Once the first module function is found, we need to go through the module->public_functions
381  // list to identify the others. See flirt doc for more information
382 
383  next_module_function = rz_analysis_get_function_at((RzAnalysis *)analysis, address + flirt_func->offset);
384  if (next_module_function) {
385  ut32 next_module_function_size;
386 
387  // get function size from flirt signature
388  ut64 flirt_fcn_size = module->length - flirt_func->offset;
389  RzFlirtFunction *next_flirt_func;
390  RzListIter *next_flirt_func_it = flirt_func_it->n;
391  while (next_flirt_func_it) {
392  next_flirt_func = next_flirt_func_it->data;
393  if (!next_flirt_func->is_local && !next_flirt_func->negative_offset) {
394  flirt_fcn_size = next_flirt_func->offset - flirt_func->offset;
395  break;
396  }
397  next_flirt_func_it = next_flirt_func_it->n;
398  }
399  // resize function if needed
400  next_module_function_size = rz_analysis_function_linear_size(next_module_function);
401  if (next_module_function_size < flirt_fcn_size) {
402  RzListIter *iter;
403  RzListIter *iter_tmp;
404  RzAnalysisFunction *fcn;
405  rz_list_foreach_safe (analysis->fcns, iter, iter_tmp, fcn) {
406  if (fcn != next_module_function &&
407  fcn->addr >= next_module_function->addr + next_module_function_size &&
408  fcn->addr < next_module_function->addr + flirt_fcn_size) {
409  RzListIter *iter_bb;
410  RzAnalysisBlock *block;
411  rz_list_foreach (fcn->bbs, iter_bb, block) {
412  rz_analysis_function_add_block(next_module_function, block);
413  }
414  next_module_function->ninstr += fcn->ninstr;
416  }
417  }
418  rz_analysis_function_resize(next_module_function, flirt_fcn_size);
419  next_module_function_size = rz_analysis_function_linear_size(next_module_function);
420  rz_analysis_trim_jmprefs((RzAnalysis *)analysis, next_module_function);
421  }
422 
423  // filter name
424  rz_name_filter(flirt_func->name, -1, true);
425 
426  // verify that the name is unique
427  char *name = rz_str_newf("flirt.%s", flirt_func->name);
428  if (!name) {
429  RZ_LOG_ERROR("FLIRT: cannot allocate string buffer for name\n");
430  return false;
431  }
432 
433  while (!rz_analysis_function_rename(next_module_function, name)) {
434  free(name);
435  name_index++;
436  name = rz_str_newf("flirt.%s_%u", flirt_func->name, name_index);
437  if (!name) {
438  RZ_LOG_ERROR("FLIRT: cannot allocate string buffer for name\n");
439  return false;
440  }
441  }
442 
443  // remove old flag
444  RzFlagItem *fit = analysis->flb.get_at_by_spaces(analysis->flb.f, next_module_function->addr, "fcn.", "func.", NULL);
445  if (fit) {
446  analysis->flb.unset(analysis->flb.f, fit);
447  }
448 
449  // set new flag
450  analysis->flb.set(analysis->flb.f, name, next_module_function->addr, next_module_function_size);
451  RZ_LOG_DEBUG("FLIRT: Found %s\n", next_module_function->name);
452  free(name);
453  }
454  }
455  return true;
456 }
RZ_API void rz_analysis_function_add_block(RzAnalysisFunction *fcn, RzAnalysisBlock *bb)
Definition: function.c:264
RZ_API RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
RZ_API ut64 rz_analysis_function_linear_size(RzAnalysisFunction *fcn)
Definition: function.c:318
RZ_API bool rz_analysis_function_rename(RzAnalysisFunction *fcn, const char *name)
Definition: function.c:240
RZ_API bool rz_analysis_function_delete(RzAnalysisFunction *fcn)
Definition: function.c:180
#define NULL
Definition: cris-opc.c:27
static int buf_size
Definition: debug_qnx.c:35
RZ_API int rz_analysis_function_resize(RzAnalysisFunction *fcn, int newsize)
Definition: fcn.c:90
RZ_API void rz_analysis_trim_jmprefs(RzAnalysis *analysis, RzAnalysisFunction *fcn)
Definition: fcn.c:1578
ut16 flirt_crc16(const ut8 *data_p, size_t length)
Definition: flirt.c:204
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
RZ_API bool rz_name_filter(char *name, int len, bool strict)
Definition: name.c:43
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
Definition: z80asm.h:102
RzList * fcns
Definition: rz_analysis.h:565
RzFlagBind flb
Definition: rz_analysis.h:575
RzFlagGetAtBySpaces get_at_by_spaces
Definition: rz_flag.h:82
RzFlagSet set
Definition: rz_flag.h:84
RzFlag * f
Definition: rz_flag.h:78
RzFlagUnset unset
Definition: rz_flag.h:85
struct rz_list_iter_t * n
Definition: rz_list.h:15
void * data
Definition: rz_list.h:14
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References rz_analysis_function_t::addr, b, rz_analysis_function_t::bbs, buf_size, rz_list_iter_t::data, rz_flag_bind_t::f, rz_analysis_t::fcns, rz_analysis_t::flb, flirt_crc16(), free(), rz_flag_bind_t::get_at_by_spaces, rz_flirt_function_t::is_local, rz_list_iter_t::n, rz_analysis_function_t::name, rz_flirt_function_t::name, rz_flirt_function_t::negative_offset, rz_analysis_function_t::ninstr, NULL, rz_flirt_tail_byte_t::offset, rz_flirt_function_t::offset, rz_analysis_function_add_block(), rz_analysis_function_delete(), rz_analysis_function_linear_size(), rz_analysis_function_rename(), rz_analysis_function_resize(), rz_analysis_get_function_at(), rz_analysis_trim_jmprefs(), RZ_LOG_DEBUG, RZ_LOG_ERROR, rz_name_filter(), rz_str_newf(), rz_flag_bind_t::set, rz_flag_bind_t::unset, ut64(), and rz_flirt_tail_byte_t::value.

Referenced by node_match_buffer().

◆ node_match_buffer()

static int node_match_buffer ( RzAnalysis analysis,
const RzFlirtNode node,
ut8 b,
ut64  address,
ut32  buf_size,
ut32  buf_idx 
)
static

Definition at line 458 of file flirt.c.

458  {
459  RzListIter *node_child_it, *module_it;
460  RzFlirtNode *child;
462 
463  if (is_pattern_matching(node->length, node->pattern_bytes, node->pattern_mask, b + buf_idx, buf_size - buf_idx)) {
464  if (node->child_list) {
465  rz_list_foreach (node->child_list, node_child_it, child) {
466  if (node_match_buffer(analysis, child, b, address, buf_size, buf_idx + node->length)) {
467  return true;
468  }
469  }
470  } else if (node->module_list) {
471  rz_list_foreach (node->module_list, module_it, module) {
472  if (module_match_buffer(analysis, module, b, address, buf_size)) {
473  return true;
474  }
475  }
476  }
477  }
478 
479  return false;
480 }
static int node_match_buffer(RzAnalysis *analysis, const RzFlirtNode *node, ut8 *b, ut64 address, ut32 buf_size, ut32 buf_idx)
Definition: flirt.c:458
static int module_match_buffer(RzAnalysis *analysis, const RzFlirtModule *module, ut8 *b, ut64 address, ut32 buf_size)
Checks if the module matches the buffer and renames the matched functions.
Definition: flirt.c:359
static bool is_pattern_matching(ut32 p_size, const ut8 *pattern, const ut8 *mask, const ut8 *b, ut32 b_size)
Checks if a pattern does match the buffer data.
Definition: flirt.c:336
RzList * child_list
Definition: rz_flirt.h:177
RzList * module_list
Definition: rz_flirt.h:178

References b, buf_size, rz_flirt_node_t::child_list, is_pattern_matching(), rz_flirt_node_t::length, rz_flirt_node_t::module_list, module_match_buffer(), rz_flirt_node_t::pattern_bytes, and rz_flirt_node_t::pattern_mask.

Referenced by node_match_functions().

◆ node_match_functions()

static bool node_match_functions ( RzAnalysis analysis,
const RzFlirtNode root_node 
)
static

Tries to find matching functions between the signature infos in root_node and the analyzed functions in analysis.

Parameters
analysisThe analysis
root_nodeThe root node
Returns
False on error, otherwise true

Definition at line 490 of file flirt.c.

490  {
491  bool ret = true;
492 
493  if (rz_list_length(analysis->fcns) == 0) {
494  RZ_LOG_ERROR("FLIRT: There are no analyzed functions. Have you run 'aa'?\n");
495  return ret;
496  }
497 
498  analysis->flb.push_fs(analysis->flb.f, "flirt");
499  RzListIter *it_func;
500  RzAnalysisFunction *func;
501  rz_list_foreach (analysis->fcns, it_func, func) {
502  if (func->type != RZ_ANALYSIS_FCN_TYPE_FCN && func->type != RZ_ANALYSIS_FCN_TYPE_LOC) { // scan only for unknown functions
503  continue;
504  }
505 
506  ut64 func_size = rz_analysis_function_linear_size(func);
507  ut8 *func_buf = malloc(func_size);
508  if (!func_buf) {
509  ret = false;
510  break;
511  }
512  if (!analysis->iob.read_at(analysis->iob.io, func->addr, func_buf, (int)func_size)) {
513  RZ_LOG_ERROR("FLIRT: Couldn't read function %s at 0x%" PFMT64x "\n", func->name, func->addr);
514  RZ_FREE(func_buf);
515  ret = false;
516  break;
517  }
518  RzListIter *node_child_it;
519  RzFlirtNode *child;
520  rz_list_foreach (root_node->child_list, node_child_it, child) {
521  if (node_match_buffer(analysis, child, func_buf, func->addr, func_size, 0)) {
522  break;
523  }
524  }
525  RZ_FREE(func_buf);
526  }
527  analysis->flb.pop_fs(analysis->flb.f);
528 
529  return ret;
530 }
void * malloc(size_t size)
Definition: malloc.c:123
@ RZ_ANALYSIS_FCN_TYPE_LOC
Definition: rz_analysis.h:194
@ RZ_ANALYSIS_FCN_TYPE_FCN
Definition: rz_analysis.h:193
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
RzIOBind iob
Definition: rz_analysis.h:574
RzFlagPopSpace pop_fs
Definition: rz_flag.h:90
RzFlagPushSpace push_fs
Definition: rz_flag.h:89
RzIOReadAt read_at
Definition: rz_io.h:240
RzIO * io
Definition: rz_io.h:232

References rz_analysis_function_t::addr, rz_flirt_node_t::child_list, rz_flag_bind_t::f, rz_analysis_t::fcns, rz_analysis_t::flb, rz_io_bind_t::io, rz_analysis_t::iob, malloc(), rz_analysis_function_t::name, node_match_buffer(), PFMT64x, rz_flag_bind_t::pop_fs, rz_flag_bind_t::push_fs, rz_io_bind_t::read_at, RZ_ANALYSIS_FCN_TYPE_FCN, RZ_ANALYSIS_FCN_TYPE_LOC, rz_analysis_function_linear_size(), RZ_FREE, rz_list_length(), RZ_LOG_ERROR, rz_analysis_function_t::type, and ut64().

Referenced by rz_sign_flirt_apply().

◆ parse_leaf()

static ut8 parse_leaf ( ParseStatus b,
RzFlirtNode node 
)
static

Definition at line 762 of file flirt.c.

762  {
763  /* parses a signature leaf: modules with same leading pattern */
764  /* returns false on parsing error */
765  ut8 flags, crc_length;
766  ut16 crc16;
768 
770  do { // loop for all modules having the same prefix
771 
772  crc_length = read_byte(b);
773  if (is_status_err_or_eof(b)) {
774  RZ_LOG_ERROR("FLIRT: failed to read crc16 length.\n");
775  goto err_exit;
776  }
777  crc16 = read_short(b);
778  if (is_status_err_or_eof(b)) {
779  RZ_LOG_ERROR("FLIRT: failed to read crc16.\n");
780  goto err_exit;
781  }
782  sig_dbg("dbg: crc_len: %02X crc16: %04X\n", crc_length, crc16);
783 
784  do { // loop for all modules having the same crc
786  if (!module) {
787  RZ_LOG_ERROR("FLIRT: failed to allocate RzFlirtModule.\n");
788  goto err_exit;
789  }
790 
791  module->crc_length = crc_length;
792  module->crc16 = crc16;
793 
794  if (b->version >= 9) { // seems like version 9 introduced some larger length
795  /*/!\ XXX don't trust ./zipsig output because it will write a version 9 header, but keep the old version offsets*/
796  module->length = read_multiple_bytes(b); // should be < 0x8000
797  if (is_status_err_or_eof(b)) {
798  RZ_LOG_ERROR("FLIRT: failed to read module length because EOF (version >= 9).\n");
799  goto err_exit;
800  }
801  } else {
802  module->length = read_max_2_bytes(b); // should be < 0x8000
803  if (is_status_err_or_eof(b)) {
804  RZ_LOG_ERROR("FLIRT: failed to read module length because EOF.\n");
805  goto err_exit;
806  }
807  }
808  sig_dbg("dbg: module_length: %04X\n", module->length);
809 
811  goto err_exit;
812  }
813 
814  if (flags & IDASIG_PARSE_READ_TAIL_BYTES) { // we need to read some tail bytes because in this leaf we have functions with same crc
816  goto err_exit;
817  }
818  }
819  if (flags & IDASIG_PARSE_READ_REFERENCED_FUNCTIONS) { // we need to read some referenced functions
821  goto err_exit;
822  }
823  }
824 
827  } while (flags & IDASIG_PARSE_MORE_MODULES); // same prefix but different crc
828 
829  return true;
830 
831 err_exit:
833  return false;
834 }
static ut8 read_module_public_functions(RzFlirtModule *module, ParseStatus *b, ut8 *flags)
Definition: flirt.c:687
void module_free(RzFlirtModule *module)
Definition: flirt.c:284
static ut8 read_module_tail_bytes(RzFlirtModule *module, ParseStatus *b)
Definition: flirt.c:532
static ut8 read_byte(ParseStatus *b)
Definition: flirt.c:230
static ut8 read_module_referenced_functions(RzFlirtModule *module, ParseStatus *b)
Definition: flirt.c:597
static ut16 read_max_2_bytes(ParseStatus *b)
Definition: flirt.c:261
static ut16 read_short(ParseStatus *b)
Definition: flirt.c:249
static ut32 read_multiple_bytes(ParseStatus *b)
Definition: flirt.c:268
#define is_status_err_or_eof(p)
Definition: flirt.c:183
#define sig_dbg(...)
Definition: flirt.c:117
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
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
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11

References b, flags, IDASIG_PARSE_MORE_MODULES, IDASIG_PARSE_MORE_MODULES_WITH_SAME_CRC, IDASIG_PARSE_READ_REFERENCED_FUNCTIONS, IDASIG_PARSE_READ_TAIL_BYTES, is_status_err_or_eof, module_free(), rz_flirt_node_t::module_list, NULL, read_byte(), read_max_2_bytes(), read_module_public_functions(), read_module_referenced_functions(), read_module_tail_bytes(), read_multiple_bytes(), read_short(), rz_list_append(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, and sig_dbg.

Referenced by parse_tree().

◆ parse_tree()

static ut8 parse_tree ( ParseStatus b,
RzFlirtNode root_node 
)
static

Definition at line 902 of file flirt.c.

902  {
903  /* parse a signature pattern tree or sub-tree */
904  /* returns false on parsing error */
905  RzFlirtNode *node = NULL;
906  int i, tree_nodes = read_multiple_bytes(b); // confirmed it's not read_byte(), XXX could it be read_max_2_bytes() ???
907  if (is_status_err_or_eof(b)) {
908  RZ_LOG_ERROR("FLIRT: failed to read tree node number because EOF.\n");
909  return false;
910  }
911  sig_dbg("dbg: tree_nodes %02x\n", tree_nodes);
912  if (tree_nodes == 0) { // if there's no tree nodes remaining, that means we are on the leaf
913  return parse_leaf(b, root_node);
914  }
916 
917  for (i = 0; i < tree_nodes; i++) {
918  if (!(node = RZ_NEW0(RzFlirtNode))) {
919  RZ_LOG_ERROR("FLIRT: failed to allocate child tree node.\n");
920  goto err_exit;
921  }
922  if (!read_node_length(node, b) || node->length > 0x40) {
923  RZ_LOG_ERROR("FLIRT: failed to read pattern mask length (length %u).\n", node->length);
924  goto err_exit;
925  }
926  if (!read_node_variant_mask(node, b)) {
927  RZ_LOG_ERROR("FLIRT: failed to read variant mask.\n");
928  goto err_exit;
929  }
930  if (!read_node_bytes(node, b)) {
931  RZ_LOG_ERROR("FLIRT: failed to read pattern.\n");
932  goto err_exit;
933  }
934  if (!parse_tree(b, node)) {
935  goto err_exit; // parse child nodes
936  }
937  rz_list_append(root_node->child_list, node);
938  }
939  return true;
940 err_exit:
942  return false;
943 }
RZ_API void rz_sign_flirt_node_free(RZ_NULLABLE RzFlirtNode *node)
Frees an RzFlirtNode struct.
Definition: flirt.c:299
static bool read_node_variant_mask(RzFlirtNode *node, ParseStatus *b)
Definition: flirt.c:845
static bool read_node_bytes(RzFlirtNode *node, ParseStatus *b)
Definition: flirt.c:870
static ut8 parse_tree(ParseStatus *b, RzFlirtNode *root_node)
Definition: flirt.c:902
static bool read_node_length(RzFlirtNode *node, ParseStatus *b)
Definition: flirt.c:836
static ut8 parse_leaf(ParseStatus *b, RzFlirtNode *node)
Definition: flirt.c:762

References b, rz_flirt_node_t::child_list, i, is_status_err_or_eof, rz_flirt_node_t::length, NULL, parse_leaf(), read_multiple_bytes(), read_node_bytes(), read_node_length(), read_node_variant_mask(), rz_list_append(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, rz_sign_flirt_node_free(), and sig_dbg.

Referenced by rz_sign_flirt_parse_compressed_pattern_from_buffer().

◆ parse_v10_header()

static int parse_v10_header ( RzBuffer buf,
idasig_v10_t header 
)
static

Definition at line 1005 of file flirt.c.

1005  {
1006  if (!rz_buf_read_le16(buf, &header->unknown)) {
1007  RZ_LOG_ERROR("FLIRT: invalid sig file (EOF in v10 header).\n");
1008  return false;
1009  }
1010 
1011  return true;
1012 }
voidpf void * buf
Definition: ioapi.h:138
#define rz_buf_read_le16(b, result)
Read a big endian or little endian (ut16, ut32, ut64) at the specified offset in the buffer and shift...
Definition: rz_buf.h:266

References header, rz_buf_read_le16, and RZ_LOG_ERROR.

Referenced by rz_sign_flirt_parse_compressed_pattern_from_buffer(), and rz_sign_flirt_parse_header_compressed_pattern_from_buffer().

◆ parse_v5_header()

static bool parse_v5_header ( RzBuffer buf,
idasig_v5_t header 
)
static

Definition at line 945 of file flirt.c.

945  {
947  if (rz_buf_read(buf, header->magic, sizeof(header->magic)) != sizeof(header->magic)) {
948  return false;
949  }
950  if (rz_buf_read(buf, &header->version, sizeof(header->version)) != sizeof(header->version)) {
951  return false;
952  }
953  if (rz_buf_read(buf, &header->arch, sizeof(header->arch)) != sizeof(header->arch)) {
954  return false;
955  }
956  if (!rz_buf_read_le32(buf, &header->file_types)) {
957  return false;
958  }
959  if (!rz_buf_read_le16(buf, &header->os_types)) {
960  return false;
961  }
962  if (!rz_buf_read_le16(buf, &header->app_types)) {
963  return false;
964  }
965  if (!rz_buf_read_le16(buf, &header->features)) {
966  return false;
967  }
968  if (!rz_buf_read_le16(buf, &header->old_n_functions)) {
969  return false;
970  }
971  if (!rz_buf_read_le16(buf, &header->crc16)) {
972  return false;
973  }
974  if (rz_buf_read(buf, header->ctype, sizeof(header->ctype)) != sizeof(header->ctype)) {
975  return false;
976  }
977  if (rz_buf_read(buf, (unsigned char *)&header->library_name_len, sizeof(header->library_name_len)) != sizeof(header->library_name_len)) {
978  return false;
979  }
980  if (!rz_buf_read_le16(buf, &header->ctypes_crc16)) {
981  return false;
982  }
983 
984  return true;
985 }
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
#define RZ_BUF_SET
Definition: rz_buf.h:14
#define rz_buf_read_le32(b, result)
Definition: rz_buf.h:267

References header, rz_buf_read(), rz_buf_read_le16, rz_buf_read_le32, rz_buf_seek(), and RZ_BUF_SET.

Referenced by rz_sign_flirt_parse_compressed_pattern_from_buffer(), and rz_sign_flirt_parse_header_compressed_pattern_from_buffer().

◆ parse_v6_v7_header()

static int parse_v6_v7_header ( RzBuffer buf,
idasig_v6_v7_t header 
)
static

Definition at line 987 of file flirt.c.

987  {
988  if (!rz_buf_read_le32(buf, &header->n_functions)) {
989  RZ_LOG_ERROR("FLIRT: invalid sig file (EOF in v6/v7 header).\n");
990  return false;
991  }
992 
993  return true;
994 }

References header, rz_buf_read_le32, and RZ_LOG_ERROR.

Referenced by rz_sign_flirt_parse_compressed_pattern_from_buffer(), and rz_sign_flirt_parse_header_compressed_pattern_from_buffer().

◆ parse_v8_v9_header()

static int parse_v8_v9_header ( RzBuffer buf,
idasig_v8_v9_t header 
)
static

Definition at line 996 of file flirt.c.

996  {
997  if (!rz_buf_read_le16(buf, &header->pattern_size)) {
998  RZ_LOG_ERROR("FLIRT: invalid sig file (EOF in v8/v9 header).\n");
999  return false;
1000  }
1001 
1002  return true;
1003 }

References header, rz_buf_read_le16, and RZ_LOG_ERROR.

Referenced by rz_sign_flirt_parse_compressed_pattern_from_buffer(), and rz_sign_flirt_parse_header_compressed_pattern_from_buffer().

◆ read_byte()

static ut8 read_byte ( ParseStatus b)
static

Definition at line 230 of file flirt.c.

230  {
231  ut8 r = 0;
232  int length;
233 
234  if (b->eof || b->error) {
235  return 0;
236  }
237  if ((length = rz_buf_read(b->buffer, &r, 1)) != 1) {
238  if (length == -1) {
239  b->error = true;
240  }
241  if (length == 0) {
242  b->eof = true;
243  }
244  return 0;
245  }
246  return r;
247 }
#define r
Definition: crypto_rc6.c:12

References b, length, r, and rz_buf_read().

Referenced by parse_leaf(), read_max_2_bytes(), read_module_public_functions(), read_module_referenced_functions(), read_module_tail_bytes(), read_multiple_bytes(), read_node_bytes(), read_node_length(), and read_short().

◆ read_max_2_bytes()

static ut16 read_max_2_bytes ( ParseStatus b)
static

Definition at line 261 of file flirt.c.

261  {
262  ut16 r = read_byte(b);
263  return (r & 0x80)
264  ? ((r & 0x7f) << 8) + read_byte(b)
265  : r;
266 }

References b, r, and read_byte().

Referenced by parse_leaf(), read_module_public_functions(), read_module_referenced_functions(), read_module_tail_bytes(), and read_node_variant_mask().

◆ read_module_public_functions()

static ut8 read_module_public_functions ( RzFlirtModule module,
ParseStatus b,
ut8 flags 
)
static

Definition at line 687 of file flirt.c.

687  {
688  /* Reads and set the public functions names and offsets associated within a module */
689  /* returns false on parsing error */
690  int i;
691  ut32 offset = 0;
692  ut8 current_byte;
693  RzFlirtFunction *function = NULL;
694 
695  module->public_functions = rz_list_newf((RzListFree)free);
696 
697  do {
698  function = RZ_NEW0(RzFlirtFunction);
699  if (b->version >= 9) { // seems like version 9 introduced some larger offsets
700  offset += read_multiple_bytes(b); // offsets are dependent of the previous ones
701  if (is_status_err_or_eof(b)) {
702  RZ_LOG_ERROR("FLIRT: failed to read public function offset because EOF (version >= 9).\n");
703  goto err_exit;
704  }
705  } else {
706  offset += read_max_2_bytes(b); // offsets are dependent of the previous ones
707  if (is_status_err_or_eof(b)) {
708  RZ_LOG_ERROR("FLIRT: failed to read public function offset because EOF.\n");
709  goto err_exit;
710  }
711  }
712  function->offset = offset;
713 
714  current_byte = read_byte(b);
715  if (is_status_err_or_eof(b)) {
716  RZ_LOG_ERROR("FLIRT: failed to read public function flags because EOF.\n");
717  goto err_exit;
718  }
719  if (current_byte < 0x20) {
720  if (current_byte & IDASIG_FUNCTION_LOCAL) { // static function
721  function->is_local = true;
722  }
723  if (current_byte & IDASIG_FUNCTION_UNRESOLVED_COLLISION) {
724  // unresolved collision (happens in *.exc while creating .sig from .pat)
725  function->is_collision = true;
726  }
727  current_byte = read_byte(b);
728  if (is_status_err_or_eof(b)) {
729  RZ_LOG_ERROR("FLIRT: failed to read public function current byte because EOF.\n");
730  goto err_exit;
731  }
732  }
733 
734  for (i = 0; current_byte >= 0x20 && i < RZ_FLIRT_NAME_MAX; i++) {
735  function->name[i] = current_byte;
736  current_byte = read_byte(b);
737  if (is_status_err_or_eof(b)) {
738  RZ_LOG_ERROR("FLIRT: failed to read public function name[%u] because EOF.\n", i);
739  goto err_exit;
740  }
741  }
742 
743  if (i == RZ_FLIRT_NAME_MAX) {
744  RZ_LOG_WARN("FLIRT: public function name is too long\n");
745  function->name[RZ_FLIRT_NAME_MAX - 1] = '\0';
746  } else {
747  function->name[i] = '\0';
748  }
749 
750  sig_dbg("dbg: %04X: %s \n", function->offset, function->name);
751  *flags = current_byte;
752  rz_list_append(module->public_functions, function);
754 
755  return true;
756 
757 err_exit:
758  free(function);
759  return false;
760 }
voidpf uLong offset
Definition: ioapi.h:144
#define RZ_FLIRT_NAME_MAX
Definition: rz_flirt.h:17

References b, flags, free(), i, IDASIG_FUNCTION_LOCAL, IDASIG_FUNCTION_UNRESOLVED_COLLISION, IDASIG_PARSE_MORE_PUBLIC_NAMES, is_status_err_or_eof, NULL, read_byte(), read_max_2_bytes(), read_multiple_bytes(), RZ_FLIRT_NAME_MAX, rz_list_append(), rz_list_newf(), RZ_LOG_ERROR, RZ_LOG_WARN, RZ_NEW0, and sig_dbg.

Referenced by parse_leaf().

◆ read_module_referenced_functions()

static ut8 read_module_referenced_functions ( RzFlirtModule module,
ParseStatus b 
)
static

Definition at line 597 of file flirt.c.

597  {
598  /* parses a module referenced functions */
599  /* returns false on parsing error */
600  ut32 i, j;
601  ut32 number_of_referenced_functions;
602  ut32 ref_function_name_length;
603  RzFlirtFunction *ref_function = NULL;
604 
605  module->referenced_functions = rz_list_newf((RzListFree)free);
606 
607  if (b->version == 8 || b->version == 9) {
608  // this counter was introduced in version 8 and kept in version 9
609  number_of_referenced_functions = read_max_2_bytes(b);
610  if (is_status_err_or_eof(b)) {
611  RZ_LOG_ERROR("FLIRT: failed to read referenced function count because EOF (version 8 or 9).\n");
612  goto err_exit;
613  }
614  } else if (b->version > 9) {
615  // this counter was changed from version 10
616  number_of_referenced_functions = read_multiple_bytes(b);
617  if (is_status_err_or_eof(b)) {
618  RZ_LOG_ERROR("FLIRT: failed to read referenced function count because EOF (version > 9).\n");
619  goto err_exit;
620  }
621  } else { // suppose there's only one
622  number_of_referenced_functions = 1;
623  }
624  sig_dbg("dbg: n refs: %02X\n", number_of_referenced_functions);
625 
626  for (i = 0; i < number_of_referenced_functions; i++) {
627  ref_function = RZ_NEW0(RzFlirtFunction);
628  if (!ref_function) {
629  RZ_LOG_ERROR("FLIRT: failed to allocate RzFlirtFunction.\n");
630  goto err_exit;
631  }
632  if (b->version >= 9) {
633  ref_function->offset = read_multiple_bytes(b);
634  if (is_status_err_or_eof(b)) {
635  RZ_LOG_ERROR("FLIRT: failed to read referenced function offset because EOF (version >= 9).\n");
636  goto err_exit;
637  }
638  } else {
639  ref_function->offset = read_max_2_bytes(b);
640  if (is_status_err_or_eof(b)) {
641  RZ_LOG_ERROR("FLIRT: failed to read referenced function offset because EOF.\n");
642  goto err_exit;
643  }
644  }
645  ref_function_name_length = read_byte(b);
646  if (is_status_err_or_eof(b)) {
647  RZ_LOG_ERROR("FLIRT: failed to read referenced function name length because EOF.\n");
648  goto err_exit;
649  }
650  if (!ref_function_name_length) {
651  // not sure why it's not read_multiple_bytes() in the first place
652  ref_function_name_length = read_multiple_bytes(b); // XXX might be read_max_2_bytes, need more data
653  if (is_status_err_or_eof(b)) {
654  RZ_LOG_ERROR("FLIRT: failed to read referenced function name length because EOF (2).\n");
655  goto err_exit;
656  }
657  }
658  if (ref_function_name_length >= RZ_FLIRT_NAME_MAX) {
659  RZ_LOG_ERROR("FLIRT: invalid referenced function name length (%u >= %u).\n", ref_function_name_length, RZ_FLIRT_NAME_MAX);
660  goto err_exit;
661  }
662  sig_dbg("dbg: REF length %02X\n", ref_function_name_length);
663  for (j = 0; j < ref_function_name_length; j++) {
664  ref_function->name[j] = read_byte(b);
665  if (is_status_err_or_eof(b)) {
666  RZ_LOG_ERROR("FLIRT: failed to read referenced function name[%u] because EOF.\n", j);
667  goto err_exit;
668  }
669  }
670  if (!ref_function->name[ref_function_name_length]) {
671  // if the last byte of the name is 0, it means the offset is negative
672  ref_function->negative_offset = true;
673  } else {
674  ref_function->name[ref_function_name_length] = '\0';
675  }
676  rz_list_append(module->referenced_functions, ref_function);
677  sig_dbg("dbg: (REF: %04X: %s)\n", ref_function->offset, ref_function->name);
678  }
679 
680  return true;
681 
682 err_exit:
683  free(ref_function);
684  return false;
685 }

References b, free(), i, is_status_err_or_eof, rz_flirt_function_t::name, rz_flirt_function_t::negative_offset, NULL, rz_flirt_function_t::offset, read_byte(), read_max_2_bytes(), read_multiple_bytes(), RZ_FLIRT_NAME_MAX, rz_list_append(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, and sig_dbg.

Referenced by parse_leaf().

◆ read_module_tail_bytes()

static ut8 read_module_tail_bytes ( RzFlirtModule module,
ParseStatus b 
)
static

Definition at line 532 of file flirt.c.

532  {
533  /* parses a module tail bytes */
534  /* returns false on parsing error */
535  int i;
536  ut32 number_of_tail_bytes;
537  RzFlirtTailByte *tail_byte = NULL;
538  if (!(module->tail_bytes = rz_list_newf((RzListFree)free))) {
539  RZ_LOG_ERROR("FLIRT: failed to allocate tail bytes list.\n");
540  goto err_exit;
541  }
542 
543  if (b->version == 8 || b->version == 9) {
544  // this counter was introduced in version 8 and kept in version 9
545  number_of_tail_bytes = read_max_2_bytes(b);
546  if (is_status_err_or_eof(b)) {
547  RZ_LOG_ERROR("FLIRT: failed to read referenced function count because EOF (version 8 or 9).\n");
548  goto err_exit;
549  }
550  } else if (b->version > 9) {
551  // this counter was changed from version 10
552  number_of_tail_bytes = read_multiple_bytes(b);
553  if (is_status_err_or_eof(b)) {
554  RZ_LOG_ERROR("FLIRT: failed to read referenced function count because EOF (version > 9).\n");
555  goto err_exit;
556  }
557  } else { // suppose there's only one
558  number_of_tail_bytes = 1;
559  }
560 
561  for (i = 0; i < number_of_tail_bytes; i++) {
562  tail_byte = RZ_NEW0(RzFlirtTailByte);
563  if (!tail_byte) {
564  return false;
565  }
566  if (b->version >= 9) {
567  /*/!\ XXX don't trust ./zipsig output because it will write a version 9 header, but keep the old version offsets*/
568  tail_byte->offset = read_multiple_bytes(b);
569  if (is_status_err_or_eof(b)) {
570  RZ_LOG_ERROR("FLIRT: failed to read tail byte offset because EOF (version >= 9).\n");
571  goto err_exit;
572  }
573  } else {
574  tail_byte->offset = read_max_2_bytes(b);
575  if (is_status_err_or_eof(b)) {
576  RZ_LOG_ERROR("FLIRT: failed to read tail byte offset because EOF.\n");
577  goto err_exit;
578  }
579  }
580  tail_byte->value = read_byte(b);
581  if (is_status_err_or_eof(b)) {
582  RZ_LOG_ERROR("FLIRT: failed to read tail byte value because EOF.\n");
583  goto err_exit;
584  }
585  rz_list_append(module->tail_bytes, tail_byte);
586  sig_dbg("dbg: read tail byte: %04X: %02X\n", tail_byte->offset, tail_byte->value);
587  }
588 
589  return true;
590 
591 err_exit:
592  free(tail_byte);
593  rz_list_free(module->tail_bytes);
594  return false;
595 }

References b, free(), i, is_status_err_or_eof, NULL, rz_flirt_tail_byte_t::offset, read_byte(), read_max_2_bytes(), read_multiple_bytes(), rz_list_append(), rz_list_free(), rz_list_newf(), RZ_LOG_ERROR, RZ_NEW0, sig_dbg, and rz_flirt_tail_byte_t::value.

Referenced by parse_leaf().

◆ read_multiple_bytes()

static ut32 read_multiple_bytes ( ParseStatus b)
static

Definition at line 268 of file flirt.c.

268  {
269  ut32 r = read_byte(b);
270  if ((r & 0x80) != 0x80) {
271  return r;
272  }
273  if ((r & 0xc0) != 0xc0) {
274  return ((r & 0x7f) << 8) + read_byte(b);
275  }
276  if ((r & 0xe0) != 0xe0) {
277  r = ((r & 0x3f) << 24) + (read_byte(b) << 16);
278  r += read_short(b);
279  return r;
280  }
281  return read_word(b);
282 }
static ut32 read_word(ParseStatus *b)
Definition: flirt.c:255

References b, r, read_byte(), read_short(), and read_word().

Referenced by parse_leaf(), parse_tree(), read_module_public_functions(), read_module_referenced_functions(), read_module_tail_bytes(), and read_node_variant_mask().

◆ read_node_bytes()

static bool read_node_bytes ( RzFlirtNode node,
ParseStatus b 
)
static

Definition at line 870 of file flirt.c.

870  {
871  /* Reads the node bytes, and also sets the variant bytes in pattern_mask */
872  /* returns false on parsing error */
873  int i;
874  ut64 current_mask_bit = 0;
875  if ((int)node->length < 0) {
876  return false;
877  }
878  current_mask_bit = 1ULL << (node->length - 1);
879  if (!(node->pattern_bytes = malloc(node->length))) {
880  return false;
881  }
882  if (!(node->pattern_mask = malloc(node->length))) {
883  return false;
884  }
885  for (i = 0; i < node->length; i++, current_mask_bit >>= 1) {
886  if (node->variant_mask & current_mask_bit) {
887  node->pattern_bytes[i] = 0;
888  node->pattern_mask[i] = 0;
889  } else {
890  node->pattern_bytes[i] = read_byte(b);
891  node->pattern_mask[i] = 0xFF;
892  if (is_status_err_or_eof(b)) {
893  return false;
894  }
895  }
896  }
897  sig_dbg_buffer("bytes", node->pattern_bytes, node->length);
898  sig_dbg_buffer("mask ", node->pattern_mask, node->length);
899  return true;
900 }
#define sig_dbg_buffer(n, b, s)
Definition: flirt.c:118

References b, i, is_status_err_or_eof, rz_flirt_node_t::length, malloc(), rz_flirt_node_t::pattern_bytes, rz_flirt_node_t::pattern_mask, read_byte(), sig_dbg_buffer, ut64(), and rz_flirt_node_t::variant_mask.

Referenced by parse_tree().

◆ read_node_length()

static bool read_node_length ( RzFlirtNode node,
ParseStatus b 
)
static

Definition at line 836 of file flirt.c.

836  {
837  node->length = read_byte(b);
838  if (is_status_err_or_eof(b)) {
839  return false;
840  }
841  sig_dbg("dbg: node length: %02X\n", node->length);
842  return true;
843 }

References b, is_status_err_or_eof, rz_flirt_node_t::length, read_byte(), and sig_dbg.

Referenced by parse_tree().

◆ read_node_variant_mask()

static bool read_node_variant_mask ( RzFlirtNode node,
ParseStatus b 
)
static

Definition at line 845 of file flirt.c.

845  {
846  /* Reads and sets a node's variant bytes mask. This mask is then used to */
847  /* read the non-variant bytes following. */
848  /* returns false on parsing error */
849  if (node->length < 0x10) {
851  if (is_status_err_or_eof(b)) {
852  return false;
853  }
854  } else if (node->length <= 0x20) {
856  if (is_status_err_or_eof(b)) {
857  return false;
858  }
859  } else if (node->length <= 0x40) { // it shouldn't be more than 64 bytes
861  if (is_status_err_or_eof(b)) {
862  return false;
863  }
864  }
865 
866  sig_dbg("dbg: variant_mask %08llx\n", node->variant_mask);
867  return true;
868 }

References b, is_status_err_or_eof, rz_flirt_node_t::length, read_max_2_bytes(), read_multiple_bytes(), sig_dbg, ut64(), and rz_flirt_node_t::variant_mask.

Referenced by parse_tree().

◆ read_short()

static ut16 read_short ( ParseStatus b)
static

Definition at line 249 of file flirt.c.

249  {
250  ut16 r = (read_byte(b) << 8);
251  r += read_byte(b);
252  return r;
253 }

References b, r, and read_byte().

Referenced by parse_leaf(), read_multiple_bytes(), and read_word().

◆ read_word()

static ut32 read_word ( ParseStatus b)
static

Definition at line 255 of file flirt.c.

255  {
256  ut32 r = ((ut32)(read_short(b)) << 16);
257  r += read_short(b);
258  return r;
259 }

References b, r, and read_short().

Referenced by read_multiple_bytes().

◆ rz_sign_flirt_apply()

RZ_API bool rz_sign_flirt_apply ( RZ_NONNULL RzAnalysis analysis,
RZ_NONNULL const char *  flirt_file,
ut8  expected_arch 
)

Parses the FLIRT file and applies the signatures.

Parameters
analysisThe RzAnalysis structure
flirt_fileThe FLIRT file to parse
Returns
true if the signatures were sucessfully applied to the file

Definition at line 1289 of file flirt.c.

1289  {
1290  rz_return_val_if_fail(analysis && RZ_STR_ISNOTEMPTY(flirt_file), false);
1291  RzBuffer *flirt_buf = NULL;
1292  RzFlirtNode *node = NULL;
1293 
1294  if (expected_arch > RZ_FLIRT_SIG_ARCH_ANY) {
1295  RZ_LOG_ERROR("FLIRT: unknown architecture %u\n", expected_arch);
1296  return false;
1297  }
1298 
1299  const char *extension = rz_str_lchr(flirt_file, '.');
1300  if (RZ_STR_ISEMPTY(extension) || (strcmp(extension, ".sig") != 0 && strcmp(extension, ".pat") != 0)) {
1301  RZ_LOG_ERROR("FLIRT: unknown extension '%s'\n", extension);
1302  return false;
1303  }
1304 
1305  if (!(flirt_buf = rz_buf_new_slurp(flirt_file))) {
1306  RZ_LOG_ERROR("FLIRT: Can't open %s\n", flirt_file);
1307  return false;
1308  }
1309 
1310  if (!strcmp(extension, ".pat")) {
1312  } else {
1313  node = rz_sign_flirt_parse_compressed_pattern_from_buffer(flirt_buf, expected_arch, NULL);
1314  }
1315 
1316  rz_buf_free(flirt_buf);
1317  if (node) {
1318  if (!node_match_functions(analysis, node)) {
1319  RZ_LOG_ERROR("FLIRT: Error while scanning the file %s\n", flirt_file);
1320  }
1322  return true;
1323  }
1324  RZ_LOG_ERROR("FLIRT: We encountered an error while parsing the file %s. Sorry.\n", flirt_file);
1325  return false;
1326 }
static bool 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 ...
Definition: flirt.c:490
RZ_API RZ_OWN RzFlirtNode * rz_sign_flirt_parse_compressed_pattern_from_buffer(RZ_NONNULL RzBuffer *flirt_buf, ut8 expected_arch, RZ_NULLABLE RzFlirtInfo *info)
Parses the RzBuffer containing a FLIRT structure and returns an RzFlirtNode.
Definition: flirt.c:1136
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API RZ_OWN RzBuffer * rz_buf_new_slurp(const char *file)
Creates a new buffer from a file.
Definition: buf.c:384
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 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_FLIRT_NODE_OPTIMIZE_MAX
optimize the tree structure and drops the tail bytes
Definition: rz_flirt.h:188
@ RZ_FLIRT_SIG_ARCH_ANY
Definition: rz_flirt.h:99
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
RZ_API const char * rz_str_lchr(const char *str, char chr)
Definition: str.c:669
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67

References node_match_functions(), NULL, rz_buf_free(), rz_buf_new_slurp(), RZ_FLIRT_NODE_OPTIMIZE_MAX, RZ_FLIRT_SIG_ARCH_ANY, RZ_LOG_ERROR, rz_return_val_if_fail, rz_sign_flirt_node_free(), rz_sign_flirt_parse_compressed_pattern_from_buffer(), rz_sign_flirt_parse_string_pattern_from_buffer(), RZ_STR_ISEMPTY, RZ_STR_ISNOTEMPTY, and rz_str_lchr().

Referenced by rz_core_analysis_sigdb_apply(), and rz_flirt_scan_handler().

◆ rz_sign_flirt_info_fini()

RZ_API void rz_sign_flirt_info_fini ( RZ_NULLABLE RzFlirtInfo info)

Frees an RzFlirtInfo struct elements without freeing the pointer.

Parameters
RzFlirtInfoThe RzFlirtInfo elements to be freed

Definition at line 315 of file flirt.c.

315  {
316  if (!info) {
317  return;
318  }
319  if (info->type == RZ_FLIRT_FILE_TYPE_SIG) {
320  free(info->u.sig.name);
321  }
322  memset(info, 0, sizeof(RzFlirtInfo));
323 }
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
return memset(p, 0, total)
@ RZ_FLIRT_FILE_TYPE_SIG
.sig compressed pattern file
Definition: rz_flirt.h:193
char * type
Definition: rz_bin.h:211

References free(), info(), memset(), RZ_FLIRT_FILE_TYPE_SIG, and rz_bin_info_t::type.

Referenced by rz_core_flirt_dump_file(), and sigdb_signature_resolve_details().

◆ rz_sign_flirt_node_count_nodes()

RZ_API ut32 rz_sign_flirt_node_count_nodes ( RZ_NONNULL const RzFlirtNode node)

Counts the number of FLIRT signatures in the node.

Parameters
flirt_fileThe FLIRT node to use to count
Returns
Number of signatures

Definition at line 1334 of file flirt.c.

1334  {
1335  rz_return_val_if_fail(node, 0);
1336  ut32 count = 0;
1337  RzListIter *it;
1338  RzFlirtNode *child;
1339  rz_list_foreach (node->child_list, it, child) {
1341  }
1342  if (rz_list_length(node->module_list) > 0) {
1343  count += 1;
1344  }
1345  return count;
1346 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
RZ_API ut32 rz_sign_flirt_node_count_nodes(RZ_NONNULL const RzFlirtNode *node)
Counts the number of FLIRT signatures in the node.
Definition: flirt.c:1334

References count, rz_list_length(), rz_return_val_if_fail, and rz_sign_flirt_node_count_nodes().

Referenced by rz_core_flirt_create_file(), rz_sign_flirt_node_count_nodes(), rz_sign_flirt_parse_compressed_pattern_from_buffer(), rz_sign_flirt_parse_string_pattern_from_buffer(), and rz_sign_flirt_write_compressed_pattern_to_buffer().

◆ rz_sign_flirt_node_free()

RZ_API void rz_sign_flirt_node_free ( RZ_NULLABLE RzFlirtNode node)

Frees an RzFlirtNode struct.

Parameters
RzFlirtNodeThe RzFlirtNode to be freed

Definition at line 299 of file flirt.c.

299  {
300  if (!node) {
301  return;
302  }
303  free(node->pattern_mask);
304  free(node->pattern_bytes);
305  rz_list_free(node->module_list);
306  rz_list_free(node->child_list);
307  free(node);
308 }

References free(), and rz_list_free().

Referenced by flirt_create_child(), flirt_create_child_from_analysis(), flirt_node_optimize(), flirt_node_shorten_and_insert(), flirt_pat_parse_line(), parse_tree(), rz_core_flirt_convert_file(), rz_core_flirt_create_file(), rz_core_flirt_dump_file(), rz_sign_flirt_apply(), rz_sign_flirt_node_new(), rz_sign_flirt_parse_string_pattern_from_buffer(), and sigdb_signature_resolve_details().

◆ rz_sign_flirt_parse_compressed_pattern_from_buffer()

RZ_API RZ_OWN RzFlirtNode* rz_sign_flirt_parse_compressed_pattern_from_buffer ( RZ_NONNULL RzBuffer flirt_buf,
ut8  expected_arch,
RZ_NULLABLE RzFlirtInfo info 
)

Parses the RzBuffer containing a FLIRT structure and returns an RzFlirtNode.

Parses the RzBuffer containing a FLIRT structure and returns an RzFlirtNode if expected_arch matches the id or RZ_FLIRT_SIG_ARCH_ANY is set.

Parameters
flirt_bufThe buffer to read
expected_archThe expected arch to be used for the buffer
infoPointer to a RzFlirtInfo that can be used to get info about the sig file
Returns
Parsed FLIRT node

Definition at line 1136 of file flirt.c.

1136  {
1137  rz_return_val_if_fail(flirt_buf && expected_arch <= RZ_FLIRT_SIG_ARCH_ANY, NULL);
1138 
1139  ut8 *name = NULL;
1140  ut8 *buf = NULL, *decompressed_buf = NULL;
1141  RzBuffer *rz_buf = NULL;
1142  int size, decompressed_size;
1143  RzFlirtNode *node = NULL;
1144  RzFlirtNode *ret = NULL;
1145  idasig_v5_t *header = NULL;
1146  idasig_v6_v7_t *v6_v7 = NULL;
1147  idasig_v8_v9_t *v8_v9 = NULL;
1148  idasig_v10_t *v10 = NULL;
1149 
1150  ParseStatus ps = { 0 };
1151 
1152  if (!(ps.version = flirt_parse_version(flirt_buf))) {
1153  goto exit;
1154  }
1155 
1156  if (ps.version < 5 || ps.version > 10) {
1157  RZ_LOG_ERROR("FLIRT: Unsupported flirt signature version\n");
1158  goto exit;
1159  }
1160 
1161  if (!(header = RZ_NEW0(idasig_v5_t))) {
1162  goto exit;
1163  }
1164 
1165  parse_v5_header(flirt_buf, header);
1166 
1167  if (expected_arch != RZ_FLIRT_SIG_ARCH_ANY && header->arch != expected_arch) {
1168  RZ_LOG_ERROR("FLIRT: the binary architecture did not match the .sig one.\n");
1169  goto exit;
1170  }
1171 
1172  if (ps.version >= 6) {
1173  if (!(v6_v7 = RZ_NEW0(idasig_v6_v7_t))) {
1174  goto exit;
1175  }
1176  if (!parse_v6_v7_header(flirt_buf, v6_v7)) {
1177  goto exit;
1178  }
1179 
1180  if (ps.version >= 8) {
1181  if (!(v8_v9 = RZ_NEW0(idasig_v8_v9_t))) {
1182  goto exit;
1183  }
1184  if (!parse_v8_v9_header(flirt_buf, v8_v9)) {
1185  goto exit;
1186  }
1187 
1188  if (ps.version >= 10) {
1189  if (!(v10 = RZ_NEW0(idasig_v10_t))) {
1190  goto exit;
1191  }
1192  if (!parse_v10_header(flirt_buf, v10)) {
1193  goto exit;
1194  }
1195  }
1196  }
1197  }
1198 
1199  name = malloc(header->library_name_len + 1);
1200  if (!name) {
1201  RZ_LOG_ERROR("FLIRT: failed to allocate library name\n");
1202  goto exit;
1203  }
1204 
1205  if (rz_buf_read(flirt_buf, name, header->library_name_len) != header->library_name_len) {
1206  RZ_LOG_ERROR("FLIRT: failed to read library name\n");
1207  goto exit;
1208  }
1209 
1210  name[header->library_name_len] = '\0';
1211 
1212  size = rz_buf_size(flirt_buf) - rz_buf_tell(flirt_buf);
1213  buf = malloc(size);
1214  if (!buf) {
1215  RZ_LOG_ERROR("FLIRT: failed to allocate buffer for signature body\n");
1216  goto exit;
1217  }
1218 
1219  if (rz_buf_read(flirt_buf, buf, size) != size) {
1220  RZ_LOG_ERROR("FLIRT: failed to read signature body\n");
1221  goto exit;
1222  }
1223 
1224  if (header->features & IDASIG_FEATURE_COMPRESSED) {
1225  if (ps.version >= 5 && ps.version < 7) {
1226  if (!(decompressed_buf = rz_inflate_ignore_header(buf, size, NULL, &decompressed_size))) {
1227  RZ_LOG_ERROR("FLIRT: Failed to decompress buffer.\n");
1228  goto exit;
1229  }
1230  } else if (ps.version >= 7) {
1231  if (!(decompressed_buf = rz_inflate(buf, size, NULL, &decompressed_size))) {
1232  RZ_LOG_ERROR("FLIRT: Failed to decompress buffer.\n");
1233  goto exit;
1234  }
1235  } else {
1236  RZ_LOG_ERROR("FLIRT: Sorry we do not support compressed signatures with version %d.\n", ps.version);
1237  goto exit;
1238  }
1239 
1240  RZ_FREE(buf);
1241  buf = decompressed_buf;
1242  size = decompressed_size;
1243  }
1244  rz_buf = rz_buf_new_with_pointers(buf, size, false);
1245  if (!rz_buf) {
1246  RZ_LOG_ERROR("FLIRT: failed to allocate new RzBuffer\n");
1247  goto exit;
1248  }
1249  ps.buffer = rz_buf;
1250 
1251  if (!(node = RZ_NEW0(RzFlirtNode))) {
1252  RZ_LOG_ERROR("FLIRT: failed to allocate root RzFlirtNode\n");
1253  goto exit;
1254  }
1255 
1256  if (parse_tree(&ps, node)) {
1257  ret = node;
1258  } else {
1259  free(node);
1260  }
1261 
1262  if (info && ret) {
1264  info->u.sig.version = ps.version;
1265  info->u.sig.architecture = header->arch;
1266  info->u.sig.n_modules = rz_sign_flirt_node_count_nodes(ret);
1267  info->u.sig.name = (char *)name;
1268  name = NULL;
1269  }
1270 
1271 exit:
1272  free(buf);
1273  rz_buf_free(rz_buf);
1274  free(header);
1275  free(v6_v7);
1276  free(v8_v9);
1277  free(v10);
1278  free(name);
1279  return ret;
1280 }
static int parse_v10_header(RzBuffer *buf, idasig_v10_t *header)
Definition: flirt.c:1005
static int parse_v6_v7_header(RzBuffer *buf, idasig_v6_v7_t *header)
Definition: flirt.c:987
static ut8 flirt_parse_version(RzBuffer *buffer)
Returns the FLIRT file version read from the RzBuffer This function returns the FLIRT file version,...
Definition: flirt.c:1021
static int parse_v8_v9_header(RzBuffer *buf, idasig_v8_v9_t *header)
Definition: flirt.c:996
static bool parse_v5_header(RzBuffer *buf, idasig_v5_t *header)
Definition: flirt.c:945
#define IDASIG_FEATURE_COMPRESSED
Definition: flirt.c:135
voidpf void uLong size
Definition: ioapi.h:138
RZ_API ut64 rz_buf_tell(RZ_NONNULL RzBuffer *b)
Return the current cursor position.
Definition: buf.c:1238
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_pointers(const ut8 *bytes, ut64 len, bool steal)
Creates a new buffer with a bytes array.
Definition: buf.c:552
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
RZ_API ut8 * rz_inflate_ignore_header(RZ_NONNULL const ut8 *src, int srcLen, int *srcConsumed, int *dstLen)
inflate zlib compressed or gzipped. The input must be a raw stream with no header or trailer.
Definition: compression.c:28
RZ_API ut8 * rz_inflate(RZ_NONNULL const ut8 *src, int srcLen, int *srcConsumed, int *dstLen)
inflate zlib compressed or gzipped, automatically accepts either the zlib or gzip format,...
Definition: compression.c:18
ut8 version
Definition: flirt.c:180
RzBuffer * buffer
Definition: flirt.c:177

References parse_status_t::buffer, test-lz4-list::exit, flirt_parse_version(), free(), header, IDASIG_FEATURE_COMPRESSED, info(), malloc(), NULL, parse_tree(), parse_v10_header(), parse_v5_header(), parse_v6_v7_header(), parse_v8_v9_header(), rz_buf_free(), rz_buf_new_with_pointers(), rz_buf_read(), rz_buf_size(), rz_buf_tell(), RZ_FLIRT_FILE_TYPE_SIG, RZ_FLIRT_SIG_ARCH_ANY, RZ_FREE, rz_inflate(), rz_inflate_ignore_header(), RZ_LOG_ERROR, RZ_NEW0, rz_return_val_if_fail, rz_sign_flirt_node_count_nodes(), rz_bin_info_t::type, and parse_status_t::version.

Referenced by rz_core_flirt_convert_file(), rz_core_flirt_dump_file(), and rz_sign_flirt_apply().

◆ rz_sign_flirt_parse_header_compressed_pattern_from_buffer()

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.

Parses the RzBuffer containing a FLIRT structure and returns an RzFlirtNode if expected_arch matches the id or RZ_FLIRT_SIG_ARCH_ANY is set.

Parameters
flirt_bufThe buffer to read
expected_archThe expected arch to be used for the buffer
infoPointer to a RzFlirtInfo that can be used to get info about the sig file
Returns
Parsed FLIRT node

Definition at line 1062 of file flirt.c.

1062  {
1063  rz_return_val_if_fail(flirt_buf && info, false);
1064 
1065  bool res = false;
1066  ut8 *name = NULL;
1067  idasig_v5_t v5 = { 0 };
1068  idasig_v6_v7_t v6_v7 = { 0 };
1069  idasig_v8_v9_t v8_v9 = { 0 };
1070  idasig_v10_t v10 = { 0 };
1071 
1072  if (!parse_v5_header(flirt_buf, &v5)) {
1073  RZ_LOG_ERROR("FLIRT: invalid sig header.\n");
1074  goto exit;
1075  }
1076 
1077  if (memcmp((const char *)v5.magic, "IDASGN", 6)) {
1078  RZ_LOG_ERROR("FLIRT: invalid sig magic.\n");
1079  goto exit;
1080  }
1081 
1082  if (v5.version < 5 || v5.version > 10) {
1083  RZ_LOG_ERROR("FLIRT: Unsupported flirt signature version\n");
1084  goto exit;
1085  }
1086 
1087  if (v5.version >= 6 && !parse_v6_v7_header(flirt_buf, &v6_v7)) {
1088  goto exit;
1089  }
1090 
1091  if (v5.version >= 8 && !parse_v8_v9_header(flirt_buf, &v8_v9)) {
1092  goto exit;
1093  }
1094 
1095  if (v5.version >= 10 && !parse_v10_header(flirt_buf, &v10)) {
1096  goto exit;
1097  }
1098 
1099  name = malloc(v5.library_name_len + 1);
1100  if (!name) {
1101  RZ_LOG_ERROR("FLIRT: failed to allocate library name\n");
1102  goto exit;
1103  }
1104 
1105  if (rz_buf_read(flirt_buf, name, v5.library_name_len) != v5.library_name_len) {
1106  RZ_LOG_ERROR("FLIRT: failed to read library name\n");
1107  goto exit;
1108  }
1109 
1110  name[v5.library_name_len] = '\0';
1111 
1113  info->u.sig.version = v5.version;
1114  info->u.sig.architecture = v5.arch;
1115  info->u.sig.n_modules = v5.version < 6 ? v5.old_n_functions : v6_v7.n_functions;
1116  info->u.sig.name = (char *)name;
1117  name = NULL;
1118  res = true;
1119 
1120 exit:
1121  free(name);
1122  return res;
1123 }
ut8 magic[6]
Definition: flirt.c:150
ut8 arch
Definition: flirt.c:152
ut8 library_name_len
Definition: flirt.c:160
ut8 version
Definition: flirt.c:151
ut16 old_n_functions
Definition: flirt.c:157
ut32 n_functions
Definition: flirt.c:165

References idasig_v5_t::arch, test-lz4-list::exit, free(), info(), idasig_v5_t::library_name_len, idasig_v5_t::magic, malloc(), idasig_v6_v7_t::n_functions, NULL, idasig_v5_t::old_n_functions, parse_v10_header(), parse_v5_header(), parse_v6_v7_header(), parse_v8_v9_header(), rz_buf_read(), RZ_FLIRT_FILE_TYPE_SIG, RZ_LOG_ERROR, rz_return_val_if_fail, rz_bin_info_t::type, and idasig_v5_t::version.

Referenced by sigdb_signature_resolve_details().

◆ rz_sign_flirt_write_compressed_pattern_to_buffer()

RZ_API bool rz_sign_flirt_write_compressed_pattern_to_buffer ( RZ_NONNULL const RzFlirtNode node,
RZ_NONNULL RzBuffer buffer,
RzFlirtCompressedOptions options 
)

Writes in the the RzBuffer the FLIRT signatures in compressed format.

Parameters
nodeThe FLIRT node to use as input
bufferThe buffer to write to
Returns
Parsed FLIRT node

Definition at line 1580 of file flirt.c.

1580  {
1581  rz_return_val_if_fail(node && buffer && options, false);
1582  RzBuffer *body = buffer;
1583 
1584  if (options->version < 5 || options->version > 10) {
1585  RZ_LOG_ERROR("FLIRT: unsupported sig type version %u\n", options->version);
1586  return false;
1587  } else if (options->arch >= RZ_FLIRT_SIG_ARCH_ANY) {
1588  RZ_LOG_ERROR("FLIRT: unsupported architecture %u\n", options->arch);
1589  return false;
1590  } else if (RZ_STR_ISEMPTY(options->libname)) {
1591  RZ_LOG_ERROR("FLIRT: library name is empty\n");
1592  return false;
1593  }
1594 
1595  size_t library_name_len = strlen(options->libname);
1596  if (library_name_len > RZ_FLIRT_LIBRARY_NAME_MAX) {
1597  RZ_LOG_ERROR("FLIRT: library name is too big. max size is %u\n", RZ_FLIRT_LIBRARY_NAME_MAX);
1598  return false;
1599  }
1600 
1601  if (options->deflate) {
1602  if (options->version < 7) {
1603  RZ_LOG_ERROR("FLIRT: cannot deflate body due FLIRT version being < 7\n");
1604  return false;
1605  }
1606 
1607  body = rz_buf_new_empty(0);
1608  if (!body) {
1609  RZ_LOG_ERROR("FLIRT: cannot allocate body buffer\n");
1610  return false;
1611  }
1612  }
1613 
1614  ut8 tmp[32];
1615  ut32 n_functions = rz_sign_flirt_node_count_nodes(node);
1616 
1617  // magic
1618  rz_buf_append_string(buffer, "IDASGN");
1619 
1620  // version
1621  rz_buf_append_le_bits(buffer, tmp, options->version, 8);
1622 
1623  // arch
1625 
1626  // file_types (little endian)
1627  rz_buf_append_le_bits(buffer, tmp, options->file, 32);
1628 
1629  // os_types (little endian)
1631 
1632  // app_types (little endian)
1634 
1635  // features (little endian)
1637 
1638  // n_functions (little endian) - used only in v5.
1639  rz_buf_append_le_bits(buffer, tmp, options->version >= 6 ? 0 : n_functions, 16);
1640 
1641  // crc16 (little endian)
1642  rz_buf_append_le_bits(buffer, tmp, 0, 16);
1643 
1644  // ctype (little endian)
1645  memset(tmp, 0, 12);
1647 
1648  // library_name_len (max 255)
1649  rz_buf_append_le_bits(buffer, tmp, library_name_len, 8);
1650 
1651  // crc16_ctypes (little endian)
1653 
1654  if (options->version >= 6) {
1655  // n_functions (little endian)
1656  rz_buf_append_le_bits(buffer, tmp, n_functions, 32);
1657  }
1658 
1659  if (options->version >= 8) {
1660  // pattern_size (little endian) - we always use 32 bytes prelude
1661  rz_buf_append_le_bits(buffer, tmp, 32, 16);
1662  }
1663 
1664  if (options->version >= 10) {
1665  // unknown (little endian)
1666  rz_buf_append_le_bits(buffer, tmp, 0, 16);
1667  }
1668 
1669  // library name
1670  rz_buf_append_string(buffer, options->libname);
1671 
1672  if (!flirt_write_node(node, body, options->version)) {
1673  rz_buf_free(body);
1674  return false;
1675  }
1676 
1677  bool ret = true;
1678  if (options->deflate) {
1679  ut64 block_size = 1ull << 20; // 1 Mb
1680  if (!rz_deflatew_buf(body, buffer, block_size, NULL, 15)) {
1681  RZ_LOG_ERROR("FLIRT: cannot deflate body\n");
1682  ret = false;
1683  }
1684  rz_buf_free(body);
1685  }
1686  return ret;
1687 }
struct buffer buffer
#define IDASIG_FEATURE_NONE
Definition: flirt.c:130
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
RZ_API RZ_OWN RzBuffer * rz_buf_new_empty(ut64 len)
Creates a new empty buffer with a predefined size;.
Definition: buf.c:285
RZ_API bool rz_deflatew_buf(RZ_NONNULL RzBuffer *src, RZ_NONNULL RzBuffer *dst, ut64 block_size, ut8 *src_consumed, int wbits)
Definition: compression.c:327
#define RZ_FLIRT_LIBRARY_NAME_MAX
Definition: rz_flirt.h:18

References flirt_write_node(), IDASIG_FEATURE_COMPRESSED, IDASIG_FEATURE_NONE, memset(), NULL, options, rz_buf_append_bytes(), rz_buf_append_le_bits, rz_buf_append_string(), rz_buf_free(), rz_buf_new_empty(), rz_deflatew_buf(), RZ_FLIRT_LIBRARY_NAME_MAX, RZ_FLIRT_SIG_ARCH_ANY, RZ_LOG_ERROR, rz_return_val_if_fail, rz_sign_flirt_node_count_nodes(), RZ_STR_ISEMPTY, autogen_x86imm::tmp, and ut64().

Referenced by rz_core_flirt_convert_file(), and rz_core_flirt_create_file().

◆ rz_write_versioned_vle()

static bool rz_write_versioned_vle ( RzBuffer buffer,
ut32  value,
ut8  version 
)
static

Definition at line 1406 of file flirt.c.

1406  {
1407  if (version < 9) {
1408  return rz_write_vle16(buffer, value);
1409  }
1410  return rz_write_vle32(buffer, value);
1411 }

References rz_write_vle16(), rz_write_vle32(), and value.

Referenced by flirt_write_module().

◆ rz_write_vle16()

static bool rz_write_vle16 ( RzBuffer buffer,
ut16  val 
)
inlinestatic

Definition at line 1348 of file flirt.c.

1348  {
1349  ut8 tmp[10];
1350  ut32 n_bytes = 0;
1351  if (val > 0x7FFF) {
1352  RZ_LOG_ERROR("FLIRT: the variable length value is too big\n");
1353  return false;
1354  } else if (val > 0x7F) {
1355  // 16 bit value with max value 0x1FFF
1356  n_bytes = 2;
1357  tmp[0] = 0x80 | (val >> 8);
1358  tmp[1] = val & 0xFF;
1359  } else {
1360  // 8 bit value with max value 0x1F
1361  n_bytes = 1;
1362  tmp[0] = val;
1363  }
1364  rz_buf_append_bytes(buffer, tmp, n_bytes);
1365  return true;
1366 }
ut16 val
Definition: armass64_const.h:6

References rz_buf_append_bytes(), RZ_LOG_ERROR, autogen_x86imm::tmp, and val.

Referenced by flirt_write_module(), flirt_write_node(), and rz_write_versioned_vle().

◆ rz_write_vle32()

static bool rz_write_vle32 ( RzBuffer buffer,
ut32  val 
)
inlinestatic

Definition at line 1368 of file flirt.c.

1368  {
1369  ut8 tmp[10];
1370  ut32 n_bytes = 0;
1371 
1372  if (val > 0x1FFFFFFF) {
1373  n_bytes = 5;
1374  tmp[0] = 0xFF; // includes the 0xE0 mask
1375  tmp[1] = (val >> 24) & 0xFF;
1376  tmp[2] = (val >> 16) & 0xFF;
1377  tmp[3] = (val >> 8) & 0xFF;
1378  tmp[4] = val & 0xFF;
1379  } else if (val > 0x3FFF) {
1380  n_bytes = 4;
1381  tmp[0] = 0xC0 | ((val >> 24) & 0x3F);
1382  tmp[1] = (val >> 16) & 0xFF;
1383  tmp[2] = (val >> 8) & 0xFF;
1384  tmp[3] = val & 0xFF;
1385  } else if (val > 0x7F) {
1386  n_bytes = 2;
1387  tmp[0] = 0x80 | ((val >> 8) & 0x3F);
1388  tmp[1] = val & 0xFF;
1389  } else {
1390  n_bytes = 1;
1391  tmp[0] = val;
1392  }
1393 
1394  rz_buf_append_bytes(buffer, tmp, n_bytes);
1395  return true;
1396 }

References rz_buf_append_bytes(), autogen_x86imm::tmp, and val.

Referenced by flirt_write_module(), flirt_write_node(), rz_write_versioned_vle(), and rz_write_vle64().

◆ rz_write_vle64()

static bool rz_write_vle64 ( RzBuffer buffer,
ut64  val 
)
inlinestatic

Definition at line 1398 of file flirt.c.

1398  {
1399  return rz_write_vle32(buffer, (val >> 32) & UT32_MAX) && rz_write_vle32(buffer, val & UT32_MAX);
1400 }

References rz_write_vle32(), UT32_MAX, and val.

Referenced by flirt_write_node().