* Implement rap:// remote radare protocol support

- Fully compatible with radare1
  - Server  $ r2 rap://:9999
  - Client  $ r2 rap://127.0.0.1:9999//etc/fstab
* r_io has been refactorized to support client/server io plugins
  - Requires make clean
* Enhacements in Visual mode:
  - [] keys change scr.cols eval variable (hex columns)
  - Handle offscreen cursor and selection
  - Handle <0 seeking in visual mode
This commit is contained in:
pancake 2011-02-05 00:20:28 +01:00
parent 5742b10641
commit 53587faf25
11 changed files with 174 additions and 79 deletions

48
TODO
View File

@ -6,9 +6,20 @@
Visual mode
-----------
- cursor mode by default? (imho no)
- cursor can move outside screen (visual broken)
- scrollup by bwdisasm not yet implemented
* Add print support for bitfields (pb, pm b...)
* For each "call" or "push offset"+"ret" create a function.
- And, if deep code analysis is enabled:
- Search every possible function by searching typical prologs and put them in a queue.
- Perform the same actions as in the previous steps with the entry points.
* Stolen from pyew
- e anal.ops = true
INT num: Interruptions. Typically used as antiemulation (INT 4) and antidebugging tricks (INT 3).
UD2: Undefined instruction. Found in some packers/protectors as an antiemulation tricks.
RDTSC: Widely used in malware to check if the software is being traced. A typical way to detect binary instrumentation (PIN, DynamoRIO, etc...).
SIDT/SGDT: Store Interrupt/Global Descriptor Table. Trick used to detect some Virtual Machines (known as the red pill trick).
CPUID: Used to detect Virtual Machines and emulators.
// NOP args: NOP with arguments are typical antiemulation tricks.
SYSENTER: Direct system calls. Commonly, used as antiemulation tricks.
* RAsmOp RAnalOp // Aop->Op
* implement aoe = anal op exec
@ -19,7 +30,6 @@ Visual mode
pancake
-------
* Implement BLOCK in r_core_sysenv_begin|end ()
* Fix r2 rap://:9999 and c2s comms
* r2-swig : Distribute generated .i files and cxx files.. so build is faster
- ./configure --without-valaswig # compile without generating cxx files
- build with swig/
@ -33,9 +43,20 @@ earada
* Implement print Zoom mode (copypasta from r1) (useful for forensics) <-- MUST
* mount /mnt/ must chop last '/'
* test fatfs and others
* Add SSL support to r_socket
* remove all uses of alloca() // mingw and grep reports them all :)
* typedef all function pointers, like in r_bp
* Implement /A : search AES
* Implement case-insensitive search (e search.casematters ?) any better name? Use /i?
* Implement /. to search using a file .. isnt zignatures about this?
* Implement /p to search for patterns
- implement it in r_core ?? or add r_io_bind support
* Implement search and replace /s
- insert or append? (see r1 cfg vars)
nibble
------
* scrollup by bwdisasm not yet implemented
* '+' key in visual cursor mode only increments lower nibble!
- only in debugger mode :/
* register renaming (per-instruction or ranges)
@ -175,23 +196,6 @@ nibble
2nd level:
- basic block level diffing (output in graph mode)
earada
------
* Add SSL support to r_socket
* r_file_slurp should work fine for big files (not prio) r_file_slurp_buf?
- mmap if supported
- add r_file_mmap ?
- read file in blocks instead of the whole file in a single syscall
* remove all uses of alloca() // mingw and grep reports them all :)
* typedef all function pointers, like in r_bp
* Implement /A : search AES
* Implement case-insensitive search (e search.casematters ?) any better name? Use /i?
* Implement /. to search using a file .. isnt zignatures about this?
* Implement /p to search for patterns
- implement it in r_core ?? or add r_io_bind support
* Implement search and replace /s
- insert or append? (see r1 cfg vars)
Questions
=========
@ -243,6 +247,8 @@ Refactoring
Future
======
* r_file_slurp should work fine for big files (not prio) r_file_slurp_buf?
- mmap if supported - add r_file_mmap ? - read file in blocks instead of the whole file in a single syscall
* Realign flags when using project in debug mode
* FileDescriptors: dd -- copy from !fd in r1
* Initial analysis looking for xrefs to strings and so? ax? ./a@@entry0 - Launched at startup

