Add ragg2 -e to pass egg programs as argument, and improve code quality
* Use more bool and r_return asserts * Update manpage and help message * Spotted some issues in the x86 assembler
This commit is contained in:
parent
4ae7cef832
commit
51e890ca3e
|
@ -1,4 +1,4 @@
|
|||
/* radare - LGPL - Copyright 2011-2018 - pancake */
|
||||
/* radare - LGPL - Copyright 2011-2021 - pancake */
|
||||
|
||||
#include <r_egg.h>
|
||||
#include <config.h>
|
||||
|
@ -19,10 +19,12 @@ struct egg_patch_t {
|
|||
int off;
|
||||
};
|
||||
|
||||
void egg_patch_free (void *p) {
|
||||
void egg_patch_free(void *p) {
|
||||
struct egg_patch_t *ep = (struct egg_patch_t *)p;
|
||||
r_buf_free (ep->b);
|
||||
free (ep);
|
||||
if (ep) {
|
||||
r_buf_free (ep->b);
|
||||
free (ep);
|
||||
}
|
||||
}
|
||||
|
||||
R_API REgg *r_egg_new(void) {
|
||||
|
@ -73,7 +75,8 @@ beach:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
R_API int r_egg_add(REgg *a, REggPlugin *foo) {
|
||||
R_API bool r_egg_add(REgg *a, REggPlugin *foo) {
|
||||
r_return_val_if_fail (a && foo, false);
|
||||
RListIter *iter;
|
||||
RAsmPlugin *h;
|
||||
// TODO: cache foo->name length and use memcmp instead of strcmp
|
||||
|
@ -90,6 +93,7 @@ R_API int r_egg_add(REgg *a, REggPlugin *foo) {
|
|||
}
|
||||
|
||||
R_API char *r_egg_to_string(REgg *egg) {
|
||||
r_return_val_if_fail (egg, NULL);
|
||||
return r_buf_to_string (egg->buf);
|
||||
}
|
||||
|
||||
|
@ -110,6 +114,7 @@ R_API void r_egg_free(REgg *egg) {
|
|||
}
|
||||
|
||||
R_API void r_egg_reset(REgg *egg) {
|
||||
r_return_if_fail (egg);
|
||||
r_egg_lang_include_init (egg);
|
||||
// TODO: use r_list_purge instead of free/new here
|
||||
r_buf_free (egg->src);
|
||||
|
@ -121,7 +126,8 @@ R_API void r_egg_reset(REgg *egg) {
|
|||
r_list_purge (egg->patches);
|
||||
}
|
||||
|
||||
R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os) {
|
||||
R_API bool r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os) {
|
||||
r_return_val_if_fail (egg && arch, false);
|
||||
const char *asmcpu = NULL; // TODO
|
||||
egg->remit = NULL;
|
||||
|
||||
|
@ -160,14 +166,20 @@ R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const c
|
|||
egg->bits = bits;
|
||||
egg->endian = endian;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API int r_egg_include(REgg *egg, const char *file, int format) {
|
||||
R_API bool r_egg_include_str(REgg *egg, const char *arg) {
|
||||
r_buf_append_bytes (egg->src, (const ut8*)arg, strlen (arg));
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API bool r_egg_include(REgg *egg, const char *file, int format) {
|
||||
r_return_val_if_fail (egg && file, false);
|
||||
size_t sz;
|
||||
const ut8 *foo = (const ut8 *)r_file_slurp (file, &sz);
|
||||
if (!foo) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
// XXX: format breaks compiler layers
|
||||
switch (format) {
|
||||
|
@ -179,12 +191,14 @@ R_API int r_egg_include(REgg *egg, const char *file, int format) {
|
|||
break;
|
||||
default:
|
||||
r_buf_append_bytes (egg->src, foo, (ut64)sz);
|
||||
break;
|
||||
}
|
||||
free ((void *)foo);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_egg_load(REgg *egg, const char *code, int format) {
|
||||
r_return_if_fail (egg && code);
|
||||
switch (format) {
|
||||
case 'a': // assembly
|
||||
r_buf_append_bytes (egg->buf, (const ut8 *)code, strlen (code));
|
||||
|
@ -196,6 +210,7 @@ R_API void r_egg_load(REgg *egg, const char *code, int format) {
|
|||
}
|
||||
|
||||
R_API void r_egg_syscall(REgg *egg, const char *arg, ...) {
|
||||
r_return_if_fail (egg);
|
||||
RSyscallItem *item = r_syscall_get (egg->syscall,
|
||||
r_syscall_get_num (egg->syscall, arg), -1);
|
||||
if (!strcmp (arg, "close")) {
|
||||
|
@ -221,7 +236,8 @@ R_API void r_egg_math(REgg *egg) { //, char eq, const char *vs, char type, const
|
|||
//e->mathop (egg, op, type, eq, p);
|
||||
}
|
||||
|
||||
R_API int r_egg_raw(REgg *egg, const ut8 *b, int len) {
|
||||
R_API bool r_egg_raw(REgg *egg, const ut8 *b, int len) {
|
||||
r_return_val_if_fail (egg && b, false);
|
||||
int outlen = len * 2; // two hexadecimal digits per byte
|
||||
char *out = malloc (outlen + 1);
|
||||
if (!out) {
|
||||
|
@ -235,7 +251,8 @@ R_API int r_egg_raw(REgg *egg, const ut8 *b, int len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static int r_egg_raw_prepend(REgg *egg, const ut8 *b, int len) {
|
||||
static bool r_egg_raw_prepend(REgg *egg, const ut8 *b, int len) {
|
||||
r_return_val_if_fail (egg && b, false);
|
||||
int outlen = len * 2; // two hexadecimal digits per byte
|
||||
char *out = malloc (outlen + 1);
|
||||
if (!out) {
|
||||
|
@ -249,7 +266,8 @@ static int r_egg_raw_prepend(REgg *egg, const ut8 *b, int len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static int r_egg_prepend_bytes(REgg *egg, const ut8 *b, int len) {
|
||||
static bool r_egg_prepend_bytes(REgg *egg, const ut8 *b, int len) {
|
||||
r_return_val_if_fail (egg && b, false);
|
||||
if (!r_egg_raw_prepend (egg, b, len)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -259,7 +277,8 @@ static int r_egg_prepend_bytes(REgg *egg, const ut8 *b, int len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static int r_egg_append_bytes(REgg *egg, const ut8 *b, int len) {
|
||||
static bool r_egg_append_bytes(REgg *egg, const ut8 *b, int len) {
|
||||
r_return_val_if_fail (egg && b, false);
|
||||
if (!r_egg_raw (egg, b, len)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -277,6 +296,7 @@ R_API void r_egg_if(REgg *egg, const char *reg, char cmp, int v) {
|
|||
}
|
||||
|
||||
R_API void r_egg_printf(REgg *egg, const char *fmt, ...) {
|
||||
r_return_if_fail (egg && fmt);
|
||||
va_list ap;
|
||||
int len;
|
||||
char buf[1024];
|
||||
|
@ -335,7 +355,7 @@ R_API bool r_egg_assemble(REgg *egg) {
|
|||
}
|
||||
|
||||
R_API bool r_egg_compile(REgg *egg) {
|
||||
r_return_var_if_fail (egg, false);
|
||||
r_return_val_if_fail (egg, false);
|
||||
r_buf_seek (egg->src, 0, R_BUF_SET);
|
||||
char b;
|
||||
int r = r_buf_read (egg->src, (ut8 *)&b, sizeof (b));
|
||||
|
@ -385,10 +405,10 @@ R_API void r_egg_append(REgg *egg, const char *src) {
|
|||
|
||||
/* JIT : TODO: accept arguments here */
|
||||
R_API int r_egg_run(REgg *egg) {
|
||||
r_return_val_if_fail (egg, -1);
|
||||
ut64 tmpsz;
|
||||
const ut8 *tmp = r_buf_data (egg->bin, &tmpsz);
|
||||
bool res = r_sys_run (tmp, tmpsz);
|
||||
return res;
|
||||
return r_sys_run (tmp, tmpsz);
|
||||
}
|
||||
|
||||
R_API int r_egg_run_rop(REgg *egg) {
|
||||
|
@ -477,7 +497,8 @@ 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) {
|
||||
R_API bool r_egg_shellcode(REgg *egg, const char *name) {
|
||||
r_return_val_if_fail (egg && name, false);
|
||||
REggPlugin *p;
|
||||
RListIter *iter;
|
||||
RBuffer *b;
|
||||
|
@ -497,7 +518,7 @@ R_API int r_egg_shellcode(REgg *egg, const char *name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
R_API int r_egg_encode(REgg *egg, const char *name) {
|
||||
R_API bool r_egg_encode(REgg *egg, const char *name) {
|
||||
REggPlugin *p;
|
||||
RListIter *iter;
|
||||
RBuffer *b;
|
||||
|
@ -515,7 +536,7 @@ R_API int r_egg_encode(REgg *egg, const char *name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
R_API int r_egg_patch(REgg *egg, int off, const ut8 *buf, int len) {
|
||||
R_API bool r_egg_patch(REgg *egg, int off, const ut8 *buf, int len) {
|
||||
struct egg_patch_t *ep = R_NEW (struct egg_patch_t);
|
||||
if (!ep) {
|
||||
return false;
|
||||
|
|
|
@ -186,17 +186,18 @@ R_API void r_egg_lang_init(REgg *egg);
|
|||
R_API void r_egg_lang_free(REgg *egg);
|
||||
R_API char *r_egg_to_string (REgg *egg);
|
||||
R_API void r_egg_free (REgg *egg);
|
||||
R_API int r_egg_add (REgg *a, REggPlugin *foo);
|
||||
R_API bool r_egg_add (REgg *a, REggPlugin *foo);
|
||||
R_API void r_egg_reset (REgg *egg);
|
||||
R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os);
|
||||
R_API int r_egg_include(REgg *egg, const char *file, int format);
|
||||
R_API bool r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os);
|
||||
R_API bool r_egg_include(REgg *egg, const char *file, int format);
|
||||
R_API bool r_egg_include_str(REgg *egg, const char *arg);
|
||||
R_API void r_egg_load(REgg *egg, const char *code, int format);
|
||||
R_API void r_egg_syscall(REgg *egg, const char *arg, ...) R_PRINTF_CHECK(2, 3);
|
||||
R_API void r_egg_alloc(REgg *egg, int n);
|
||||
R_API void r_egg_label(REgg *egg, const char *name);
|
||||
R_API int r_egg_raw(REgg *egg, const ut8 *b, int len);
|
||||
R_API int r_egg_encode(REgg *egg, const char *name);
|
||||
R_API int r_egg_shellcode(REgg *egg, const char *name);
|
||||
R_API bool r_egg_raw(REgg *egg, const ut8 *b, int len);
|
||||
R_API bool r_egg_encode(REgg *egg, const char *name);
|
||||
R_API bool r_egg_shellcode(REgg *egg, const char *name);
|
||||
#define r_egg_get_shellcodes(x) x->plugins
|
||||
R_API void r_egg_option_set (REgg *egg, const char *k, const char *v);
|
||||
R_API char *r_egg_option_get (REgg *egg, const char *k);
|
||||
|
@ -215,7 +216,7 @@ R_API char *r_egg_get_assembly(REgg *egg);
|
|||
R_API void r_egg_append(REgg *egg, const char *src);
|
||||
R_API int r_egg_run(REgg *egg);
|
||||
R_API int r_egg_run_rop(REgg *egg);
|
||||
R_API int r_egg_patch(REgg *egg, int off, const ut8 *b, int l);
|
||||
R_API bool r_egg_patch(REgg *egg, int off, const ut8 *b, int l);
|
||||
R_API void r_egg_finalize(REgg *egg);
|
||||
|
||||
/* r_egg_Cfile.c */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* radare - LGPL - Copyright 2009-2020 - pancake */
|
||||
/* radare - LGPL - Copyright 2009-2021 - pancake */
|
||||
|
||||
#include <r_core.h>
|
||||
#include <r_types.h>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* radare - LGPL - Copyright 2011-2020 - pancake */
|
||||
/* radare - LGPL - Copyright 2011-2021 - pancake */
|
||||
|
||||
#include <r_egg.h>
|
||||
#include <r_bin.h>
|
||||
|
@ -8,8 +8,8 @@
|
|||
|
||||
static int usage(int v) {
|
||||
printf ("Usage: ragg2 [-FOLsrxhvz] [-a arch] [-b bits] [-k os] [-o file] [-I path]\n"
|
||||
" [-i sc] [-e enc] [-B hex] [-c k=v] [-C file] [-p pad] [-q off]\n"
|
||||
" [-S string] [-f fmt] [-nN dword] [-dDw off:hex] file|f.asm|-\n");
|
||||
" [-i sc] [-E enc] [-B hex] [-c k=v] [-C file] [-p pad] [-q off]\n"
|
||||
" [-S string] [-f fmt] [-nN dword] [-dDw off:hex] [-e expr] file|f.asm|-\n");
|
||||
if (v) {
|
||||
printf (
|
||||
" -a [arch] select architecture (x86, mips, arm)\n"
|
||||
|
@ -19,7 +19,8 @@ static int usage(int v) {
|
|||
" -C [file] append contents of file\n"
|
||||
" -d [off:dword] patch dword (4 bytes) at given offset\n"
|
||||
" -D [off:qword] patch qword (8 bytes) at given offset\n"
|
||||
" -e [encoder] use specific encoder. see -L\n"
|
||||
" -e [egg-expr] take egg program from string instead of file\n"
|
||||
" -E [encoder] use specific encoder. see -L\n"
|
||||
" -f [format] output format (raw, c, pe, elf, mach0, python, javascript)\n"
|
||||
" -F output native format (osx=mach0, linux=elf, ..)\n"
|
||||
" -h show this help\n"
|
||||
|
@ -125,14 +126,15 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
const char *format = "raw";
|
||||
bool show_execute = false;
|
||||
bool show_execute_rop = false;
|
||||
int show_hex = 1;
|
||||
int show_asm = 0;
|
||||
int show_raw = 0;
|
||||
bool show_hex = true;
|
||||
bool show_asm = false;
|
||||
bool show_raw = false;
|
||||
int append = 0;
|
||||
int show_str = 0;
|
||||
ut64 get_offset = 0;
|
||||
const char *shellcode = NULL;
|
||||
const char *encoder = NULL;
|
||||
const char *eggprg = NULL;
|
||||
char *sequence = NULL;
|
||||
int bits = (R_SYS_BITS & R_SYS_BITS_64)? 64: 32;
|
||||
int fmt = 0;
|
||||
|
@ -149,11 +151,14 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
case 'a':
|
||||
arch = opt.arg;
|
||||
if (!strcmp (arch, "trace")) {
|
||||
show_asm = 1;
|
||||
show_hex = 0;
|
||||
show_asm = true;
|
||||
show_hex = false;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
eggprg = opt.arg;
|
||||
break;
|
||||
case 'E':
|
||||
encoder = opt.arg;
|
||||
break;
|
||||
case 'b':
|
||||
|
@ -283,21 +288,21 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
#else
|
||||
format = "elf";
|
||||
#endif
|
||||
show_asm = 0;
|
||||
show_asm = false;
|
||||
break;
|
||||
case 'f':
|
||||
format = opt.arg;
|
||||
show_asm = 0;
|
||||
show_asm = false;
|
||||
break;
|
||||
case 's':
|
||||
show_asm = 1;
|
||||
show_hex = 0;
|
||||
show_asm = true;
|
||||
show_hex = false;
|
||||
break;
|
||||
case 'k':
|
||||
os = opt.arg;
|
||||
break;
|
||||
case 'r':
|
||||
show_raw = 1;
|
||||
show_raw = true;
|
||||
break;
|
||||
case 'x':
|
||||
// execute
|
||||
|
@ -335,11 +340,12 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (opt.ind == argc && !shellcode && !bytes && !contents && !encoder && !padding && !pattern && !append && !get_offset && !str) {
|
||||
if (opt.ind == argc && !eggprg && !shellcode && !bytes && !contents && !encoder && !padding && !pattern && !append && !get_offset && !str) {
|
||||
free (sequence);
|
||||
r_egg_free (egg);
|
||||
return usage (0);
|
||||
} else {
|
||||
}
|
||||
if (opt.ind != argc) {
|
||||
file = argv[opt.ind];
|
||||
}
|
||||
|
||||
|
@ -411,6 +417,8 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
} else {
|
||||
if (strstr (file, ".s") || strstr (file, ".asm")) {
|
||||
fmt = 'a';
|
||||
} else if (strstr (file, ".bin") || strstr (file, ".raw")) {
|
||||
fmt = 'r';
|
||||
} else {
|
||||
fmt = 0;
|
||||
}
|
||||
|
@ -419,6 +427,11 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (eggprg && !r_egg_include_str (egg, eggprg)) {
|
||||
eprintf ("Cannot parse egg program.\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
// compile source code to assembly
|
||||
|
@ -509,9 +522,11 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
}
|
||||
|
||||
// assemble to binary
|
||||
if (!r_egg_assemble (egg)) {
|
||||
eprintf ("r_egg_assemble: invalid assembly\n");
|
||||
goto fail;
|
||||
if (!show_asm) {
|
||||
if (!r_egg_assemble (egg)) {
|
||||
eprintf ("r_egg_assemble: invalid assembly\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (encoder) {
|
||||
if (!r_egg_encode (egg, encoder)) {
|
||||
|
@ -594,7 +609,7 @@ R_API int r_main_ragg2(int argc, const char **argv) {
|
|||
} // else show_raw is_above()
|
||||
break;
|
||||
case 'p': // PE
|
||||
if (strlen(format) >= 2 && format[1] == 'y') { // Python
|
||||
if (strlen (format) >= 2 && format[1] == 'y') { // Python
|
||||
r_print_code (p, 0, tmp, tmpsz, 'p');
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.Dd Sep 30, 2014
|
||||
.Dd May 4, 2021
|
||||
.Dt RAGG2 1
|
||||
.Sh NAME
|
||||
.Nm ragg2
|
||||
|
@ -12,7 +12,8 @@
|
|||
.Op Fl o Ar file
|
||||
.Op Fl i Ar shellcode
|
||||
.Op Fl I Ar path
|
||||
.Op Fl e Ar encoder
|
||||
.Op Fl e Ar eggstr
|
||||
.Op Fl E Ar encoder
|
||||
.Op Fl B Ar hexpairs
|
||||
.Op Fl c Ar k=v
|
||||
.Op Fl C Ar file
|
||||
|
@ -50,6 +51,8 @@ output file to write result of compilation
|
|||
.It Fl i Ar shellcode
|
||||
specify shellcode name to be used (see \-L)
|
||||
.It Fl e Ar encoder
|
||||
pass egg program as argument instead of in a file
|
||||
.It Fl E Ar encoder
|
||||
specify encoder name to be used (see \-L)
|
||||
.It Fl B Ar hexpair
|
||||
specify shellcode as hexpairs
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
NAME=ragg2 -a x86 -b 64 -e 'main@global{main(123)}'
|
||||
FILE=-
|
||||
CMDS=!ragg2 -a x86 -b 64 -e 'main@global{main(123)}'
|
||||
EXPECT=<<EOF
|
||||
48c7c07b00000050c3
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=ragg2 -a x86 -b 64 -p A200 -d 50:0xccccccb
|
||||
FILE=-
|
||||
CMDS=!ragg2 -a x86 -b 64 -p A200 -d 50:0xccccccb
|
||||
|
|
Loading…
Reference in New Issue