Distinguish .Shstrtab and .Strtab in Elf File

Distinguish .shstrtab and .strtab in ELF file

From the same docs: e_shstrndx: This member [in ElfN_Ehdr] holds the section header table index of the entry associated with the section name string table. If the file has no section name string table, this member holds the value SHN_UNDEF.

How to find `.strtab` in an ELF file?


How can I get the index of .strtab?

You read the Elf64_Shdrs one by one. When you've read the 28th entry, you will have read the .strtab, and you'll know its index.

You'll know that it's the .strtab section by comparing its name with ".strtab" string literal.

(You are probably intending to ask a different question, but if that's the case, you haven't expressed it well.)

Update:

Can't I do anything else rather than comparing strings

Maybe. If your real question is finding the .strtab section, then not really.

(which is somehow hard) can I assume it will be the first STRTAB in the file for example?

There is no guarantee that that will be the case.

Note: if you are worried about the speed of strcmp(), note that you can only do that strcmp() when .sh_type == SHT_STRTAB, and since there are usually at most two such sections in any given file, the concern about the speed of strcmp() is likely misplaced. Your code would look something like:

  if (shdr.sh_type == SHT_STRTAB) {
const char *sh_name = contents_of_shstrab + shdr.sh_name;
if (strcmp(sh_name, ".strtab") == 0) {
/* found .strtab; do whatever you need with it */
}
}

Update 2:

your solution is wrong, please see: http://stackoverflow.com/questions/68074508/

You can't claim that my solution is wrong, since I haven't provided a complete solution. It is also not wrong.

Here is complete code (with most error checking omitted):

#include <elf.h>
#include <fcntl.h>
#include <link.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
if (argc < 1) return 1;

int fd = open(argv[1], O_RDONLY);
if (fd == -1) return 2;

struct stat st_buf;
if (fstat(fd, &st_buf) != 0) return 3;

char *data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data == MAP_FAILED) return 4;

const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr) *)data;
const ElfW(Shdr) *shdr = (const ElfW(Shdr) *)(data + ehdr->e_shoff);

const char *shstrtab = data + shdr[ehdr->e_shstrndx].sh_offset;

for (int j = 0; j < ehdr->e_shnum; j++) {
printf("[%2d] %s\n", j, shstrtab + shdr[j].sh_name);
}

return 0;
}
$ gcc -g t.c -Wall
$ ./a.out ./a.out
[ 0]
[ 1] .interp
[ 2] .note.gnu.build-id
[ 3] .note.ABI-tag
[ 4] .gnu.hash
[ 5] .dynsym
[ 6] .dynstr
...
[32] .symtab
[33] .strtab
[34] .shstrtab

Reading ELF String Table on Linux from C

I was able to find out the answer myself :). Although it took a lot of time to code. Here is how it is done if someone wants to refer it for future -
Each Binary generally contains three String tables -

1. .dynstr
2. .shstrtab
3. .strtab

IN the above question we are concerned with .shstrtab which when expanded stands for - Section Header STRing TABle. Upon reading the ELF header we find the following field in ELF header - e_shstrndx. This is the index where we can find .shstrtab. Following formula can be used to calculate how it will be done -

offset = ((elfHdr.e_shstrndx)*elfHdr.e_shentsize)+elfHdr.e_shoff

Meaning of each parameter -

elfHdr.e_shstrndx = index where we can find .shstrtab
elfHdr.e_shentsize = Size of each Section Header
elfHdr.e_shoff = Offset at which section header starts.

How are strings encoded in an ELF file?

It's because the strings aren't being stored as static data.

For example if you had this:

const char* password = "a big refreshing lemonade";

Or even this:

static char password[] = "a big refreshing lemonade";

It is stored contiguously in the binary (You see "a big refreshing lemonade" next to each other) in the constants section.

If you look at the assembly output, you see this:

 6:test.c        ****     char password[] = "a big refreshing lemonade";
23 .loc 1 6 0
24 001e 48B86120 movabsq $7309940773697495137, %rax
24 62696720
24 7265
25 0028 48BA6672 movabsq $7453010330678293094, %rdx
25 65736869
25 6E67
26 0032 488945D0 movq %rax, -48(%rbp)
27 0036 488955D8 movq %rdx, -40(%rbp)
28 003a 48B8206C movabsq $7233183901389515808, %rax
28 656D6F6E
28 6164
29 0044 488945E0 movq %rax, -32(%rbp)
30 0048 66C745E8 movw $101, -24(%rbp)
30 6500

Where you see a lot of movabsq, which loads a 64 bit constant. So, what it does load 8 bytes at a time into password.

You'll notice that the first constant (7309940773697495137) is the little-endian form of "a big re"

Understanding ELF TBSS and TDATA section loading

Although the size of TLS here is 0xb12a. The alignment of 0x8 will make the TLS pointer move to 0xb130 which is the address of variable observed here.



Related Topics



Leave a reply



Submit