Moving the ELF64 relocation table - shared-libraries

I'm attempting to move the .rela.plt relocation table of a shared object to the end of the file (Because I'm going to add new relocation entries in the future).
First, I read all entries in the .rela.plt section. The original section is at offset 0x528, and .rela.dyn is at 0x600. Then I copy the contents of .rela.dyn at the end of the file; to the offset 0xa528. I update the section header table entry for .rela.dyn by adding 0xa000 to both the sh_addr and sh_offset fields. I update the DT_RELA entry in the dynamic table with the new address; and finally I add a LOAD segment (with permissions RWX) to the end of the program header table.
As a result, R_X86_64_RELATIVE entries in the relocation table are resolved correctly; but the dynamic linker does not update the addresses for external calls in the GOT, therefore causing a segmentation fault. This does not happen in 32-bit shared objects.
What am I missing?

I solved the problem by adding the .rel.plt table right after the .rel.dyn table. That is, there should not be a single redundant byte in between; no alignment padding, no other sections, no whatever. The dynamic loader expects the relocation segments to be continuous for some reason. The JMPREL entry in the dynamic section seems redundant at x64.

Related

ELF section identification

In an ELF executable file, I over-wrote all the section names by zero-valued bytes. Even then, the file can be linked and executed correctly. How does the OS identify various sections like the symbols-table, etc. in the file? I was under the impression that the section names serve this purpose. A related question is that what is the use of section names then?
I over-wrote all the section names ...
... the file can be linked ... correctly.
Unlike the object files used in 32-bit Windows, the section names in ELF object files are ignored if no linker script is used.
Each "PROGBITS" section contains flags that specify if the section is writeable, executable and/or not even part of the image (debug information).
(Actually, the object files used by Windows also have such flags, but they are typically set to 0 and the section name is used to distinguish between code and data sections.)
For other section types (such as symbol tables) it is clear how they have to be handled anyway.
... the file can be ... executed correctly.
For executable files and shared libraries, the sections are ignored anyway. Instead, the "program headers" of the file are used.
A "program header" tells the OS that a certain address range in the file must be loaded to memory. A "program header" may cover multiple sections. And "program headers" don't have names.
Example:
Sections:
Name Address Offset in file Length
.text 0x10100 0x100 0x30 read-only
.rodata 0x10130 0x130 0x20 read-only
.data 0x20250 0x150 0x10 read-write
.sdata 0x20260 0x160 0x10 read-write
Program headers:
Address Offset in file Length
0x10100 0x100 0x50 read-only
0x20250 0x150 0x20 read-write

how to get absolute virtual addresses in Global Offset Table

after compiling code, my function(function name: overwriteFunc, symbol: _ZN4test13overwriteFuncEiml#plt).
It seems like I have address in Procedure Linkage Table. Then is there a way I could find my function absolute virtual address in Global offset table? Should I read some segment of private table of some .so, elf file?
Thanks

Modifying contents of data section in ELF

I have a program that initializes an array to 0. I have pointed the value of that array to a custom section using: __attribute__((section(".mysection")))
struct my_struct my_array[1] __attribute__((section(".mysection"))) = {
{0, 0},
};
The above is only so that we have a default and the linker marks the section as loadable and also includes it in the appropriate section list.
Now I wish to edit the generated ELF and modify the contents of that struct as I choose. I already have a binary file which contains the contents that I wish to have for that section.
I tried using --remove-section and --add-section but could not force the new section to be part of the sections.
Not sure if --update-section would help here, but the microcontroller I have doesn't have --update-section in objcopy and when I try the public version of it, that says that it doesnt support the bfd target.
FWIW, the ELF doesnt use any relocatable addresses etc. All addresses are physical addresses in memory.
Is there a way to achieve this? I just need to replace the contents of the section and modify its length.
In case other, more simple ways, are not suitable, you may implement such functionality by using ELFIO library.

Trouble using Libelf/Elfio libraries : ELF not executable anymore

I'm using Libelf and Elfio to try and add a new section to ELF files. I would like it to be executable, just like .text.
This is my problem : with Libelf, as soon as I load (elf_begin()), update (elf_update()) and release (elf_end()) my ELF, it stops to be executable (seg fault when launching). readelf -S displays the sections but returns also the error :
readelf: Warning: the .dynamic section is not contained within the dynamic segment
I didn't find any function in Libelf to "add" the .dynamic section to the DYNAMIC segment.
But I can do that with Elfio (with the segment->add_section_index() function), but then I have to manually add every other section to every other segment, as Elfio seems to overwrite them when loading the ELF.
Has anyone any experience with those libraries ?
My final goal is to be able to create a new executable section in the ELF, and modify its entry point to jump and execute directly that new section, in order to create a packer.
Libelf does not manage the segments (i. e. the program header entries) of an executable ELF file. It does, however, by default re-layout the sections when you call elf_update().
After the re-layout, the program header entries will most probably contain obsolete offsets.
The loader will then try (or refuse) to load sections from file offsets that were only correct before the edit.
Thus the error message: the .dynamic section is now at another offset in the file, and the loader notices that it is not in the DYNAMIC segment anymore.
You can tell Libelf that you are responsible for the section layout by calling elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT).
But then again, adding a new section will not be so easy anymore...

sprof "PLTREL not found error"

I'm trying to profile our shared library, but whenever I have the environmental variable LD_PROFILE set, I get "PLTREL not found in object ". What gives? Is there some sort of linker flag I'm missing or what? There seems to be no information about this on the internets. The man page for sprof is about 10 words long.
According to an unanswered question on Google Groups, it looks like you aren't the very first person with this problem.
I think pltrel means plt-relative; in some ELF design notes,
There is a .plt section created in the code segment, which is an array of function stubs used to handle the run-time resolution of library calls.
And here's yet a little more:
The next section I want to mention is the .plt section. This contains the jump table that is used when we call functions in the shared library. By default the .plt entries are all initialized by the linker not to point to the correct target functions, but instead to point to the dynamic loader itself. Thus, the first time you call any given function, the dynamic loader looks up the function and fixes the target of the .plt so that the next time this .plt slot is used we call the correct function. After making this change, the dynamic loader calls the function itself.
Sounds to me like there's an issue with how the shared library was compiled or assembled. Hopefully a few more searches to elf PLT section gets you on the right track.
Found this that may be relevante for you:
Known issues with LD_AUDIT
➢ LD_AUDIT does not work with Shared Libraries with no code in them.
➢ Example ICU-4.0 “libicudata.so”
➢ Error: “no PLTREL found in object /usr/lib/libicudata.so.40”
➢ Recompile after patching libicudata by sed'ing -nostdlib etc away sed -i --
"s/-nodefaultlibs -nostdlib//" config/mh-linux
It seems the same applies for LD_PROFILE

Resources