Python PE parsing module for analyzing Portable Executable (PE) files with comprehensive header, section, and directory entry support
—
Methods for reading and writing data within PE files, including address translation between file offsets and relative virtual addresses (RVAs). These functions enable direct manipulation of PE file contents.
Convert between file offsets and relative virtual addresses (RVAs) for accurate data access.
def get_rva_from_offset(self, offset):
"""
Convert file offset to relative virtual address (RVA).
Args:
offset (int): File offset
Returns:
int: RVA corresponding to the offset, or None if invalid
"""
def get_offset_from_rva(self, rva):
"""
Convert relative virtual address (RVA) to file offset.
Args:
rva (int): Relative virtual address
Returns:
int: File offset corresponding to the RVA, or None if invalid
"""
def get_physical_by_rva(self, rva):
"""
Get physical address from RVA.
Args:
rva (int): Relative virtual address
Returns:
int: Physical address
"""Read raw data and strings from PE files at specific locations.
def get_data(self, rva=0, length=None):
"""
Get data at RVA regardless of section boundaries.
Args:
rva (int): Relative virtual address to read from
length (int, optional): Number of bytes to read. If None, reads to end.
Returns:
bytes: Data at the specified RVA
"""
def get_string_at_rva(self, rva, max_length=1048576):
"""
Get null-terminated ASCII string at RVA.
Args:
rva (int): Relative virtual address
max_length (int): Maximum string length to prevent excessive memory use
Returns:
bytes: ASCII string (without null terminator)
"""
def get_string_u_at_rva(self, rva, max_length=65536, encoding=None):
"""
Get null-terminated Unicode string at RVA.
Args:
rva (int): Relative virtual address
max_length (int): Maximum string length in characters
encoding (str, optional): Text encoding to use
Returns:
str: Unicode string
"""
def get_bytes_from_data(self, offset, data):
"""
Get bytes from data buffer starting at offset.
Args:
offset (int): Offset into data buffer
data (bytes): Data buffer
Returns:
bytes: Extracted bytes
"""
def get_string_from_data(self, offset, data):
"""
Get null-terminated ASCII string from data buffer.
Args:
offset (int): Offset into data buffer
data (bytes): Data buffer
Returns:
bytes: ASCII string (without null terminator)
"""Read and write integer values at specific addresses with various sizes.
def get_dword_at_rva(self, rva):
"""
Get 32-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
Returns:
int: 32-bit value at RVA
"""
def get_word_at_rva(self, rva):
"""
Get 16-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
Returns:
int: 16-bit value at RVA
"""
def get_qword_at_rva(self, rva):
"""
Get 64-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
Returns:
int: 64-bit value at RVA
"""
def set_dword_at_rva(self, rva, dword):
"""
Set 32-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
dword (int): 32-bit value to write
"""
def set_word_at_rva(self, rva, word):
"""
Set 16-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
word (int): 16-bit value to write
"""
def set_qword_at_rva(self, rva, qword):
"""
Set 64-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
qword (int): 64-bit value to write
"""
def set_bytes_at_rva(self, rva, data):
"""
Set bytes at RVA.
Args:
rva (int): Relative virtual address
data (bytes): Data bytes to write
"""
def get_dword_from_offset(self, offset):
"""
Get 32-bit unsigned integer at file offset.
Args:
offset (int): File offset
Returns:
int: 32-bit value at offset
"""
def set_dword_at_offset(self, offset, dword):
"""
Set 32-bit unsigned integer at file offset.
Args:
offset (int): File offset
dword (int): 32-bit value to write
"""
def get_word_at_rva(self, rva):
"""
Get 16-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
Returns:
int: 16-bit value at RVA
"""
def set_word_at_rva(self, rva, word):
"""
Set 16-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
word (int): 16-bit value to write
"""
def get_word_from_offset(self, offset):
"""
Get 16-bit unsigned integer at file offset.
Args:
offset (int): File offset
Returns:
int: 16-bit value at offset
"""
def set_word_at_offset(self, offset, word):
"""
Set 16-bit unsigned integer at file offset.
Args:
offset (int): File offset
word (int): 16-bit value to write
"""
def get_qword_at_rva(self, rva):
"""
Get 64-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
Returns:
int: 64-bit value at RVA
"""
def set_qword_at_rva(self, rva, qword):
"""
Set 64-bit unsigned integer at RVA.
Args:
rva (int): Relative virtual address
qword (int): 64-bit value to write
"""
def get_qword_from_offset(self, offset):
"""
Get 64-bit unsigned integer at file offset.
Args:
offset (int): File offset
Returns:
int: 64-bit value at offset
"""
def set_qword_at_offset(self, offset, qword):
"""
Set 64-bit unsigned integer at file offset.
Args:
offset (int): File offset
qword (int): 64-bit value to write
"""Read and write arbitrary byte sequences at specific locations.
def set_bytes_at_rva(self, rva, data):
"""
Set bytes at RVA.
Args:
rva (int): Relative virtual address
data (bytes): Data to write
"""
def set_bytes_at_offset(self, offset, data):
"""
Set bytes at file offset.
Args:
offset (int): File offset
data (bytes): Data to write
"""
def set_data_bytes(self, offset, data):
"""
Set bytes in internal PE data buffer.
Args:
offset (int): Offset into internal data
data (bytes): Data to write
"""Manage modified section data and apply changes to the PE structure.
def merge_modified_section_data(self):
"""
Update PE internal data with modified section data.
This method applies any changes made to section data back to the
main PE data structure, ensuring consistency between section objects
and the underlying file data.
"""import pefile
with pefile.PE('executable.exe') as pe:
# Read ASCII string at specific RVA
string_data = pe.get_string_at_rva(0x1000)
print(f"ASCII string: {string_data}")
# Read Unicode string
unicode_string = pe.get_string_u_at_rva(0x2000)
print(f"Unicode string: {unicode_string}")
# Read raw data
raw_data = pe.get_data(0x3000, 100) # Read 100 bytes
print(f"Raw data: {raw_data.hex()}")import pefile
with pefile.PE('executable.exe') as pe:
# Convert between file offset and RVA
file_offset = 0x1000
rva = pe.get_rva_from_offset(file_offset)
print(f"File offset {hex(file_offset)} -> RVA {hex(rva)}")
# Convert back
back_to_offset = pe.get_offset_from_rva(rva)
print(f"RVA {hex(rva)} -> File offset {hex(back_to_offset)}")import pefile
# Load PE file
pe = pefile.PE('executable.exe')
# Modify a DWORD value at specific RVA
original_value = pe.get_dword_at_rva(0x1000)
print(f"Original value: {hex(original_value)}")
pe.set_dword_at_rva(0x1000, 0x12345678)
new_value = pe.get_dword_at_rva(0x1000)
print(f"New value: {hex(new_value)}")
# Write modified PE file
pe.write('modified_executable.exe')
pe.close()import pefile
with pefile.PE('executable.exe') as pe:
# Access section by RVA
section = pe.get_section_by_rva(0x1000)
if section:
print(f"Section name: {section.Name.decode('utf-8').strip()}")
# Modify section data
section_data = bytearray(section.get_data())
section_data[0:4] = b'TEST' # Replace first 4 bytes
# Update section with modified data
section.set_data(bytes(section_data))
# Apply changes to PE structure
pe.merge_modified_section_data()import pefile
with pefile.PE('executable.exe') as pe:
# Check if file has overlay data
overlay_start = pe.get_overlay_data_start_offset()
if overlay_start:
print(f"Overlay starts at offset: {hex(overlay_start)}")
# Get overlay data
overlay = pe.get_overlay()
print(f"Overlay size: {len(overlay)} bytes")
# Remove overlay and get clean PE
clean_pe_data = pe.trim()
with open('clean_executable.exe', 'wb') as f:
f.write(clean_pe_data)Install with Tessl CLI
npx tessl i tessl/pypi-pefile