ret2dl_resolve

Sections

PLT

Lors de l'exécution d'un programme dynamiquement linké celui ci va être mené à faire appel à des fonctions de librairies externes. Pour se faire il va faire ce qu'on appelle le lazy loading. C'est à dire qu'il va résoudre les fonctions nécessaires de la libc pour mettre l'adresse d'une fonction dns son entrée dans la GOT.

GOT

Lors de l'appel d'une fonction via la PLT le programme va tout d'abord regarder si l'entrée de GOT de la fonction est vide ou contient déjà l'adresse de la fonction résolue de la libc.

Dynamic Symbols & Relocations

Un symbole représente une fonction ou une variable globale et est identifiée par un nom. Chaque symbole est décrit à l'aide de sa structure Elf32_Sym.

Elf32_Rel structure (JMPREL)

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

- r_offset : address of GOT entry where the resolved function will be stored
- r_info (ex: 0x107):
        * 0x1 -> Index into Symbol Table (SYMTAB)
        * 0x7 -> Function lookup value

Elf32_Sym structure (SYMTAB)

struct elf32_sym {
        Elf32_Word st_name;     // Symbol name (index into String Table -> STRTAB)
        Elf32_Addr st_value;    // Value or address associated with the symbol
        Elf32_Word st_size;     // Size of the symbol
        unsigned char st_info;  // Symbol's type and binding attributes
        unsigned char st_other; // Must be zero; reserved
        Elf32_Half st_shndx;    // Which section (header table index) it's defined in
} Elf32_Sym;

Elf32_Dyn structure (DYNAMIC)

#define DT_NULL 0     /* Marks end of dynamic section */
#define DT_NEEDED 1   /* Name of needed library */
#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
#define DT_PLTGOT 3   /* Processor defined value */
#define DT_HASH 4     /* Address of symbol hash table */
#define DT_STRTAB 5   /* Address of string table */
#define DT_SYMTAB 6   /* Address of symbol table */
#define DT_RELA 7     /* Address of Rela relocs */
#define DT_RELASZ 8   /* Total size of Rela relocs */
#define DT_RELAENT 9  /* Size of one Rela reloc */
#define DT_STRSZ 10   /* Size of string table */
#define DT_SYMENT 11  /* Size of one symbol table entry */
#define DT_INIT 12    /* Address of init function */
#define DT_FINI 13    /* Address of termination function */
#define DT_SONAME 14  /* Name of shared object */
#define DT_RPATH 15   /* Library search path */
#define DT_SYMBOLIC 16/* Start symbol search here */
#define DT_REL 17     /* Address of Rel relocs */
#define DT_RELSZ 18   /* Total size of Rel relocs */
#define DT_RELENT 19  /* Size of one Rel reloc */
#define DT_PLTREL 20  /* Type of reloc in PLT */
#define DT_DEBUG 21   /* For debugging; unspecified */
#define DT_TEXTREL 22 /* Reloc might modify .text */
#define DT_JMPREL 23  /* Address of PLT relocs */

typedef struct {
	Elf32_Sword d_tag;  // Dynamic entry type
   	union {
   		Elf32_Word d_val;
   		Elf32_Addr d_ptr;
	} d_un; // Address of table
} Elf32_Dyn;

_dl_runtime_resolve

0xf7feadd0 <+0>:     push   eax
0xf7feadd1 <+1>:     push   ecx
0xf7feadd2 <+2>:     push   edx
0xf7feadd3 <+3>:     mov    edx,DWORD PTR [esp+0x10] ; reloc_offset
0xf7feadd7 <+7>:     mov    eax,DWORD PTR [esp+0xc]  ; link_map structure (index of Elf32_Rel structure from JMPREL section)
0xf7feaddb <+11>:    call   0xf7fe4f10 <_dl_fixup>
0xf7feade0 <+16>:    pop    edx
0xf7feade1 <+17>:    mov    ecx,DWORD PTR [esp]
0xf7feade4 <+20>:    mov    DWORD PTR [esp],eax
0xf7feade7 <+23>:    mov    eax,DWORD PTR [esp+0x4]
0xf7feadeb <+27>:    ret    0xc

_dl_fixup

0xf7fe4f10 <+0>:     push   ebp
0xf7fe4f11 <+1>:     push   edi
0xf7fe4f12 <+2>:     push   esi
0xf7fe4f13 <+3>:     push   ebx
0xf7fe4f14 <+4>:     call   0xf7ff18b3 <__x86.get_pc_thunk.di>

; EDI = GOT address of ld
0xf7fe4f19 <+9>:     add    edi,0x180e7 
0xf7fe4f1f <+15>:    sub    esp,0x2c

; store link_map->l_info[DT_STRTAB] "Address of string table Elf32_Dyn at index 5" in ECX (STRTAB addr)
; https://code.woboq.org/userspace/glibc/elf/elf.h.html#854
0xf7fe4f22 <+18>:    mov    ecx,DWORD PTR [eax+0x34]

; store link_map->l_info[DT_SYMTAB] "Address of string table Elf32_Dyn at index 6" in EBX (SYMTAB addr)
0xf7fe4f25 <+21>:    mov    ebx,DWORD PTR [eax+0x38]

