zelos.memory module

class zelos.memory.Memory(emu, hook_manager, state, disableNX: bool = False)

Bases: object

Responsbile for interactions with emulated memory.

HEAP_BASE = 2415919104
HEAP_MAX_SIZE = 104857600
VALLOC_BASE = 12910592
MAX_UINT64 = 18446744073709551615
MAX_UINT32 = 4294967295
copy(other_memory: zelos.memory.Memory) → None

Duplicates memory regions from other_memory into this memory.

Parameters

other_memory – Memory to duplicate.

clear() → None

Clears all of memory

read(addr: int, size: int) → bytearray

Copies specified region of memory. Requires that the specified address is mapped.

Parameters
  • addr – Address to start reading from.

  • size – Number of bytes to read.

Returns

Bytes corresponding to data held in memory.

write(addr: int, data: bytes) → int

Writes specified bytes to memory. Requires that the specified address is mapped.

Parameters
  • addr – Address to start writing data to.

  • data – Bytes to write in memory.

Returns

Number of bytes written.

read_int(addr: int, sz: int = None, signed: bool = False) → int

Reads an integer value from the specified address. Can handle multiple sizes and representations of integers.

Parameters
  • addr – Address to begin reading int from.

  • sz – Size (# of bytes) of integer representation.

  • signed – If true, interpret bytes as signed integer. Default false.

Returns

Integer represntation of bytes read.

write_int(addr: int, value: int, sz: int = None, signed: bool = False) → int

Writes an integer value to the specified address. Can handle multiple sizes and representations of integers.

Parameters
  • addr – Address in memory to write integer to.

  • value – Integer to write into memory.

  • sz – Size (# of bytes) to write into memory.

  • signed – If true, write number as signed integer. Default false.

Returns

Number of bytes written to memory.

read_string(addr: int, size: int = 1024) → str

Reads a utf-8 string from memory. Stops at null terminator. Fails if a byte is uninterpretable.

Parameters
  • addr – Address in memory to start reading from.

  • size – Maximum size of string to read from memory.

Returns

String read from memory.

try_read_string(addr: int, size: int = 1024) → Optional[str]

Similar to read_string, however doesn’t log on failure. Use for when you are checking if a valid string exists.

read_wstring(addr: int, size: int = 1024) → str

Reads a utf-16 string from memory. Stops at null terminator. Fails if a byte is uninterpretable.

Parameters
  • addr – Address in memory to start reading from.

  • size – Maximum size of string to read from memory.

Returns

String read from memory.

write_string(addr: int, value: str, terminal_null_byte: bool = True) → int

Writes a string to a specified address as utf-8. By default, adds a terminal null byte.

Parameters
  • addr – Address in memory to begin writing string to.

  • value – String to write to memory.

  • terminal_null_byte – If True, adds terminal null byte. Default True.

Returns

Number of bytes written.

write_wstring(addr: int, value: int, terminal_null_byte: bool = True) → int

Writes a string to a specified address as utf-16-le. By default, adds a terminal null byte.

Parameters
  • addr – Address in memory to begin writing string to.

  • value – String to write to memory.

  • terminal_null_byte – If True, adds terminal null byte. Default True.

Returns

Number of bytes written.

readstruct(addr: int, obj: _ctypes.Structure) → _ctypes.Structure

Reads a ctypes structure from memory.

Parameters
  • addr – Address in memory to begin reading structure from.

  • obj – An instance of the structure to create from memory.

Returns

Instance of structure read from memory.

readstructarray(addr: int, count: int, obj: _ctypes.Structure) → List[_ctypes.Structure]

Read an array of ctypes structure from memory.

Parameters
  • addr – Address in memory to begin reading structure from.

  • count – number of instances of the object to read.

  • obj – An instance of the structure to create from memory.

Returns

List of structures read from memory.

writestruct(address: int, structure: _ctypes.Structure) → int

Write a ctypes Structure to memory.

Parameters
  • addr – Address in memory to begin writing to.

  • structure – An instance of the structure to write to memory.

Returns

Number of bytes written to memory.

dumpstruct(structure: _ctypes.Structure, indent_level: int = 0) → None

Prints a string representing the data held in a struct.

Parameters
  • structure – The structure to print out.

  • indent_level – Number of indents when printing output. Makes for easier reading. Defaults to no indentation.

map_anywhere(size: int, preferred_address: int = None, name: str = '', kind: str = '', module_name: str = '', min_addr: int = 4096, max_addr: int = 18446744073709551615, alignment: int = 4096, top_down: bool = False, prot: int = <ProtType.RWX: 7>, shared: bool = False) → int

Maps a region of memory with requested size, within the addresses specified. The size and start address will respect the alignment.

Parameters
  • size – # of bytes to map. This will be rounded up to match the alignment.

  • preferred_address – If the specified address is available, it will be used for the mapping.

  • name – String used to identify mapped region. Used for debugging.

  • kind – String used to identify the purpose of the mapped region. Used for debugging.

  • module_name – String used to identify the module that mapped this region.

  • min_addr – The lowest address that could be mapped.

  • max_addr – The highest address that could be mapped.

  • alignment – Ensures the size and start address are multiples of this. Must be a multiple of 0x1000. Default 0x1000.

  • top_down – If True, the region will be mapped to the highest available address instead of the lowest.

  • prot – RWX permissions of the mapped region. Defaults to granting all permissions.

  • shared – if True, region is shared with subprocesses.

Returns

Start address of mapped region.

map_file_anywhere(filename: str, offset: int = 0, size: int = 0, preferred_address: int = None, min_addr: int = 4096, max_addr: int = 18446744073709551615, alignment: int = 4096, top_down: bool = False, prot: int = <ProtType.RWX: 7>, shared: bool = False) → int

Maps a region of memory with requested size, within the addresses specified. The size and start address will respect the alignment.

Parameters
  • filename – Name of the file to memory map

  • offset – Page-aligned offset of file to start mapping

  • size – # of bytes to map. This will be rounded up to the nearest page.

  • preferred_address – If the specified address is available, it will be used for the mapping.

  • min_addr – The lowest address that could be mapped.

  • max_addr – The highest address that could be mapped.

  • alignment – Ensures the size and start address are multiples of this. Must be a multiple of 0x1000. Default 0x1000.

  • top_down – If True, the region will be mapped to the highest available address instead of the lowest.

  • prot – RWX permissions of the mapped region. Defaults to granting all permissions.

  • shared – if True, region is shared with subprocesses.

Returns

Start address of mapped region.

map(address: int, size: int, name: str = '', kind: str = '', module_name: str = '', prot: int = <ProtType.RWX: 7>, shared: bool = False, reserve: bool = False) → None

Maps a region of memory at the specified address.

Parameters
  • address – Address to map.

  • size – # of bytes to map. This will be rounded up to the nearest 0x1000.

  • name – String used to identify mapped region. Used for debugging.

  • kind – String used to identify the purpose of the mapped region. Used for debugging.

  • module_name – String used to identify the module that mapped this region.

  • prot – An integer representing the RWX protection to be set on the mapped region.

  • ptr – If specified, creates a memory map from the pointer.

  • shared – if True, region is shared with subprocesses.

  • reserve – Reserves memory to prepare for mapping. An option used in Windows.

map_file(address: int, filename: str, offset: int = 0, size: int = 0, prot: int = <ProtType.RWX: 7>, shared: bool = False) → int

Maps a region of memory at the specified address.

Parameters
  • address – Address to map.

  • filename – Name of the file to memory map

  • offset – page-aligned offset of file to start mapping

  • size – # of bytes to map. This will be rounded up to the nearest page.

  • prot – An integer representing the RWX protection to be set on the mapped region.

  • shared – if True, region is shared with subprocesses.

protect(address: int, size: int, prot: int) → None

Sets memory permissions on the specified memory region. Respects alignment of 0x1000.

Parameters
  • address – Address of memory region to modify permissions. Rounds down to nearest 0x1000.

  • size – Size of region to protect. Rounds up to nearest 0x1000.

  • prot – Desired RWX permissions.

unmap(address, size) → None

Unmaps a memory region, allowing it to be mapped again.

Parameters
  • address – Address of section to be unmapped.

  • size – Number of bytes to unmap.

get_base(address: int) → Optional[int]

Returns the base address of the memory region that contains this address.

Returns

The base address of the containing region, or None if address is not contained within any region.

get_module_base(name: str) → Optional[int]
get_perms(address: int) → int

Returns the permissions of the section containg the given address.

Parameters

address – Used to pick the containing section.

Returns

Permissions of the containing section.

get_size(address: int) → int

Returns the size of the section containg the given address.

Parameters

address – Used to pick the containing section.

Returns

Size of the containing section.

hook_first_read(region_addr, hook)
is_writable(address: int) → bool

Returns True if writing memory is allowed at the specified address.

get_region(address: int) → Optional[zelos.emulator.base.MemoryRegion]

Gets the region that this address belongs to.

get_regions()

Returns a list of all mapped memory regions.

read_ptr(addr: int) → int
read_size_t(addr: int) → int
read_int64(addr: int) → int
read_uint64(addr: int) → int
read_int32(addr: int) → int
read_uint32(addr: int) → int
read_int16(addr: int) → int
read_uint16(addr: int) → int
read_int8(addr: int) → int
read_uint8(addr: int) → int
write_ptr(addr: int, value: int) → int
write_size_t(addr: int, value: int) → int
write_int64(addr: int, value: int) → int
write_uint64(addr: int, value: int) → int
write_int32(addr: int, value: int) → int
write_uint32(addr, value)
write_int16(addr: int, value: int) → int
write_uint16(addr: int, value: int) → int
write_int8(addr: int, value: int) → int
write_uint8(addr: int, value: int) → int
find_free_space(size, preferred_address=None, min_addr=4096, max_addr=4294967295, alignment=65536, top_down=False)

Returns the start address of the next region between start and end that allows for memory of the given size to be mapped.

search(needle: bytes) → List[int]

Search for a sequence of bytes in memory. Returns all sequences that match

class zelos.memory.Heap(memory, heap_start, heap_max_size)

Bases: object

Helper class to manage heap allocation.

dealloc(size: int) → int

Returns memory from the heap.

Parameters

size – # of bytes to return from the heap.

Returns

Address of the new heap boundary.

alloc(size: int, name: str = None, align: int = 16) → int

Allocates memory to the heap. These are rounded up to the size of the alignment.

Parameters
  • size – Number of bytes to allocate.

  • name – Used to keep track of what information was allocated. Used for debugging

  • align – Ensures that the memory allocated is a multiple of this value. Defaults to 4.

Returns

Address of the new heap boundary

allocstr(s, terminal_null_byte=True, is_wide=False, alloc_name='allocstr')

Allocates a string to the heap. These are rounded up to the size of the alignment.

Parameters
  • size – Number of bytes to allocate.

  • name – Used to keep track of what information was allocated. Used for debugging

  • align – Ensures that the memory allocated is a multiple of this value. Defaults to 4.

Returns

Address of the new heap boundary