220 lines
5.9 KiB
C
220 lines
5.9 KiB
C
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
|
|
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
#include <rz_main.h>
|
|
#include <rz_core.h>
|
|
|
|
enum rz_sign_option {
|
|
RZ_SIGN_OPT_NONE = 0,
|
|
RZ_SIGN_OPT_CONVERT_FLIRT,
|
|
RZ_SIGN_OPT_CREATE_FLIRT,
|
|
RZ_SIGN_OPT_DUMP_FLIRT,
|
|
};
|
|
|
|
static void rz_sign_show_help(void) {
|
|
printf("%s%s%s", Color_CYAN, "Usage: ", Color_RESET);
|
|
printf("rz-sign [-aqv] [-e k=v] (-c pat sig | -o sig bin | -d sig)\n");
|
|
const char *options[] = {
|
|
// clang-format off
|
|
"-h", "", "Show this help",
|
|
"-a, -aa", "", "Add extra 'a' to analysis command (available only with -o option)",
|
|
"-e", "k=v", "Set an evaluable config variable (available only with -o option)",
|
|
"-c", "output.pat input.sig", "Parse a FLIRT signature and convert it to its other format",
|
|
"-o", "output.sig input.bin", "Perform an analysis on the binary and generate the FLIRT signature",
|
|
"-d", "flirt.sig", "Parse a FLIRT signature and dump its content",
|
|
"-q", "", "Quiet mode",
|
|
"-v", "", "Show version information",
|
|
// clang-format on
|
|
};
|
|
rz_print_colored_help(options, RZ_ARRAY_SIZE(options), false);
|
|
printf("Examples:\n"
|
|
" rz-sign -d signature.sig\n"
|
|
" rz-sign -c new_signature.pat old_signature.sig\n"
|
|
" rz-sign -o libc.sig libc.so.6\n");
|
|
}
|
|
|
|
static void perform_analysis(RzCore *core, size_t complexity) {
|
|
const char *cmd = NULL;
|
|
switch (complexity) {
|
|
case 0: cmd = "aa"; break;
|
|
case 1: cmd = "aaa"; break;
|
|
default: cmd = "aaaa"; break;
|
|
}
|
|
rz_core_cmd0(core, cmd);
|
|
}
|
|
|
|
RZ_API int rz_main_rz_sign(int argc, const char **argv) {
|
|
RzListIter *it;
|
|
const char *input_file = NULL;
|
|
const char *output_file = NULL;
|
|
char *config = NULL;
|
|
RzCore *core = NULL;
|
|
RzList *evars = NULL;
|
|
bool quiet = false;
|
|
RzGetopt opt;
|
|
int ret = 0;
|
|
ut32 n_nodes = 0;
|
|
|
|
int c, option = RZ_SIGN_OPT_NONE;
|
|
size_t complexity = 0;
|
|
|
|
evars = rz_list_newf(free);
|
|
if (!evars) {
|
|
RZ_LOG_ERROR("rz-sign: cannot allocate RzList\n");
|
|
return -1;
|
|
}
|
|
|
|
rz_getopt_init(&opt, argc, argv, "aqhdc:o:e:v");
|
|
while ((c = rz_getopt_next(&opt)) != -1) {
|
|
switch (c) {
|
|
case 'a':
|
|
complexity++;
|
|
break;
|
|
case 'c':
|
|
if (option != RZ_SIGN_OPT_NONE) {
|
|
RZ_LOG_ERROR("rz-sign: cannot combine option -%c with previous options\n", c);
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
option = RZ_SIGN_OPT_CONVERT_FLIRT;
|
|
output_file = opt.arg;
|
|
break;
|
|
case 'o':
|
|
if (option != RZ_SIGN_OPT_NONE) {
|
|
RZ_LOG_ERROR("rz-sign: cannot combine option -%c with previous options\n", c);
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
option = RZ_SIGN_OPT_CREATE_FLIRT;
|
|
output_file = opt.arg;
|
|
break;
|
|
case 'd':
|
|
if (option != RZ_SIGN_OPT_NONE) {
|
|
RZ_LOG_ERROR("rz-sign: cannot combine option -%c with previous options\n", c);
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
option = RZ_SIGN_OPT_DUMP_FLIRT;
|
|
break;
|
|
case 'e':
|
|
if (!(config = rz_str_dup(opt.arg)) || !rz_list_append(evars, config)) {
|
|
free(config);
|
|
RZ_LOG_ERROR("rz-sign: cannot add evaluable config variable '%s' to RzList\n", opt.arg);
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
break;
|
|
case 'q':
|
|
quiet = true;
|
|
break;
|
|
case 'v': {
|
|
RzPath *sys_path = rz_path_new();
|
|
if (!sys_path) {
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
size_t print_val = rz_main_version_print(sys_path, "rz-sign");
|
|
rz_path_free(sys_path);
|
|
ret = print_val;
|
|
goto rz_sign_end;
|
|
}
|
|
case 'h':
|
|
rz_sign_show_help();
|
|
goto rz_sign_end;
|
|
default:
|
|
RZ_LOG_ERROR("rz-sign: invalid option -%c\n", c);
|
|
rz_sign_show_help();
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
}
|
|
|
|
if (opt.ind >= argc) {
|
|
RZ_LOG_ERROR("rz-sign: input file was not provided\n");
|
|
rz_sign_show_help();
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
|
|
input_file = argv[opt.ind];
|
|
|
|
if (option == RZ_SIGN_OPT_CREATE_FLIRT && complexity > 2) {
|
|
RZ_LOG_ERROR("rz-sign: Invalid analysis complexity (too many -a defined, max -aa)\n");
|
|
rz_sign_show_help();
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
|
|
core = rz_core_new();
|
|
if (!core) {
|
|
RZ_LOG_ERROR("rz-sign: Cannot allocate RzCore\n");
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
rz_config_set_b(core->config, "scr.interactive", false);
|
|
rz_config_set_b(core->config, "analysis.apply.signature", false);
|
|
rz_cons_reset();
|
|
rz_cons_set_interactive(false);
|
|
|
|
rz_core_loadlibs(core, RZ_CORE_LOADLIBS_ALL);
|
|
|
|
if (!rz_core_file_open(core, input_file, 0, 0)) {
|
|
RZ_LOG_ERROR("rz-sign: Could not open file %s\n", input_file);
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
|
|
(void)rz_core_bin_load(core, NULL, UT64_MAX);
|
|
(void)rz_core_bin_update_arch_bits(core);
|
|
|
|
// quiet mode
|
|
if (quiet) {
|
|
rz_config_set_b(core->config, "scr.prompt", false);
|
|
rz_config_set_i(core->config, "scr.color", COLOR_MODE_DISABLED);
|
|
}
|
|
|
|
// set all evars
|
|
rz_list_foreach (evars, it, config) {
|
|
if (!rz_config_eval(core->config, config)) {
|
|
RZ_LOG_ERROR("rz-sign: invalid option '%s'\n", config);
|
|
ret = -1;
|
|
goto rz_sign_end;
|
|
}
|
|
}
|
|
|
|
switch (option) {
|
|
case RZ_SIGN_OPT_CONVERT_FLIRT:
|
|
// convert a flirt file from .pat to .sig or viceversa
|
|
if (!rz_core_flirt_convert_file(core, input_file, output_file)) {
|
|
ret = -1;
|
|
} else if (!quiet) {
|
|
rz_cons_printf("rz-sign: %s was converted to %s.\n", input_file, output_file);
|
|
}
|
|
break;
|
|
case RZ_SIGN_OPT_CREATE_FLIRT:
|
|
// run analysis to find functions
|
|
perform_analysis(core, complexity);
|
|
// create flirt file
|
|
if (!rz_core_flirt_create_file(core, output_file, &n_nodes)) {
|
|
ret = -1;
|
|
} else if (!quiet) {
|
|
rz_cons_printf("rz-sign: written %u signatures to %s.\n", n_nodes, output_file);
|
|
}
|
|
break;
|
|
case RZ_SIGN_OPT_DUMP_FLIRT:
|
|
if (!rz_core_flirt_dump_file(input_file)) {
|
|
ret = -1;
|
|
}
|
|
break;
|
|
default:
|
|
RZ_LOG_ERROR("rz-sign: missing option, please set -c or -d or -o\n");
|
|
ret = -1;
|
|
break;
|
|
}
|
|
rz_cons_flush();
|
|
|
|
rz_sign_end:
|
|
rz_list_free(evars);
|
|
rz_core_free(core);
|
|
return ret;
|
|
}
|