Various Sections of an ELF:

vagrant@kali:~$ readelf -S warehouse 
There are 30 section headers, starting at offset 0x11ac:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        08048134 000134 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4
  [ 3] .note.gnu.build-i NOTE            08048168 000168 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        0804818c 00018c 000024 04   A  5   0  4
  [ 5] .dynsym           DYNSYM          080481b0 0001b0 0000a0 10   A  6   1  4
  [ 6] .dynstr           STRTAB          08048250 000250 00007f 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          080482d0 0002d0 000014 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         080482e4 0002e4 000030 00   A  6   1  4
  [ 9] .rel.dyn          REL             08048314 000314 000010 08   A  5   0  4
  [10] .rel.plt          REL             08048324 000324 000038 08  AI  5  12  4
  [11] .init             PROGBITS        0804835c 00035c 000023 00  AX  0   0  4
  [12] .plt              PROGBITS        08048380 000380 000080 04  AX  0   0 16
  [13] .text             PROGBITS        08048400 000400 0002c2 00  AX  0   0 16
  [14] .fini             PROGBITS        080486c4 0006c4 000014 00  AX  0   0  4
  [15] .rodata           PROGBITS        080486d8 0006d8 00000b 00   A  0   0  4
  [16] .eh_frame_hdr     PROGBITS        080486e4 0006e4 000034 00   A  0   0  4
  [17] .eh_frame         PROGBITS        08048718 000718 0000e0 00   A  0   0  4
  [18] .init_array       INIT_ARRAY      080497f8 0007f8 000004 00  WA  0   0  4
  [19] .fini_array       FINI_ARRAY      080497fc 0007fc 000004 00  WA  0   0  4
  [20] .jcr              PROGBITS        08049800 000800 000004 00  WA  0   0  4
  [21] .dynamic          DYNAMIC         08049804 000804 0000e8 08  WA  6   0  4
  [22] .got              PROGBITS        080498ec 0008ec 000004 04  WA  0   0  4
  [23] .got.plt          PROGBITS        080498f0 0008f0 000028 04  WA  0   0  4
  [24] .data             PROGBITS        08049918 000918 000008 00  WA  0   0  4
  [25] .bss              NOBITS          08049920 000920 000008 00  WA  0   0  4
  [26] .comment          PROGBITS        00000000 000920 000039 01  MS  0   0  1
  [27] .shstrtab         STRTAB          00000000 000959 000106 00      0   0  1
  [28] .symtab           SYMTAB          00000000 000a60 000490 10     29  45  4
  [29] .strtab           STRTAB          00000000 000ef0 0002bc 00      0   0  1

dl_resolve(link_map,r_info)

link_map: linked list

What is symtab ?

Meaning of this statement: Elf32_Sym *sym = &SYMTAB[((reloc->r_info)>>8)]
reloc is pointer to relocation table. It finds something called r_info from there. Uses that and indexes from SYMTAB . Where is this magical
symbol table ?

gef> x/20xw 0x080481b0
0x80481b0:	0x00000000	0x00000000	0x00000000	0x00000000
0x80481c0:	0x00000043	0x00000000	0x00000000	0x00000012
0x80481d0:	0x00000031	0x00000000	0x00000000	0x00000012
0x80481e0:	0x0000001a	0x00000000	0x00000000	0x00000012
0x80481f0:	0x0000005c	0x00000000	0x00000000	0x00000020
gef> 
0x8048200:	0x0000004a	0x00000000	0x00000000	0x00000012
0x8048210:	0x0000003e	0x00000000	0x00000000	0x00000012
0x8048220:	0x00000037	0x00000000	0x00000000	0x00000012
0x8048230:	0x0000000b	0x080486dc	0x00000004	0x000f0011
0x8048240:	0x0000002b	0x08049920	0x00000004	0x00190011

These values 0x43,0x31,0x1a etc are offsets into the Symbol’s String Table. Where is that ? see .dynstr.

Add 0x43 to .dynstr base. See result.

