dissect.database.ese

Subpackages

Submodules

Package Contents

Classes

ESE

ESE database class.

Index

Represents an index on a table.

Page

Represents a logical page of an ESE database.

Record

Wrapper class for records in a table.

Table

Represents a table in an ESE database.

class dissect.database.ese.ESE(fh: BinaryIO, impacket_compat: bool = False)

ESE database class.

Loads an ESE database from the given file handle. Optionally enable impacket compatible data output.

Impacket compatibility limits what values are parsed and returns most values as a hex string. Most notably, long and multi values are not parsed.

Parameters:
  • fh – The file-like object to open an ESE database on.

  • impacket_compat – Whether to make the output impacket compatible.

Raises:

InvalidDatabase – If the file-like object does not look like an ESE database.

fh
impacket_compat = False
header
page_size
version
format_major
format_minor
catalog
page
property has_small_pages: bool

Return whether this database has small pages (<= 8K).

table(name: str) dissect.database.ese.table.Table

Get a table by name.

Parameters:

name – The table to retrieve.

tables() list[dissect.database.ese.table.Table]

Get a list of all tables.

read_page(num: int) bytes

Get the physical page data.

Parameters:

num – The physical page number to retrieve.

Raises:

IndexError – If the page number is out of bounds.

pages() collections.abc.Iterator[dissect.database.ese.page.Page]

Iterate over all pages.

exception dissect.database.ese.InvalidDatabase

Bases: dissect.database.exception.Error

Common base class for all non-exit exceptions.

exception dissect.database.ese.KeyNotFoundError

Bases: dissect.database.exception.Error

Common base class for all non-exit exceptions.

exception dissect.database.ese.NoNeighbourPageError

Bases: dissect.database.exception.Error

Common base class for all non-exit exceptions.

class dissect.database.ese.Index(table: dissect.database.ese.table.Table, record: dissect.database.ese.record.Record | None = None)

Represents an index on a table.

This is still very much WIP but works for basic indexes. For example, none of the special flags are currently implemented.

Parameters:
  • table – The table this index is from.

  • record – The record in the catalog for this index.

table
record = None
db
name
idb_flags
idx_flags
__repr__() str
property is_primary: bool
property root: dissect.database.ese.page.Page

Return the root page of this index.

property column_ids: list[int]

Return a list of column IDs that are used in this index.

property columns: list[dissect.database.ese.table.Column]

Return a list of all columns that are used in this index.

cursor() dissect.database.ese.cursor.Cursor

Create a new cursor for this index.

search(**kwargs) dissect.database.ese.record.Record

Search the index for the requested values.

Parameters:

**kwargs – The columns and values to search for.

Returns:

A Record object of the found record.

search_key(key: bytes) dissect.database.ese.page.Node

Search the index for a specific key.

Parameters:

key – The key to search for.

Returns:

A Node object of the found node.

key_from_record(record: dissect.database.ese.record.Record) bytes

Generate a key for this index from a record.

Parameters:

record – The record to generate a key for.

make_key(values: dict[str, dissect.database.ese.util.RecordValue]) bytes

Generate a key out of the given values.

Parameters:

values – A map of the column names and values to generate a key for.

class dissect.database.ese.Page(db: dissect.database.ese.ese.ESE, num: int, buf: bytes)

Represents a logical page of an ESE database.

Parameters:
  • db – An instance of ESE.

  • num – The logical page number.

  • buf – The physical page data.

db
num
buf
header
header2 = None
flags
previous_page
next_page
data
tag_reserved
tag_count
node_count
property is_small_page: bool
property is_root: bool
property is_leaf: bool
property is_parent: bool
property is_empty: bool
property is_space_tree: bool
property is_index: bool
property is_long_value: bool
property is_branch: bool
property key_prefix: bytes | None
tag(num: int) Tag

Retrieve a tag by index.

Parameters:

num – The tag number to retrieve.

Raises:

IndexError – If the tag number is out of bounds.

tags() collections.abc.Iterator[Tag]

Yield all tags.

node(num: int) BranchNode | LeafNode