View File

@ -173,8 +173,9 @@ int main(int argc, char **argv) {
const char *prj = r_config_get (r.config, "file.project");
if (prj && *prj) {
char *file = r_core_project_info (&r, prj);
if (file) fh = r_core_file_open (&r, file, perms);
else eprintf ("No file\n");
if (file) {
fh = r_core_file_open (&r, file, perms);
} else eprintf ("No file\n");
}
}
}
@ -247,8 +248,7 @@ int main(int argc, char **argv) {
r_core_cmd (&r, "fo", 0);
r_cons_flush ();
}
// read current block
r_core_seek (&r, r.offset, 1);
r_core_seek (&r, r.offset, 1); // read current block
/* XXX: find better solution.. files > 10MB does not hash */
#define SLURP_LIMIT (10*1024*1024)
@ -275,9 +275,6 @@ int main(int argc, char **argv) {
if (cmdfile)
r_core_cmd_file (&r, cmdfile);
if (r_io_is_listener (r.io)) {
r_core_serve (&r, r.io->fd);
} else
for (;;) {
do {
if (r_core_prompt (&r, R_FALSE)<1)

View File

@ -58,7 +58,7 @@ R_API const char *r_config_get(RConfig *cfg, const char *name) {
return (const char *)
(((!strcmp("true", node->value))
|| (!strcmp("1", node->value)))?
(char *)1:NULL); // XXX (char*)1 is ugly
(const char *)"true":"false"); // XXX (char*)1 is ugly
return node->value;
}
cfg->last_notfound = 1;

View File

@ -337,7 +337,7 @@ R_API int r_core_config_init(RCore *core) {
r_config_set (cfg, "asm.linesout", "true");
r_config_set (cfg, "asm.linesstyle", "false");
r_config_set (cfg, "asm.lineswide", "false");
r_config_set_i_cb (cfg, "asm.lineswidth", 0, &config_asmlineswidth_callback);
r_config_set_i_cb (cfg, "asm.lineswidth", 10, &config_asmlineswidth_callback);
r_config_set (cfg, "asm.linescall", "false");
r_config_set (cfg, "asm.offset", "true");
r_config_set_cb (cfg, "asm.os", R_SYS_OS, &config_asmos_callback);

View File

@ -406,13 +406,14 @@ R_API int r_core_serve(RCore *core, RIODesc *file) {
return -1;
}
eprintf ("RAP Server running\n");
eprintf ("RAP Server started (rap.loop=%s)\n", r_config_get (core->config, "rap.loop"));
#if __UNIX__
// XXX: ugly workaround
signal (SIGINT, SIG_DFL);
signal (SIGPIPE, SIG_DFL);
#endif
reaccept:
core->io->plugin = NULL;
while ((c = r_socket_accept (fd))) {
if (c == -1) {
eprintf ("rap: cannot accept\n");
@ -421,13 +422,15 @@ reaccept:
}
eprintf ("rap: client connected\n");
r_io_accept (core->io, c);
for (;;) {
i = r_socket_read (c, &cmd, 1);
if (i==0) {
eprintf ("rap: connection closed\n");
if (r_config_get_i (core->config, "rap.loop"))
if (r_config_get_i (core->config, "rap.loop")) {
eprintf ("rap: waiting for new connection\n");
goto reaccept;
}
return -1;
}

View File

@ -225,6 +225,10 @@ R_API RCoreFile *r_core_file_open(RCore *r, const char *file, int mode) {
RIODesc *fd = r_io_open (r->io, file, mode, 0644);
if (fd == NULL)
return NULL;
if (r_io_is_listener (r->io)) {
r_core_serve (r, r->io->fd);
return NULL;
}
fh = R_NEW (RCoreFile);
fh->fd = fd;

View File

@ -770,13 +770,6 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
}
r_cons_set_raw(1);
break;
/* select */
case 'H':
if (curset) {
if (ocursor==-1) ocursor=cursor;
cursor--;
} else r_core_cmd (core, "s-2", 0);
break;
case 'e':
r_core_visual_config (core);
break;
@ -786,12 +779,6 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
case 'v':
r_core_visual_anal (core);
break;
case 'J':
if (curset) {
if (ocursor==-1) ocursor = cursor;
cursor += cols;
} else r_core_cmd (core, "s++", 0);
break;
case 'g':
r_core_cmd (core, "s 0", 0);
break;
@ -800,64 +787,129 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
r_io_sundo_push (core->io);
//r_core_cmd(core, "s 0", 0);
break;
case 'K':
if (curset) {
if (ocursor==-1) ocursor=cursor;
cursor -= cols;
} else r_core_cmd (core, "s--", 0);
break;
case 'L':
if (curset) {
if (ocursor==-1) ocursor=cursor;
cursor++;
} else r_core_cmd (core, "s+2", 0);
break;
/* move */
case 'h':
if (curset) {
cursor--;
ocursor=-1;
if (cursor<0) {
r_core_seek (core, core->offset-cols, 1);
cursor ++;
}
} else r_core_cmd (core, "s-1", 0);
break;
case 'H':
if (curset) {
if (ocursor==-1) ocursor=cursor;
cursor--;
if (cursor<0) {
r_core_seek (core, core->offset-cols, 1);
cursor += cols;
ocursor += cols;
}
} else r_core_cmd (core, "s-2", 0);
break;
case 'l':
if (curset) {
cursor++;
ocursor=-1;
{
int offscreen = (core->cons->rows-3)*cols;
if (cursor>=offscreen) {
r_core_seek (core, core->offset+cols, 1);
cursor-=cols;
}
}
} else r_core_cmd (core, "s+1", 0);
break;
case 'u':
if (r_io_sundo (core->io))
r_core_seek (core, core->io->off, 1);
break;
case 'U':
if (r_io_sundo_redo (core->io))
r_core_seek (core, core->io->off, 1);
case 'L':
if (curset) {
if (ocursor==-1) ocursor=cursor;
cursor++;
{
int offscreen = (core->cons->rows-3)*cols;
if (cursor>=offscreen) {
r_core_seek (core, core->offset+cols, 1);
cursor-=cols;
ocursor-=cols;
}
}
} else r_core_cmd (core, "s+2", 0);
break;
case 'j':
// r_asm_disassemble (core->assembler, &aop, core->block, 32);
if (curset) {
if (printidx == 1)
cols = r_asm_disassemble (core->assembler, &aop, core->block, 32);
cursor += cols;
ocursor = -1;
{
int offscreen = (core->cons->rows-3)*cols;
if (cursor>=offscreen) {
r_core_seek (core, core->offset+cols, 1);
cursor-=cols;
}
}
} else {
if (printidx == 1)
cols = core->inc;
r_core_seek (core, core->offset+cols, 1);
}
break;
case 'J':
if (curset) {
if (ocursor==-1) ocursor = cursor;
cursor += cols;
{
int offscreen = (core->cons->rows-3)*cols;
if (cursor>=offscreen) {
r_core_seek (core, core->offset+cols, 1);
cursor-=cols;
ocursor-=cols;
}
}
} else r_core_cmd (core, "s++", 0);
break;
case 'k':
if (curset) {
if (printidx == 1)
cols = r_asm_disassemble (core->assembler, &aop, core->block, 32);
cursor -= cols;
if (cursor<0 && cols<core->offset) {
r_core_seek (core, core->offset-cols, 1);
cursor += cols;
}
ocursor = -1;
} else {
if (printidx == 1)
cols = core->inc;
if (cols>core->offset)
r_core_seek (core, core->offset-cols, 1);
}
break;
case 'K':
if (curset) {
if (ocursor==-1) ocursor=cursor;
cursor -= cols;
if (cursor<0 && cols<core->offset) {
r_core_seek (core, core->offset-cols, 1);
cursor += cols;
ocursor += cols;
}
} else r_core_cmd (core, "s--", 0);
break;
case '[':
{
int scrcols = r_config_get_i (core->config, "scr.cols");
if (scrcols>2)
r_config_set_i (core->config, "scr.cols", scrcols-2);
}
break;
case ']':
{
int scrcols = r_config_get_i (core->config, "scr.cols");
//if (scrcols<32)
r_config_set_i (core->config, "scr.cols", scrcols+2);
}
break;
case 's':
r_core_cmd (core, "ds", 0);
r_core_cmd (core, ".dr*", 0);
@ -957,6 +1009,14 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
obs = core->blocksize;
else r_core_block_size (core, obs);
break;
case 'u':
if (r_io_sundo (core->io))
r_core_seek (core, core->io->off, 1);
break;
case 'U':
if (r_io_sundo_redo (core->io))
r_core_seek (core, core->io->off, 1);
break;
case 'x':
r_core_cmdf (core, "./a 0x%08llx @ entry0", core->offset);
break;
@ -998,7 +1058,10 @@ R_API void r_core_visual_prompt(RCore *core, int color) {
if (autoblocksize)
switch (printidx) {
case 0:
r_core_block_size (core, core->cons->rows * 16);
{
int scrcols = r_config_get_i (core->config, "scr.cols");
r_core_block_size (core, core->cons->rows * scrcols);
}
break;
case 1: // pd
case 2: // pd+dbg

View File

@ -122,6 +122,7 @@ typedef struct r_io_plugin_t {
int (*write)(RIO *io, RIODesc *fd, const ut8 *buf, int count);
int (*close)(RIODesc *desc);
int (*resize)(RIO *io, RIODesc *fd, ut64 size);
int (*accept)(RIO *io, RIODesc *desc, int fd);
int (*plugin_open)(RIO *io, const char *);
//int (*plugin_fd)(RIO *, int);
} RIOPlugin;
@ -199,6 +200,7 @@ R_API int r_io_system(RIO *io, const char *cmd);
R_API int r_io_close(RIO *io, RIODesc *fd);
R_API ut64 r_io_size(RIO *io); //, int fd);
R_API int r_io_resize(struct r_io_t *io, ut64 newsize);
R_API int r_io_accept(RIO *io, int fd);
/* io/cache.c */
R_API void r_io_cache_commit(RIO *io);

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2010 pancake<nopcode.org> */
/* radare - LGPL - Copyright 2009-2011 pancake<nopcode.org> */
#include <r_io.h>
// TODO: to be deprecated.. this is slow and boring

View File

@ -110,9 +110,7 @@ R_API RIODesc *r_io_open(struct r_io_t *io, const char *file, int flags, int mod
fd = open (file, 1);
} else fd = open (file, 0);
#else
if (flags & R_IO_WRITE)
fd = open (file, O_RDWR, mode);
else fd = open (file, O_RDONLY, mode);
fd = open (file, (flags&R_IO_WRITE)?O_RDWR:O_RDONLY, mode);
#endif
}
if (fd >= 0) {
@ -321,6 +319,8 @@ R_API ut64 r_io_seek(struct r_io_t *io, ut64 offset, int whence) {
R_API ut64 r_io_size(RIO *io) {
ut64 size, here;
if (r_io_is_listener (io))
return UT64_MAX;
//r_io_set_fdn (io, fd);
here = r_io_seek (io, 0, R_IO_SEEK_CUR);
size = r_io_seek (io, 0, R_IO_SEEK_END);
@ -360,3 +360,11 @@ R_API int r_io_bind(RIO *io, RIOBind *bnd) {
//bnd->fd = io->fd;// do we need to store ptr to fd??
return R_TRUE;
}
R_API int r_io_accept(RIO *io, int fd) {
if (r_io_is_listener (io)) {
if (io->plugin->accept)
return io->plugin->accept (io, io->fd, fd);
}
return R_FALSE;
}

View File

@ -12,9 +12,10 @@
#define ENDIAN (0)
typedef struct {
int fd;
int client;
int listener;
} RIORap;
#define RIORAP_FD(x) (((RIORap*)(x->data))->fd)
#define RIORAP_FD(x) ((x->data)?(((RIORap*)(x->data))->client):-1)
#define RIORAP_IS_LISTEN(x) (((RIORap*)(x->data))->listener)
#define RIORAP_IS_VALID(x) ((x) && (x->data) && (x->plugin == &r_io_plugin_rap))
@ -42,6 +43,15 @@ static int rap__write(struct r_io_t *io, RIODesc *fd, const ut8 *buf, int count)
return ret;
}
static int rap__accept(RIO *io, RIODesc *desc, int fd) {
RIORap *rap = desc->data;
if (rap) {
rap->client = fd;
return R_TRUE;
}
return R_FALSE;
}
static int rap__read(struct r_io_t *io, RIODesc *fd, ut8 *buf, int count) {
int ret;
int i = (int)count;
@ -57,7 +67,8 @@ static int rap__read(struct r_io_t *io, RIODesc *fd, ut8 *buf, int count) {
// recv
ret = r_socket_read (RIORAP_FD (fd), tmp, 5);
if (ret != 5 || tmp[0] != (RMT_READ|RMT_REPLY)) {
eprintf ("rap__read: Unexpected rap read reply (0x%02x)\n", tmp[0]);
eprintf ("rap__read: Unexpected rap read reply (%d=0x%02x) expected (%d=0x%02x)\n",
ret, tmp[0], 2, (RMT_READ|RMT_REPLY));
return -1;
}
r_mem_copyendian ((ut8*)&i, tmp+1, 4, ENDIAN);
@ -66,9 +77,9 @@ static int rap__read(struct r_io_t *io, RIODesc *fd, ut8 *buf, int count) {
return -1;
}
r_socket_read_block (RIORAP_FD (fd), buf, i);
if (count>0 && count<RMT_MAX)
eprintf ("READ %d\n" ,i);
else count = 0;
if (count>0 && count<RMT_MAX) {
//eprintf ("READ %d\n" ,i);
} else count = 0;
return count;
}
@ -140,7 +151,7 @@ static RIODesc *rap__open(struct r_io_t *io, const char *pathname, int rw, int m
eprintf ("rap: listening at port %d\n", p);
rior = R_NEW (RIORap);
rior->listener = R_TRUE;
rior->fd = r_socket_listen (p);
rior->client = rior->fd = r_socket_listen (p);
// TODO: listen mode is broken.. here must go the root loop!!
#warning TODO: implement rap:/:9999 listen mode
return r_io_desc_new (&r_io_plugin_rap, rior->fd, pathname, rw, mode, rior);
@ -152,7 +163,7 @@ static RIODesc *rap__open(struct r_io_t *io, const char *pathname, int rw, int m
eprintf ("Connected to: %s at port %d\n", ptr, p);
rior = R_NEW (RIORap);
rior->listener = R_FALSE;
rior->fd = rap_fd;
rior->client = rior->fd = rap_fd;
if (file && *file) {
// send
buf[0] = RMT_OPEN;
@ -224,6 +235,7 @@ struct r_io_plugin_t r_io_plugin_rap = {
.lseek = rap__lseek,
.system = rap__system,
.write = rap__write,
.accept = rap__accept,
};
#ifndef CORELIB