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) ```c 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) ```c 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) ```c #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** ```x86asm 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** ```x86asm 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> ``` - https://code.woboq.org/userspace/glibc/elf/dl-runtime.c.html - https://docs.huihoo.com/doxygen/linux/kernel/3.7/include_2uapi_2linux_2elf_8h_source.html