Inachora kwa loader jinsi ya kupakia ELF kwenye kumbukumbu:
readelf-lWlnstatElffiletypeisDYN (Position-Independent Executablefile)Entrypoint0x1c00Thereare9programheaders,startingatoffset64ProgramHeaders:TypeOffsetVirtAddrPhysAddrFileSizMemSizFlgAlignPHDR0x0000400x00000000000000400x00000000000000400x0001f80x0001f8R0x8INTERP0x0002380x00000000000002380x00000000000002380x00001b0x00001bR0x1[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]LOAD0x0000000x00000000000000000x00000000000000000x003f7c0x003f7cRE0x10000LOAD0x00fc480x000000000001fc480x000000000001fc480x0005280x001190RW0x10000DYNAMIC0x00fc580x000000000001fc580x000000000001fc580x0002000x000200RW0x8NOTE0x0002540x00000000000002540x00000000000002540x0000e00x0000e0R0x4GNU_EH_FRAME0x0036100x00000000000036100x00000000000036100x0001b40x0001b4R0x4GNU_STACK0x0000000x00000000000000000x00000000000000000x0000000x000000RW0x10GNU_RELRO0x00fc480x000000000001fc480x000000000001fc480x0003b80x0003b8R0x1SectiontoSegmentmapping:SegmentSections...0001.interp02.interp.note.gnu.build-id.note.ABI-tag.note.package.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.text.fini.rodata.eh_frame_hdr.eh_frame03.init_array.fini_array.dynamic.got.data.bss04.dynamic05.note.gnu.build-id.note.ABI-tag.note.package06.eh_frame_hdr0708.init_array.fini_array.dynamic.got
The previous program has 9 program headers, then, the segment mapping indicates in which program header (from 00 to 08) each section is located.
PHDR - Program HeaDeR
Contains the program header tables and metadata itself.
INTERP
Indicates the path of the loader to use to load the binary into memory.
LOAD
These headers are used to indicate how to load a binary into memory.
Each LOAD header indicates a region of memory (size, permissions and alignment) and indicates the bytes of the ELF binary to copy in there.
For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections .init_array .fini_array .dynamic .got .data .bss.
DYNAMIC
This header helps to link programs to their library dependencies and apply relocations. Check the .dynamic section.
NOTE
This stores vendor metadata information about the binary.
GNU_EH_FRAME
Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions.
GNU_STACK
Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack.
GNU_RELRO
Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the GOT or the init and fini tables) after the program has loaded and before it begins running.
In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections .init_array .fini_array .dynamic .got .data .bss.
Note that RELRO can be partial or full, the partial version do not protect the section .plt.got, which is used for lazy binding and needs this memory space to have write permissions to write the address of the libraries the first time their location is searched.
TLS
Defines a table of TLS entries, which stores info about thread-local variables.
Section Headers
Section headers gives a more detailed view of the ELF binary
It also indicates the location, offset, permissions but also the type of data it section has.
Meta Sections
String table: Inayo vitu vyote vinavyohitajika na faili ya ELF (lakini si vile vinavyotumika kwa kweli na programu). Kwa mfano inayo majina ya sehemu kama .text au .data. Na ikiwa .text iko kwenye offset 45 katika jedwali la nyuzi itatumia nambari 45 katika uwanja wa jina.
Ili kupata mahali ambapo jedwali la nyuzi liko, ELF ina kipanga njia kwa jedwali la nyuzi.
Symbol table: Inayo taarifa kuhusu alama kama jina (offset katika jedwali la nyuzi), anwani, ukubwa na metadata zaidi kuhusu alama.
Main Sections
.text: Maagizo ya programu ya kuendesha.
.data: Vigezo vya kimataifa vilivyo na thamani iliyofafanuliwa katika programu.
.bss: Vigezo vya kimataifa vilivyotelekezwa bila kuanzishwa (au kuanzishwa kuwa sifuri). Vigezo hapa vinakaguliwa kiotomatiki kuwa sifuri hivyo kuzuia sifuri zisizohitajika kuongezwa kwenye binary.
.rodata: Vigezo vya kimataifa vya kudumu (sehemu ya kusoma tu).
.tdata na .tbss: Kama .data na .bss wakati vigezo vya ndani ya thread vinapotumika (__thread_local katika C++ au __thread katika C).
.dynamic: Angalia hapa chini.
Symbols
Symbols ni eneo lenye jina katika programu ambalo linaweza kuwa kazi, kitu cha data cha kimataifa, vigezo vya ndani ya thread...
readelf -s lnstat
Symbol table '.dynsym' contains 49 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
[...]
Kila kipengele cha alama kina:
Jina
Sifa za uhusiano (dhaifu, za ndani au za kimataifa): Alama ya ndani inaweza kufikiwa tu na programu yenyewe wakati alama za kimataifa zinashirikiwa nje ya programu. Kitu dhaifu ni mfano wa kazi ambayo inaweza kubadilishwa na nyingine.
Aina: NOTYPE (aina haijabainishwa), OBJECT (kibadilisha data cha kimataifa), FUNC (kazi), SECTION (sehemu), FILE (faili ya msimbo wa chanzo kwa ajili ya wadhibiti), TLS (kibadilisha cha nyuzi za ndani), GNU_IFUNC (kazi isiyo ya moja kwa moja kwa ajili ya uhamasishaji)
The NEEDED directory indicates that the program inahitaji kupakia maktaba iliyoelezwa ili kuendelea. The NEEDED directory completes once the shared maktaba imefanya kazi kikamilifu na iko tayari kwa matumizi.
Relocations
The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
Ikiwa programu imepakuliwa mahali tofauti na anwani inayopendelea (kawaida 0x400000) kwa sababu anwani hiyo tayari inatumika au kwa sababu ya ASLR au sababu nyingine yoyote, uhamasishaji wa statiki unarekebisha viashiria ambavyo vilikuwa na thamani zikitarajia binary kupakuliwa katika anwani inayopendelea.
Kwa mfano, sehemu yoyote ya aina R_AARCH64_RELATIV inapaswa kuwa imebadilisha anwani katika bias ya uhamasishaji pamoja na thamani ya kuongeza.
Dynamic Relocations and GOT
Uhamasishaji unaweza pia kurejelea alama ya nje (kama kazi kutoka kwa utegemezi). Kama kazi malloc kutoka libC. Kisha, mpakuwaji anapopakua libC katika anwani akichunguza mahali ambapo kazi ya malloc imepakuliwa, itaandika anwani hii katika jedwali la GOT (Global Offset Table) (linaloonyeshwa katika jedwali la uhamasishaji) ambapo anwani ya malloc inapaswa kufafanuliwa.
Procedure Linkage Table
Sehemu ya PLT inaruhusu kufanya uhusiano wa uvivu, ambayo inamaanisha kwamba ufumbuzi wa mahali pa kazi utafanywa mara ya kwanza inapoombwa.
Hivyo wakati programu inaita malloc, kwa kweli inaita mahali husika pa malloc katika PLT (malloc@plt). Mara ya kwanza inapoitwa inatatua anwani ya malloc na kuihifadhi ili wakati wa pili malloc inaitwa, anwani hiyo inatumika badala ya msimbo wa PLT.
Program Initialization
Baada ya programu kupakuliwa ni wakati wa kuendesha. Hata hivyo, msimbo wa kwanza unaotekelezwa sio kila wakati kazi ya main. Hii ni kwa sababu kwa mfano katika C++ ikiwa kigezo cha kimataifa ni kitu cha darasa, kitu hiki lazima kiwe kimeanzishwakabla ya main kuendesha, kama katika:
Kumbuka kwamba hizi variables za kimataifa ziko katika .data au .bss lakini katika orodha __CTOR_LIST__ na __DTOR_LIST__ vitu vya kuanzisha na kuharibu vinahifadhiwa ili kufuatilia.
Kutoka kwa msimbo wa C, inawezekana kupata matokeo sawa kwa kutumia nyongeza za GNU:
__attributte__((constructor)) //Add a constructor to execute before__attributte__((destructor)) //Add to the destructor list
From a compiler perspective, to execute these actions before and after the main function is executed, it's possible to create a init function and a fini function which would be referenced in the dynamic section as INIT and FIN. and are placed in the init and fini sections of the ELF.
The other option, as mentioned, is to reference the lists __CTOR_LIST__ and __DTOR_LIST__ in the INIT_ARRAY and FINI_ARRAY entries in the dynamic section and the length of these are indicated by INIT_ARRAYSZ and FINI_ARRAYSZ. Each entry is a function pointer that will be called without arguments.
Moreover, it's also possible to have a PREINIT_ARRAY with pointers that will be executed before the INIT_ARRAY pointers.
Initialization Order
Program inaloaded kwenye kumbukumbu, mabadiliko ya kimataifa ya static yanaanzishwa katika .data na yasiyoanzishwa yanawekwa sifuri katika .bss.
Mahitaji yote ya programu au maktaba yanaanzishwa na kuunganishwa kwa dinamik kunatekelezwa.
PREINIT_ARRAY kazi zinafanywa.
INIT_ARRAY kazi zinafanywa.
Ikiwa kuna INIT kipengee kinaitwa.
Ikiwa ni maktaba, dlopen inamalizika hapa, ikiwa ni programu, ni wakati wa kuita nukta halisi ya kuingia (main function).
Thread-Local Storage (TLS)
Zimefafanuliwa kwa kutumia neno muhimu __thread_local katika C++ au nyongeza ya GNU __thread.
Kila thread itahifadhi eneo la kipekee kwa ajili ya variable hii hivyo ni thread pekee inayoweza kufikia variable yake.
Wakati hii inatumika sehemu .tdata na .tbss zinatumika katika ELF. Ambazo ni kama .data (iliyowekwa) na .bss (siyo iliyowekwa) lakini kwa TLS.
Kila variable itakuwa na kipengee katika kichwa cha TLS kinachoelezea ukubwa na TLS offset, ambayo ni offset itakayotumia katika eneo la data la ndani la thread.
__TLS_MODULE_BASE ni alama inayotumika kurejelea anwani ya msingi ya uhifadhi wa ndani wa thread na inaelekeza kwenye eneo katika kumbukumbu ambalo lina data zote za ndani za thread za moduli.