How can I find the offset of the .got section in an ELF file that I'm parsing?
I don't want to search the section by name, because I don't want to depend on it. When I change the section names with something else, the binaries still work.
Short answer: in the general case, you can't.
The linking view of the process is given by the section header table. The GOT can be located by:
$ readelf -S $elf [...] Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [29] .got PROGBITS 00000000003a2d80 001a2d80 0000000000000278 0000000000000008 WA 0 0 8 [30] .got.plt PROGBITS 00000000003a3000 001a3000 0000000000000078 0000000000000008 WA 0 0 8
You can only recognise the GOT because of the section name (which could really be anything). The GOT entries are using SHT_PROGBITS (like many other bits of the ELF file) so you cannot use the section type to recognize them.
Moreover, the section header table is not neeeded at runtime and needs not be present in the ELF file.
Can we use the execution view instead?
The execution view is given by the program header table. However, in the program header table, there is no real notion of (non-PLT) GOT. The runtime does not care where the GOT entries are located. They could just as well be scattered anywhere in the data segment*. All that matters is that the correct relocations are present in the (runtime) relocation table.
The dynamic linker needs to be told where are the PLT GOT entries (.got.plt
). This is given by the DT_PLTGOT
entry of the dynamic section. However, it only gives the (runtime, virtual memory) location of the beginning of the GOT PLT table: you do not have the size of it.
You might try to inspect the relocation tables:
you should be able to infer the size of the PLT GOT by looking at the PLT relocations;
you might be able to infer the location and size of the non-PLT GOT by looking at the non-PLT relocations.
If I'm looking at the non PLT relocation table of libc (on x86_64), I get a bunch of R_X86_64_GLOB_DAT
entries:
$ readelf -r $elf [...] 0000003a2da0 052c00000006 R_X86_64_GLOB_DAT 00000000003a4708 stderr + 0 0000003a2da8 061400000006 R_X86_64_GLOB_DAT 00000000003a85d0 error_one_per_line + 0 0000003a2db0 06eb00000006 R_X86_64_GLOB_DAT 00000000003a57d0 __malloc_initialize_ho + 0 0000003a2db8 07f300000006 R_X86_64_GLOB_DAT 00000000003a4720 __morecore + 0 0000003a2dc8 02a400000006 R_X86_64_GLOB_DAT 00000000003a8998 __key_encryptsession_p + 0 0000003a2dd0 061000000006 R_X86_64_GLOB_DAT 00000000003a3ec8 __progname_full + 0 0000003a2dd8 049c00000006 R_X86_64_GLOB_DAT 00000000003a4010 __ctype32_tolower + 0 0000003a2de0 011900000006 R_X86_64_GLOB_DAT 00000000003a5fb8 _environ + 0 0000003a2de8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 _rtld_global + 0 0000003a2df0 011000000006 R_X86_64_GLOB_DAT 00000000003a3ec0 __progname + 0 0000003a2df8 04ff00000006 R_X86_64_GLOB_DAT 00000000003a32c4 argp_err_exit_status + 0 0000003a2e08 04ce00000006 R_X86_64_GLOB_DAT 00000000003a8538 mallwatch + 0 0000003a2e10 00bc00000006 R_X86_64_GLOB_DAT 00000000003a87d8 __rcmd_errstr + 0 0000003a2e18 056400000006 R_X86_64_GLOB_DAT 00000000003a48e0 __vdso_clock_gettime + 0 [...]
We nearly find the address of the non-PLT GOT:
$ readelf -S $elf [...] [29] .got PROGBITS 00000000003a2d80 001a2d80 0000000000000278 0000000000000008 WA 0 0 8
There are 4 missing GOT entries (I don't know why…).
(*): This means that there might not even be any (non-PLT) GOT.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With