; save ld GOT address on stack
0xf7fe4f28 <+24>:    mov    DWORD PTR [esp+0x8],edi

; get STRTAB address (Elf32_Dyn->d_ptr) and store in ESI
0xf7fe4f2c <+28>:    mov    esi,DWORD PTR [ecx+0x4]

; store link_map->l_info[DT_JMPREL] "Address of plt reloc table Elf32_Dyn at index 23" in ECX (JMPREL addr)
0xf7fe4f2f <+31>:    mov    ecx,DWORD PTR [eax+0x7c]

; get JMPREL address (Elf32_Dyn->d_ptr) and add it in EDX which contained reloc_offset passed as argument
0xf7fe4f32 <+34>:    add    edx,DWORD PTR [ecx+0x4]

; store on stack STRTAB address
0xf7fe4f35 <+37>:    mov    DWORD PTR [esp+0xc],esi

; save in EBP JMPREL address
0xf7fe4f39 <+41>:    mov    ebp,edx

; At this moment, EDX contains the address of our Elf32_Rel structure.

; get Elf32_Rel->r_info and store it in EDX
0xf7fe4f3b <+43>:    mov    edx,DWORD PTR [edx+0x4]

; get Elf32_Rel->r_offset and store it in EDI
0xf7fe4f3e <+46>:    mov    edi,DWORD PTR [ebp+0x0]

; save in ESI (Elf32_Rel->r_info >> 0x8) which is the index in Symbol Table
0xf7fe4f41 <+49>:    mov    esi,edx
0xf7fe4f43 <+51>:    shr    esi,0x8

; save in ECX ((Elf32_Rel->r_info >> 0x8) << 0x4)
0xf7fe4f46 <+54>:    mov    ecx,esi
0xf7fe4f48 <+56>:    shl    ecx,0x4

; store in ECX (Elf32_Dyn->d_ptr + ECX) which points to the start of Elf32_Sym 
; structure relative to the Elf32_Rel stucture.
0xf7fe4f4b <+59>:    add    ecx,DWORD PTR [ebx+0x4]

; add link_map->l_addr to Elf32_Rel->r_info and store in EDI result
0xf7fe4f4e <+62>:    mov    ebx,DWORD PTR [eax]
0xf7fe4f50 <+64>:    add    edi,ebx

; check (Elf32_Rel->r_info & 0xff) == ELF_MACHINE_JMP_SLOT (7)
0xf7fe4f52 <+66>:    cmp    dl,0x7

; save on stack Elf32_Sym structure address
0xf7fe4f55 <+69>:    mov    DWORD PTR [esp+0x1c],ecx

; if (Elf32_Rel->r_info & 0xff) != ELF_MACHINE_JMP_SLOT (7) -> error
0xf7fe4f59 <+73>:    jne    0xf7fe5064 <_dl_fixup+340>
0xf7fe4f5f <+79>:    test   BYTE PTR [ecx+0xd],0x3

; save in EBP Elf32_Rel->r_offset
0xf7fe4f63 <+83>:    mov    ebp,edi
0xf7fe4f65 <+85>:    jne    0xf7fe5010 <_dl_fixup+256>

; store Elf32_Dyn address of VERSYM
0xf7fe4f6b <+91>:    mov    ebx,DWORD PTR [eax+0xe4]
0xf7fe4f71 <+97>:    xor    edx,edx
0xf7fe4f73 <+99>:    test   ebx,ebx
0xf7fe4f75 <+101>:   je     0xf7fe4f9a <_dl_fixup+138>

; store VERSYM address in EDX
0xf7fe4f77 <+103>:   mov    edx,DWORD PTR [ebx+0x4]
0xf7fe4f7a <+106>:   movzx  edx,WORD PTR [edx+esi*2]
0xf7fe4f7e <+110>:   and    edx,0x7fff
0xf7fe4f84 <+116>:   shl    edx,0x4
0xf7fe4f87 <+119>:   add    edx,DWORD PTR [eax+0x170]
0xf7fe4f8d <+125>:   mov    ebx,DWORD PTR [edx+0x4]
0xf7fe4f90 <+128>:   test   ebx,ebx
0xf7fe4f92 <+130>:   mov    ebx,0x0
0xf7fe4f97 <+135>:   cmove  edx,ebx
0xf7fe4f9a <+138>:   mov    esi,DWORD PTR gs:0xc
0xf7fe4fa1 <+145>:   test   esi,esi
0xf7fe4fa3 <+147>:   mov    ebx,0x1
0xf7fe4fa8 <+152>:   jne    0xf7fe5018 <_dl_fixup+264>

