Support for remote raw commands (client/server)

See the '.:' command
Full integration with awk bindings
Add install make target for the awk bindings
Handle as debug mode if io->file->debug
Fix typo quite/quiet in rabin2
Resolve $pc,$bp,$sp,$a0.. in r_core_num
Minor random fixups
This commit is contained in:
pancake 2012-11-05 02:00:34 +01:00
parent 07929b169d
commit 7c1e0c85d9
20 changed files with 220 additions and 20 deletions

View File

@ -68,7 +68,7 @@ static int rabin_show_help() {
" -L list supported bin plugins\n"
" -@ [addr] show section, symbol or import at addr\n"
" -n [str] show section, symbol or import named str\n"
" -q be quite, just show fewer data\n"
" -q be quiet, just show fewer data\n"
" -x extract bins contained in file\n"
" -Z size of binary\n"
" -z strings\n"

View File

@ -124,7 +124,7 @@ int main(int argc, char **argv) {
const char *asmarch = NULL;
const char *asmbits = NULL;
ut64 mapaddr = 0LL;
int quite = R_FALSE;
int quiet = R_FALSE;
int is_gdb = R_FALSE;
RList *cmds = r_list_new ();
RList *evals = r_list_new ();
@ -155,7 +155,7 @@ int main(int argc, char **argv) {
case 'm': mapaddr = r_num_math (r.num, optarg); break;
case 'q':
r_config_set (r.config, "scr.prompt", "false");
quite = R_TRUE;
quiet = R_TRUE;
break;
case 'p': r_config_set (r.config, "file.project", optarg); break;
case 'P': patchfile = optarg; break;
@ -312,6 +312,9 @@ int main(int argc, char **argv) {
if (asmarch) r_config_set (r.config, "asm.arch", asmarch);
if (asmbits) r_config_set (r.config, "asm.bits", asmbits);
debug = r.file && r.file->fd && r.file->fd->plugin && \
r.file->fd->plugin->debug != NULL;
r_config_set_i (r.config, "cfg.debug", debug);
if (debug) {
int pid, *p = r.file->fd->data;
if (!p) {
@ -393,7 +396,7 @@ int main(int argc, char **argv) {
int ret = r_core_cmd_file (&r, cmdfile[i]);
if (ret ==-2)
eprintf ("Cannot open '%s'\n", cmdfile[i]);
if (ret<0 || (ret==0 && quite))
if (ret<0 || (ret==0 && quiet))
return 0;
}
@ -402,7 +405,7 @@ int main(int argc, char **argv) {
r_core_cmd0 (&r, cmdn);
r_cons_flush ();
}
if ((cmdfile[0] || !r_list_empty (cmds)) && quite)
if ((cmdfile[0] || !r_list_empty (cmds)) && quiet)
return 0;
r_list_free (cmds);
/////

View File

@ -74,6 +74,7 @@ symstall install-symlink:
ln -fs ${PWD}/$${b} ${LFX}/radare2/${VERSION}/ ; \
fi ; \
done ; \
ln -fs ${LFX}/radare2/${VERSION} ${LFX}/radare2/last ; \
done
install: install-includes install-pkgconfig
@ -96,6 +97,7 @@ install: install-includes install-pkgconfig
${INSTALL_DATA} $$a ${LFX}/radare2/${VERSION} ; done
@echo "lang/p/radare.* ${DESTDIR}/${PFX}/${LIBDIR}/radare2/${VERSION}"
${INSTALL_DATA} lang/p/radare.* ${LFX}/radare2/${VERSION}
ln -fs ${LFX}/radare2/${VERSION} ${LFX}/radare2/last
deinstall uninstall:
# libraries

View File

@ -95,11 +95,11 @@ static int bin_info (RCore *r, int mode) {
"\"relocs\":%s}",
info->rclass,
info->bclass,
info->big_endian? "big":"little",
info->big_endian? "big": "little",
info->machine,
info->arch,
info->os,
info->has_va,
info->has_va? "true": "false",
info->bits,
r_str_bool (R_BIN_DBG_STRIPPED (info->dbg_info)),
r_str_bool (R_BIN_DBG_STATIC (info->dbg_info)),

View File

@ -136,6 +136,7 @@ static int cmd_rap(void *data, const char *input) {
case '+': r_core_rtr_add (core, input+1); break;
case '-': r_core_rtr_remove (core, input+1); break;
case '=': r_core_rtr_session (core, input+1); break;
//case ':': r_core_rtr_cmds (core, input+1); break;
case '<': r_core_rtr_pushout (core, input+1); break;
case '!': r_io_system (core->io, input+1); break;
default: r_core_rtr_cmd (core, input);
@ -227,6 +228,29 @@ static int cmd_interpret(void *data, const char *input) {
case '\0':
r_core_cmd_repeat (core, 0);
break;
case ':':
if ((ptr = strchr (input+1, ' '))) {
char *rbuf, *port, *host;
char *cmd = ptr+1;
/* .:port cmd */
/* .:host:port cmd */
*ptr = 0;
eol = strchr (input+1, ':');
if (eol) {
*eol = 0;
host = input+1;
port = eol+1;
} else {
host = "localhost";
port = input+((input[1]==':')?2:1);
}
rbuf = r_core_rtr_cmds_query (core, host, port, cmd);
if (rbuf) {
r_cons_printf ("%s", rbuf);
free (rbuf);
}
} else r_core_rtr_cmds (core, input+1);
break;
case '.': // same as \n
r_core_cmd_repeat (core, 1);
break;
@ -246,6 +270,7 @@ static int cmd_interpret(void *data, const char *input) {
"Usage: . [file] | [!command] | [(macro)]\n"
" . ; repeat last command backward\n"
" .. ; repeat last command forward (same as \\n)\n"
" .:8080 ; listen for commands on given tcp port\n"
" . foo.rs ; interpret r script\n"
" .!rabin -ri $FILE ; interpret output of command\n"
" .(foo 1 2 3) ; run macro 'foo' with args 1, 2, 3\n"

View File

@ -111,7 +111,11 @@ static void cmd_debug_pid(RCore *core, const char *input) {
}
break;
case 'a':
r_debug_attach (core->dbg, (int) r_num_math (core->num, input+2));
if (input[2]) {
r_debug_attach (core->dbg, (int) r_num_math (core->num, input+2));
} else {
r_debug_attach (core->dbg, core->file->fd->fd);
}
r_debug_select (core->dbg, core->dbg->pid, core->dbg->tid);
r_config_set_i (core->config, "dbg.swstep",
(core->dbg->h && !core->dbg->h->canstep));

View File

@ -330,6 +330,7 @@ static int cmd_help(void *data, const char *input) {
" $o = here (current disk io offset)\n"
" $s = file size\n"
" $b = block size\n"
" $w = get word size, 4 if asm.bits=32, 8 if 64, ...\n"
" $S = section offset\n"
" $SS = section size\n"
" $j = jump address (e.g. jmp 0x10, jz 0x10 => 0x10)\n"

View File

@ -83,6 +83,21 @@ r_num_calc_index (core->num, q);
if (str[0]=='$') {
*ok = 1;
r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize);
/* debug */ // XXX spaguetti!
if (!strcmp (str+1, "pc")) {
return r_debug_reg_get (core->dbg, "pc");
} else if (!strcmp (str+1, "sp")) {
return r_debug_reg_get (core->dbg, "sp");
} else if (!strcmp (str+1, "bp")) {
return r_debug_reg_get (core->dbg, "bp");
} else if (!strcmp (str+1, "a0")) {
return r_debug_reg_get (core->dbg, "a0");
} else if (!strcmp (str+1, "a1")) {
return r_debug_reg_get (core->dbg, "a1");
} else if (!strcmp (str+1, "a2")) {
return r_debug_reg_get (core->dbg, "a2");
}
/* other */
switch (str[1]) {
case '{':
{
@ -104,6 +119,10 @@ r_num_calc_index (core->num, q);
case 'l': return op.length;
case 'b': return core->blocksize;
case 's': return core->file->size;
case 'w': {
int bits = r_config_get_i (core->config, "asm.bits");
return bits/8;
} break;
case 'S': {
RIOSection *s = r_io_section_get (core->io,
r_io_section_vaddr_to_offset (core->io, core->offset));

View File

@ -8,6 +8,7 @@
#define rtr_host core->rtr_host
static RSocket *s = NULL;
static const char *listenport = NULL;
static void http_break (void *u) {
RSocket* sock;
@ -15,11 +16,10 @@ static void http_break (void *u) {
const int timeout = 1; // 1 second
RCore *core = (RCore*)u;
if (((size_t)u)>0xff) {
port = r_config_get (core->config, "http.port");
port = listenport? listenport: r_config_get (core->config, "http.port");
sock = r_socket_new (0);
eprintf ("Shutting down http server...\n");
if (r_socket_connect (sock, "localhost", port, R_SOCKET_PROTO_TCP, timeout))
r_socket_free (sock);
r_socket_connect (sock, "localhost", port, R_SOCKET_PROTO_TCP, timeout);
r_socket_free (sock);
}
r_socket_free (s);
s = NULL;
@ -132,6 +132,7 @@ R_API int r_core_rtr_http(RCore *core, int launch) {
R_API void r_core_rtr_help(RCore *core) {
r_cons_printf (
" = ; list all open connections\n"
//" =:port [cmd] ; same as .: but allow to send command if cmd\n"
" =<[fd] cmd ; send output of local command to remote fd\n"
" =[fd] cmd ; exec cmd at remote 'fd' (last open is default one)\n"
" =! cmd ; run command via r_io_system\n"
@ -290,7 +291,7 @@ R_API void r_core_rtr_add(RCore *core, const char *_input) {
if (!rtr_host[i].fd) {
rtr_host[i].proto = proto;
memcpy (rtr_host[i].host, host, 512);
rtr_host[i].port = atoi(port);
rtr_host[i].port = atoi (port);
memcpy (rtr_host[i].file, file, 1024);
rtr_host[i].fd = fd;
rtr_n = i;
@ -403,3 +404,69 @@ R_API void r_core_rtr_cmd(RCore *core, const char *input) {
r_cons_printf ("%s\n", cmd_output);
free ((void *)cmd_output);
}
// TODO: support len for binary data?
R_API char *r_core_rtr_cmds_query (RCore *core, const char *host, const char *port, const char *cmd) {
int retries = 6;
unsigned char buf[1024];
char *rbuf = NULL;
const int timeout = 0;
RSocket *s = r_socket_new (0);
for (;retries>0; usleep (10*1000)) {
if (r_socket_connect (s, host, port, R_SOCKET_PROTO_TCP, timeout))
break;
retries--;
}
if (retries>0) {
rbuf = strdup ("");
r_socket_write (s, (void*)cmd, strlen (cmd));
//r_socket_write (s, "px\n", 3);
for (;;) {
int ret = r_socket_read (s, buf, sizeof (buf));
if (ret<1) break;
buf[ret] = 0;
rbuf = r_str_concat (rbuf, (const char *)buf);
}
} else {
eprintf ("Cannot connect\n");
}
r_socket_free (s);
return rbuf;
}
R_API int r_core_rtr_cmds (RCore *core, const char *port) {
int i, ret;
char *str;
unsigned char buf[4096];
RSocket *ch, *s = r_socket_new (0);
if (!r_socket_listen (s, port, NULL)) {
eprintf ("Error listening on port %s\n", port);
return R_FALSE;
}
eprintf ("Listening for commands on port %s\n", port);
listenport = port;
for (;;) {
r_cons_break (http_break, core);
ch = r_socket_accept (s);
if (r_cons_singleton()->breaked) break;
buf[0] = 0;
ret = r_socket_read (ch, buf, sizeof (buf));
if (ret>0) {
buf[ret] = 0;
for (i=0;buf[i];i++)
if (buf[i] == '\n')
buf[i] = buf[i+1]? ';':'\0';
eprintf ("(%s)\n", buf);
if (!r_config_get_i (core->config, "scr.prompt") \
&& !strcmp ((char*)buf, "q!"))
return 0; // XXX memleak
str = r_core_cmd_str (core, (const char *)buf);
r_socket_write (ch, str, strlen (str));
}
free (str);
r_socket_close (ch);
r_cons_break_end ();
}
return 0;
}

View File

@ -35,6 +35,7 @@ R_API int r_debug_trace_pc (RDebug *dbg) {
r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE);
if ((ri = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], -1))) {
ut64 addr = r_reg_get_value (dbg->reg, ri);
if (addr)
if (dbg->iob.read_at (dbg->iob.io, addr, buf, sizeof (buf))>0) {
if (r_anal_op (dbg->anal, &op, addr, buf, sizeof (buf))>0) {
if (oldpc!=0LL)

View File

@ -263,6 +263,8 @@ typedef struct r_core_bin_filter_t {
R_API int r_core_bin_info (RCore *core, int action, int mode, int va, RCoreBinFilter *filter, ut64 offset);
/* rtr */
R_API int r_core_rtr_cmds (RCore *core, const char *port);
R_API char *r_core_rtr_cmds_query (RCore *core, const char *host, const char *port, const char *cmd);
R_API void r_core_rtr_help(RCore *core);
R_API void r_core_rtr_pushout(RCore *core, const char *input);
R_API void r_core_rtr_list(RCore *core);

View File

@ -300,7 +300,7 @@ struct r_io_plugin_t r_io_plugin_debug = {
.plugin_open = __plugin_open,
.lseek = NULL,
.system = NULL,
.debug = (void *)1,
.debug = (void *)(size_t)1,
//void *widget;
/*
struct debug_t *debug;

View File

@ -255,7 +255,7 @@ struct r_io_plugin_t r_io_plugin_mach = {
.lseek = __lseek,
.system = __system,
.write = __write,
// .debug ?
.debug = (void*)(size_t)1
};
#else

View File

@ -178,6 +178,7 @@ struct r_io_plugin_t r_io_plugin_ptrace = {
.lseek = __lseek,
.system = __system,
.write = __write,
.debug = (void*)(size_t)1
};
#else
struct r_io_plugin_t r_io_plugin_ptrace = {

View File

@ -116,6 +116,7 @@ struct r_io_plugin_t r_io_plugin_w32dbg = {
.system = __system,
.init = __init,
.write = __write,
.debug = (void*)(size_t)1
//void *widget;
/*
struct debug_t *debug;

View File

@ -144,7 +144,7 @@ R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int
hints.ai_protocol = proto;
gai = getaddrinfo (host, port, &hints, &res);
if (gai != 0) {
eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
//eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
return R_FALSE;
}
for (rp = res; rp != NULL; rp = rp->ai_next) {
@ -179,7 +179,7 @@ R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int
}
freeaddrinfo (res);
if (rp == NULL) {
eprintf ("Could not connect\n");
//eprintf ("Could not connect\n");
return R_FALSE;
}
}
@ -249,7 +249,7 @@ R_API int r_socket_listen (RSocket *s, const char *port, const char *certfile) {
memset (&sa, 0, sizeof (sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl (s->local? INADDR_LOOPBACK: INADDR_ANY);
sa.sin_port = htons (atoi (port));
sa.sin_port = htons (atoi (port)); // WTF we should honor etc/services
if (bind (s->fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
close (s->fd);
@ -432,6 +432,7 @@ R_API void r_socket_printf(RSocket *s, const char *fmt, ...) {
}
R_API int r_socket_read(RSocket *s, unsigned char *buf, int len) {
if (!s) return -1;
#if HAVE_LIB_SSL
if (s->is_ssl)
if (s->bio)

View File

@ -19,7 +19,7 @@ endif
LANGS=
# Experimental:
# LANGS+=gir
ALANGS=gir python ruby perl lua go java guile php5
ALANGS=awk gir python ruby perl lua go java guile php5
.PHONY: ${ALANGS}
define ADD_lang
@ -197,6 +197,11 @@ install-vapi:
mkdir -p ${DESTDIR}${PREFIX}/share/vala/vapi
${INSTALL_DATA} vapi/*.vapi vapi/*.deps ${DESTDIR}${PREFIX}/share/vala/vapi
AWKDIR=${DESTDIR}${PREFIX}/lib/radare2/${VERSION}/awk
install-awk:
mkdir -p ${AWKDIR}
cp -f awk/* ${AWKDIR}/
install-gir:
cd gir && ${MAKE} install

40
r2-bindings/awk/dbg Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/awk -f r2.awk -f
function getreg(x) {
ret=r2cmd(o,"?v $"x);
if(ret==0) {
print("Cannot debug program")
exit(1)
}
return num(ret)
}
function step(count) {
r2cmd(o,"ds "count)
r2cmd(o,".dr*")
}
BEGIN {
target="/bin/ls"
file="dbg://"target
if ((o=r2open())==0) {
print("Cannot open program for debugging")
exit(1)
}
pc=getreg("pc")
sp=getreg("sp")
bp=getreg("bp")
print("PC="pc)
print("SP="sp)
print("BP="bp)
print(r2cmd(o,"dr="))
print(r2cmd(o,"pdi 5@$pc"))
step(4)
print("Analyzing code...")
r2cmd(o,"af")
print(r2cmd(o,"pdf"))
r2close(o)
}

12
r2-bindings/awk/io Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/awk -f r2.awk -f
BEGIN {
file="/bin/ls"
port=r2open()
if(port) {
print(r2cmd(port, "px"));
r2close(port)
}else{
print("Cannot open r2 server")
}
}

View File

@ -4,6 +4,8 @@
BEGIN {
file=""
arch="arm"
port=0
host="localhost"
bits=32
offset=0
iova=1
@ -12,10 +14,12 @@ BEGIN {
# API
function sys(cmd) {
res = ""
n=0
while((cmd|getline line)>0) {
n++
res=res""line"\n"
}
close(x)
if(n==0) return 0
return res
}
@ -34,8 +38,20 @@ function imports() { return sys("rabin2 -vqi '"file"'"); }
function strings() { return sys("rabin2 -vqz '"file"'"); }
function sections() { return sys("rabin2 -vqS '"file"'"); }
function num(x) { return 0+x }
function cmd(c) { return sys("r2 -qc '"cmd"' '"file"'") }
function read(off,num) { return sys("r2 -qc 'p8 "num"@"off"' '"file"'") }
function write(off,x) { return sys("r2 -wqc 'wx "x"@"off"' '"file"'") }
function prompt(x,y) {printf(x);getline y; return chop(y); }
function search_hex(x) { return sys("rafind2 -x '"x"' '"file"'") }
function search_str(x) { return sys("rafind2 -s '"x"' '"file"'") }
# session server
function r2open() {
srand()rand()
port=1024+int(8192*rand())
if(system("r2 -qc .:"port" "file" >/dev/null 2>&1 &"))
return 0
return port
}
function r2cmd(port, cmd) { return sys("r2 -qc'\".:"host":"port" "cmd"\"' -") }
function r2close(port) { r2cmd(port,"q!") }