# User highlighted regions (analysis.highlights)

analysis.highlights: malcat.UserHighlights

  The `analysis.highlights` object is a `malcat.UserHighlights` instance that gives you access to all the regions highlighted by the user.

Highlighted regions are simple text are regions which were given a title, a note text and a category by the user. They can be viewed in the Hexadecimal view or the Structure/text view (see Highlight/annotate a region). They are saved within a `.malcat` project. In addition to the UI, highlighted regions can also be parsed and edited programmatically as we will see in this chapter.

Highlighting user regions using the UI

## Navigating over and editing highlighted regions

To list and search for user highlights, you can use the methods from the `UserHighlights` class:

class malcat.UserHighlights

  This class contains all highlighted regions added by the user, either via the user interface or the python bindings. Note that all addresses used in this class are effective addresses. See Addressing in Malcat for more details.

  ### Navigation

  __iter__()

    Iterate over all the user highlighted regions

        for hl in analysis.highlights:
            print(f"{analysis.ppa(hl.address)}: [{hl.category}] {hl.title}")

    Return type:

      iterator over `UserHighlight`

  __getitem__(interval)

    Iterate over all the user highlighted regions contained in the interval (effective address):

        hls = list(analysis.highlights[analysis.p2a(0) : analysis.p2a(0x5000)])
        print("there are {} highlighted regions in range[#0-#5000[".format(len(coms)))

    Parameters:

      interval (slice) – effective address interval

    Return type:

      iterator over the list of comments (`UserHighlight`)

  __getitem__(ea)

    Returns the `UserHighlight` at the effective address ea.

        ep_rva = analysis.struct['OptionalHeader']['AddressOfEntryPoint']
        ep_hl = analysis.highlights[analysis.r2a(ep_rva)]

    Parameters:

      ea (int) – effective address

    Return type:

      `UserHighlight`

    Raises:

      `KeyError` if no user highlight is defined at ea

  __contains__(ea)

    return True iff there exists a highlighted region at effective address ea

    Parameters:

      ea (int) – address to query

    Return type:

      bool

  find(ea)

    return the `UserHighlight` at the effective address ea, or None if no one can be found.

    Parameters:

      ea (int) – effective address for the query

    Return type:

      `UserHighlight` or None

  find_forward(ea)

    return the `UserHighlight` which at the effective address ea or the one after ea, or None if no `UserHighlight` is defined beyond ea.

        first_hl = analysis.highlights.find_forward(0)
        if first_hl is None:
            raise ValueError("No highlighted region!")

    Parameters:

      ea (int) – effective address for the query

    Return type:

      `UserHighlight` or None

  find_backward(ea)

    return the `UserHighlight` which at the effective address ea or the first one before ea, or None if no `UserHighlight` is defined before ea.

        last_hl = analysis.highlights.find_backward(analysis.map.end)
        if last_hl is None:
            raise ValueError("No highlighted region!")

    Parameters:

      ea (int) – effective address for the query

    Return type:

      `UserHighlight` or None

  __len__()

    return the number of user highlighted regions

        if len(analysis.highlights) == 0:
            raise ValueError("No highlighted region!")

    Return type:

      int

  ### Edit

  add(hl_region)

    add a new highlighted region object to the analysis. Returns true on success. Will register the operation into the Undo/redo manager.

        address_start = analysis.v2a(0x401000)
        address_end = analysis.v2a(0x402000)
        c = malcat.UserHighlight(address_start, address_end - address_start, "title", "a comment text", malcat.Category.DEBUG)
        if not analysis.highlights.add(c):
            raise ValueError(f"Could not highlight user region [{analysis.ppa(address_start)}-{analysis.ppa(address_end)}[")

    Parameters:

      hl_region (UserHighlight) – the region to highlight

    Return type:

      bool

  __setitem__(interval, title)

    > highlight the given effective address interval and set the region’s title. The region will have no comment and the default category DEBUG. Like `add()`, but with a simplified prototype. Will also register the operation into the Undo/redo manager.

    >     analysis.highlights[analysis.v2a(0x401000) : analysis.v2a(0x402000)] = "the region title"

    > param slice interval:

    >   effective address interval

    > param str title:

    >   the title of the highlighted region

    remove(ea)

      remove an existing highlighted region object from the analysis. Returns true on success. Will register the delete operation into the Undo/redo manager.

          if not analysis.highlights.remove(analysis.v2a(0x401000)):
              raise ValueError(f"Could not remove highlighted region at {analysis.ppa(address)}")

      Parameters:

        ea (int) – the address of the highlighted region to delete

      Return type:

        bool

  __delitem__(ea)

    shortcut for `remove()`

        del analysis.highlights[analysis.v2a(0x401000)]

    Parameters:

      ea (int) – the address of the highlighted region to delete

## User highlighted region object

A user highlighted region is a file interval which has been given a title, a comment and a category by the user:

class malcat.UserHighlight
  __init__(ea, size, title, text='', category=malcat.Category.DEBUG)

    > Create a new highlighted region instance, for use with the `UserHighlights.add()` function

    >     address_start = analysis.v2a(0x401000)
    >     address_end = analysis.v2a(0x402000)
    >     c = malcat.UserHighlight(address_start, address_end - address_start, "title", "a comment text", malcat.Category.DEBUG)
    >     if not analysis.highlights.add(c):
    >         raise ValueError(f"Could not highlight user region [{analysis.ppa(address_start)}-{analysis.ppa(address_end)}[")

    > param int ea:

    >   the start address of the region to highlight

    > param int size:

    >   the size of the region

    > param str title:

    >   the title of the region

    > param str text:

    >   the comment for the region

    > param malcat.Category category:

    >   the category of the region

    address: int (effective address)

      the address of the highlighted region

    size: int

      the size of the highlighted region

    title: str

      the title of the highlighted region

    content: str

      the content of the comment. May contains newlines.

    __repr__()

      return the value of the `title` property

      Return type:

        str

    __len__()

      return the value of the `size` property

      Return type:

        int

The category of a highlighted region dictates its color in the UI and wether it will be displayed or not, depending on Highlighting.

class malcat.Category

  This enum describes the category of a note in Malcat.

  HEADER
  CODE
  DATA
  MATCH
  METADATA
  REFERENCE
  DEBUG
  FIXUP
  RESOURCE
  ANOMALY

## Note about editing user highlights

### Undo/redo

Each highlighted region you add gets saved in the list of undoable operations, which can be somewhat expensive if you plan to add thousands of highlighted regions. In general, if you plan to do a lot of modifications (highlighted regions or other types of edits like file writes for instance), you can chose to deactivate undos:

    analysis.history.record(False)
    # ... add your highlighted regions, they won't appear in the undo list
    for i in range(malcat.map.end):
         malcat.highlights[i:i+1] = "..."
    # ... reactivate undo/redo
    analysis.history.record(True)

Note

Edits which are not recorded to the undo list are invisible to Malcat. It means Malcat will not see that the file has been modified and the UI won’t offer you to save your modifications on quit.

If you stil want to record your edits in the undo/redo but you would like to group them in just one operation, you can do it too:

    with analysis.history.group()
        # ... add your highlighted regions
    for i in range(malcat.map.end):
         malcat.highlights[i:i+1] = "..."
     analysis.history.undo()     # <-- will undo all highlighted regions in one go