-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added handling of program segments and overlapping parts #9
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -208,12 +208,34 @@ def __bytes__(self): | |
self.Elf.Ehdr.e_shentsize = 0 | ||
self.Elf.Ehdr.e_shnum = 0 | ||
|
||
# update section offsets in section headers | ||
orig_poffset = [] | ||
for i, Phdr in enumerate(self.Elf.Phdr_table): | ||
program = self.Elf.programs[i] | ||
program_len = len(program) | ||
Phdr.p_filesz = program_len | ||
orig_poffset.append(Phdr.p_offset) | ||
if isinstance(program, memoryview): | ||
idx, hdr = next((i, x) for i, x in enumerate(self.Elf.Phdr_table) if program.obj is self.Elf.programs[i]) | ||
Phdr.p_offset = Phdr.p_offset - orig_poffset[idx] + hdr.p_offset | ||
else: | ||
Phdr.p_offset = cursor | ||
cursor += program_len | ||
|
||
# update section offsets in section headers | ||
for i, Shdr in enumerate(self.Elf.Shdr_table): | ||
section_len = len(self.Elf.sections[i]) | ||
Shdr.sh_offset = cursor | ||
section = self.Elf.sections[i] | ||
section_len = len(section) | ||
# Check for all zeros - strip such sections | ||
if next((False for b in section if b != 0x00), True): | ||
Shdr.sh_offset = -1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, now I understand why you are checking sh_offset for negative values. Don't do it that way. Someone might try to serialize Shdr in the meantime and will get exception, because of that. If the goal is to strip a section, just do it here. You have access to section, so it could be assigned to None, empty array or anything that can unambiguously mark it as empty. |
||
elif isinstance(section, memoryview): | ||
idx, hdr = next((i, x) for i, x in enumerate(self.Elf.Phdr_table) if section.obj is self.Elf.programs[i]) | ||
Shdr.sh_offset = Shdr.sh_offset - orig_poffset[idx] + hdr.p_offset | ||
else: | ||
Shdr.sh_offset = cursor | ||
cursor += section_len | ||
Shdr.sh_size = section_len | ||
cursor += section_len | ||
|
||
return bytes(self.Elf) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -766,7 +766,7 @@ class Elf32: | |
# \param sections List of section contents | ||
# \param little Endianness of ELF file | ||
def __init__(self, Ehdr=None, Phdr_table=None, Shdr_table=None, | ||
sections=None, little=False): | ||
programs=None, sections=None, little=False): | ||
if Ehdr is None: | ||
Ehdr = Elf32_Ehdr() | ||
if Phdr_table is None: | ||
|
@@ -775,6 +775,8 @@ def __init__(self, Ehdr=None, Phdr_table=None, Shdr_table=None, | |
Shdr_table = [] | ||
if sections is None: | ||
sections = [] | ||
if programs is None: | ||
programs = [] | ||
|
||
if isinstance(Ehdr, Elf32_Ehdr): | ||
## Instance of \link Elf32_Ehdr \endlink | ||
|
@@ -796,6 +798,14 @@ def __init__(self, Ehdr=None, Phdr_table=None, Shdr_table=None, | |
else: | ||
raise Exception('Shdr table must be a list of Elf32_Shdr objects') | ||
|
||
if isinstance(programs, list): | ||
## List of section content | ||
# \details Contains raw bytes objects or any type that can be | ||
# converted using bytes function | ||
self.programs = programs | ||
else: | ||
raise Exception('Programs must be a list containing program content') | ||
|
||
if isinstance(sections, list): | ||
## List of section content | ||
# \details Contains raw bytes objects or any type that can be | ||
|
@@ -847,15 +857,27 @@ def __bytes__(self): | |
headers[cursor] = Shdr | ||
cursor += self.Ehdr.e_shentsize | ||
|
||
# programs | ||
for i, Phdr in enumerate(self.Phdr_table): | ||
if len(self.programs[i]) != 0 and not isinstance(self.programs[i], memoryview): | ||
headers[Phdr.p_offset] = self.programs[i] | ||
|
||
# sections | ||
for i, Shdr in enumerate(self.Shdr_table): | ||
if len(self.sections[i]) != 0: | ||
if Shdr.sh_offset < 0: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sh_offset of negative value is impossible to serialize. Maybe it should be forbidden on shdr object creation? It is going to result in exception, if just shdr object serialization is performed, so sounds like a better place to prevent such situation. |
||
pass | ||
elif len(self.sections[i]) != 0 and not isinstance(self.sections[i], memoryview): | ||
headers[Shdr.sh_offset] = self.sections[i] | ||
|
||
# find file size | ||
end_of_file = sorted(headers.keys())[-1] | ||
end_of_file += len(headers[end_of_file]) | ||
|
||
# Set all invalid offsets to end of file | ||
for i, Shdr in enumerate(self.Shdr_table): | ||
if Shdr.sh_offset < 0: | ||
Shdr.sh_offset = end_of_file | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't do any magic in this file. If for some reason, this kind of stuff is required, please do it in ELF() class. In here, invalid structures must be treated as perfectly fine. |
||
|
||
# create and populate buffer | ||
b = bytes(end_of_file) | ||
for off in headers: | ||
|
@@ -878,6 +900,18 @@ def __bytes__(self): | |
b = makeelf.utils.bytes_xor(b, aligned) | ||
return b | ||
|
||
def create_section_from_hdr(blob, programs, phdrs, hdr): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to document new functions you're adding. It is hard for anyone else to use such functions. This is even more important to other two functions, as there is no single call to them. |
||
first = hdr.sh_offset | ||
last = first + hdr.sh_size | ||
program, idx = next(((p, idx) for idx, p in enumerate(phdrs) if p.p_offset <= first and last <= (p.p_offset + p.p_filesz)), (None, None)) | ||
if program != None and hdr.sh_size > 0: | ||
section = memoryview(programs[idx])[first - program.p_offset:last - program.p_offset] | ||
elif blob and last <= len(blob): | ||
section = bytearray(blob[first:last]) | ||
else: | ||
section = bytearray([0x00 for i in range(hdr.sh_size)]) | ||
return section | ||
|
||
## | ||
# \brief Deserialization of object | ||
# | ||
|
@@ -905,16 +939,67 @@ def from_bytes(b, little=False): | |
Shdr, b = Elf32_Shdr.from_bytes(b, little) | ||
Shdr_a.append(Shdr) | ||
|
||
# Programs | ||
programs = [] | ||
Phdr_f = [] | ||
Phdr_a = sorted(Phdr_a, key=lambda p: -p.p_filesz) | ||
for Phdr in Phdr_a: | ||
first = Phdr.p_offset | ||
last = first + Phdr.p_filesz | ||
program, idx = next(((p, idx) for idx, p in enumerate(Phdr_f) if p.p_offset <= first and last <= (p.p_offset + p.p_filesz)), (None, None)) | ||
if not program or Phdr.p_filesz == 0: | ||
program = bytearray(blob[first:last]) | ||
else: | ||
program = memoryview(programs[idx])[first - program.p_offset:last - program.p_offset] | ||
programs.append(program) | ||
Phdr_f.append(Phdr) | ||
|
||
# Sections | ||
sections = [] | ||
# TODO: support of section content handlers, i.e. _Strtab, _Symtab | ||
for i, Shdr in enumerate(Shdr_a): | ||
first = Shdr.sh_offset | ||
last = first + Shdr.sh_size | ||
section = blob[first:last] | ||
for Shdr in Shdr_a: | ||
section = Elf32.create_section_from_hdr(blob, programs, Phdr_a, Shdr) | ||
sections.append(section) | ||
|
||
return Elf32(Ehdr, Phdr_a, Shdr_a, sections, little=Ehdr.little), None | ||
return Elf32(Ehdr, Phdr_a, Shdr_a, programs, sections, little=Ehdr.little), None | ||
|
||
def extend_program(self, idx, extension): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, move this function to elf module. elfstruct's purpose is to provide a kind of a model for storing data in ELF file. Any manipulations should be done outside of it. |
||
program = self.programs[idx] | ||
Phdr = self.Phdr_table[idx] | ||
to_update = [] | ||
for i, Shdr in enumerate(self.Shdr_table): | ||
section = self.sections[i] | ||
if not isinstance(section, memoryview): | ||
continue | ||
if not section.obj is program: | ||
continue | ||
to_update.append((i, Shdr)) | ||
section.release() | ||
self.programs[idx].extend(extension) | ||
program = self.programs[idx] | ||
Phdr.p_filesz = len(program) | ||
for i, Shdr in to_update: | ||
first = Shdr.sh_offset - Phdr.p_offset | ||
last = first + Shdr.sh_size | ||
self.sections[i] = memoryview(program)[first:last] | ||
return program | ||
|
||
def resize_section(self, section, size): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same situation here |
||
idx, Shdr = next(((idx, p) for idx, p in enumerate(self.Shdr_table) if self.sections[idx] is section)) | ||
if len(section) == 0: | ||
Shdr.sh_size = size | ||
self.sections[idx] = Elf32.create_section_from_hdr(None, self.programs, self.Phdr_table, Shdr) | ||
return | ||
if not isinstance(section, memoryview): | ||
if len(section) > size: | ||
self.sections[idx] = section[:size] | ||
else: | ||
self.sections[idx].extend([0xFF for i in range(size - len(section))]) | ||
return | ||
pidx, Phdr = next(((i, p) for i, p in enumerate(self.Phdr_table) if self.programs[i] is section.obj)) | ||
first = Shdr.sh_offset - Phdr.p_offset | ||
last = first + size | ||
self.sections[idx] = memoryview(self.programs[pidx])[first:last] | ||
|
||
## | ||
# \brief Length of object | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you meant program headers, as you're changing Phdr