From 26fcb804d2194f825b3df7492735a516a1af441d Mon Sep 17 00:00:00 2001 From: pancake Date: Mon, 29 Apr 2024 12:50:42 +0200 Subject: [PATCH 1/2] WIP: Fix R_ARM_CALL relocs --- libr/bin/format/elf/elf.c | 3 ++ libr/bin/p/bin_elf.inc.c | 71 +++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/libr/bin/format/elf/elf.c b/libr/bin/format/elf/elf.c index e9b8bebfd3a24..4dd1992f37be5 100644 --- a/libr/bin/format/elf/elf.c +++ b/libr/bin/format/elf/elf.c @@ -1647,6 +1647,9 @@ static ut64 get_import_addr_arm(ELFOBJ *eo, RBinElfReloc *rel) { const ut64 pos = COMPUTE_PLTGOT_POSITION (rel, got_addr, 0x3); switch (rel->type) { + case R_ARM_CALL: + // never reached + break; case R_ARM_JUMP_SLOT: plt_addr += pos * 12 + 20; if (plt_addr & 1) { diff --git a/libr/bin/p/bin_elf.inc.c b/libr/bin/p/bin_elf.inc.c index 12ff57afad665..18e2e3c2c5331 100644 --- a/libr/bin/p/bin_elf.inc.c +++ b/libr/bin/p/bin_elf.inc.c @@ -468,6 +468,7 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) { r_return_val_if_fail (eo && rel, NULL); ut64 B = eo->baddr; ut64 P = rel->rva; // rva has taken baddr into account + ut64 G = got_addr; RBinReloc *r = R_NEW0 (RBinReloc); if (!r) { return NULL; @@ -509,8 +510,8 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) { case R_386_GLOB_DAT: SET(32); break; case R_386_JMP_SLOT: SET(32); break; case R_386_RELATIVE: ADD(32, B); break; - case R_386_GOTOFF: ADD(32, -(st64)got_addr); break; - case R_386_GOTPC: ADD(32, got_addr - P); break; + case R_386_GOTOFF: ADD(32, -(st64)G); break; + case R_386_GOTPC: ADD(32, G- P); break; case R_386_16: ADD(16, 0); break; case R_386_PC16: ADD(16,-(st64)P); break; case R_386_8: ADD(8, 0); break; @@ -529,7 +530,7 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) { case R_X86_64_NONE: break; // malloc then free. meh. then again, there's no real world use for _NONE. case R_X86_64_64: ADD(64, 0); break; case R_X86_64_PLT32: ADD(32,-(st64)P /* +L */); break; - case R_X86_64_GOT32: ADD(32, got_addr); break; + case R_X86_64_GOT32: ADD(32, G); break; case R_X86_64_PC32: ADD(32,-(st64)P); break; case R_X86_64_GLOB_DAT: r->vaddr -= rel->sto; SET(64); break; case R_X86_64_JUMP_SLOT: r->vaddr -= rel->sto; SET(64); break; @@ -563,9 +564,25 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) { case R_ARM_JUMP_SLOT: ADD(32, 0); break; case R_ARM_COPY: ADD(32, 0); break; // copy symbol at runtime case R_ARM_RELATIVE: ADD(32, B); break; - case R_ARM_GOTOFF: ADD(32,-(st64)got_addr); break; - case R_ARM_GOTPC: ADD(32, got_addr - P); break; - case R_ARM_CALL: ADD(24, -(st64)P); break; + case R_ARM_GOTOFF: ADD(32,-(st64)G); break; + case R_ARM_GOTPC: ADD(32, G - P); break; + case R_ARM_CALL: // ADD(24, got_addr -P); + // eprintf ("CAL %llx\n", got_addr); + // eprintf ("CAL %llx\n", P); + // SET(24); + // P = address of bl instruction to patch + r->type = R_BIN_RELOC_24; + if (G == UT64_MAX) { + r->addend = B-P; // 171295; + eprintf( "jeje 0x%x 0x%x\n", P, B); + } else { + r->addend = got_addr -P; + } + rel->addend = r->addend; + // rel->addend = 685182 /4; // 171295 + r->additive = DT_RELA; + return r; + break; case R_ARM_JUMP24: ADD(24, -(st64)P); break; case R_ARM_THM_JUMP24: ADD(24, -(st64)P); break; case R_ARM_PREL31: ADD(32, -(st64)P); break; @@ -786,14 +803,46 @@ static void _patch_reloc(ELFOBJ *bo, ut16 e_machine, RIOBind *iob, RBinElfReloc } break; case EM_ARM: - if (!rel->sym && rel->mode == DT_REL) { + if (rel->type == R_ARM_CALL) { + // read original bytes of the "bl" instruction iob->read_at (iob->io, rel->rva, buf, 4); - V = r_read_ble32 (buf, bo->endian); + V = r_read_le32 (buf); + + int delta = A; + if (rel->rva == 0x08001ec8) { + eprintf ("DELTA = %llx\n",A); + } + delta &= 0xfffff; +#if 0 + if (rel->rva == 0x08001ec8) { + eprintf ("RAW DELTA 0x%llx -> %llx\n", P, delta); + eprintf ("V 0x%llx + %d\n", P , delta); + } + // delta = 685182 / 4; + #endif +#if 1 + V+=delta; + V &= 0xffffff; + V |= (0xeb << 24); +#endif + // eprintf ("DELTA %x %x %x = %d\n", B ,P, L, delta); + // V += (1 << 24); // (rel->rva - (S/2) / 4); + r_write_le32 (buf, V); + if (rel->rva == 0x08001ec8) { + eprintf ("delta = %d\n", delta); + } + iob->overlay_write_at (iob->io, rel->rva, buf, 4); + // ignored } else { - V = S + A; + if (!rel->sym && rel->mode == DT_REL) { + iob->read_at (iob->io, rel->rva, buf, 4); + V = r_read_ble32 (buf, bo->endian); + } else { + V = S + A; + } + r_write_le32 (buf, V); + iob->overlay_write_at (iob->io, rel->rva, buf, 4); } - r_write_le32 (buf, V); - iob->overlay_write_at (iob->io, rel->rva, buf, 4); break; case EM_AARCH64: V = S + A; From 144b79daebb82c968999277ffd22f5dd945eb976 Mon Sep 17 00:00:00 2001 From: pancake Date: Tue, 30 Apr 2024 12:37:59 +0200 Subject: [PATCH 2/2] wip --- libr/bin/format/elf/elf.c | 32 +++++++++++++++++++++++++++----- libr/bin/p/bin_elf.inc.c | 33 +++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/libr/bin/format/elf/elf.c b/libr/bin/format/elf/elf.c index 4dd1992f37be5..2ac97095a8f1c 100644 --- a/libr/bin/format/elf/elf.c +++ b/libr/bin/format/elf/elf.c @@ -5275,6 +5275,8 @@ static bool reloc_fill_local_address(ELFOBJ *eo) { GotPltBounds ri = {0}; RBinElfSection *s; + ut64 di0 = UT64_MAX; + ut64 di1 = UT64_MAX; // find got/plt section bounadries r_vector_foreach (&eo->g_sections, s) { if (!strcmp (s->name, ".got")) { @@ -5282,8 +5284,14 @@ static bool reloc_fill_local_address(ELFOBJ *eo) { ri.got_min = s->offset; ri.got_max = s->offset + s->size; ri.got_va = s->rva; - } - if (!strcmp (s->name, ".plt")) { +#if 1 + } else if (!strcmp (s->name, ".debug_info")) { + // di0 = s->rva; + // di1 = s->rva + s->size; + di0 = s->offset; + di1 = s->offset + s->size; +#endif + } else if (!strcmp (s->name, ".plt")) { ri.plt_min = s->offset; ri.plt_max = s->offset + s->size; ri.plt_va = s->rva; @@ -5294,7 +5302,9 @@ static bool reloc_fill_local_address(ELFOBJ *eo) { } } if (!ri.got || !ri.plt) { - return false; + if (di0 == UT64_MAX) { + return false; + } } ut64 baddr = eo->user_baddr; // 0x10000; if (baddr == UT64_MAX) { @@ -5304,13 +5314,22 @@ static bool reloc_fill_local_address(ELFOBJ *eo) { // resolve got and plt r_vector_foreach (&eo->g_relocs, reloc) { const ut64 raddr = reloc->offset; + if (!ri.got && !ri.plt) { + index++; + ut64 ra = baddr + di0 + (index * 4); + ra += 685182; + reloc->addend = 0; // index; + // reloc->rva = ra + baddr; // address to patch + reloc->laddr = ra; + continue; + } if (raddr < ri.got_min || raddr >= ri.got_max) { continue; } ut64 rvaddr = reloc->offset; // rva (eo, reloc->offset, reloc->rva); ut64 pltptr = 0; // relocated buf tells the section to look at #if R_BIN_ELF64 - r_buf_read_at (eo->b, rvaddr, (ut8*)&pltptr, 8); + r_buf_read_at (eo->b, rvaddr, (ut8*)&pltptr, 8); #else ut32 n32 = 0; r_buf_read_at (eo->b, rvaddr, (ut8*)&n32, 4); @@ -5334,7 +5353,6 @@ static bool reloc_fill_local_address(ELFOBJ *eo) { #else index++; #endif - // TODO: if (reloc->type == 22) { // on arm! // extra check of bounds ut64 naddr = baddr + pltptr + (index * 12) + 0x20; if (reloc->type == 1026) { naddr = baddr + pltptr + (index * 16) + 64 - 16; @@ -5345,6 +5363,10 @@ static bool reloc_fill_local_address(ELFOBJ *eo) { } else { R_LOG_DEBUG ("Cannot resolve reloc reference"); } + } else { + index++; + ut64 naddr = baddr + (index * 12) + 0x20; + reloc->laddr = naddr; } } } diff --git a/libr/bin/p/bin_elf.inc.c b/libr/bin/p/bin_elf.inc.c index 18e2e3c2c5331..ac567739696e9 100644 --- a/libr/bin/p/bin_elf.inc.c +++ b/libr/bin/p/bin_elf.inc.c @@ -567,18 +567,18 @@ static RBinReloc *reloc_convert(ELFOBJ* eo, RBinElfReloc *rel, ut64 got_addr) { case R_ARM_GOTOFF: ADD(32,-(st64)G); break; case R_ARM_GOTPC: ADD(32, G - P); break; case R_ARM_CALL: // ADD(24, got_addr -P); - // eprintf ("CAL %llx\n", got_addr); - // eprintf ("CAL %llx\n", P); - // SET(24); - // P = address of bl instruction to patch r->type = R_BIN_RELOC_24; if (G == UT64_MAX) { r->addend = B-P; // 171295; - eprintf( "jeje 0x%x 0x%x\n", P, B); + eprintf( "jeje 0x%x 0x%x\n", P, got_addr); } else { + eprintf( "joje 0x%x 0x%x\n", P, got_addr); r->addend = got_addr -P; } - rel->addend = r->addend; + // r->addend = 0x08004dad; + r->addend = 0x00004dad; + // rel->laddr += 685182; + rel->addend = r->addend + rel->laddr; // rel->addend = 685182 /4; // 171295 r->additive = DT_RELA; return r; @@ -746,7 +746,13 @@ static RList* relocs(RBinFile *bf) { if (got_addr == UT64_MAX && eo->ehdr.e_type == ET_REL) { got_addr = Elf_(get_section_addr) (eo, ".got.r2"); } - +#if 0 + if (got_addr == UT64_MAX) { + // XXX + got_addr = Elf_(get_section_addr) (eo, ".debug_info"); + // got_addr = 0x08001e60; + } +#endif const RVector *relocs = Elf_(load_relocs) (eo); if (!relocs) { return ret; @@ -761,9 +767,9 @@ static RList* relocs(RBinFile *bf) { r_vector_foreach (relocs, reloc) { RBinReloc *already_inserted = ht_up_find (reloc_ht, reloc->rva, NULL); if (already_inserted) { + R_LOG_DEBUG ("Reloc already inserted at 0x%08"PFMT64x, reloc->rva); continue; } - RBinReloc *ptr = reloc_convert (eo, reloc, got_addr); if (ptr && ptr->paddr != UT64_MAX) { r_list_append (ret, ptr); @@ -795,23 +801,22 @@ static void _patch_reloc(ELFOBJ *bo, ut16 e_machine, RIOBind *iob, RBinElfReloc case EM_S390: switch (rel->type) { case R_390_GLOB_DAT: // globals - iob->overlay_write_at (iob->io, rel->rva, buf, 8); - break; - case R_390_RELATIVE: + case R_390_RELATIVE: // pic iob->overlay_write_at (iob->io, rel->rva, buf, 8); break; } break; case EM_ARM: if (rel->type == R_ARM_CALL) { + eprintf ("one\n"); // read original bytes of the "bl" instruction iob->read_at (iob->io, rel->rva, buf, 4); V = r_read_le32 (buf); int delta = A; - if (rel->rva == 0x08001ec8) { +// if (rel->rva == 0x08001ec8) { eprintf ("DELTA = %llx\n",A); - } +// } delta &= 0xfffff; #if 0 if (rel->rva == 0x08001ec8) { @@ -995,7 +1000,7 @@ static void _patch_reloc(ELFOBJ *bo, ut16 e_machine, RIOBind *iob, RBinElfReloc V = B + A; break; default: - //eprintf ("relocation %d not handle at this time\n", rel->type); + R_LOG_WARN ("relocation %d not handle at this time", rel->type); break; } switch (word) {