# Carved files (analysis.carved)

analysis.carved: malcat.CarvedFiles

  The `analysis.carved` object is a `malcat.CarvedFiles` instance that gives you access to all the carved files extracted by the File carving algorithm.

Note that in addition to this documentation, you can find usage examples in the sample script which is loaded when you hit `F8`.

## What are carved files?

Malcat can list and extract two different types of sub-files:

- The current File parsers will parse the structures of the current file and interpret their content, looking for descriptions or links to stored / packed files. These can be archive members in a ZIP file, files in an ISO image or resource items defined in a PE program for instance. These are listed inside the Virtual File System tab.

- Malcat will run a File carving algorithm and scan the entire file range for embedded files of known types (like binwalk, but without all the FPs). This pass can identify files even in raw dumps. These are listed inside the Carved files tab.

The `analysis.carved` gives you access to the second category, i.e. the list of carved files. These files have been successfully parsed by one of Malcat’s File parsers.

## Accessing / enumerating carved files

class malcat.CarvedFiles

  This class contains all the carved files extracted by the File carving algorithm. Note that all addresses used in this class are effective addresses. See Addressing in Malcat for more details.

  __iter__()

    Iterate over all the carved files :: for sub in analysis.carved:

    > print(f”* Found sub-file ‘{sub.name}’ in .rsrc at #{analysis.map.to_phys(sub.address):x} ({sub.size} bytes): {sub.type} [{sub.category}]”)

    Return type:

      iterator over `CarvedFile`

  __getitem__(interval)

    Iterate over all the sub-files carved within the given interval (effective address): ::

        rsrc = analysis.map[".rsrc"]
        for sub in analysis.carved[rsrc.start:rsrc.end]:
            print(f"* Found sub-file '{sub.name}' in .rsrc at #{analysis.map.to_phys(sub.address):x} ({sub.size} bytes): {sub.type} [{sub.category}]")

    Parameters:

      interval (slice) – effective address interval

    Return type:

      iterator over the list of functions (`CarvedFile`)

  __getitem__(ea)

    Returns the `CarvedFile` containing the effective address ea.

        subfile = analysis.carved[0x500]

    Parameters:

      ea (int) – effective address

    Return type:

      `CarvedFile` instance

    Raises:

      `KeyError` if ea does not belong to the file’s effective address space

  __contains__(ea)

    return True iff the effective address ea lies within a carved file

    Parameters:

      ea (int) – address to query

    Return type:

      bool

  find(ea)

    return the `CarvedFile` which starts at or contains the effective address ea, or None if no one can be found.

    Parameters:

      ea (int) – effective address for the query

    Return type:

      `CarvedFile` or None

  find_forward(ea)

    return the `CarvedFile` which starts at or contains the effective address ea or starts directly after ea, or None if no `CarvedFile` is defined beyond ea.

        first_carved_file = analysis.carved.find_forward(0)
        if first_carved_file is None:
            raise ValueError("No file carved!")

    Parameters:

      ea (int) – effective address for the query

    Return type:

      `CarvedFile` or None

  find_backward(ea)

    return the `CarvedFile` which starts at or contains the effective address ea or the first one that start before ea, or None if no `CarvedFile` is defined before ea.

        last_carved_file = analysis.carved.find_backward(analysis.map.end)
        if last_carved_file is None:
            raise ValueError("No file carved!")

    Parameters:

      ea (int) – effective address for the query

    Return type:

      `CarvedFile` or None

  __len__()

    return the number of successfully carved files

        if len(analysis.carved) == 0:
            raise ValueError("No carved files!")

    Return type:

      int

## The carved file object

class malcat.CarvedFile

  This class represents one sub-file that has been extracted by the File carving algorithm.

  address: int (effective address)

    the start of the carved file

  start: int (effective address)

    > same as `address`

  end: int (effective address)

    last effective address inside the carved file + 1

  size: int

    size in bytes of the carved file: `end` - `start`

  __len__()

    return the size in bytes of the carved file: `end` - `start`

  name: str

    nice name for the carved file, e.g. `PNG.#9ee5`. Sometimes a better name is given, if the carved file is part of a named structure like a PE resource.

  type: str

    the type of the identified file as givem by the correspondig file parser: “PE”, “BMP”, etc.

  category: malcat.FileType.Category

    the category fo the corresponding file’s type, i.e. if it’s a program, an archive, an image, etc. Use by some anomaly functions.

  open()

    open the careved object into a file that you can use with `malcat.analyse()`. Note that you don’t need to close the file, it happens automatically. Also the file won’t take any place in RAM.

    Return type:

      malcat.File

## Dumping a carved object to disk

If you want to save the content of one or multiple carved objects, you can do it simply using Malcat’s File object (analysis.file):

    import re

    for sub in analysis.carved:
        offset = analysis.a2p(sub.address)
        data = sub.open().read()
        # data = analysis.file[offset:offset + sub.size] # equivalent
        filename = re.sub('[^\w_.)( -]', '_', sub.name)
        with open(filename, "wb") as f:
            f.write(data)