; prepare arguments for _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, version, ELF_RTYPE_CLASS_PLT, flags, NULL);
0xf7fe4faa <+154>:   push   0x0 ; NULL
0xf7fe4fac <+156>:   push   ebx ; flags
0xf7fe4fad <+157>:   push   0x1 ; ELF_RTYPE_CLASS_PLT
0xf7fe4faf <+159>:   push   edx ; version
0xf7fe4fb0 <+160>:   push   DWORD PTR [eax+0x1cc] ; link_map->l_scope
0xf7fe4fb6 <+166>:   lea    edx,[esp+0x30]
0xf7fe4fba <+170>:   push   edx ; &sym
0xf7fe4fbb <+171>:   push   eax ; link_map
0xf7fe4fbc <+172>:   mov    edi,DWORD PTR [esp+0x28]
0xf7fe4fc0 <+176>:   add    edi,DWORD PTR [ecx]
0xf7fe4fc2 <+178>:   push   edi ; strtab + sym->st_name
0xf7fe4fc3 <+179>:   call   0xf7fdfec0 <_dl_lookup_symbol_x>

; just write at Elf32_Rel->r_offset address the function that was looked up
0xf7fe4fc8 <+184>:   mov    edi,eax
0xf7fe4fca <+186>:   mov    eax,gs:0xc
0xf7fe4fd0 <+192>:   add    esp,0x20
0xf7fe4fd3 <+195>:   test   eax,eax
0xf7fe4fd5 <+197>:   jne    0xf7fe5030 <_dl_fixup+288>
0xf7fe4fd7 <+199>:   mov    ecx,DWORD PTR [esp+0x1c]
0xf7fe4fdb <+203>:   xor    eax,eax
0xf7fe4fdd <+205>:   test   ecx,ecx
0xf7fe4fdf <+207>:   je     0xf7fe4ff6 <_dl_fixup+230>
0xf7fe4fe1 <+209>:   test   edi,edi
0xf7fe4fe3 <+211>:   je     0xf7fe4fe7 <_dl_fixup+215>
0xf7fe4fe5 <+213>:   mov    eax,DWORD PTR [edi]
0xf7fe4fe7 <+215>:   movzx  edx,BYTE PTR [ecx+0xc]
0xf7fe4feb <+219>:   add    eax,DWORD PTR [ecx+0x4]
0xf7fe4fee <+222>:   and    edx,0xf
0xf7fe4ff1 <+225>:   cmp    dl,0xa
0xf7fe4ff4 <+228>:   je     0xf7fe5060 <_dl_fixup+336>
0xf7fe4ff6 <+230>:   mov    esi,DWORD PTR [esp+0x8]
0xf7fe4ffa <+234>:   mov    edx,DWORD PTR [esi-0x6d0]
0xf7fe5000 <+240>:   test   edx,edx
0xf7fe5002 <+242>:   jne    0xf7fe5007 <_dl_fixup+247>
0xf7fe5004 <+244>:   mov    DWORD PTR [ebp+0x0],eax
0xf7fe5007 <+247>:   add    esp,0x2c
0xf7fe500a <+250>:   pop    ebx
0xf7fe500b <+251>:   pop    esi
0xf7fe500c <+252>:   pop    edi
0xf7fe500d <+253>:   pop    ebp
0xf7fe500e <+254>:   ret
0xf7fe500f <+255>:   nop
0xf7fe5010 <+256>:   mov    eax,ebx
0xf7fe5012 <+258>:   jmp    0xf7fe4fe7 <_dl_fixup+215>
0xf7fe5014 <+260>:   lea    esi,[esi+eiz*1+0x0]
0xf7fe5018 <+264>:   mov    DWORD PTR gs:0x1c,0x1
0xf7fe5023 <+275>:   mov    ebx,0x5
0xf7fe5028 <+280>:   jmp    0xf7fe4faa <_dl_fixup+154>
0xf7fe502a <+282>:   lea    esi,[esi+0x0]
0xf7fe5030 <+288>:   xor    esi,esi
0xf7fe5032 <+290>:   mov    eax,esi
0xf7fe5034 <+292>:   xchg   DWORD PTR gs:0x1c,eax
0xf7fe503b <+299>:   cmp    eax,0x2
0xf7fe503e <+302>:   jne    0xf7fe4fd7 <_dl_fixup+199>
0xf7fe5040 <+304>:   mov    ebx,DWORD PTR gs:0x8
0xf7fe5047 <+311>:   mov    eax,0xf0
0xf7fe504c <+316>:   add    ebx,0x1c
0xf7fe504f <+319>:   mov    ecx,0x81
0xf7fe5054 <+324>:   mov    edx,0x1
0xf7fe5059 <+329>:   int    0x80
0xf7fe505b <+331>:   jmp    0xf7fe4fd7 <_dl_fixup+199>
0xf7fe5060 <+336>:   call   eax
0xf7fe5062 <+338>:   jmp    0xf7fe4ff6 <_dl_fixup+230>
0xf7fe5064 <+340>:   mov    edi,DWORD PTR [esp+0x8]
0xf7fe5068 <+344>:   lea    eax,[edi-0x7acc]
0xf7fe506e <+350>:   push   eax
0xf7fe506f <+351>:   lea    eax,[edi-0x9cf3]
0xf7fe5075 <+357>:   push   0x50
0xf7fe5077 <+359>:   push   eax
0xf7fe5078 <+360>:   lea    eax,[edi-0x7b3c]
0xf7fe507e <+366>:   push   eax
0xf7fe507f <+367>:   call   0xf7feeb00 <__GI___assert_fail>