fix elf segment address on an objcopy output binary

229 views Asked by At

I'm trying to inject some compiled code into an elf executable. The strategy is to write some bytes at the end of the 'code' segment. The reason why I chose that segment is because I need my payload to be executed too. I'd like to extend the segment by the required amount, when the padding between segments is too small, so that it can host my payload. objcopy can do that just fine with objcopy <exec> --update-section <name>=<file>.

My host will be section .fini, and the section after that one is .rodata. After executing objcopy, the code segment's file size and memory image size are the correct amount. Section and segment offsets are also patched when they need to be. And the code is present at the expected offset (confirmed by objdump).

My problem is that none of the segments' virtual addresses were patched, which causes the code segment to overlap on the next section/segment, which results in a segfault during _dl_start because the code is considered to be in a read-only segment. Below are some snippets from the output generated by readelf.

before objcopy:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [16] .fini             PROGBITS         00000000000a3e84  000a3e84
       0000000000000009  0000000000000000  AX       0     0     4
  [17] .rodata           PROGBITS         00000000000a4000  000a4000
       000000000003b488  0000000000000000   A       0     0     32

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000063000 0x0000000000063000 0x0000000000063000
                 0x0000000000040e8d 0x0000000000040e8d  R E    0x1000
  LOAD           0x00000000000a4000 0x00000000000a4000 0x00000000000a4000
                 0x0000000000043ccc 0x0000000000043ccc  R      0x1000

and after:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [16] .fini             PROGBITS         00000000000a3e84  000a3e84
       00000000000002bd  0000000000000000  AX       0     0     4
  [17] .rodata           PROGBITS         00000000000a4000  000a5000
       000000000003b488  0000000000000000   A       0     0     32

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000063000 0x0000000000063000 0x0000000000063000
                 0x0000000000041141 0x0000000000041141  R E    0x1000
  LOAD           0x00000000000a5000 0x00000000000a4000 0x00000000000a4000
                 0x0000000000043ccc 0x0000000000043ccc  R      0x1000

my system: Linux 6.1.0-13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.55-1 (2023-09-29) x86_64 GNU/Linux

Does anybody know how to further patch the binary to make it functional while still having a valid elf in the end?

1

There are 1 answers

2
Employed Russian On BEST ANSWER

Does anybody know how to further patch the binary to make it functional

This isn't going to work -- you have a linked binary, which means the linker has "baked" data addresses into code.

You wish to move data to a different address, but that requires updating all of the "baked in" addresses, and the info (relocations) needed to perform such an update has already been discarded.

What you need to do is add a new executable segment (sections don't matter at runtime), and put your payload into that new segment.