Refactor cmd_wt()

This commit is contained in:
Lazula 2022-07-23 16:39:03 -05:00 committed by pancake
parent 65ff60cf02
commit 4ce57c06a8
3 changed files with 175 additions and 184 deletions

View File

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

View File

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

View File

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