Address mapping (analysis.map)
- analysis.map: MappingAnnotation
The
analysis.map
object is aMappingAnnotation
instance that allows you to access the File layout and convert addresses between three forms (see Addressing in Malcat).
Addressing in Malcat
Malcat can manipulate addresses in three different forms:
Physical addresses: a file offset, used within the
analysis.file
object for instanceVirtual addresses: an absolute memory address
Effective addresses: a contiguous address space which contains both physical and virtual address spaces.
Unless specified differently, most of Malcat python methods manipulate effective addresses. But what is exactly this effective address space? Think of a PE file organized as follow:
a 0x200 bytes header
a
.bss
purely virtual section, loaded at address 0x401000-0x402000a
.text
section, loaded at address 0x402000-0x404300 and stored at file offset 0x200 - 0x2200 (the last 0x300 bytes are not file-backed)an overlay which won’t be loaded in memory, stored at file offset 0x2200-0x3000
Some of Malcat’s analyses are only interested in the physical representation of the file, like the Entropy computation and do not care about the virtual space. Some analyses want to take the virtual space into account (e.g. the Cross References Scanner), some want both. Having to juggle constantly between physical and virtual addresses is difficult. A solution is to use an effective address space which is the concatenation of both address space:
it starts with the header at address [0x0-0x200[
then maps the .bss section at address [0x200-0x1200[
then maps the .text section at address [0x1200-0x3500[
and finally maps the overlay at address [0x3500-0x4300[
This make most analysis work much easier because the effective address space is contiguous. We can describe all the parts of a file (physical and virtual spaces) by using an integer in the range [0x0-0x4300[.
Note
For simple file types (i.e. files formats which don’t specify any specific mapping), the three address spaces are equivalent, i.e. physical address = virtual address = effective address
Mapping object
- class malcat.MappingAnnotation
This class contains region layout information for a file.
- base: int
the file’s imagebase, i.e. the virtual address it will be loaded in memory. Will be 0 if the file is not loaded into memory.
- end: int
the maximum effective address valid for this file
- regions: List[malcat.Region]
the list of the file’s regions
- __iter__()
Iterate over the file’s regions
- Returns:
iterator over the list of regions
- Return type:
iterator
- __contains__(address)
Check if an effective address belongs to the file’s mapping
- Parameters:
address (int) – an effective address
- Returns:
true iff address <=
end
- Return type:
bool
- __contains__(name)
Check if the file contains any region named name. Example:
has_reloc = ".reloc" in analysis.map
- Parameters:
name (str) – a section/region name
- Returns:
true iff there is a region such as
malcat.Region.name
== name- Return type:
bool
- get_region(address)
Get the region containing a given effective address
- Parameters:
address (int) – an effective address
- Returns:
the region containing address or None if none
- Return type:
malcat.Region or None
- __getitem__(address)
Return the region containing a given effective address. Example:
ep_rva = analysis.struct["OptionalHeader"]["AddressOfEntryPoint"] ep_region = analysis.map[analysis.map.r2a(ep_rva)] print("EP located inside section {}".format(ep_region.name))
- Parameters:
address (int) – an effective address
- Returns:
the region containing address
- Return type:
- Raises:
KeyError
if address does not belong to any region
- __getitem__(name)
Get the first region named name. Example:
if ".rsrc" in analysis.map: rsrc_offset = analysis.map[".rsrc"].phys rsrc_size = analysis.map[".rsrc"].phys_size rsrc_data = analysis.file[rsrc_offset : rsrc_offset + rsrc_size]
- Parameters:
name (str) – name of the region
- Returns:
the first region named name
- Return type:
- Raises:
KeyError
if no region could be found
Conversion functions
The
analysis.map
object allows you to convert addresses to and from the three different address spaces. Note that not all addresses may be converted. Physical address may not lay in the file, and virtual addresses may not be valid for a given mapping. In this case, the conversion functions will returnNone
.Offsets
- from_phys(offset)
converts a file offset to an effective address. Example:
offset = 0x1000 va = analysis.map.to_virt(analysis.map.from_phys(offset))
- Parameters:
offset (int) – a file offset, e.g.
0x10
.- Returns:
the corresponding effective address or
None
if the file offset is greater or equal than the file size- Return type:
int
- to_phys(effective_address)
converts an effective address to a file offset. Example:
va = 0x401000 offset = analysis.map.to_phys(analysis.map.from_virt(va))
- Parameters:
effective_address (int) – an effective address.
- Returns:
the corresponding file offset or
None
if the effective address belongs to a purely virtual address space.- Return type:
int
Also if you don’t like typing:
- p2a(offset)
shortcut for
analysis.map.from_phys()
.
- a2p(effective_address)
shortcut for
analysis.map.to_phys()
.
Virtual address
- from_virt(virtual_address)
converts a virtual address to an effective address. Example:
va = 0x401000 offset = analysis.map.to_phys(analysis.map.from_virt(va))
- Parameters:
virtual_address (int) – a virtual memory address, e.g.
0x401000
.- Returns:
the corresponding effective address or
None
if the virtual address is not mapped.- Return type:
int
- to_virt(effective_address)
converts an effective address to a virtual address. Example:
offset = 0x1000 va = analysis.map.to_virt(analysis.map.from_phys(offset))
- Parameters:
effective_address (int) – an effective address.
- Returns:
the corresponding virtual address or
None
if the effective address does not belong to a virtual-mapped space.- Return type:
int
Also if you don’t like typing:
- v2a(virtual_address)
shortcut for
analysis.map.from_virt()
.
- a2v(effective_address)
shortcut for
analysis.map.to_virt()
.
RVA
- from_rva(rva)
converts a Relative Virtual Address to an effective address. This is strictly equivalent to
analysis.map.from_virt(malct.map.base + rva)
.- Parameters:
offset (int) – a relative virtual address, e.g.
0x1000
.- Returns:
the corresponding effective address or
None
if the RVA does not belong to a virtual-mapped space.- Return type:
int
- to_rva(effective_address)
converts an effective address to a Relative Virtual Address
- Parameters:
effective_address – an effective address.
- Returns:
the corresponding Relative Virtual Address or
None
if the effective address does not belong to a virtual-mapped space.- Return type:
int
Also if you don’t like typing:
- r2a(rva)
shortcut for
analysis.map.from_rva()
.
- a2r(effective_address)
shortcut for
analysis.map.to_rva()
.
File layout and regions
The analysis.map
object allows you also to list all the regions of the file. A region is a contiguous memory interval which has a physical and/or a virtual address and a name. It does not have to be a 1:1 mapping to a program’s section. For instance, a PE file will feature, in addition to the PE sections, a “header” region and (maybe) an “overlay” region. For an ELF file, the regions are computed using both segments AND sections information.
You can get the list of regions from the MappingAnnotation.regions
list or using other query methods from analysis.map
. A region is an instance of Region
which is decribed below:
- class malcat.Region
A region is a contiguous memory interval which has a physical and/or a virtual address and a name.
- name: str
name of region (e.g. “.text”)
- address: int
effective address of the first byte of the region
- size: int
size of region in the effective address space. This is the maximum size between its physical and virtual size.
- phys: int
file offset of first bit of region
- phys_size: int
size of region on disk
- virt: int
address of region in memory
- virt_size: int
size of region in memory
- read: bool
True iff region has read rights
- write: bool
True iff region has write rights
- exec: bool
True iff region has exec rights