diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b2dcb8d9..e59499344 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,7 @@ The table below shows which release corresponds to each branch, and what date th - [#2502][2502] Fix loading ELF files without valid .dynamic section - [#2476][2476] Deprecate 'keepends' argument in favor of 'drop' in `tube.recvline*` - [#2364][2364] Deprecate direct commandline scripts invocation and exclude nonsense ones +- [#2496][2496] Add linux ko file search support [2508]: https://github.com/Gallopsled/pwntools/pull/2508 [2471]: https://github.com/Gallopsled/pwntools/pull/2471 @@ -107,6 +108,7 @@ The table below shows which release corresponds to each branch, and what date th [2502]: https://github.com/Gallopsled/pwntools/pull/2502 [2476]: https://github.com/Gallopsled/pwntools/pull/2476 [2364]: https://github.com/Gallopsled/pwntools/pull/2364 +[2496]: https://github.com/Gallopsled/pwntools/pull/2496 ## 4.14.0 (`beta`) diff --git a/pwnlib/elf/elf.py b/pwnlib/elf/elf.py index d93bfca8b..9d2939882 100644 --- a/pwnlib/elf/elf.py +++ b/pwnlib/elf/elf.py @@ -53,7 +53,7 @@ from elftools.elf.constants import SHN_INDICES from elftools.elf.descriptions import describe_e_type from elftools.elf.dynamic import DynamicSection -from elftools.elf.elffile import ELFFile +from elftools.elf.elffile import ELFFile, PAGESIZE from elftools.elf.enums import ENUM_GNU_PROPERTY_X86_FEATURE_1_FLAGS from elftools.elf.gnuversions import GNUVerDefSection from elftools.elf.relocation import RelocationSection, RelrRelocationSection @@ -1259,7 +1259,49 @@ def search(self, needle, writable = False, executable = False): break yield (addr + offset + load_address_fixup) offset += 1 - + if not segments: + if writable: + ko_check_segments = [".data"] + elif executable: + ko_check_segments = [".text"] + else: + ko_check_segments = [".text",".note",".rodata",".data"] + for section in super().iter_sections(): + if section.name not in ko_check_segments and \ + not any(section.name.startswith(ko_check_segment) for ko_check_segment in ko_check_segments): + continue + filesz = section['sh_size'] + offset = section['sh_offset'] + data = self.mmap[offset:offset + filesz] + data += b'\x00' + offset = 0 + while True: + offset = data.find(needle, offset) + if offset == -1: + break + # ko_file: header->.note->.text->.rodata->.data + # after insmod: text page(executable page), note and rodate page(read only page), data page(writable page) + if section.name == ".text": + addr = 0 + elif section.name.startswith(".note") : + text_filesz=self.get_section_by_name(".text")['sh_size'] + addr = (text_filesz//PAGESIZE + 1)*PAGESIZE + section['sh_offset'] - self.header['e_ehsize'] + elif section.name.startswith(".rodata"): + text_filesz=self.get_section_by_name(".text")['sh_size'] + text_offset=self.get_section_by_name(".text")['sh_offset'] + addr = (text_filesz//PAGESIZE + 1)*PAGESIZE + text_offset - self.header['e_ehsize'] + elif section.name == ".data" : + text_filesz=self.get_section_by_name(".text")['sh_size'] + rodata_filesz=0 + note_filez=0 + for section in super().iter_sections(): + if section.name.startswith(".rodata"): + rodata_filesz += section['sh_size'] + elif section.name.startswith(".node"): + note_filesz += section['sh_size'] + addr = (text_filesz//PAGESIZE + 1 + (note_filez+rodata_filesz)//PAGESIZE + 1)*PAGESIZE + yield (addr + offset + load_address_fixup) + offset += 1 def offset_to_vaddr(self, offset): """offset_to_vaddr(offset) -> int