Retrieve a node by index.

Nodes are just tags, but indexed from the first tag.

Parameters:

num – The node number to retrieve.

Raises:

IndexError – If the node number is out of bounds.

nodes() collections.abc.Iterator[BranchNode | LeafNode]

Yield all nodes.

iter_leaf_nodes() collections.abc.Iterator[LeafNode]

Walk the page tree and yield leaf nodes.

Two methods can be used, one is to travel down to the first leaf, and keep reading next_page’s, the other is to traverse the tree branches.

Impacket uses the first method, but gets caught in an infinite loop on some dirty databases. Traversing the branches seems safer, at the risk of missing a couple (possibly corrupt) pages.

For this reason, we actually explicitly check if the last page we parse has a next_page attribute, and also parse that. This methods seems to work so far.

__repr__() str
class dissect.database.ese.Record(table: dissect.database.ese.table.Table, node: dissect.database.ese.page.Node)

Wrapper class for records in a table.

The actual parsing of the data is done in RecordData, but this class allows you to easily retrieve all the values by either using the .get() method, accessing them as attributes or dictionary keys on this class.

Parameters:
  • table – The table this record is from.

  • node – The node of this record.

__str__() str
__repr__() str
__hash__() int
__getitem__(attr: str) dissect.database.ese.util.RecordValue
__getattr__(attr: str) dissect.database.ese.util.RecordValue
__eq__(value: object) bool
__ne__(value: object) bool
__lt__(value: object) bool
__le__(value: object) bool
__gt__(value: object) bool
__ge__(value: object) bool
get(attr: str, raw: bool = False) dissect.database.ese.util.RecordValue

Retrieve a value from the record with the given name.

Optionally receive the raw data as it’s stored in the record.

Parameters:
  • attr – The column name to retrieve the value of.

  • raw – Whether to return the raw data stored in the record instead of the parsed value.

as_dict(raw: bool = False) dict[str, dissect.database.ese.util.RecordValue]
class dissect.database.ese.Table(db: dissect.database.ese.ese.ESE, name: str, root_page: int, columns: list[Column] | None = None, indexes: list[dissect.database.ese.index.Index] | None = None, record: dissect.database.ese.record.Record = None)

Represents a table in an ESE database.

Contains all the relevant metadata of the table, as well as all columns and indices that have been added by the catalog.

Parameters:
  • db – An instance of ESE.

  • name – The table name.

  • root_page – The root page of the table.

  • columns – A list of Column for this table.

  • indexes – A list of Index for this table.

  • record – The Record of this table from the catalog table.

db
name
root_page
columns: list[Column] = []
indexes: list[dissect.database.ese.index.Index] = []
record = None
__repr__() str
property root: dissect.database.ese.page.Page

Return the root page of the table.

property lv_page: dissect.database.ese.page.Page

Return the long value page of the table.

Raises:

TypeError – If the table has no long values.

column(name: str) Column

Return the column with the given name.

Parameters:

name – The name of the column to return.

Raises:

KeyError – If no column with the given name exists.

property column_names: list[str]

Return a list of all the column names.

property primary_index: dissect.database.ese.index.Index | None
cursor() dissect.database.ese.cursor.Cursor | None

Create a new cursor for this table.

index(name: str) dissect.database.ese.index.Index

Return the index with the given name.

Parameters:

name – The name of the index to return.

Raises:

KeyError – If no index with the given name exists.

find_index(column_names: list[str]) dissect.database.ese.index.Index | None

Find the most suitable index to search for the given columns.

Parameters:

column_names – A list of column names to find the best index for.

search(**kwargs: dissect.database.ese.util.RecordValue) dissect.database.ese.record.Record | None

Search for a record in the table.

Parameters:

**kwargs – The columns and values to search for.

Returns:

The first record that matches the search criteria, or None if no record was found.

records() collections.abc.Iterator[dissect.database.ese.record.Record]

Return an iterator of all the records of the table.

get_long_value(key: bytes) bytes

Retrieve a value from the long value page of the table.

Parameters:

key – The lookup key for the long value.