Skip to content

Commit ae233ee

Browse files
committed
Initial commit
1 parent 4ff3e9f commit ae233ee

39 files changed

Lines changed: 7665 additions & 59 deletions

dissect/executable/elf/elf.py

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@
2727
class ELF:
2828
def __init__(self, fh: BinaryIO):
2929
self.fh = fh
30-
offset = fh.tell()
30+
31+
fh.seek(0)
3132
self.e_ident = fh.read(0x10)
32-
fh.seek(offset)
3333

3434
if self.e_ident[:4] != c_common_elf.ELFMAG:
35-
raise InvalidSignatureError("Invalid header magic")
35+
raise InvalidSignatureError(
36+
f"Invalid ELF header magic, expected {c_common_elf.ELFMAG!r}, got {self.e_ident[:4]!r}"
37+
)
3638

3739
c_elf_version = c_elf_32
3840
if self.e_ident[c_common_elf.EI_CLASS] == c_common_elf.ELFCLASS64:
@@ -43,20 +45,22 @@ def __init__(self, fh: BinaryIO):
4345
is_little = self.e_ident[c_common_elf.EI_DATA] == c_common_elf.ELFDATA2LSB
4446
self.c_elf.endian = "<" if is_little else ">"
4547

48+
fh.seek(0)
4649
self.header = self.c_elf.Ehdr(fh)
50+
4751
self.segments = SegmentTable.from_elf(self)
48-
self.section_table = SectionTable.from_elf(self)
49-
self.symbol_tables: list[SymbolTable] = self.section_table.by_type([SHT.SYMTAB, SHT.DYNSYM])
52+
self.sections = SectionTable.from_elf(self)
53+
self.symbol_tables: list[SymbolTable] = self.sections.by_type([SHT.SYMTAB, SHT.DYNSYM])
5054

5155
def __repr__(self) -> str:
5256
return str(self.header)
5357

5458
def dump(self) -> bytes:
5559
output_data = [
5660
self.segments.dump_table(),
57-
self.section_table.dump_table(),
61+
self.sections.dump_table(),
5862
*self.segments.dump_data(),
59-
*self.section_table.dump_data(),
63+
*self.sections.dump_data(),
6064
]
6165
output_data.sort(key=itemgetter(0))
6266

@@ -87,12 +91,12 @@ def dynamic(self) -> bool:
8791

8892

8993
class Table(Generic[T]):
90-
def __init__(self, entries: int) -> None:
91-
self.entries = entries
92-
self.items: list[T] = [None] * entries
94+
def __init__(self, num: int) -> None:
95+
self.num = num
96+
self.items: list[T] = [None] * num
9397

9498
def __iter__(self) -> Iterator[T]:
95-
for idx in range(self.entries):
99+
for idx in range(self.num):
96100
yield self[idx]
97101

