Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support resizing the BSS section with rabin2 -O ##bin #23003

Merged
merged 3 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 20 additions & 22 deletions libr/bin/bin_write.c
Original file line number Diff line number Diff line change
@@ -1,64 +1,62 @@
/* radare2 - LGPL - Copyright 2009-2019 - pancake, nibble */
/* radare2 - LGPL - Copyright 2009-2024 - pancake, nibble */

#include <r_types.h>
#include <r_util.h>
#include <r_bin.h>

/* XXX Implement r__bin_wr_scn_{ set, del } instead */
// R2_600 evaluate return bool here
R_API ut64 r_bin_wr_scn_resize(RBin *bin, const char *name, ut64 size) {
R_RETURN_VAL_IF_FAIL (bin, UT64_MAX);
R_RETURN_VAL_IF_FAIL (bin && name, UT64_MAX);
RBinFile *bf = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
if (plugin && plugin->write && plugin->write->scn_resize) {
return plugin->write->scn_resize (bf, name, size);
RBinWriteScnResize scn_resize = R_UNWRAP3 (plugin, write, scn_resize);
if (scn_resize) {
return scn_resize (bf, name, size);
}
return 0;
}

R_API bool r_bin_wr_scn_perms(RBin *bin, const char *name, int perms) {
R_RETURN_VAL_IF_FAIL (bin && name, false);
RBinFile *bf = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
if (plugin && plugin->write && plugin->write->scn_perms) {
return plugin->write->scn_perms (bf, name, perms);
RBinWriteScnPerms scn_perms = R_UNWRAP3 (plugin, write, scn_perms);
if (scn_perms) {
return scn_perms (bf, name, perms);
}
return false;
}

R_API bool r_bin_wr_rpath_del(RBin *bin) {
R_RETURN_VAL_IF_FAIL (bin, false);
RBinFile *bf = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
if (plugin && plugin->write && plugin->write->rpath_del) {
return plugin->write->rpath_del (bf);
}
return false;
RBinWriteRpathDel rpath_del = R_UNWRAP3 (plugin, write, rpath_del);
return rpath_del? rpath_del (bf): false;
}

R_API bool r_bin_wr_output(RBin *bin, const char *filename) {
r_return_val_if_fail (bin && filename, false);
R_RETURN_VAL_IF_FAIL (bin && filename, false);
RBinFile *bf = r_bin_cur (bin);
if (!bf || !bf->buf) {
return false;
}
ut64 tmpsz;
ut64 tmpsz = 0;
const ut8 *tmp = r_buf_data (bf->buf, &tmpsz);
return r_file_dump (filename, tmp, tmpsz, 0);
}

R_API bool r_bin_wr_entry(RBin *bin, ut64 addr) {
R_RETURN_VAL_IF_FAIL (bin, false);
RBinFile *bf = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
if (plugin && plugin->write && plugin->write->entry) {
return plugin->write->entry (bf, addr);
}
return false;
RBinWriteEntry entry = R_UNWRAP3 (plugin, write, entry);
return entry? entry (bf, addr): false;
}

R_API bool r_bin_wr_addlib(RBin *bin, const char *lib) {
R_RETURN_VAL_IF_FAIL (bin && lib, false);
RBinFile *bf = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
if (plugin && plugin->write && plugin->write->addlib) {
return plugin->write->addlib (bin->cur, lib);
}
return false;
RBinWriteAddLib addlib = R_UNWRAP3 (plugin, write, addlib);
return addlib? addlib (bin->cur, lib): false;
}
90 changes: 58 additions & 32 deletions libr/bin/format/elf/elf_write.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2010-2023 pancake, nibble */
/* radare - LGPL - Copyright 2010-2024 pancake, nibble */

#include <r_util.h>
#include "elf.h"
Expand All @@ -13,15 +13,15 @@ ut64 Elf_(resize_section)(RBinFile *bf, const char *name, ut64 size) {
Elf_(Phdr) *phdr = bin->phdr, *phdrp;
Elf_(Shdr) *shdr = bin->shdr, *shdrp;
const char *strtab = bin->shstrtab;
ut8 *buf;
ut64 off, got_offset = 0, got_addr = 0, rsz_offset = 0, delta = 0;
ut64 rsz_osize = 0, rsz_size = size, rest_size = 0;
int i, j, done = 0;

if (size == 0) {
eprintf ("0 size section?\n");
R_LOG_ERROR ("0 size section?");
return 0;
}
bool section_not_found = true;

/* calculate delta */
for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++) {
Expand All @@ -31,22 +31,33 @@ ut64 Elf_(resize_section)(RBinFile *bf, const char *name, ut64 size) {
}
const char *sh_name = &strtab[shdrp->sh_name];
if (sh_name && !strncmp (name, sh_name, ELF_STRING_LENGTH)) {
delta = rsz_size - shdrp->sh_size;
rsz_offset = (ut64)shdrp->sh_offset;
rsz_osize = (ut64)shdrp->sh_size;
section_not_found = false;
if (shdrp->sh_type == 8) {
// is virtual section. so we only need to patch the headers
delta = 0;
shdrp->sh_size = rsz_size;
off = ehdr->e_shoff + (i * sizeof (Elf_(Shdr)));
r_buf_write_at (bf->buf, off, (ut8*)shdrp, sizeof (Elf_(Shdr)));
return 0;
} else {
delta = rsz_size - shdrp->sh_size;
rsz_offset = (ut64)shdrp->sh_offset;
rsz_osize = (ut64)shdrp->sh_size;
}
break;
}
}

if (delta == 0) {
if (section_not_found) {
R_LOG_ERROR ("Cannot find section");
return 0;
}

eprintf ("delta: %"PFMT64d"\n", delta);
R_LOG_INFO ("File size delta: %"PFMT64d, delta);

/* rewrite rel's (imports) */
for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++) {
if (!strcmp (&strtab[shdrp->sh_name], ".got")) {
if (!strncmp (&strtab[shdrp->sh_name], ".got", ELF_STRING_LENGTH)) {
got_addr = (ut64)shdrp->sh_addr;
got_offset = (ut64)shdrp->sh_offset;
}
Expand All @@ -56,20 +67,20 @@ ut64 Elf_(resize_section)(RBinFile *bf, const char *name, ut64 size) {
}

for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++) {
if (!strcmp (&strtab[shdrp->sh_name], ".rel.plt")) {
if (!strncmp (&strtab[shdrp->sh_name], ".rel.plt", ELF_STRING_LENGTH)) {
Elf_(Rel) *rel, *relp;
rel = (Elf_(Rel) *)malloc (1 + shdrp->sh_size);
if (!rel) {
r_sys_perror ("malloc");
return 0;
}
if (r_buf_read_at (bin->b, shdrp->sh_offset, (ut8*)rel, shdrp->sh_size) == -1) {
r_sys_perror("read (rel)");
r_sys_perror ("read (rel)");
}
for (j = 0, relp = rel; j < shdrp->sh_size; j += sizeof (Elf_(Rel)), relp++) {
/* rewrite relp->r_offset */
if (relp->r_offset - got_addr + got_offset >= rsz_offset + rsz_osize) {
relp->r_offset+=delta;
relp->r_offset += delta;
off = shdrp->sh_offset + j;
if (r_buf_write_at (bin->b, off, (ut8*)relp, sizeof (Elf_(Rel))) == -1) {
r_sys_perror("write (imports)");
Expand All @@ -91,8 +102,8 @@ ut64 Elf_(resize_section)(RBinFile *bf, const char *name, ut64 size) {
for (j = 0, relp = rel; j < shdrp->sh_size; j += sizeof (Elf_(Rela)), relp++) {
/* rewrite relp->r_offset */
if (relp->r_offset - got_addr + got_offset >= rsz_offset + rsz_osize) {
relp->r_offset+=delta;
off = shdrp->sh_offset + j;
relp->r_offset += delta;
if (r_buf_write_at (bin->b, off, (ut8*)relp, sizeof (Elf_(Rela))) == -1) {
r_sys_perror("write (imports)");
}
Expand All @@ -105,20 +116,28 @@ ut64 Elf_(resize_section)(RBinFile *bf, const char *name, ut64 size) {

/* rewrite section headers */
for (i = 0, shdrp = shdr; i < ehdr->e_shnum; i++, shdrp++) {
if (!done && !strncmp (name, &strtab[shdrp->sh_name], ELF_STRING_LENGTH)) {
off = ehdr->e_shoff + (i * sizeof (Elf_(Shdr)));
if (!done && !strncmp (name, strtab + shdrp->sh_name, ELF_STRING_LENGTH)) {
R_LOG_INFO ("patching the virtual section size from %d to %d", shdrp->sh_size, rsz_size);
shdrp->sh_size = rsz_size;
done = 1;
r_buf_write_at (bf->buf, off + i, (ut8*)&shdrp, sizeof (Elf_(Shdr)));
done = true;
} else if (shdrp->sh_offset >= rsz_offset + rsz_osize) {
shdrp->sh_offset += delta;
if (shdrp->sh_addr) {
shdrp->sh_addr += delta;
}
}
off = ehdr->e_shoff + i * sizeof (Elf_(Shdr));
R_LOG_INFO ("patching write");
#if 0
r_buf_write_at (bf->buf, off, (ut8*)&shdrp, sizeof (Elf_(Shdr)));
#else
// TODO: write to bf->buf if the final bin needs to be patched
if (r_buf_write_at (bin->b, off, (ut8*)shdrp, sizeof (Elf_(Shdr))) == -1) {
r_sys_perror ("write (shdr)");
}
printf ("-> elf section (%s)\n", &strtab[shdrp->sh_name]);
#endif
R_LOG_DEBUG ("-> elf section (%s)", strtab + shdrp->sh_name);
}

/* rewrite program headers */
Expand Down Expand Up @@ -151,36 +170,43 @@ ut64 Elf_(resize_section)(RBinFile *bf, const char *name, ut64 size) {
/* rewrite other elf pointers (entrypoint, phoff, shoff) */
if (ehdr->e_entry - bin->baddr >= rsz_offset + rsz_osize) {
ehdr->e_entry += delta;
R_LOG_INFO ("patch entry");
}
if (ehdr->e_phoff >= rsz_offset + rsz_osize) {
ehdr->e_phoff += delta;
R_LOG_INFO ("patch phoff");
}
if (ehdr->e_shoff >= rsz_offset + rsz_osize) {
ehdr->e_shoff += delta;
R_LOG_INFO ("patch shoff");
}
R_LOG_INFO ("writing ehdr");
if (r_buf_write_at (bin->b, 0, (ut8*)ehdr, sizeof (Elf_(Ehdr))) == -1) {
r_sys_perror ("write (ehdr)");
}

/* inverse order to write bodies .. avoid overlapping here */
/* Inverse order to write bodies to avoid overlapping */
/* XXX Check when delta is negative */
rest_size = bin->size - (rsz_offset + rsz_osize);

buf = (ut8 *)malloc (1 + bin->size);
if (!buf) {
R_LOG_ERROR ("Cannot allocate %d", bin->size);
return 0;
if (delta == 0) {
R_LOG_INFO ("Size unchanged");
} else {
ut8 *buf = (ut8 *)malloc (1 + bin->size);
if (!buf) {
R_LOG_ERROR ("Cannot allocate %d", bin->size);
return 0;
}
r_buf_read_at (bin->b, 0, (ut8*)buf, bin->size);
r_buf_set_bytes (bin->b, (ut8*)buf, (int)(rsz_offset + rsz_size + rest_size));
printf ("COPY FROM 0x%08"PFMT64x"\n", (ut64)(rsz_offset + rsz_osize));
r_buf_read_at (bin->b, rsz_offset + rsz_osize, (ut8*)buf, rest_size);
printf ("COPY TO 0x%08"PFMT64x"\n", (ut64)(rsz_offset + rsz_size));
r_buf_write_at (bin->b, rsz_offset + rsz_size, (ut8*)buf, rest_size);
printf ("Shifted %d byte(s)\n", (int)delta);
bin->size = r_buf_size (bin->b);
free (buf);
}
r_buf_read_at (bin->b, 0, (ut8*)buf, bin->size);
r_buf_set_bytes (bin->b, (ut8*)buf, (int)(rsz_offset + rsz_size + rest_size));

printf ("COPY FROM 0x%08"PFMT64x"\n", (ut64)(rsz_offset + rsz_osize));
r_buf_read_at (bin->b, rsz_offset + rsz_osize, (ut8*)buf, rest_size);
printf ("COPY TO 0x%08"PFMT64x"\n", (ut64)(rsz_offset+rsz_size));
r_buf_write_at (bin->b, rsz_offset + rsz_size, (ut8*)buf, rest_size);
printf ("Shifted %d byte(s)\n", (int)delta);
free (buf);
bin->size = r_buf_size (bin->b);

return delta;
}
Expand Down
2 changes: 1 addition & 1 deletion libr/core/cmd_anal.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13488,13 +13488,13 @@ static int cmd_anal_all(RCore *core, const char *input) {
r_core_cmd0 (core, "aef@@F");
} else if (input[1] == 'r') {
ut64 cur = core->offset;
bool hasnext = r_config_get_b (core->config, "anal.hasnext");
RListIter *iter;
RIOMap *map;
RList *list = r_core_get_boundaries_prot (core, R_PERM_X, NULL, "anal");
if (!list) {
break;
}
bool hasnext = r_config_get_b (core->config, "anal.hasnext");
r_list_foreach (list, iter, map) {
r_core_seek (core, r_io_map_begin (map), true);
r_config_set_b (core->config, "anal.hasnext", true);
Expand Down
15 changes: 10 additions & 5 deletions libr/include/r_bin.h
Original file line number Diff line number Diff line change
Expand Up @@ -700,12 +700,17 @@ typedef struct r_bin_dbginfo_t {
bool (*get_line)(RBinFile *arch, ut64 addr, char *file, int len, int *line, int *column);
} RBinDbgInfo;

typedef bool (*RBinWriteAddLib)(RBinFile *bf, const char *lib);
typedef ut64 (*RBinWriteScnResize)(RBinFile *bf, const char *name, ut64 newsize);
typedef bool (*RBinWriteScnPerms)(RBinFile *bf, const char *name, int perms);
typedef bool (*RBinWriteEntry)(RBinFile *bf, ut64 addr);
typedef int (*RBinWriteRpathDel)(RBinFile *bf);
typedef struct r_bin_write_t {
ut64 (*scn_resize)(RBinFile *bf, const char *name, ut64 size); // R2_600 return bool instead
bool (*scn_perms)(RBinFile *bf, const char *name, int perms);
int (*rpath_del)(RBinFile *bf); // R2_600 return bool instead
bool (*entry)(RBinFile *bf, ut64 addr);
bool (*addlib)(RBinFile *bf, const char *lib);
RBinWriteScnResize scn_resize;
RBinWriteScnPerms scn_perms;
RBinWriteRpathDel rpath_del;
RBinWriteEntry entry;
RBinWriteAddLib addlib;
} RBinWrite;

typedef int (*RBinGetOffset)(RBin *bin, int type, int idx);
Expand Down
2 changes: 1 addition & 1 deletion libr/main/rabin2.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ typedef struct rabin2_state_t {
static int rabin_show_help(int v) {
printf ("Usage: rabin2 [-AcdeEghHiIjlLMqrRsSUvVxzZ] [-@ at] [-a arch] [-b bits] [-B addr]\n"
" [-C F:C:D] [-f str] [-m addr] [-n str] [-N m:M] [-P[-P] pdb]\n"
" [-o str] [-O str] [-k query] [-D lang mangledsymbol] file\n");
" [-o str] [-O help] [-k query] [-D lang mangledsymbol] file\n");
if (v) {
printf (
" -@ [addr] show section, symbol or import at addr\n"
Expand Down
28 changes: 14 additions & 14 deletions test/db/formats/dwarf
Original file line number Diff line number Diff line change
Expand Up @@ -721,20 +721,20 @@ colu: 12
addr: 0x00001149
EOF
EXPECT_ERR=<<EOF
DEBUG: [cbin.c:3368] (section .dynstr) Css 141 @ 0x480
DEBUG: [cbin.c:3368] (section .rela.dyn) Cd 8[24] @ 0x550
DEBUG: [cbin.c:3368] (section .rela.plt) Cd 8[3] @ 0x610
DEBUG: [cbin.c:3368] (section .init_array) Cd 8[1] @ 0x3db8
DEBUG: [cbin.c:3368] (section .fini_array) Cd 8[1] @ 0x3dc0
DEBUG: [cbin.c:3368] (section .dynamic) Cd 8[62] @ 0x3dc8
DEBUG: [cbin.c:3368] (section .got) Cd 8[9] @ 0x3fb8
DEBUG: [cbin.c:3368] (section .dynstr) Css 141 @ 0x480
DEBUG: [cbin.c:3368] (section .rela.dyn) Cd 8[24] @ 0x550
DEBUG: [cbin.c:3368] (section .rela.plt) Cd 8[3] @ 0x610
DEBUG: [cbin.c:3368] (section .init_array) Cd 8[1] @ 0x3db8
DEBUG: [cbin.c:3368] (section .fini_array) Cd 8[1] @ 0x3dc0
DEBUG: [cbin.c:3368] (section .dynamic) Cd 8[62] @ 0x3dc8
DEBUG: [cbin.c:3368] (section .got) Cd 8[9] @ 0x3fb8
DEBUG: [cbin.c:3375] (section .dynstr) Css 141 @ 0x480
DEBUG: [cbin.c:3375] (section .rela.dyn) Cd 8[24] @ 0x550
DEBUG: [cbin.c:3375] (section .rela.plt) Cd 8[3] @ 0x610
DEBUG: [cbin.c:3375] (section .init_array) Cd 8[1] @ 0x3db8
DEBUG: [cbin.c:3375] (section .fini_array) Cd 8[1] @ 0x3dc0
DEBUG: [cbin.c:3375] (section .dynamic) Cd 8[62] @ 0x3dc8
DEBUG: [cbin.c:3375] (section .got) Cd 8[9] @ 0x3fb8
DEBUG: [cbin.c:3375] (section .dynstr) Css 141 @ 0x480
DEBUG: [cbin.c:3375] (section .rela.dyn) Cd 8[24] @ 0x550
DEBUG: [cbin.c:3375] (section .rela.plt) Cd 8[3] @ 0x610
DEBUG: [cbin.c:3375] (section .init_array) Cd 8[1] @ 0x3db8
DEBUG: [cbin.c:3375] (section .fini_array) Cd 8[1] @ 0x3dc0
DEBUG: [cbin.c:3375] (section .dynamic) Cd 8[62] @ 0x3dc8
DEBUG: [cbin.c:3375] (section .got) Cd 8[9] @ 0x3fb8
WARN: [cbin.c:1904] Relocs has not been applied. Please use `-e bin.relocs.apply=true` or `-e bin.cache=true` next time
DEBUG: [cbin.c:2620] Cannot resolve symbol address __libc_start_main
DEBUG: [cbin.c:2620] Cannot resolve symbol address _ITM_deregisterTMCloneTable
Expand Down
Loading