radare2/libr/egg/egg.c

540 lines
12 KiB
C
Raw Normal View History

/* radare - LGPL - Copyright 2011-2018 - pancake */
#include <r_egg.h>
#include <config.h>
R_LIB_VERSION (r_egg);
// TODO: must be plugins
extern REggEmit emit_x86;
extern REggEmit emit_x64;
extern REggEmit emit_arm;
extern REggEmit emit_trace;
2014-05-03 12:21:03 +00:00
static REggPlugin *egg_static_plugins[] =
{ R_EGG_STATIC_PLUGINS };
R_API REgg *r_egg_new () {
int i;
REgg *egg = R_NEW0 (REgg);
if (!egg) {
return NULL;
}
egg->src = r_buf_new ();
if (!egg->src) {
goto beach;
}
egg->buf = r_buf_new ();
if (!egg->buf) {
goto beach;
}
egg->bin = r_buf_new ();
if (!egg->bin) {
goto beach;
}
2014-03-24 23:34:23 +00:00
egg->remit = &emit_x86;
egg->syscall = r_syscall_new ();
if (!egg->syscall) {
goto beach;
}
egg->rasm = r_asm_new ();
if (!egg->rasm) {
goto beach;
}
egg->bits = 0;
egg->endian = 0;
egg->db = sdb_new (NULL, NULL, 0);
if (!egg->db) {
goto beach;
}
egg->patches = r_list_new ();
if (!egg->patches) {
goto beach;
}
egg->patches->free = (RListFree)r_buf_free;
egg->plugins = r_list_new ();
for (i=0; egg_static_plugins[i]; i++) {
2016-04-03 21:52:36 +00:00
r_egg_add (egg, egg_static_plugins[i]);
}
return egg;
2016-05-24 20:22:15 +00:00
beach:
r_egg_free (egg);
return NULL;
}
R_API int r_egg_add (REgg *a, REggPlugin *foo) {
RListIter *iter;
RAsmPlugin *h;
// TODO: cache foo->name length and use memcmp instead of strcmp
2018-03-14 11:41:39 +00:00
if (!foo->name) {
2015-09-14 00:08:31 +00:00
return false;
2018-03-14 11:41:39 +00:00
}
2017-07-30 08:15:51 +00:00
r_list_foreach (a->plugins, iter, h) {
if (!strcmp (h->name, foo->name)) {
2015-09-14 00:08:31 +00:00
return false;
2017-07-30 08:15:51 +00:00
}
}
r_list_append (a->plugins, foo);
2015-09-14 00:08:31 +00:00
return true;
}
R_API char *r_egg_to_string (REgg *egg) {
return strdup ((const char *)egg->buf->buf);
}
R_API void r_egg_free (REgg *egg) {
2018-03-14 11:41:39 +00:00
if (egg) {
r_buf_free (egg->src);
r_buf_free (egg->buf);
r_buf_free (egg->bin);
r_list_free (egg->list);
r_asm_free (egg->rasm);
r_syscall_free (egg->syscall);
sdb_free (egg->db);
r_list_free (egg->plugins);
r_list_free (egg->patches);
r_egg_lang_free (egg);
free (egg);
}
}
R_API void r_egg_reset (REgg *egg) {
r_egg_lang_include_init (egg);
// TODO: use r_list_purge instead of free/new here
r_buf_free (egg->src);
r_buf_free (egg->buf);
r_buf_free (egg->bin);
egg->src = r_buf_new ();
egg->buf = r_buf_new ();
egg->bin = r_buf_new ();
r_list_purge (egg->patches);
}
R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os) {
2018-01-24 14:12:33 +00:00
const char *asmcpu = NULL; // TODO
2014-03-24 23:34:23 +00:00
egg->remit = NULL;
egg->os = os? r_str_hash (os): R_EGG_OS_DEFAULT;
//eprintf ("%s -> %x (linux=%x) (darwin=%x)\n", os, egg->os, R_EGG_OS_LINUX, R_EGG_OS_DARWIN);
// TODO: setup egg->arch for all archs
if (!strcmp (arch, "x86")) {
egg->arch = R_SYS_ARCH_X86;
switch (bits) {
case 32:
2018-01-24 14:12:33 +00:00
r_syscall_setup (egg->syscall, arch, bits, asmcpu, os);
2014-03-24 23:34:23 +00:00
egg->remit = &emit_x86;
egg->bits = bits;
break;
case 64:
2018-01-24 14:12:33 +00:00
r_syscall_setup (egg->syscall, arch, bits, asmcpu, os);
2014-03-24 23:34:23 +00:00
egg->remit = &emit_x64;
egg->bits = bits;
break;
}
} else
if (!strcmp (arch, "arm")) {
egg->arch = R_SYS_ARCH_ARM;
switch (bits) {
case 16:
case 32:
2018-01-24 14:12:33 +00:00
r_syscall_setup (egg->syscall, arch, bits, asmcpu, os);
2014-03-24 23:34:23 +00:00
egg->remit = &emit_arm;
egg->bits = bits;
egg->endian = endian;
break;
}
} else
if (!strcmp (arch, "trace")) {
//r_syscall_setup (egg->syscall, arch, os, bits);
2014-03-24 23:34:23 +00:00
egg->remit = &emit_trace;
egg->bits = bits;
egg->endian = endian;
}
return 0;
}
R_API int r_egg_include(REgg *egg, const char *file, int format) {
int sz;
const ut8 *foo = (const ut8*)r_file_slurp (file, &sz);
if (!foo) {
return 0;
}
// XXX: format breaks compiler layers
switch (format) {
case 'r': // raw
r_egg_raw (egg, foo, sz);
break;
case 'a': // assembly
r_buf_append_bytes (egg->buf, foo, sz);
break;
default:
r_buf_append_bytes (egg->src, foo, sz);
}
free ((void *)foo);
return 1;
}
R_API void r_egg_load(REgg *egg, const char *code, int format) {
switch (format) {
case 'a': // assembly
r_buf_append_bytes (egg->buf, (const ut8*)code, strlen (code));
break;
default:
r_buf_append_bytes (egg->src, (const ut8*)code, strlen (code));
break;
}
}
R_API void r_egg_syscall(REgg *egg, const char *arg, ...) {
RSyscallItem *item = r_syscall_get (egg->syscall,
r_syscall_get_num (egg->syscall, arg), -1);
if (!strcmp (arg, "close")) {
2014-03-24 23:34:23 +00:00
//egg->remit->syscall_args ();
}
if (!item) {
return;
}
2014-03-24 23:34:23 +00:00
egg->remit->syscall (egg, item->num);
}
R_API void r_egg_alloc(REgg *egg, int n) {
// add esp, n
}
R_API void r_egg_label(REgg *egg, const char *name) {
r_egg_printf (egg, "%s:\n", name);
}
2011-07-27 08:30:23 +00:00
R_API void r_egg_math (REgg *egg) {//, char eq, const char *vs, char type, const char *sr
// TODO
//e->mathop (egg, op, type, eq, p);
}
R_API int r_egg_raw(REgg *egg, const ut8 *b, int len) {
int outlen = len * 2; // two hexadecimal digits per byte
char *out = malloc (outlen + 1);
if (!out) {
return false;
}
int olen = r_hex_bin2str (b, len, out);
eprintf ("OUTLEN (%d) = %d\n", len, olen);
eprintf ("STROUT (%d)\n", strlen (out));
r_buf_append_bytes (egg->buf, (const ut8*)".hex ", 5);
r_buf_append_bytes (egg->buf, (const ut8*)out, outlen);
r_buf_append_bytes (egg->buf, (const ut8*)"\n", 1);
2014-05-03 12:21:03 +00:00
free (out);
2015-09-14 00:08:31 +00:00
return true;
}
static int r_egg_raw_prepend(REgg *egg, const ut8 *b, int len) {
int outlen = len * 2; // two hexadecimal digits per byte
char *out = malloc (outlen + 1);
if (!out) {
return false;
}
r_hex_bin2str (b, len, out);
r_buf_prepend_bytes (egg->buf, (const ut8*)"\n", 1);
r_buf_prepend_bytes (egg->buf, (const ut8*)out, outlen);
r_buf_prepend_bytes (egg->buf, (const ut8*)".hex ", 5);
free (out);
2015-09-14 00:08:31 +00:00
return true;
}
static int r_egg_prepend_bytes(REgg *egg, const ut8 *b, int len) {
if (!r_egg_raw_prepend (egg, b, len)) {
2015-09-14 00:08:31 +00:00
return false;
2016-10-02 21:46:57 +00:00
}
if (!r_buf_prepend_bytes (egg->bin, b, len)) {
2015-09-14 00:08:31 +00:00
return false;
2016-10-02 21:46:57 +00:00
}
2015-09-14 00:08:31 +00:00
return true;
}
static int r_egg_append_bytes(REgg *egg, const ut8 *b, int len) {
if (!r_egg_raw (egg, b, len)) {
2015-09-14 00:08:31 +00:00
return false;
}
if (!r_buf_append_bytes (egg->bin, b, len)) {
2015-09-14 00:08:31 +00:00
return false;
}
2015-09-14 00:08:31 +00:00
return true;
}
// r_egg_block (egg, FRAME | IF | ELSE | ENDIF | FOR | WHILE, sz)
R_API void r_egg_if(REgg *egg, const char *reg, char cmp, int v) {
// egg->depth++;
}
R_API void r_egg_printf(REgg *egg, const char *fmt, ...) {
va_list ap;
int len;
char buf[1024];
va_start (ap, fmt);
len = vsnprintf (buf, sizeof (buf), fmt, ap);
r_buf_append_bytes (egg->buf, (const ut8*)buf, len);
va_end (ap);
}
R_API bool r_egg_assemble_asm(REgg *egg, char **asm_list) {
2014-01-15 00:56:28 +00:00
RAsmCode *asmcode = NULL;
char *code = NULL;
char *asm_name = NULL;
if (asm_list) {
char **asm_;
for (asm_ = asm_list; *asm_; asm_+= 2) {
if (!strcmp (egg->remit->arch, asm_[0])) {
asm_name = asm_[1];
break;
}
}
}
if (!asm_name) {
if (egg->remit == &emit_x86 || egg->remit == &emit_x64) {
asm_name = "x86.nz";
} else if (egg->remit == &emit_arm) {
asm_name = "arm";
}
}
if (asm_name) {
r_asm_use (egg->rasm, asm_name);
r_asm_set_bits (egg->rasm, egg->bits);
r_asm_set_big_endian (egg->rasm, egg->endian);
r_asm_set_syntax (egg->rasm, R_ASM_SYNTAX_INTEL);
code = r_buf_to_string (egg->buf);
asmcode = r_asm_massemble (egg->rasm, code);
if (asmcode) {
if (asmcode->len > 0) {
r_buf_append_bytes (egg->bin, asmcode->buf, asmcode->len);
}
// LEAK r_asm_code_free (asmcode);
} else {
eprintf ("fail assembling\n");
}
}
2014-01-15 00:56:28 +00:00
free (code);
bool ret = (asmcode != NULL);
2014-01-15 00:56:28 +00:00
r_asm_code_free (asmcode);
return ret;
}
R_API bool r_egg_assemble(REgg *egg) {
return r_egg_assemble_asm (egg, NULL);
}
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
R_API int r_egg_compile(REgg *egg) {
const char *b = (const char *)egg->src->buf;
2014-03-28 14:57:50 +00:00
if (!b || !egg->remit) {
2015-09-14 00:08:31 +00:00
return true;
2014-03-28 14:57:50 +00:00
}
// only emit begin if code is found
2013-09-13 22:51:42 +00:00
#if 0
if (*b)
2014-03-24 23:34:23 +00:00
if (egg->remit) {
if (egg->remit->init)
egg->remit->init (egg);
}
2013-09-13 22:51:42 +00:00
#endif
r_egg_lang_init (egg);
2015-04-16 15:49:17 +00:00
if (b && *b) {
for (; b[0]; b++) {
r_egg_lang_parsechar (egg, *b);
// XXX: some parse fail errors are false positives :(
}
}
if (egg->context>0) {
eprintf ("ERROR: expected '}' at the end of the file. %d left\n", egg->context);
2015-09-14 00:08:31 +00:00
return false;
}
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
// TODO: handle errors here
2015-09-14 00:08:31 +00:00
return true;
* Deprecate rarc2 and rarc2-tool - Replaced by ragg2 - the new r_egg based tool for r2 * Add r_egg_assemble as a 2nd step for compilation * Fix memory leak in r_egg_free * Add support for 'cmp' and more 'test' variants for x86.nz - Ignore 'dword ptr' string - More test cases * Fix SCSIZE issue in rasc2 -s --HG-- rename : binr/rarc2/Makefile => binr/old.rarc2/Makefile rename : binr/rarc2/README => binr/old.rarc2/README rename : binr/rarc2/config.def.h => binr/old.rarc2/config.def.h rename : binr/rarc2/config.h => binr/old.rarc2/config.h rename : binr/rarc2/emit_arm.c => binr/old.rarc2/emit_arm.c rename : binr/rarc2/emit_x64.c => binr/old.rarc2/emit_x64.c rename : binr/rarc2/emit_x86.c => binr/old.rarc2/emit_x86.c rename : binr/rarc2/i/libc.r => binr/old.rarc2/i/libc.r rename : binr/rarc2/i/socket.r => binr/old.rarc2/i/socket.r rename : binr/rarc2/osxtest.r => binr/old.rarc2/osxtest.r rename : binr/rarc2/out.c => binr/old.rarc2/out.c rename : binr/rarc2/rarc2-tool => binr/old.rarc2/rarc2-tool rename : binr/rarc2/rarc2.c => binr/old.rarc2/rarc2.c rename : binr/rarc2/rarc2.h => binr/old.rarc2/rarc2.h rename : binr/rarc2/t/Makefile => binr/old.rarc2/t/Makefile rename : binr/rarc2/t/argv.r => binr/old.rarc2/t/argv.r rename : binr/rarc2/t/bytedump.r => binr/old.rarc2/t/bytedump.r rename : binr/rarc2/t/data.r => binr/old.rarc2/t/data.r rename : binr/rarc2/t/dump.r => binr/old.rarc2/t/dump.r rename : binr/rarc2/t/hello.r => binr/old.rarc2/t/hello.r rename : binr/rarc2/t/hi.r => binr/old.rarc2/t/hi.r rename : binr/rarc2/t/if.r => binr/old.rarc2/t/if.r rename : binr/rarc2/t/inline.r => binr/old.rarc2/t/inline.r rename : binr/rarc2/t/input.r => binr/old.rarc2/t/input.r rename : binr/rarc2/t/loop.r => binr/old.rarc2/t/loop.r rename : binr/rarc2/t/ptr.r => binr/old.rarc2/t/ptr.r rename : binr/rarc2/t/rawsys.r => binr/old.rarc2/t/rawsys.r rename : binr/rarc2/t/rawsys64.r => binr/old.rarc2/t/rawsys64.r rename : binr/rarc2/t/regs.r => binr/old.rarc2/t/regs.r rename : binr/rarc2/t/ret.r => binr/old.rarc2/t/ret.r rename : binr/rarc2/t/room.r => binr/old.rarc2/t/room.r rename : binr/rarc2/t/segfault.r => binr/old.rarc2/t/segfault.r rename : binr/rarc2/t/shell.r => binr/old.rarc2/t/shell.r rename : binr/rarc2/t/sub.r => binr/old.rarc2/t/sub.r rename : binr/rarc2/t/syscall.r => binr/old.rarc2/t/syscall.r rename : binr/rarc2/test.r => binr/old.rarc2/test.r rename : libr/egg/t/syscall.r => binr/ragg2/syscall.r
2011-08-08 00:07:26 +00:00
}
R_API RBuffer *r_egg_get_bin(REgg *egg) {
// TODO increment reference
return egg->bin;
}
//R_API int r_egg_dump (REgg *egg, const char *file) { }
R_API char *r_egg_get_source(REgg *egg) {
return r_buf_to_string (egg->src);
}
R_API char *r_egg_get_assembly(REgg *egg) {
return r_buf_to_string (egg->buf);
}
2011-07-27 08:30:23 +00:00
R_API void r_egg_append(REgg *egg, const char *src) {
r_buf_append_bytes (egg->src, (const ut8*)src, strlen (src));
}
/* JIT : TODO: accept arguments here */
R_API int r_egg_run(REgg *egg) {
return r_sys_run (egg->bin->buf, egg->bin->length);
}
#define R_EGG_FILL_TYPE_TRAP
#define R_EGG_FILL_TYPE_NOP
#define R_EGG_FILL_TYPE_CHAR
#define R_EGG_FILL_TYPE_SEQ
#define R_EGG_FILL_TYPE_SEQ
static inline char *eon(char *n) {
while (*n && (*n >= '0' && *n <= '9')) {
n++;
}
return n;
}
2015-04-08 21:39:14 +00:00
/* padding looks like:
([snatSNAT][0-9]+)*
*/
R_API int r_egg_padding (REgg *egg, const char *pad) {
2015-04-08 21:39:14 +00:00
int number;
ut8* buf, padding_byte;
char *p, *o = strdup (pad);
2016-10-02 21:46:57 +00:00
for (p = o; *p; ) { // parse pad string
2015-04-08 21:39:14 +00:00
const char f = *p++;
number = strtol(p, NULL, 10);
2016-10-02 21:46:57 +00:00
if (number < 1) {
2015-04-08 21:39:14 +00:00
eprintf ("Invalid padding length at %d\n", number);
free (o);
2015-09-14 00:08:31 +00:00
return false;
}
2015-04-08 21:39:14 +00:00
p = eon(p);
switch (f) {
2015-04-08 21:39:14 +00:00
case 's': case 'S': padding_byte = 0; break;
case 'n': case 'N': padding_byte = 0x90; break;
case 'a': case 'A': padding_byte = 'A'; break;
case 't': case 'T': padding_byte = 0xcc; break;
default:
eprintf ("Invalid padding format (%c)\n", *p);
2015-04-08 21:39:14 +00:00
eprintf ("Valid ones are:\n");
eprintf (" s S : NULL byte");
eprintf (" n N : nop");
eprintf (" a A : 0x41");
eprintf (" t T : trap (0xcc)");
free (o);
2015-09-14 00:08:31 +00:00
return false;
}
2014-05-03 12:21:03 +00:00
2015-04-08 21:39:14 +00:00
buf = malloc (number);
if (!buf) {
free (o);
2015-09-14 00:08:31 +00:00
return false;
}
2015-04-08 21:39:14 +00:00
memset (buf, padding_byte, number);
2016-10-02 21:46:57 +00:00
if (f >= 'a' && f <= 'z') {
r_egg_prepend_bytes(egg, buf, number);
2015-04-08 21:39:14 +00:00
} else {
r_egg_append_bytes(egg, buf, number);
2015-04-08 21:39:14 +00:00
}
free (buf);
}
free (o);
2015-09-14 00:08:31 +00:00
return true;
}
R_API void r_egg_fill(REgg *egg, int pos, int type, int argc, int length) {
// TODO
}
R_API void r_egg_option_set(REgg *egg, const char *key, const char *val) {
sdb_set (egg->db, key, val, 0);
}
R_API char *r_egg_option_get(REgg *egg, const char *key) {
return sdb_get (egg->db, key, NULL);
}
R_API int r_egg_shellcode(REgg *egg, const char *name) {
REggPlugin *p;
RListIter *iter;
RBuffer *b;
r_list_foreach (egg->plugins, iter, p) {
if (p->type == R_EGG_PLUGIN_SHELLCODE && !strcmp (name, p->name)) {
b = p->build (egg);
if (!b) {
2018-01-05 09:37:20 +00:00
eprintf ("%s Shellcode has failed\n", p->name);
2015-09-14 00:08:31 +00:00
return false;
}
r_egg_raw (egg, b->buf, b->length);
r_buf_free (b);
2015-09-14 00:08:31 +00:00
return true;
}
}
2015-09-14 00:08:31 +00:00
return false;
}
R_API int r_egg_encode(REgg *egg, const char *name) {
REggPlugin *p;
RListIter *iter;
RBuffer *b;
r_list_foreach (egg->plugins, iter, p) {
if (p->type == R_EGG_PLUGIN_ENCODER && !strcmp (name, p->name)) {
b = p->build (egg);
if (!b) {
return false;
}
r_buf_free (egg->bin);
egg->bin = b;
2015-09-14 00:08:31 +00:00
return true;
}
}
2015-09-14 00:08:31 +00:00
return false;
}
R_API int r_egg_patch(REgg *egg, int off, const ut8 *buf, int len) {
RBuffer *b = r_buf_new ();
if (!b) {
return false;
}
if (!r_buf_set_bytes (b, buf, len)) {
r_buf_free (b);
2015-09-14 00:08:31 +00:00
return false;
}
b->cur = off;
r_list_append (egg->patches, b);
2015-09-14 00:08:31 +00:00
return true;
}
R_API void r_egg_finalize(REgg *egg) {
RBuffer *b;
RListIter *iter;
2016-10-02 21:46:57 +00:00
if (!egg->bin->buf) {
2018-10-12 10:18:22 +00:00
r_buf_free (egg->bin);
egg->bin = r_buf_new ();
2016-10-02 21:46:57 +00:00
}
r_list_foreach (egg->patches, iter, b) {
2016-10-02 21:46:57 +00:00
if (b->cur < 0) {
r_egg_append_bytes (egg, b->buf, b->length);
} else {
// TODO: use r_buf_cpy_buf or what
if (b->length + b->cur > egg->bin->length) {
eprintf ("Cannot patch outside\n");
return;
}
memcpy (egg->bin->buf + b->cur, b->buf, b->length);
}
}
}
R_API void r_egg_pattern(REgg *egg, int size) {
char *ret = r_debruijn_pattern ((int)size, 0, NULL);
if (ret) {
r_egg_prepend_bytes (egg, (const ut8*)ret, strlen(ret));
free (ret);
} else {
eprintf ("Invalid debruijn pattern length.\n");
}
}