98102
def __getitem__(self, idx: int) -> T:
@@ -125,7 +129,7 @@ def __init__(self, fh: BinaryIO, idx: int | None = None, c_elf: cstruct = c_elf_
125129

126130
def __repr__(self) -> str:
127131
return (
128-
f"<{self.__class__.__name__} idx={self.idx} name={self.name} type={self.type}"
132+
f"<{self.__class__.__name__} idx={self.idx} name={self.name!r} type={self.type}"
129133
f" offset=0x{self.offset:x} size=0x{self.size:x}>"
130134
)
131135

@@ -138,16 +142,12 @@ def _set_link(self, table: SectionTable) -> None:
138142
self._link = table[self.header.sh_link]
139143

140144
@classmethod
141-
def from_section_table(cls, section_table: SectionTable, idx: int) -> Section:
142-
result = cls(section_table.fh, idx=idx, c_elf=section_table.c_elf)
143-
result._set_link(section_table)
144-
145-
string_table = section_table.string_table
146-
if isinstance(result, StringTable):
147-
string_table = result
145+
def from_section_table(cls, table: SectionTable, idx: int) -> Section:
146+
result = cls(table.fh, idx=idx, c_elf=table.c_elf)
147+
result._set_link(table)
148148

149-
if string_table:
150-
result._set_name(string_table)
149+
if sh_strtab := (result if idx == table._sh_strtab_idx else table._sh_strtab):
150+
result._set_name(sh_strtab)
151151

152152
return result
153153

@@ -163,7 +163,7 @@ def link(self) -> Section | None:
163163
return self._link
164164

165165
@cached_property
166-
def contents(self) -> bytes:
166+
def data(self) -> bytes:
167167
self.fh.seek(self.offset)
168168
return self.fh.read(self.size)
169169

@@ -173,20 +173,22 @@ def __init__(
173173
self,
174174
fh: BinaryIO,
175175
offset: int,
176-
entries: int,
176+
num: int,
177177
size: int,
178-
string_index: int | None = None,
178+
sh_strtab_idx: int | None = None,
179179
c_elf: cstruct = c_elf_64,
180180
):
181-
super().__init__(entries)
181+
super().__init__(num)
182182
self.fh = fh
183183
self.offset = offset
184184
self.size = size
185-
self.string_table = None
186185
self.c_elf = c_elf
187186

188-
if string_index:
189-
self.string_table: StringTable = self[string_index]
187+
self._sh_strtab_idx = sh_strtab_idx
188+
self._sh_strtab = None
189+
190+
if sh_strtab_idx:
191+
self._sh_strtab: StringTable = self[sh_strtab_idx]
190192

191193
def __repr__(self) -> str:
192194
return f"<SectionTable offset=0x{self.offset:x} size=0x{self.size:x}>"
@@ -206,11 +208,14 @@ def _create_item(self, idx: int) -> Section:
206208

207209
@classmethod
208210
def from_elf(cls, elf: ELF) -> SectionTable:
209-
offset = elf.header.e_shoff
210-
entries = elf.header.e_shnum
211-
size = elf.header.e_shentsize
212-
other_index = elf.header.e_shstrndx
213-
return cls(elf.fh, offset, entries, size, other_index, elf.c_elf)
211+
return cls(
212+
elf.fh,
213+
elf.header.e_shoff,
214+
elf.header.e_shnum,
215+
elf.header.e_shentsize,
216+
elf.header.e_shstrndx,
217+
elf.c_elf,
218+
)
214219

215220
def by_type(self, section_types: list[int] | int) -> list[Section]:
216221
types = section_types
@@ -223,14 +228,14 @@ def related_sections(self, segment: Segment) -> list[Section]:
223228
return self.find(lambda x: x.is_related(segment))
224229

225230
def by_name(self, name: str) -> list[Section]:
226-
return self.find(lambda x: x.name in name)
231+
return self.find(lambda x: name == x.name)
227232

228233
def dump_table(self) -> tuple[int, bytes]:
229234
buf = bytearray()
230235
return self.offset, buf.join([x.header.dumps() for x in self])
231236

232237
def dump_data(self) -> list[tuple[int, bytes]]:
233-
return [(x.offset, x.contents) for x in self]
238+
return [(x.offset, x.data) for x in self]
234239

235240

236241
class Segment:
@@ -268,7 +273,7 @@ def is_related(self, section: Section) -> bool:
268273
return self.offset <= section.offset < self.end
269274

270275
@property
271-
def contents(self) -> bytes:
276+
def data(self) -> bytes:
272277
if not self._data:
273278
self.fh.seek(self.offset)
274279
self._data = self.fh.read(self.size)
@@ -320,7 +325,7 @@ def by_type(self, segment_types: list[int] | int) -> list[Segment]:
320325
return self.find(lambda x: x.type in types)
321326

322327
def dump_data(self) -> list[tuple[int, bytearray]]:
323-
return [(x.offset, x.contents) for x in self]
328+
return [(x.offset, x.data) for x in self]
324329

325330
def dump_table(self) -> tuple[int, bytearray]:
326331
buf = bytearray()
@@ -337,9 +342,9 @@ def __getitem__(self, offset: int) -> str:
337342
return self._get_string(offset)
338343

339344
def _get_string(self, index: int) -> str:
340-
if index > len(self.contents) or index == SHN.UNDEF:
345+
if index > self.size or index == SHN.UNDEF:
341346
return None
342-
return self.c_elf.char[None](self.contents[index:]).decode("utf8")
347+
return self.c_elf.char[None](self.data[index:]).decode("utf8")
343348

344349

345350
class Symbol:
@@ -372,7 +377,7 @@ def _set_name(self, table: StringTable) -> None:
372377
@classmethod
373378
def from_symbol_table(cls, table: SymbolTable, idx: int) -> Symbol:
374379
offset = idx * table.entry_size
375-
data = table.contents[offset : offset + table.entry_size]
380+
data = table.data[offset : offset + table.entry_size]
376381
output = cls(io.BytesIO(data), idx, table.c_elf)
377382
output._set_name(table.link)
378383
return output

dissect/executable/pe/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from dissect.executable.pe.pe import PE
2+
3+
__all__ = [
4+
"PE",
5+
]

0 commit comments

Comments
 (0)