gef> x/xs 0x08048250+0x43
0x8048293:	"strcmp"
gef> x/xs 0x08048250+0x44
0x8048294:	"trcmp"
gef> x/xs 0x08048250+0x42
0x8048292:	""
gef> x/xs 0x08048250+0x43
0x8048293:	"strcmp"
gef> x/xs 0x08048250+0x31
0x8048281:	"fgets"
gef> x/xs 0x08048250+0x1a
0x804826a:	"__stack_chk_fail"
gef> x/xs 0x08048250+0x5c
0x80482ac:	"__gmon_start__"
gef> 

Check this one out !!

0x8048230:	0x0000000b	0x080486dc	0x00000004	0x000f0011
gef> x/xs 0x08048250+0xb
0x804825b:	"_IO_stdin_used"
gef> x/xw 0x080486dc
0x80486dc <_IO_stdin_used>:	0x00020001

So there must be some struct or something.
Here it is !!

typedef struct {
Elf32_Word st_name;
Elf32_Addr st_value; 
Elf32_Word st_size; 
unsigned char st_info; 
unsigned char st_other; 
Elf32_Half st_shndx;
} Elf32_Sym;

So that size is 4 + 4 + 4 + 1 + 1 + 2 = (perfect) 16 bytes

RELOCATION

typedef struct {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;

This is what a relocation entry struct is. Check the .rel.dyn ELF section.
Lets see in gdb.

gef> x/20xw 0x08048314
0x8048314:	0x080498ec	0x00000406	0x08049920	0x00000905
0x8048324:	0x080498fc	0x00000107	0x08049900	0x00000207
0x8048334:	0x08049904	0x00000307	0x08049908	0x00000407
0x8048344:	0x0804990c	0x00000507	0x08049910	0x00000607
0x8048354:	0x08049914	0x00000707	0x08ec8353	0x0000cbe8

These addresses all point to the GOT table of the ELF. Yes these r_offset in this case is the actual virtual address (Think of it like offset from 0).
Just to make sure:

gef> x/xw 0x080498fc
0x80498fc <strcmp@got.plt>:	0x08048396
gef> 

But what’s r_info ?
remember the formula that we didn’t understand ?

Elf32_Sym *sym = &SYMTAB[((reloc->r_info)>>8)]

Yep that one. So that is what is referenced from SYMTAB as base.
So whats happening is program jumps to this region, figures out the r_offset for the appropiate GOT_address and uses its r_info.
It then maps that to the symbol_memory_layout that we saw that was filled with the struct ELF32_Sym. From there, it gets the symbol’s name,address,type,scope(local/global) everything. (like we saw with _IO_stdin_used)

.dynamic

.dynamic is another section header in ELF. Lets see what it contains:

gef> x/20xw 0x08049804
0x8049804:	0x00000001	0x00000001	0x0000000c	0x0804835c
0x8049814:	0x0000000d	0x080486c4	0x00000019	0x080497f8
0x8049824:	0x0000001b	0x00000004	0x0000001a	0x080497fc
0x8049834:	0x0000001c	0x00000004	0x6ffffef5	0x0804818c
0x8049844:	0x00000005	0x08048250	0x00000006	0x080481b0
gef> x/xw 0x0804835c
0x804835c <_init>:	0x08ec8353
gef> x/xw 0x080486c4
0x80486c4 <_fini>:	0x08ec8353

It contains pointers to ALL the sections of the ELF. Compare with the result you get from readelf -S warehouse.

In the warehouse exploit, we were NULLifying an address which contained a pointer to the last entry of the .dynamic section.
This means that linkmap + 0xe4 (which contains this magical address) has something to do with the process……Its Imp.

Finally, now that the ELF knows everything about the function it has to find in the libc, it resolves it.

result = _dl_lookup_symbol_x (strtab + sym-> st_name, l, & sym, l-> l_scope, version, ELF_RTYPE_CLASS_PLT, flags, NULL );

Once resolved, this entire process need not be repeated for that function since the got entry would now be filled with the actual libc address……coz now the program knows right !!