rizin/librz/core/cmd/cmd_egg.c

296 lines
7.3 KiB
C

// SPDX-FileCopyrightText: 2009-2018 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2021 Anton Kochkov <anton.kochkov@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_core.h>
#include <rz_egg.h>
static const char *RzEggConfigOptions[] = {
"egg.shellcode",
"egg.encoder",
"egg.padding",
"key",
"cmd",
"suid",
NULL
};
static void egg_option(RzEgg *egg, const char *key, const char *input) {
if (!*input) {
return;
}
if (input[1] != ' ') {
char *a = rz_egg_option_get(egg, key);
if (a) {
rz_cons_println(a);
free(a);
}
} else {
rz_egg_option_set(egg, key, input + 2);
}
}
static void showBuffer(RzBuffer *b) {
int i;
if (b && rz_buf_size(b) > 0) {
rz_buf_seek(b, 0, RZ_BUF_SET);
for (i = 0; i < rz_buf_size(b); i++) {
ut8 tmp;
if (!rz_buf_read8(b, &tmp)) {
return;
}
rz_cons_printf("%02x", tmp);
}
rz_cons_newline();
}
}
static bool egg_compile(RzEgg *egg) {
rz_egg_compile(egg);
if (!rz_egg_assemble(egg)) {
RZ_LOG_ERROR("core: rz_egg_assemble: invalid assembly\n");
return false;
}
char *p = rz_egg_option_get(egg, "egg.padding");
if (p && *p) {
rz_egg_padding(egg, p);
free(p);
}
p = rz_egg_option_get(egg, "egg.encoder");
if (p && *p) {
rz_egg_encode(egg, p);
free(p);
}
RzBuffer *b;
if ((b = rz_egg_get_bin(egg))) {
showBuffer(b);
return true;
}
return false;
}
static bool rz_core_egg_compile(RzEgg *egg) {
int ret = false;
char *p = rz_egg_option_get(egg, "egg.shellcode");
if (p && *p) {
if (!rz_egg_shellcode(egg, p)) {
RZ_LOG_ERROR("core: Unknown shellcode '%s'\n", p);
free(p);
return false;
}
free(p);
} else {
RZ_LOG_ERROR("core: Setup a shellcode before (gi command)\n");
free(p);
return false;
}
ret = egg_compile(egg);
rz_egg_option_set(egg, "egg.shellcode", "");
rz_egg_option_set(egg, "egg.padding", "");
rz_egg_option_set(egg, "egg.encoder", "");
rz_egg_option_set(egg, "key", "");
rz_egg_reset(egg);
return ret;
}
static RzEgg *rz_core_egg_setup(RzCore *core) {
RzEgg *egg = core->egg;
const char *arch = rz_config_get(core->config, "asm.arch");
const char *os = rz_config_get(core->config, "asm.os");
int bits = rz_config_get_i(core->config, "asm.bits");
if (!rz_egg_setup(egg, arch, bits, 0, os)) {
RZ_LOG_ERROR("Cannot setup shellcode compiler for chosen configuration\n");
return NULL;
}
return egg;
}
static RzCmdStatus rz_core_egg_compile_file(RzCore *core, const char *file) {
rz_return_val_if_fail(file, false);
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
if (!rz_egg_load_file(egg, file)) {
RZ_LOG_ERROR("Cannot load file \"%s\"\n", file);
return RZ_CMD_STATUS_ERROR;
}
if (!egg_compile(egg)) {
RZ_LOG_ERROR("Cannot compile file \"%s\"\n", file);
return RZ_CMD_STATUS_ERROR;
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_compile_handler(RzCore *core, int argc, const char **argv) {
if (argc > 1) {
return rz_core_egg_compile_file(core, argv[1]);
} else {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
if (!rz_core_egg_compile(egg)) {
RZ_LOG_ERROR("Cannot compile the shellcode\n");
return RZ_CMD_STATUS_ERROR;
}
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_config_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
if (argc < 2) {
// List all available config options and their values
size_t i;
for (i = 0; RzEggConfigOptions[i]; i++) {
const char *p = RzEggConfigOptions[i];
if (rz_egg_option_get(egg, p)) {
rz_cons_printf("%s : %s\n", p, rz_egg_option_get(egg, p));
} else {
rz_cons_printf("%s : %s\n", p, "");
}
}
return RZ_CMD_STATUS_OK;
}
int i;
for (i = 1; i < argc; i++) {
// Set the config option
RzList *l = rz_str_split_duplist_n(argv[i], "=", 1, false);
if (!l) {
return RZ_CMD_STATUS_ERROR;
}
size_t llen = rz_list_length(l);
if (!llen) {
return RZ_CMD_STATUS_ERROR;
}
char *key = rz_list_get_n(l, 0);
if (RZ_STR_ISEMPTY(key)) {
RZ_LOG_ERROR("No config option name specified\n");
rz_list_free(l);
return RZ_CMD_STATUS_ERROR;
}
// If there is value specified - set it, if not - just show the value
if (llen == 1) {
// No value
char *o = rz_egg_option_get(egg, key);
if (!o) {
RZ_LOG_ERROR("No such config option exists\n");
rz_list_free(l);
return RZ_CMD_STATUS_ERROR;
}
rz_cons_print(o);
free(o);
} else if (llen == 2) {
char *value = rz_list_get_n(l, 1);
if (RZ_STR_ISEMPTY(value)) {
RZ_LOG_ERROR("No config option value specified\n");
rz_list_free(l);
return RZ_CMD_STATUS_ERROR;
}
rz_egg_option_set(egg, key, value);
}
rz_list_free(l);
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_list_plugins_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
RzListIter *iter;
RzEggPlugin *p;
rz_list_foreach (egg->plugins, iter, p) {
rz_cons_printf("%s %6s : %s\n",
(p->type == RZ_EGG_PLUGIN_SHELLCODE) ? "shc" : "enc", p->name, p->desc);
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_syscall_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
RzBuffer *buf = NULL;
if (argc > 2) {
// With syscall parameters specified
buf = rz_core_syscall(core, argv[1], argv[2]);
} else {
// Without any parameters
buf = rz_core_syscall(core, argv[1], "");
}
if (buf) {
showBuffer(buf);
}
egg->lang.nsyscalls = 0;
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_type_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
rz_egg_option_set(egg, "egg.shellcode", argv[1]);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_padding_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
rz_egg_option_set(egg, "egg.padding", argv[1]);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_encoder_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
rz_egg_option_set(egg, "key", argv[2]);
rz_egg_option_set(egg, "egg.encoder", argv[1]);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_reset_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
egg_option(egg, "egg.padding", "");
egg_option(egg, "egg.shellcode", "");
egg_option(egg, "egg.encoder", "");
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_egg_show_config_handler(RzCore *core, int argc, const char **argv) {
RzEgg *egg = rz_core_egg_setup(core);
if (!egg) {
return RZ_CMD_STATUS_ERROR;
}
rz_cons_printf("Configuration options\n");
int i;
for (i = 0; RzEggConfigOptions[i]; i++) {
const char *p = RzEggConfigOptions[i];
if (rz_egg_option_get(egg, p)) {
rz_cons_printf("%s : %s\n", p, rz_egg_option_get(egg, p));
} else {
rz_cons_printf("%s : %s\n", p, "");
}
}
rz_cons_printf("\nTarget options\n");
rz_cons_printf("arch : %s\n", core->analysis->cpu);
rz_cons_printf("os : %s\n", core->analysis->os);
rz_cons_printf("bits : %d\n", core->analysis->bits);
return RZ_CMD_STATUS_OK;
}