Skip to content

Commit fc0c81e

Browse files
committed
Fix pe parsing for section with 8bytes name
1 parent bd52b1a commit fc0c81e

2 files changed

Lines changed: 36 additions & 5 deletions

File tree

tests/test_parse_pe.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,6 @@ def test_pe_parsing_strange_optional_header_size(tmp_path, proc32):
9191
# Also check that section retrieval works (as its position is based on OptionalHeader Size)
9292
assert set(s.name for s in mod.pe.sections) == {".text", ".data", ".l1"}
9393

94-
95-
96-
9794
# Make a test from current_process parsing ?
9895
def test_pe_parsing_dotnet32_process_64(proc64, pe_dotnet32):
9996
# .NET pe32 loadable in 64bit process -> rewrite of the OptionalHeader
@@ -126,6 +123,27 @@ def test_pe_parsing_dotnet32_current_process_64(proc64, pe_dotnet32):
126123
assert imported_dlls == ['mscoree.dll']
127124
assert ".text" in sections_names
128125

126+
# PE header of Syschpe32\ntdll.dll with a 8 chars sections .hexpthk that broke the parseur
127+
# This PE as 8 bytes sections name + VirtualSize non aligned on 0x100 so there is a non-null non-ascii byte after the name
128+
PE_SECTION_8CHARS = b"""
129+
eJzzjZrAwMzAwMACxP//MzDsYIAABwbC4AMRagYbCHBlYPBhZEYRu8HAxMjNyMnAwMQAwSAgAMUK
130+
II4DhA2UY4VKw2hwQLFAmBBTFSBqQYQAwig4MECyg4ogAGiuMRZxvQgIuMDIAPcDAxuqGgUGhgS9
131+
SAjQhgqA1XGgqnNgYDigFwUBYHmYX7gwzHtAmW9GwSgYBfQAnU8b3zAAy4aMr/+BQNTGwIGht0aF
132+
IwMkF54BKg0yGBQcGAL+izoApTrfHJ4wvMAAB/+AA4/UnJx8hfL8opwUhbSi/FyFRIWAypKM/Dy3
133+
/KLwzLyU/PJihZLU4hIFUMU5CoYd0DBAsJuAbBsD7OpA7YsEIM4B4goD3GIMDO6pJcElKR6JeSk5
134+
qSB+eFFmSapbJpgTlJqYAmUyAFOXa0VqMkN2alFeao6xkV5KTg6NPDkKcAIAM7/CEw=="""
135+
136+
def test_pe_parsing_section_8_chars(proc32, tmp_path):
137+
pe_path = (tmp_path / "pe_parsing_8chars_section.exe")
138+
pe_data = pe_data = zlib.decompress(b64decode(PE_SECTION_8CHARS))
139+
140+
with pe_path.open("wb") as f:
141+
f.write(pe_data)
142+
143+
mod = proc32.load_library(str(pe_path))
144+
# check that section retrieval works
145+
assert set(s.name for s in mod.pe.sections) == {u".XXXXXXX", u".YYYYYYY", u".ZZZZZZZ"}
146+
129147
# A "Portable Executable 32 .NET Assembly" DLL
130148
# Result of compiling a simple hello-world
131149
# Can be loaded into a 64b process to witness 32 -> 64b PE conversion at load time

windows/pe_parse.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def name(self):
109109
if self.target is None:
110110
name = get_string(self.target, ctypes.addressof(self.Name))[:8]
111111
else:
112-
name = get_string(self.target, self._base_addr)[:8]
112+
name = self.target.read_memory(self._base_addr, 8).split(b"\x00", 1)[0].decode("ascii")
113113
# Decode as UTF-8 as the MS doc say ?
114114
return name
115115

@@ -451,4 +451,17 @@ def imports(self):
451451
iat_entry.name = str(name) if name else ""
452452
name = get_string(self.target, self.baseaddr + import_descriptor.Name)
453453
res.setdefault(name.lower(), []).extend(IAT)
454-
return res
454+
return res
455+
456+
@utils.fixedpropety
457+
def binid(self):
458+
"""Return the hex-string {TimeStamp}{SizeOfCode} used by PDB to identify a PE.
459+
460+
I do not know the official name of this value...
461+
462+
:type: :class:`str`
463+
"""
464+
nth = self.get_NT_HEADER()
465+
timestamp = nth.FileHeader.TimeDateStamp
466+
image_size = nth.OptionalHeader.SizeOfImage
467+
return "{timestamp:08x}{image_size:x}".format(timestamp=timestamp, image_size=image_size)

0 commit comments

Comments
 (0)