# Address mapping (analysis.map)

analysis.map: MappingAnnotation

  The `analysis.map` object is a `MappingAnnotation` 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 instance

- Virtual 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-0x402000

- a `.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:

      malcat.Region

    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:

      malcat.Region

    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 return `None`.

  #### 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.

  __len__()
    Return type:

      int

    Returns:

      same as `size`

  start: int

    same as `address`

  end: int

    same as `address` + `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