mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-29 16:10:52 +00:00
Refactor cmd_wt()
This commit is contained in:
parent
65ff60cf02
commit
4ce57c06a8
@ -26,7 +26,7 @@ static const char *help_msg_w[] = {
|
||||
"wp","[?] -|file","apply radare patch file. See wp? fmi",
|
||||
"wr"," 10","write 10 random bytes",
|
||||
"ws","[?] pstring","write pascal string: 1 byte for length + N for the string",
|
||||
"wt","[?] file [sz]","write to file (from current seek, blocksize or sz bytes)",
|
||||
"wt","[afs][?] [filename] [size]","write to file (from current seek, blocksize or sz bytes)",
|
||||
"ww"," foobar","write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'",
|
||||
"wx","[?][fs] 9090","write two intel nops (from wxfile or wxseek)",
|
||||
"wX"," 1b2c3d","fill current block with cyclic hexpairs",
|
||||
@ -144,17 +144,13 @@ static const char *help_msg_wp[] = {
|
||||
};
|
||||
|
||||
static const char *help_msg_wt[] = {
|
||||
"Usage:", "wt[a] file [size]", " Write 'size' bytes in current block to 'file'",
|
||||
"Usage:", "wt[afs] [filename] [size]", " Write current block or [size] bytes from offset to file",
|
||||
"wta", " [filename]", "append to 'filename'",
|
||||
"wtf", " [filename] [size]", "write to file (see also 'wxf' and 'wf?')",
|
||||
"wtf!", " [filename]", "write to file from current address to eof",
|
||||
"wtff", " [prefix]", "write block from current seek to [prefix]-[offset]",
|
||||
"wts"," host:port [sz]", "send data to remote host:port via tcp://",
|
||||
NULL
|
||||
};
|
||||
static const char *help_msg_wts[] = {
|
||||
"Usage:", "wts host:port [sz]", " Write 'size' bytes to tcp connection at host:port",
|
||||
"wts", " localhost:9999 1M", "Copy 1MB over tcp/ip",
|
||||
"wtf!", " [filename]", "write to file from current address to eof (ignores given size)",
|
||||
"wtff", " [prefix] [size]", "write block from current seek to \"<prefix>-<offset>\"",
|
||||
"wts", " host:port [size]", "send data to remote socket at tcp://host:port",
|
||||
"NOTE:", "", "filename defaults to \"<cfg.prefixdump>.<offset>\"",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -1437,23 +1433,29 @@ static int cmd_wz(RCore *core, const char *input) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_wt(void *data, const char *input_) {
|
||||
RCore *core = (RCore *)data;
|
||||
char *input = strdup (input_);
|
||||
char *original_input = input; // to be freed later
|
||||
char *filename = NULL;
|
||||
bool free_filename = false;
|
||||
char _fn[32];
|
||||
_fn[0] = 0;
|
||||
char *size_sep;
|
||||
static int cmd_wt(RCore *core, const char *input) {
|
||||
R_BORROW const char *prefix = r_config_get (core->config, "cfg.prefixdump");
|
||||
R_BORROW char *filename = NULL;
|
||||
char default_filename_sep = '.';
|
||||
char fn_local[32]; // for using sprintf instead of str_newf; doesnt need free()
|
||||
int ret = 0;
|
||||
|
||||
bool append = false;
|
||||
st64 sz = core->blocksize;
|
||||
ut64 poff = core->offset; // physical address; for writing arbitrary sizes
|
||||
|
||||
int argc;
|
||||
char **argv = r_str_argv (input, &argc);
|
||||
char **argv;
|
||||
|
||||
argv = r_str_argv (input, &argc);
|
||||
|
||||
fn_local[0] = 0;
|
||||
filename = argv[1]; // NULL if argc < 2
|
||||
|
||||
input++;
|
||||
switch (*input) {
|
||||
case 's': { // "wts"
|
||||
ut64 addr = 0;
|
||||
st64 sz = r_io_size (core->io);
|
||||
char *host_port;
|
||||
R_BORROW char *host;
|
||||
R_BORROW char *port;
|
||||
@ -1461,16 +1463,16 @@ static int cmd_wt(void *data, const char *input_) {
|
||||
RSocket *sock;
|
||||
|
||||
if (argc < 2) {
|
||||
// TODO wt? message needs updating
|
||||
// TODO: need wts[?] in wt help? for recur. help
|
||||
r_core_cmd_help (core, help_msg_wts);
|
||||
break;
|
||||
r_core_cmd_help_match (core, help_msg_wt, "wts", true);
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
st64 sz = r_io_size (core->io);
|
||||
if (sz <= 0) {
|
||||
sz = r_io_size (core->io);
|
||||
if (sz < 0) {
|
||||
R_LOG_ERROR ("Unknown file size");
|
||||
break;
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
host_port = strdup (argv[1]);
|
||||
@ -1478,15 +1480,22 @@ static int cmd_wt(void *data, const char *input_) {
|
||||
host = host_port;
|
||||
port = strchr (host_port, ':');
|
||||
if (!port) {
|
||||
r_core_cmd_help (core, help_msg_wts);
|
||||
r_core_cmd_help_match (core, help_msg_wt, "wts", true);
|
||||
free (host_port);
|
||||
break;
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
*port++ = 0;
|
||||
|
||||
if (argc > 2) {
|
||||
sz = r_num_math (core->num, argv[2]);
|
||||
if (sz < 0) {
|
||||
R_LOG_ERROR ("%s is not a valid size", argv[2]);
|
||||
free (host_port);
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
addr = core->offset;
|
||||
}
|
||||
|
||||
@ -1501,181 +1510,163 @@ static int cmd_wt(void *data, const char *input_) {
|
||||
bool sockret = r_socket_write (sock, buf + sent, sz - sent);
|
||||
if (!sockret) {
|
||||
R_LOG_ERROR ("Socket write error");
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
R_LOG_ERROR ("Connection to %s failed", host_port);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
free (host_port);
|
||||
free (buf);
|
||||
r_socket_free (sock);
|
||||
break;
|
||||
goto leave;
|
||||
}
|
||||
case '?': // "wt?"
|
||||
case '\0': // "wt"
|
||||
r_core_cmd_help (core, help_msg_wt);
|
||||
break;
|
||||
}
|
||||
|
||||
r_str_argv_free (argv);
|
||||
|
||||
bool append = false;
|
||||
bool toend = false;
|
||||
st64 sz = core->blocksize;
|
||||
ut64 poff = core->offset;
|
||||
if (*input == 'f') { // "wtf"
|
||||
input++;
|
||||
if (*input == '?') {
|
||||
r_core_cmd_help (core, help_msg_wt);
|
||||
goto ret;
|
||||
}
|
||||
if (*input == '!') {
|
||||
if (input[1] == '?') {
|
||||
r_core_cmd_help (core, help_msg_wt);
|
||||
goto ret;
|
||||
case 'f': // "wtf"
|
||||
switch (input[1]) {
|
||||
case '?': // "wtf?"
|
||||
r_core_cmd_help_match (core, help_msg_wt, "wtf", true);
|
||||
ret = 1;
|
||||
goto leave;
|
||||
case '!': { // "wtf!"
|
||||
RIOMap *map;
|
||||
if (input[2] == '?') {
|
||||
r_core_cmd_help_match (core, help_msg_wt, "wtf!", true);
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
RIOMap *map = r_io_map_get_at (core->io, poff);
|
||||
toend = true;
|
||||
//use physical address
|
||||
poff = map ? poff - r_io_map_begin (map) + map->delta : poff;
|
||||
input++;
|
||||
}
|
||||
if (*input == 'f') { // "wtff"
|
||||
if (input[1] == '?') {
|
||||
r_core_cmd_help (core, help_msg_wt);
|
||||
goto ret;
|
||||
}
|
||||
const char *prefix = r_str_trim_head_ro (input + 2);
|
||||
if (!*prefix) {
|
||||
prefix = "dump";
|
||||
}
|
||||
input++;
|
||||
filename = r_str_newf ("%s-0x%08"PFMT64x, prefix, core->offset);
|
||||
free_filename = true;
|
||||
} else {
|
||||
if (*input) {
|
||||
if (input[1] == '?') {
|
||||
r_core_cmd_help (core, help_msg_wt);
|
||||
goto ret;
|
||||
}
|
||||
filename = (char *)r_str_trim_head_ro (input);
|
||||
if (r_str_startswith (filename, "base64:")) {
|
||||
const char *encoded = filename + 7;
|
||||
char *decoded = (char *)sdb_decode (encoded, NULL);
|
||||
if (decoded) {
|
||||
filename = decoded;
|
||||
free_filename = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filename = "";
|
||||
}
|
||||
}
|
||||
} else if (*input == 'a') { // "wta"
|
||||
append = 1;
|
||||
input++;
|
||||
if (input[0] == ' ') {
|
||||
filename = input + 1;
|
||||
} else {
|
||||
const char* prefix = r_config_get (core->config, "cfg.prefixdump");
|
||||
snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, poff);
|
||||
filename = _fn;
|
||||
}
|
||||
} else if (*input != ' ') {
|
||||
const char* prefix = r_config_get (core->config, "cfg.prefixdump");
|
||||
snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, poff);
|
||||
filename = _fn;
|
||||
} else {
|
||||
filename = input + 1;
|
||||
}
|
||||
|
||||
if (R_STR_ISEMPTY (filename)) {
|
||||
const char* prefix = r_config_get (core->config, "cfg.prefixdump");
|
||||
snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, poff);
|
||||
filename = _fn;
|
||||
}
|
||||
map = r_io_map_get_at (core->io, poff);
|
||||
if (map) {
|
||||
// convert vaddr to paddr
|
||||
poff = poff - r_io_map_begin (map) + map->delta;
|
||||
}
|
||||
|
||||
size_sep = *input? strchr (input + 1, ' '): NULL;
|
||||
|
||||
/* TODO: I think this logic can be cleaned up, size_sep looks tacked-on */
|
||||
if (size_sep) {
|
||||
if (toend) {
|
||||
sz = r_io_fd_size (core->io, core->io->desc->fd) - core->offset;
|
||||
if (sz < 0) {
|
||||
eprintf ("Warning: File size is unknown.\n");
|
||||
}
|
||||
} else {
|
||||
sz = (st64) r_num_math (core->num, size_sep + 1);
|
||||
/* Don't attempt to write if we can't parse size */
|
||||
if (sz < 1) {
|
||||
eprintf ("%s is not a valid size.\n", size_sep + 1);
|
||||
sz = -1;
|
||||
}
|
||||
*size_sep = '\0';
|
||||
}
|
||||
|
||||
// XXX: this branch didn't handle aliases at all before
|
||||
// but im not fixing the duplication rn
|
||||
if (*filename == '$') {
|
||||
if (append) {
|
||||
if (sz > 0 && r_cmd_alias_append_raw (core->rcmd, filename+1, core->block, sz)) {
|
||||
const char *fn = r_str_trim_head_ro (filename + 1);
|
||||
eprintf ("Alias \"$%s\" is a command - will not attempt to append.\n", fn);
|
||||
}
|
||||
} else {
|
||||
if (sz > 0) {
|
||||
r_cmd_alias_set_raw (core->rcmd, filename+1, core->block, sz);
|
||||
// ignore given size
|
||||
if (argc > 2) {
|
||||
argc = 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'f': // "wtff"
|
||||
if (input[2] == '?') {
|
||||
r_core_cmd_help_match (core, help_msg_wt, "wtff", true);
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
prefix = argv[1];
|
||||
}
|
||||
|
||||
default_filename_sep = '-';
|
||||
break;
|
||||
default: // "wtf"
|
||||
if (input[2] == '?') {
|
||||
r_core_cmd_help_match (core, help_msg_wt, "wtf", true);
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (r_str_startswith (filename, "base64:")) {
|
||||
const char *encoded = filename + 7;
|
||||
int len = r_base64_decode ((ut8 *)fn_local, encoded, sizeof (fn_local));
|
||||
// prevent string overrun
|
||||
fn_local[31] = 0;
|
||||
|
||||
if (len < 32) {
|
||||
filename = fn_local;
|
||||
} else {
|
||||
R_LOG_WARN ("Couldn't decode b64 filename");
|
||||
R_LOG_WARN ("Ensure it correctly decodes to less than 32 characters");
|
||||
filename = "";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* XXX: r_core_dump vs r_file_dump below? */
|
||||
if (sz > 0 && !r_core_dump (core, filename, poff, (ut64)sz, append)) {
|
||||
sz = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
append = true;
|
||||
break;
|
||||
case '\0': // "wt"
|
||||
case ' ': // "wt "
|
||||
break;
|
||||
case '?': // "wt?"
|
||||
default:
|
||||
r_core_cmd_help (core, help_msg_wt);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
// default filename is prefix.addr
|
||||
if (R_STR_ISEMPTY (filename)) {
|
||||
snprintf (fn_local, sizeof (fn_local), "%s%c0x%08" PFMT64x,
|
||||
prefix, default_filename_sep, poff);
|
||||
filename = fn_local;
|
||||
}
|
||||
|
||||
// don't overwrite forced size
|
||||
if (sz == core->blocksize && argc > 2) {
|
||||
sz = (st64)r_num_math (core->num, argv[2]);
|
||||
}
|
||||
|
||||
// Don't attempt to write 0 bytes
|
||||
if (sz < 1) {
|
||||
R_LOG_ERROR ("%s is not a valid size", argv[2]);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (*filename == '$') {
|
||||
ut8 *buf = core->block;
|
||||
bool free_buf = false;
|
||||
|
||||
filename++;
|
||||
|
||||
// manual buffer if given arbitrary size
|
||||
if (sz > core->blocksize) {
|
||||
buf = malloc (sz);
|
||||
if (!buf) {
|
||||
R_LOG_ERROR ("malloc() failure");
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
r_io_read_at (core->io, poff, buf, sz);
|
||||
free_buf = true;
|
||||
}
|
||||
|
||||
if (append) {
|
||||
if (r_cmd_alias_append_raw (core->rcmd, filename, buf, sz)) {
|
||||
R_LOG_ERROR ("Will not append to command alias \"$%s\"", filename);
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
if (toend) {
|
||||
sz = r_io_fd_size (core->io, core->io->desc->fd);
|
||||
if (sz < 0) {
|
||||
eprintf ("Warning: File size is unknown.\n");
|
||||
}
|
||||
if (sz != -1 && core->offset <= sz) {
|
||||
sz -= core->offset;
|
||||
if (!r_core_dump (core, filename, core->offset, (ut64)sz, append)) {
|
||||
sz = -1;
|
||||
}
|
||||
} else {
|
||||
sz = -1;
|
||||
}
|
||||
} else {
|
||||
if (*filename == '$') {
|
||||
if (append) {
|
||||
if (r_cmd_alias_append_raw (core->rcmd, filename+1, core->block, sz)) {
|
||||
eprintf ("Alias \"$%s\" is a command - will not attempt to append.\n", filename+1);
|
||||
}
|
||||
} else {
|
||||
r_cmd_alias_set_raw (core->rcmd, filename+1, core->block, sz);
|
||||
}
|
||||
} else {
|
||||
if (sz > 0 && !r_file_dump (filename, core->block, sz, append)) {
|
||||
sz = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
r_cmd_alias_set_raw (core->rcmd, filename, buf, sz);
|
||||
}
|
||||
if (sz >= 0) {
|
||||
eprintf ("Dumped %" PFMT64d " bytes from 0x%08" PFMT64x" into %s\n",
|
||||
sz, poff, filename);
|
||||
|
||||
if (free_buf) {
|
||||
free (buf);
|
||||
}
|
||||
goto leave;
|
||||
}
|
||||
ret:
|
||||
free (original_input);
|
||||
if (free_filename) {
|
||||
free (filename);
|
||||
|
||||
// use core if reading past end of block
|
||||
if (sz <= core->blocksize) {
|
||||
ret = r_file_dump (filename, core->block, sz, append);
|
||||
} else {
|
||||
ret = r_core_dump (core, filename, poff, (ut64)sz, append);
|
||||
}
|
||||
return 0;
|
||||
|
||||
// dump functions return bool; true on success
|
||||
if (ret) {
|
||||
R_LOG_INFO ("Dumped %" PFMT64d " bytes from 0x%08" PFMT64x" into %s", sz, poff, filename);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
leave:
|
||||
r_str_argv_free (argv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmd_ww(void *data, const char *input) {
|
||||
@ -2226,7 +2217,7 @@ static int cmd_write(void *data, const char *input) {
|
||||
cmd_wz (core, input + 1);
|
||||
break;
|
||||
case 't': // "wt"
|
||||
cmd_wt (core, input + 1);
|
||||
cmd_wt (core, input);
|
||||
break;
|
||||
case 'f': // "wf"
|
||||
cmd_wf (core, input + 1);
|
||||
|
@ -205,7 +205,7 @@ s 0x100
|
||||
w6d ANqmyJXUINu0P3rTV/v+0dffk9F3VNMfk7DuNot7wItWZlTrOnTG7rRAwQs7v90SnnDjFsW3NVhnI47yn09+9bXS4PBGpt765qAGIV/jM/5TFxQYzklwNWz/KAtOpgADeODzvobSuWxyv43RosHP9djjDqYsftuZfQOky6mlzyGFwuAMlJl4BlgG2PrHp++fi/1Ft3wgUPkk9cXNmpTvH1bPK+topPHAqsm6cXGpEPynVbMjdQQcmfnhZ5N1VrLMJd63jYKoTSxyB53jsK3fVwKSeneWlxGPeHgi7s7VuvOzcYA1Gc1hi9T+boSrTdyt4FYkdu01BmatKFR7/Q5usA==
|
||||
wtff $d
|
||||
w0 256
|
||||
wff $d-0x00000100
|
||||
wff $d
|
||||
p8 256
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
|
@ -248,7 +248,7 @@ EXPECT=<<EOF
|
||||
1024
|
||||
EOF
|
||||
EXPECT_ERR=<<EOF
|
||||
Dumped 1024 bytes from 0x00000000 into a_piece_of_ls_saved_to_PWD
|
||||
INFO: Dumped 1024 bytes from 0x00000000 into a_piece_of_ls_saved_to_PWD
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user