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:
pancake 2021-05-04 13:16:55 +02:00
parent 4ae7cef832
commit 51e890ca3e
6 changed files with 98 additions and 50 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2020 - pancake */
/* radare - LGPL - Copyright 2009-2021 - pancake */
#include <r_core.h>
#include <r_types.h>

View File

@ -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;

View File

@ -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

View File

@ -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