Skip to content

Commit

Permalink
Timestamps migration and updates (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
puffyCid authored Jun 10, 2024
1 parent 4570cf8 commit b58ff76
Show file tree
Hide file tree
Showing 113 changed files with 2,246 additions and 703 deletions.
18 changes: 15 additions & 3 deletions .github/workflows/pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,26 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Download macOS Intel script tester binary
- name: Download script tester binary macOS
if: matrix.info.os == 'macOS-latest'
run: wget -O ./tests/macos/script_tester_macos_intel https://github.com/puffyCid/artemis/releases/download/v0.1.0/script_tester_macos_intel && chmod +x ./tests/macos/script_tester_macos_intel

- name: Install Deno
- name: Download script tester binary Windows
if: matrix.info.os == 'windows-latest'
run: Invoke-WebRequest https://github.com/puffyCid/artemis/releases/download/v0.1.0/script_tester.exe -OutFile .\tests\windows\script_tester.exe

- name: Install Deno macOS
if: matrix.info.os == 'macOS-latest'
run: brew install deno

- name: Compile and run tests (macOS)
- name: Install Deno Windows
if: matrix.info.os == 'windows-latest'
run: choco.exe install deno

- name: Compile and run tests macOS
if: matrix.info.os == 'macOS-latest'
run: cd tests/macos && sudo bash compile_tests.sh

- name: Compile and run tests Windows
if: matrix.info.os == 'windows-latest'
run: cd tests\windows && .\compile_tests.bat
114 changes: 79 additions & 35 deletions artemis-docs/docs/API/API Scenarios/ese.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,39 @@ description: How to extract data from ESE databases

# ESE Databases

The Windows Extensible Storage Engine ([ESE](https://en.wikipedia.org/wiki/Extensible_Storage_Engine)) is an open source database file used by several Windows components. It is used by several different types of interesting forensic artifacts such as:
The Windows Extensible Storage Engine
([ESE](https://en.wikipedia.org/wiki/Extensible_Storage_Engine)) is an open
source database file used by several Windows components. It is used by several
different types of interesting forensic artifacts such as:

- Windows BITS
- Windows Search

Artemis allows analysts to extract and explorer ESE databases using the TypeScript API.
However, these database files may become very large. For example, the Windows Search database can range from 200MBs to 8GBs in size.
Artemis allows analysts to extract and explorer ESE databases using the
TypeScript API. However, these database files may become very large. For
example, the Windows Search database can range from 200MBs to 8GBs in size.

So we must careful that we do not read all of the data into memory.

Artemis provides a TypeScript EseDatabase class to help us parse and interact with ESE databases.
Artemis provides a TypeScript EseDatabase class to help us parse and interact
with ESE databases.

## ESE Parsing Guide

Let walkthrough a scenario where we can leverage the artemis API to extract data from the Windows [User Access Logging database](https://www.crowdstrike.com/blog/user-access-logging-ual-overview/) (UAL).
The guide below assumes you have cloned the artemis API repository to your local system. However, you may also import the API remotely, you will just need to update the imports.
Let walkthrough a scenario where we can leverage the artemis API to extract data
from the Windows
[User Access Logging database](https://www.crowdstrike.com/blog/user-access-logging-ual-overview/)
(UAL). The guide below assumes you have cloned the artemis API repository to
your local system. However, you may also import the API remotely, you will just
need to change the imports paths.

The functions in this guide are documented [here](../Artifacts/windows.md#ese-database-class)
The functions in this guide are documented
[here](../Artifacts/windows.md#ese-database-class)

### Create a EseDatabase class instance

Before we can parse a ESE database we need to initialize an instance of the EseDatabase class. This is not too difficult :)
Before we can parse a ESE database we need to initialize an instance of the
EseDatabase class. This is not too difficult :)

```typescript
import { EseDatabase } from "./artemis-api/src/windows/ese.ts";
Expand All @@ -40,14 +51,17 @@ function main() {
main();
```

The above code initializes a new EseDatabase instance that we will use to parse the UAL database.
The above code initializes a new EseDatabase instance that we will use to parse
the UAL database.

### Extract the Catalog

Before we can do any parsing of the database we must get the Catalog.
The Catalog is a special table in all ESE databases that contains metadata on all tables and columns in the database.
Before we can do any parsing of the database we must get the Catalog. The
Catalog is a special table in all ESE databases that contains metadata on all
tables and columns in the database.

There are 4 high level steps required in order to extract data from an ESE database:
There are 4 high level steps required in order to extract data from an ESE
database:

1. Parse and extract the Catalog
2. Get the metadata associated with the ESE table(s) we are interested in
Expand Down Expand Up @@ -76,7 +90,9 @@ function main() {
main();
```

As mentioned the Catalog contains metadata on all Tables and Columns in an ESE database. We can use this the help explore what kind of data exists in the database.
As mentioned the Catalog contains metadata on all Tables and Columns in an ESE
database. We can use this the help explore what kind of data exists in the
database.

```typescript
import { EseDatabase } from "./artemis-api/src/windows/ese.ts";
Expand Down Expand Up @@ -104,12 +120,15 @@ main();

:::warning

Make sure you are checking for errors when parsing the ESE database. If artemis encounters an error you will probably not be able to parse the entire database.
If artemis fails to parse the Catalog, then you will not be able to parse the database.
Make sure you are checking for errors when parsing the ESE database. If artemis
encounters an error you will probably not be able to parse the entire database.
If artemis fails to parse the Catalog, then you will not be able to parse the
database.

:::

The code above loops through the Catalog and prints out probably the most interesting properties in the object:
The code above loops through the Catalog and prints out probably the most
interesting properties in the object:

- The name of the Catalog entry
- The CatalogType for that entry.
Expand All @@ -129,18 +148,22 @@ export enum CatalogType {
}
```

Only the enums Table and Column are the most interesting. The remaining types are associated with the database internals.
Only the enums Table and Column are the most interesting. The remaining types
are associated with the database internals.

:::info

All ESE objects that artemis returns are defined in the [ESE](../../Artifacts/Windows%20Artfacts/ese.md) artifact.
Do not worry too much about the large amount of objects, artemis will handle all of the complexity and heavy lifting for parsing the data.
All ESE objects that artemis returns are defined in the
[ESE](../../Artifacts/Windows%20Artfacts/ese.md) artifact. Do not worry too much
about the large amount of objects, artemis will handle all of the complexity and
heavy lifting for parsing the data.

:::

### Getting Table information

Since we are parsing the Current.mdb database, we are mainly interested the CLIENTS table.
Since we are parsing the Current.mdb database, we are mainly interested the
CLIENTS table.

The code below shows how to extract metadata associated with the CLIENTS table.

Expand Down Expand Up @@ -168,11 +191,14 @@ function main() {
main();
```

The tableInfo function will extract all metadata from the Catalog that is associated with our table name (CLIENTS).
The tableInfo function will extract all metadata from the Catalog that is
associated with our table name (CLIENTS).

### Get Pages associated with Table

We are now at step 3 of the 4 step process. We now must get all of the pages associated with our table (CLIENTS). These pages will point to where our data is.
We are now at step 3 of the 4 step process. We now must get all of the pages
associated with our table (CLIENTS). These pages will point to where our data
is.

```typescript
import { EseDatabase } from "./artemis-api/src/windows/ese.ts";
Expand Down Expand Up @@ -208,7 +234,9 @@ The code above will now get all of the pages associated with the table CLIENTS!

### Getting our data

We are now at the last step in order to get our data! This last step is the most important, because **you** will decide how much memory artemis will use in order to parse the database to get our data.
We are now at the last step in order to get our data! This last step is the most
important, because **you** will decide how much memory artemis will use in order
to parse the database to get our data.

```typescript
import { EseDatabase } from "./artemis-api/src/windows/ese.ts";
Expand Down Expand Up @@ -248,21 +276,26 @@ function main() {
main();
```

The code above calls the function getRows() which will get our data associated with CLIENTS table.
The code above calls the function getRows() which will get our data associated
with CLIENTS table.

:::warning

The number of pages and table content will determine the amount of memory artemis uses.
The number of pages and table content will determine the amount of memory
artemis uses.

Ex: If a table has 5 columns and 1000 pages and provide 1000 pages to getRows(), artemis will return back all of the data.
This **may** be ok. If the 5 columns only have numbers or small text then it **probably** will not require a lot of memory.
Ex: If a table has 5 columns and 1000 pages and you provide 1000 pages to getRows(),
artemis will return back all of the data. This **may** be ok. If the 5 columns
only have numbers or small text then it **probably** will not require a lot of
memory.

However, if each column contain 1MB of data and there are 1000 rows, then artemis will end up using a lot of memory.
However, if each column contain 1MB of data and there are 1000 rows, then
artemis will end up using a lot of memory.

:::

Since the Current.mdb database can potentially be very large we do not want to parse all pages at once.
We will need to parse them in chunks.
Since the Current.mdb database can potentially be very large we do not want to
parse all pages at once. We will need to parse them in chunks.

```typescript
import { EseDatabase } from "./artemis-api/src/windows/ese.ts";
Expand Down Expand Up @@ -334,20 +367,31 @@ function main() {
main();
```

The above code puts our pages into smaller chunks before calling the function getRows(), this allows to us to get all of the data associated with the CLIENTS table while keeping memory usage low.
The above code puts our pages into smaller chunks before calling the function
getRows(), this allows to us to get all of the data associated with the CLIENTS
table while keeping memory usage low.

Additional details on ColumnTypes and EseTable structure can be found [here](../../Artifacts/Windows%20Artfacts/ese.md)
Additional details on ColumnTypes and EseTable structure can be found
[here](../../Artifacts/Windows%20Artfacts/ese.md)

:::info

There is no perfect number when deciding the number of pages to provide to getRows(). In general the higher the page number the faster artemis will be when parsing the database but at the cost of memory usage.
There is no perfect number when deciding the number of pages to provide to
getRows(). In general the higher the page number the faster artemis will be when
parsing the database but at the cost of memory usage.

If you do not know what kind of data is an ESE database table:

- Review the TableInfo object!
- A safe page number would probably be between 50-100

For additional background, the Windows Search database contains almost 600 columns and can grow to be very very large.
Artemis uses 400 page chunks to parse the Search database, which uses ~800-900MBs of memory.
For additional background, the Windows Search database contains almost 600
columns and can grow to be very very large. Artemis uses 400 page chunks to
parse the Search database, which uses ~800-900MBs of memory.

:::

# ESE References

- https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/ese-deep-dive-part-1-the-anatomy-of-an-ese-database/ba-p/400496
- https://github.com/libyal/libesedb/blob/main/documentation/Extensible%20Storage%20Engine%20(ESE)%20Database%20File%20(EDB)%20format.asciidoc
33 changes: 33 additions & 0 deletions artemis-docs/docs/API/Artifacts/applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,36 @@ All Chromium derived browsers should be supported.
| -------- | ------------ | --------------------------------------------------------- |
| platform | PlatformType | OS platform to parse. Supports Windows and macOS (Darwin) |
| path | string | Optional path to a Chromium Login Data database |

### extractDefenderRules(platform, alt_file, limit) -> DefinitionRule[] | ApplicationError

An experimental function to attempt to extract Windows Defender Signatures.
Defender can contain thousands/millions? of signatures so this function can
potentially run for a long time.

By default it will only extract 30 signatures. You can extract all signatures by
setting the limit to 0.

By default it will attempt to extract all Defender signatures at:

- %SYSTEMDRIVE%\\ProgramData\\Microsoft\\Windows Defender\\Definition
Updates\\\{\*\\\*.vdm
- /Library/Application Support/Microsoft/Defender/definitions.noindex/\*/\*.vdm

You may also provide an optional alternative path to the vmd file

| Param | Type | Description |
| -------- | ------------ | ------------------------------------------------------ |
| platform | PlatformType | OS platform to extract rules from |
| alt_dir | string | Alternative directory containing the UAL log databases |
| limit | number | Number of rules to return. Default is 30 |

### officeMruFiles(platform, alt_file) -> OfficeRecentFilesMacos[] | OfficeRecentFilesWindows[] | ApplicationError

Extract Microsoft Office MRU entries. Supports both macOS and Windows. By default will parse MRU entries for all users.
You may also provide an optional alternative path to the MRU plist or NTUSER.DAT file.

| Param | Type | Description |
| -------- | ------------ | --------------------------------------------------------- |
| platform | PlatformType | OS platform to parse. Supports Windows and macOS (Darwin) |
| alt_file | string | Optional path to a MRU plist or NTUSER.DAT |
Loading

0 comments on commit b58ff76

Please sign in to comment.