mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-11 23:16:05 +00:00
359 lines
10 KiB
C
359 lines
10 KiB
C
/* radare - LGPL - Copyright 2009-2013 - pancake */
|
|
|
|
#include <r_core.h>
|
|
|
|
R_API ut64 r_core_file_resize(struct r_core_t *core, ut64 newsize) {
|
|
if (newsize==0 && core->file)
|
|
return core->file->size;
|
|
return 0LL;
|
|
}
|
|
|
|
// TODO: add support for args
|
|
R_API int r_core_file_reopen(RCore *core, const char *args, int perm) {
|
|
char *path;
|
|
ut64 addr = 0; // XXX ? check file->map ?
|
|
RCoreFile *file, *ofile = core->file;
|
|
int newpid, ret = R_FALSE;
|
|
if (r_sandbox_enable (0)) {
|
|
eprintf ("Cannot reopen in sandbox\n");
|
|
return R_FALSE;
|
|
}
|
|
if (!core->file) {
|
|
eprintf ("No file opened to reopen\n");
|
|
return R_FALSE;
|
|
}
|
|
newpid = core->file->fd->fd;
|
|
if (!perm) perm = core->file->rwx;
|
|
path = strdup (core->file->uri);
|
|
if (r_config_get_i (core->config, "cfg.debug"))
|
|
r_debug_kill (core->dbg, 0, R_FALSE, 9); // KILL
|
|
file = r_core_file_open (core, path, perm, addr);
|
|
if (file) {
|
|
eprintf ("File %s reopened in %s mode\n", path,
|
|
perm&R_IO_WRITE?"read-write": "read-only");
|
|
ret = R_TRUE;
|
|
// close old file
|
|
//r_core_file_close (core, core->file);
|
|
r_core_file_close_fd (core, newpid);
|
|
core->file = file;
|
|
} else {
|
|
eprintf ("Oops. Cannot reopen file.\n");
|
|
core->file = ofile; // XXX: not necessary?
|
|
}
|
|
// TODO: in debugger must select new PID
|
|
if (r_config_get_i (core->config, "cfg.debug")) {
|
|
if (core->file && core->file->fd)
|
|
newpid = core->file->fd->fd;
|
|
r_debug_select (core->dbg, newpid, newpid);
|
|
}
|
|
r_core_block_read (core, 0);
|
|
free (path);
|
|
return ret;
|
|
}
|
|
|
|
// NOTE: probably not all environment vars takes sesnse
|
|
// because they can be replaced by commands in the given
|
|
// command.. we should only expose the most essential and
|
|
// unidirectional ones.
|
|
R_API void r_core_sysenv_help() {
|
|
r_cons_printf (
|
|
"Usage: !<cmd>\n"
|
|
" ! list all historic commands\n"
|
|
" !ls execute 'ls' in shell\n"
|
|
" !!ls~txt printo utput of 'ls' and grep for 'txt'\n"
|
|
" .!rabin2 -rvi ${FILE} run each output line as a r2 cmd\n"
|
|
" !echo $SIZE display file size\n"
|
|
"Environment:\n"
|
|
" FILE file name\n"
|
|
" SIZE file size\n"
|
|
" OFFSET 10base offset 64bit value\n"
|
|
" XOFFSET same as above, but in 16 base\n"
|
|
" BSIZE block size\n"
|
|
" ENDIAN 'big' or 'little'\n"
|
|
" ARCH value of asm.arch\n"
|
|
" DEBUG debug mode enabled? (1,0)\n"
|
|
" IOVA is io.va true? virtual addressing (1,0)\n"
|
|
" BLOCK TODO: dump current block to tmp file\n"
|
|
" BYTES TODO: variable with bytes in curblock\n"
|
|
);
|
|
}
|
|
|
|
R_API void r_core_sysenv_end(RCore *core, const char *cmd) {
|
|
// TODO: remove tmpfilez
|
|
if (strstr (cmd, "BLOCK")) {
|
|
// remove temporary BLOCK file
|
|
char *f = r_sys_getenv ("BLOCK");
|
|
if (f) {
|
|
r_file_rm (f);
|
|
r_sys_setenv ("BLOCK", NULL);
|
|
}
|
|
}
|
|
r_sys_setenv ("BYTES", NULL);
|
|
r_sys_setenv ("OFFSET", NULL);
|
|
}
|
|
|
|
R_API char *r_core_sysenv_begin(RCore *core, const char *cmd) {
|
|
char buf[64], *ret, *f;
|
|
#if DISCUSS
|
|
// EDITOR cfg.editor (vim or so)
|
|
CURSOR cursor position (offset from curseek)
|
|
COLOR scr.color?1:0
|
|
VERBOSE cfg.verbose
|
|
// only if cmd matches BYTES or BLOCK ?
|
|
BYTES hexpairs of current block
|
|
BLOCK temporally file with contents of current block
|
|
#endif
|
|
if (!core->file)
|
|
return NULL;
|
|
ret = strdup (cmd);
|
|
if (strstr (cmd, "BLOCK")) {
|
|
// replace BLOCK in RET string
|
|
if ((f = r_file_temp ("r2block"))) {
|
|
if (r_file_dump (f, core->block, core->blocksize))
|
|
r_sys_setenv ("BLOCK", f);
|
|
free (f);
|
|
}
|
|
}
|
|
if (strstr (cmd, "BYTES")) {
|
|
char *s = r_hex_bin2strdup (core->block, core->blocksize);
|
|
r_sys_setenv ("BYTES", s);
|
|
free (s);
|
|
}
|
|
if (core->file->filename)
|
|
r_sys_setenv ("FILE", core->file->filename);
|
|
snprintf (buf, sizeof (buf), "%"PFMT64d, core->offset);
|
|
r_sys_setenv ("OFFSET", buf);
|
|
snprintf (buf, sizeof (buf), "0x%08"PFMT64x, core->offset);
|
|
r_sys_setenv ("XOFFSET", buf);
|
|
snprintf (buf, sizeof (buf), "%"PFMT64d, core->file->size);
|
|
r_sys_setenv ("SIZE", buf);
|
|
r_sys_setenv ("ENDIAN", core->assembler->big_endian?"big":"little");
|
|
snprintf (buf, sizeof (buf), "%d", core->blocksize);
|
|
r_sys_setenv ("BSIZE", buf);
|
|
r_sys_setenv ("ARCH", r_config_get (core->config, "asm.arch"));
|
|
r_sys_setenv ("DEBUG", r_config_get_i (core->config, "cfg.debug")?"1":"0");
|
|
r_sys_setenv ("IOVA", r_config_get_i (core->config, "io.va")?"1":"0");
|
|
return ret;
|
|
}
|
|
|
|
R_API int r_core_bin_load(RCore *r, const char *file) {
|
|
int i, va = r->io->va || r->io->debug;
|
|
RListIter *iter;
|
|
const char *p;
|
|
ut64 offset;
|
|
RIOMap *im;
|
|
|
|
if (file == NULL)
|
|
if (r->file)
|
|
file = r->file->filename;
|
|
if (!file) {
|
|
eprintf ("r_core_bin_load: no file specified\n");
|
|
return R_FALSE;
|
|
}
|
|
p = strstr (file, "://");
|
|
if (p) file = p+3;
|
|
while (*file==' ') file++;
|
|
/* TODO: fat bins are loaded multiple times, this is a problem that must be fixed . see '-->' marks. */
|
|
/* r_bin_select, r_bin_select_idx and r_bin_load end up loading the bin */
|
|
if (r_bin_load (r->bin, file, R_FALSE)) { // --->
|
|
if (r->bin->narch>1 && r_config_get_i (r->config, "scr.prompt")) {
|
|
RBinObject *o = r->bin->cur.o;
|
|
eprintf ("NOTE: Fat binary found. Selected sub-bin is: -a %s -b %d\n",
|
|
r->assembler->cur->arch, r->assembler->bits);
|
|
eprintf ("NOTE: Use -a and -b to select sub binary in fat binary\n");
|
|
for (i=0; i<r->bin->narch; i++) {
|
|
r_bin_select_idx (r->bin, i); // -->
|
|
if (o->info) {
|
|
eprintf (" $ r2 -a %s -b %d %s # 0x%08"PFMT64x"\n",
|
|
o->info->arch,
|
|
o->info->bits,
|
|
r->bin->file,
|
|
r->bin->cur.offset);
|
|
} else eprintf ("No extract info found.\n");
|
|
}
|
|
r_bin_select (r->bin, r->assembler->cur->arch, r->assembler->bits, NULL); // -->
|
|
}
|
|
/* Fix for fat bins */
|
|
r_list_foreach (r->io->maps, iter, im) {
|
|
if (r->bin->cur.size > 0) {
|
|
im->delta = r->bin->cur.offset;
|
|
im->to = im->from + r->bin->cur.size;
|
|
}
|
|
}
|
|
} else if (!r_bin_load (r->bin, file, R_TRUE)) {
|
|
return R_FALSE;
|
|
}
|
|
if (!r->file) {
|
|
int bits;
|
|
RBinObject *obj = r_bin_get_object (r->bin);
|
|
if (obj && obj->info && obj->info->bits) {
|
|
r_config_set_i (r->config, "asm.bits", obj->info->bits);
|
|
}
|
|
return R_TRUE;
|
|
}
|
|
r->file->obj = r_bin_get_object (r->bin);
|
|
|
|
r_config_set_i (r->config, "io.va",
|
|
(r->file->obj->info)? r->file->obj->info->has_va: 0);
|
|
offset = r_bin_get_offset (r->bin);
|
|
r_core_bin_info (r, R_CORE_BIN_ACC_ALL, R_CORE_BIN_SET, va, NULL, offset);
|
|
if (!strcmp (r->bin->cur.curplugin->name, "dex")) {
|
|
r_core_cmd0 (r, "\"(fix-dex,wx `#sha1 $s-32 @32` @12 ; wx `#adler32 $s-12 @12` @8)\"\n");
|
|
}
|
|
if (r_config_get_i (r->config, "file.analyze"))
|
|
r_core_cmd0 (r, "aa");
|
|
return R_TRUE;
|
|
}
|
|
|
|
R_API RCoreFile *r_core_file_open(RCore *r, const char *file, int mode, ut64 loadaddr) {
|
|
const char *cp;
|
|
RCoreFile *fh;
|
|
RIODesc *fd;
|
|
char *p;
|
|
if (!strcmp (file, "-")) {
|
|
file = "malloc://512";
|
|
mode = 4|2;
|
|
}
|
|
r->io->bits = r->assembler->bits; // TODO: we need an api for this
|
|
fd = r_io_open (r->io, file, mode, 0644);
|
|
if (fd == NULL) {
|
|
if (mode & 2) {
|
|
if (!r_io_create (r->io, file, 0644, 0))
|
|
return NULL;
|
|
if (!(fd = r_io_open (r->io, file, mode, 0644)))
|
|
return NULL;
|
|
} else return NULL;
|
|
}
|
|
if (r_io_is_listener (r->io)) {
|
|
r_core_serve (r, fd);
|
|
return NULL;
|
|
}
|
|
|
|
fh = R_NEW (RCoreFile);
|
|
fh->fd = fd;
|
|
fh->map = NULL;
|
|
fh->uri = strdup (fd->name);
|
|
fh->size = r_file_size (fh->uri);
|
|
if (!fh->size)
|
|
fh->size = r_io_size (r->io);
|
|
fh->filename = strdup (fh->uri);
|
|
p = strstr (fh->filename, "://");
|
|
if (p != NULL) {
|
|
char *s = strdup (p+3);
|
|
free (fh->filename);
|
|
fh->filename = s;
|
|
}
|
|
fh->rwx = mode;
|
|
r->file = fh;
|
|
r->io->plugin = fd->plugin;
|
|
fh->size = r_io_size (r->io);
|
|
r_list_append (r->files, fh);
|
|
|
|
cp = r_config_get (r->config, "cmd.open");
|
|
if (cp && *cp)
|
|
r_core_cmd (r, cp, 0);
|
|
r_config_set (r->config, "file.path", file);
|
|
r_config_set_i (r->config, "zoom.to", loadaddr+fh->size);
|
|
fh->map = r_io_map_add (r->io, fh->fd->fd, mode, 0, loadaddr, fh->size);
|
|
|
|
r_core_block_read (r, 0);
|
|
return fh;
|
|
}
|
|
|
|
R_API void r_core_file_free(RCoreFile *cf) {
|
|
if (!cf) return;
|
|
R_FREE (cf->uri);
|
|
R_FREE (cf->filename);
|
|
R_FREE (cf->map);
|
|
r_io_desc_free (cf->fd);
|
|
cf->fd = NULL;
|
|
}
|
|
|
|
R_API int r_core_file_close(struct r_core_t *r, struct r_core_file_t *fh) {
|
|
int ret = r_io_close (r->io, fh->fd);
|
|
// TODO: free fh->obj
|
|
//r_list_delete (fh);
|
|
//list_del (&(fh->list));
|
|
// TODO: set previous opened file as current one
|
|
return ret;
|
|
}
|
|
|
|
R_API RCoreFile *r_core_file_get_fd(RCore *core, int fd) {
|
|
RCoreFile *file;
|
|
RListIter *iter;
|
|
r_list_foreach (core->files, iter, file) {
|
|
if (file->fd->fd == fd)
|
|
return file;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
R_API int r_core_file_list(RCore *core) {
|
|
int count = 0;
|
|
RCoreFile *f;
|
|
RListIter *iter;
|
|
r_list_foreach (core->files, iter, f) {
|
|
if (f->map)
|
|
r_cons_printf ("%c %d %s @ 0x%"PFMT64x" ; %s\n",
|
|
core->io->raised == f->fd->fd?'*':'-',
|
|
f->fd->fd, f->uri, f->map->from,
|
|
f->fd->flags & R_IO_WRITE? "rw": "r");
|
|
else r_cons_printf ("- %d %s\n", f->fd->fd, f->uri);
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
R_API int r_core_file_close_fd(RCore *core, int fd) {
|
|
RCoreFile *file;
|
|
RListIter *iter;
|
|
r_list_foreach (core->files, iter, file) {
|
|
if (file->fd->fd == fd) {
|
|
r_io_close (core->io, file->fd);
|
|
r_list_delete (core->files, iter);
|
|
if (r_list_empty (core->files))
|
|
core->file = NULL;
|
|
return R_TRUE;
|
|
}
|
|
}
|
|
return R_FALSE;
|
|
}
|
|
|
|
R_API int r_core_hash_load(RCore *r, const char *file) {
|
|
const ut8 *md5, *sha1;
|
|
char hash[128], *p;
|
|
int i, buf_len = 0;
|
|
ut8 *buf = NULL;
|
|
RHash *ctx;
|
|
ut64 limit;
|
|
|
|
limit = r_config_get_i (r->config, "cfg.hashlimit");
|
|
if (r->file->size > limit)
|
|
return R_FALSE;
|
|
buf = (ut8*)r_file_slurp (file, &buf_len);
|
|
if (buf==NULL)
|
|
return R_FALSE;
|
|
ctx = r_hash_new (R_TRUE, R_HASH_MD5);
|
|
md5 = r_hash_do_md5 (ctx, buf, buf_len);
|
|
p = hash;
|
|
for (i=0; i<R_HASH_SIZE_MD5; i++) {
|
|
sprintf (p, "%02x", md5[i]);
|
|
p += 2;
|
|
}
|
|
*p = 0;
|
|
r_config_set (r->config, "file.md5", hash);
|
|
r_hash_free (ctx);
|
|
ctx = r_hash_new (R_TRUE, R_HASH_SHA1);
|
|
sha1 = r_hash_do_sha1 (ctx, buf, buf_len);
|
|
p = hash;
|
|
for (i=0; i<R_HASH_SIZE_SHA1; i++) {
|
|
sprintf (p, "%02x", sha1[i]);
|
|
p += 2;
|
|
}
|
|
*p = 0;
|
|
r_config_set (r->config, "file.sha1", hash);
|
|
r_hash_free (ctx);
|
|
free (buf);
|
|
return R_TRUE;
|
|
}
|