diff --git a/artemis-docs/docs/API/Artifacts/linux.md b/artemis-docs/docs/API/Artifacts/linux.md index ce8b27c8..8404936b 100644 --- a/artemis-docs/docs/API/Artifacts/linux.md +++ b/artemis-docs/docs/API/Artifacts/linux.md @@ -18,7 +18,7 @@ Parse a single logon related file. Path end with one of the following: | ----- | -------- | ---------------------------------- | | path | `string` | Path to `wtmp, utmp, or btmp` file | -### getElf(path) -> `ElfInfo | null` +### getElf(path) -> `ElfInfo | LinuxError` Parse an ELF executable file. @@ -26,7 +26,7 @@ Parse an ELF executable file. | ----- | -------- | ---------------- | | path | `string` | Path to ELF file | -### getJournal(path) -> `Journal[] | null` +### getJournal(path) -> `Journal[] | LinuxError` Parse a systemd [Journal](../../Artifacts/Linux%20Artifacts/journals.md) file. diff --git a/artemis-docs/docs/API/Artifacts/macos.md b/artemis-docs/docs/API/Artifacts/macos.md index 231a5c15..00ea7829 100644 --- a/artemis-docs/docs/API/Artifacts/macos.md +++ b/artemis-docs/docs/API/Artifacts/macos.md @@ -14,7 +14,7 @@ Return all local users on macOS sysem Return all local groups on macOS sysem -### parseAlias(data) -> `Alias | Error` +### parseAlias(data) -> `Alias | MacosError` Parse macOS [alias](https://en.wikipedia.org/wiki/Alias_(Mac_OS)) data. Alias files are a legacy shortcut format. May be encountered in `plist` files such as @@ -33,11 +33,11 @@ Emond was been removed on Ventura. Parse the ExecPolicy sqlite database on macOS -### firewallStatus() -> `Firewall | Error` +### firewallStatus() -> `Firewall | MacosError` Return firewall information and status on macOS -### getFsevents() -> `Fsevents[] | null` +### getFsevents() -> `Fsevents[] | MacosError` Parse macOS [FsEvents](../../Artifacts/macOS%20Artifacts/fsevents.md) @@ -53,7 +53,7 @@ Return all Launch agents on macOS Return all LoginItems on macOS -### getMacho(path) -> `MachoInfo[] | null` +### getMacho(path) -> `MachoInfo[] | MacosError` Parse a macho file and return metadata about the binary. @@ -61,7 +61,7 @@ Parse a macho file and return metadata about the binary. | ----- | -------- | -------------------- | | path | `string` | Path to macho binary | -### getPlist(path) -> `Record | number[] | Error` +### getPlist(path) -> `Record | number[] | MacosError` Parse a plist file. Supports parsing a provide plist file path or the raw bytes of plist data. Sometimes a plist file may contain another base64 encoded plist. @@ -71,7 +71,7 @@ This function can parse the raw plist bytes. | ----- | ------------------------------------- | ------------------------------------- | | path | string | Uint8Array | Path to plist file or raw plist bytes | -### passwordPolicy() -> `PasswordPolicy[] | Error` +### passwordPolicy() -> `PasswordPolicy[] | MacosError` Get password policies on macOS. Will parse plist file at `/var/db/dslocal/nodes/Default/config/shadowhash.plist` @@ -110,7 +110,7 @@ Parse a single UnifiedLog file (.tracev3) on macOS. Typically found at | ----- | -------- | --------------------- | | path | `string` | Path to .tracev3 file | -### parseRequirementBlob(data) -> `SingleRequirement | Error` +### parseRequirementBlob(data) -> `SingleRequirement | MacosError` Parse the Requirement Blob from raw codesigning bytes. This part of Apple's CodeSigning framework. This data can be found in macho binaries and also plist diff --git a/artemis-docs/docs/API/Artifacts/windows.md b/artemis-docs/docs/API/Artifacts/windows.md index 85f8f210..73718e5c 100644 --- a/artemis-docs/docs/API/Artifacts/windows.md +++ b/artemis-docs/docs/API/Artifacts/windows.md @@ -86,7 +86,7 @@ Read an Alternative Data Stream at provided file path. | path | `string` | Path to file read | | ads_name | `string` | ADS data to read | -### getPe(path) -> `PeInfo | null` +### getPe(path) -> `PeInfo | WindowsError` Parse PE file at provided path. diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/userassist.md b/artemis-docs/docs/Artifacts/Windows Artfacts/userassist.md index 49ed880a..a866ac89 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/userassist.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/userassist.md @@ -39,6 +39,7 @@ artifact_name = "userassist" [artifacts.userassist] # Optional # alt_drive = 'C' +# resolve_descriptions = true ``` # Collection Options @@ -46,6 +47,9 @@ artifact_name = "userassist" - `alt_drive` Expects a single character value. Will use an alternative drive letter when parsing `UserAssist`. This configuration is **optional**. By default artemis will use the `%systemdrive%` value (typically `C`) +- `resolve_descriptions` Enable folder description GUID lookups. Artemis will + attempt to parse the SYSTEM hive to lookup folder descriptions. This + configuration is **optional**. Default is **false**. # Output Structure diff --git a/src/applications/errors.ts b/src/applications/errors.ts new file mode 100644 index 00000000..93512834 --- /dev/null +++ b/src/applications/errors.ts @@ -0,0 +1,7 @@ +import { ErrorBase } from "../utils/error.ts"; + +export type ErrorName = + | "LIBREOFFICE" + | "VSCODE"; + +export class ApplicationError extends ErrorBase {} diff --git a/src/applications/libreoffice.ts b/src/applications/libreoffice.ts index 1ee06e13..2594a10d 100644 --- a/src/applications/libreoffice.ts +++ b/src/applications/libreoffice.ts @@ -1,13 +1,16 @@ import { readXml } from "../encoding/xml.ts"; import { glob } from "../filesystem/files.ts"; import { PlatformType } from "../system/systeminfo.ts"; +import { ApplicationError } from "./errors.ts"; /** * Return a list of files opened by LibreOffice for all users * @param platform OS Platform type to lookup * @returns Array of `History` entries */ -export function recentFiles(platform: PlatformType): History[] | Error { +export function recentFiles( + platform: PlatformType, +): History[] | ApplicationError { // Get all user paths let path = ""; switch (platform) { @@ -28,7 +31,10 @@ export function recentFiles(platform: PlatformType): History[] | Error { const paths = glob(path); if (paths instanceof Error) { - return paths; + return new ApplicationError( + "LIBREOFFICE", + `failed to glob paths: ${paths}`, + ); } const entries = []; diff --git a/src/applications/vscode.ts b/src/applications/vscode.ts index f29f689b..e50d6499 100644 --- a/src/applications/vscode.ts +++ b/src/applications/vscode.ts @@ -2,13 +2,16 @@ import { encode } from "../encoding/base64.ts"; import { encodeBytes } from "../encoding/bytes.ts"; import { glob, readTextFile } from "../filesystem/files.ts"; import { PlatformType } from "../system/systeminfo.ts"; +import { ApplicationError } from "./errors.ts"; /** * Return the local file history for all VSCode files. Also supports VSCodium. * @param platform OS Platform type to lookup * @returns Array of `FileHistory` entries */ -export function fileHistory(platform: PlatformType): FileHistory[] | Error { +export function fileHistory( + platform: PlatformType, +): FileHistory[] | ApplicationError { // Get all user paths let path = ""; switch (platform) { @@ -29,7 +32,7 @@ export function fileHistory(platform: PlatformType): FileHistory[] | Error { const paths = glob(path); if (paths instanceof Error) { - return paths; + return new ApplicationError("VSCODE", `failed to glob paths: ${paths}`); } const entries = []; diff --git a/src/linux/elf.ts b/src/linux/elf.ts index 0b658c85..b4a89414 100644 --- a/src/linux/elf.ts +++ b/src/linux/elf.ts @@ -1,17 +1,18 @@ import { ElfInfo } from "../../types/linux/elf.d.ts"; +import { LinuxError } from "./errors.ts"; /** * Function to parse an `elf` executable. * @param path Full path to a `elf` file - * @returns Basic `ElfInfo` interface or null + * @returns Basic `ElfInfo` interface or LinuxError */ -export function getElf(path: string): ElfInfo | null { - //@ts-ignore: Custom Artemis function - const data = Deno.core.ops.get_elf(path); - if (data === "") { - return null; +export function getElf(path: string): ElfInfo | LinuxError { + try { + //@ts-ignore: Custom Artemis function + const data = Deno.core.ops.get_elf(path); + const elf: ElfInfo = JSON.parse(data); + return elf; + } catch (err) { + return new LinuxError("ELF", `failed to parse elf ${path}: ${err}`); } - - const elf: ElfInfo = JSON.parse(data); - return elf; } diff --git a/src/linux/errors.ts b/src/linux/errors.ts new file mode 100644 index 00000000..69ee3d15 --- /dev/null +++ b/src/linux/errors.ts @@ -0,0 +1,7 @@ +import { ErrorBase } from "../utils/error.ts"; + +export type ErrorName = + | "ELF" + | "JOURNAL"; + +export class LinuxError extends ErrorBase {} diff --git a/src/linux/journal.ts b/src/linux/journal.ts index e9b87d94..c58c2aa2 100644 --- a/src/linux/journal.ts +++ b/src/linux/journal.ts @@ -1,17 +1,21 @@ import { Journal } from "../../types/linux/journal.d.ts"; +import { LinuxError } from "./errors.ts"; /** * Function to parse a `journal` file * @param path Path to journal file. It should end with `.journal`. * @returns Array of `Journal` entries */ -export function getJournal(path: string): Journal[] | null { - //@ts-ignore: Custom Artemis function - const data = Deno.core.ops.get_journal(path); - if (data === "") { - return null; +export function getJournal(path: string): Journal[] | LinuxError { + try { + //@ts-ignore: Custom Artemis function + const data = Deno.core.ops.get_journal(path); + const journal: Journal[] = JSON.parse(data); + return journal; + } catch (err) { + return new LinuxError( + "JOURNAL", + `failed to parse journal file ${path}: ${err}`, + ); } - - const journal: Journal[] = JSON.parse(data); - return journal; } diff --git a/src/macos/errors.ts b/src/macos/errors.ts index 60a7d47c..cd0e32a6 100644 --- a/src/macos/errors.ts +++ b/src/macos/errors.ts @@ -4,6 +4,8 @@ export type ErrorName = | "ALIAS" | "PLIST" | "FIREWALL" - | "POLICY"; + | "POLICY" + | "MACHO" + | "FSEVENTS"; export class MacosError extends ErrorBase {} diff --git a/src/macos/fsevents.ts b/src/macos/fsevents.ts index a879d90c..e31ea037 100644 --- a/src/macos/fsevents.ts +++ b/src/macos/fsevents.ts @@ -1,17 +1,21 @@ import { Fsevents } from "../../types/macos/fsevents.d.ts"; +import { MacosError } from "./errors.ts"; /** * Function to parse the `FsEvents` on a macOS system * @param path Full path to a `fsevents` file * @returns Array of `FsEvent` records */ -export function getFsevents(path: string): Fsevents[] | null { - //@ts-ignore: Custom Artemis function - const data = Deno.core.ops.get_fsevents(path); - if (data === "") { - return null; +export function getFsevents(path: string): Fsevents[] | MacosError { + try { + //@ts-ignore: Custom Artemis function + const data = Deno.core.ops.get_fsevents(path); + const fsevents: Fsevents[] = JSON.parse(data); + return fsevents; + } catch (err) { + return new MacosError( + "FSEVENTS", + `failed to parse fsevents ${path}: ${err}`, + ); } - - const fsevents: Fsevents[] = JSON.parse(data); - return fsevents; } diff --git a/src/macos/macho.ts b/src/macos/macho.ts index 4e090e69..6e0af838 100644 --- a/src/macos/macho.ts +++ b/src/macos/macho.ts @@ -1,17 +1,18 @@ import { MachoInfo } from "../../types/macos/macho.d.ts"; +import { MacosError } from "./errors.ts"; /** * Function to parse a `macho` executable. * @param path Full path to a `macho` file - * @returns Basic `MachoInfo` interface array or null + * @returns Basic `MachoInfo` interface array or MacosError */ -export function getMacho(path: string): MachoInfo[] | null { - //@ts-ignore: Custom Artemis function - const data = Deno.core.ops.get_macho(path); - if (data === "") { - return null; +export function getMacho(path: string): MachoInfo[] | MacosError { + try { + //@ts-ignore: Custom Artemis function + const data = Deno.core.ops.get_macho(path); + const macho: MachoInfo[] = JSON.parse(data); + return macho; + } catch (err) { + return new MacosError("MACHO", `filed to parse macho file ${path}: ${err}`); } - - const macho: MachoInfo[] = JSON.parse(data); - return macho; } diff --git a/src/macos/plist.ts b/src/macos/plist.ts index 4bc78b05..cc2b81e8 100644 --- a/src/macos/plist.ts +++ b/src/macos/plist.ts @@ -2,7 +2,7 @@ import { MacosError } from "./errors.ts"; /** * Function to parse a `plist` file. This function either returns a `plist` as a JSON struct - * or null + * or MacosError * @param path Full path to a `plist` file or the raw bytes of `plist` * @returns `plist` data represented as a JSON object or an object representing an error */ diff --git a/src/windows/errors.ts b/src/windows/errors.ts new file mode 100644 index 00000000..90bfdd5e --- /dev/null +++ b/src/windows/errors.ts @@ -0,0 +1,5 @@ +import { ErrorBase } from "../utils/error.ts"; + +export type ErrorName = "PE"; + +export class WindowsError extends ErrorBase {} diff --git a/src/windows/pe.ts b/src/windows/pe.ts index 7347f4b0..a7d70031 100644 --- a/src/windows/pe.ts +++ b/src/windows/pe.ts @@ -1,17 +1,18 @@ import { PeInfo } from "../../types/windows/pe.d.ts"; +import { WindowsError } from "./errors.ts"; /** * Function to parse a `pe` executable. * @param path Full path to a `pe` file - * @returns Basic `PeInfo` interface or null + * @returns Basic `PeInfo` interface or WindowsError */ -export function getPe(path: string): PeInfo | null { - //@ts-ignore: Custom Artemis function - const data: string = Deno.core.ops.get_pe(path); - if (data === "") { - return null; +export function getPe(path: string): PeInfo | WindowsError { + try { + //@ts-ignore: Custom Artemis function + const data: string = Deno.core.ops.get_pe(path); + const result: PeInfo = JSON.parse(data); + return result; + } catch (err) { + return new WindowsError("PE", `failed to parse pe file ${path}: ${err}`); } - - const result: PeInfo = JSON.parse(data); - return result; } diff --git a/src/windows/userassist.ts b/src/windows/userassist.ts index 267a29d6..77c5e448 100644 --- a/src/windows/userassist.ts +++ b/src/windows/userassist.ts @@ -2,11 +2,12 @@ import { UserAssist } from "../../types/windows/userassist.d.ts"; /** * Function to parse `UserAssist` entries on the systemdrive + * @param resolve Enable folder description GUID lookups by parsing the SYSTEM Registry file before parsing UserAssist. * @returns Array of `UserAssist` entries parsed from the sysystemdrive letter */ -export function getUserassist(): UserAssist[] { +export function getUserassist(resolve: boolean): UserAssist[] { //@ts-ignore: Custom Artemis function - const data: string = Deno.core.ops.get_userassist(); + const data: string = Deno.core.ops.get_userassist(resolve); const results: UserAssist[] = JSON.parse(data); return results; @@ -15,11 +16,15 @@ export function getUserassist(): UserAssist[] { /** * Function to parse `UserAssist` entries on an alternative drive * @param drive drive letter + * @param resolve Enable folder description GUID lookups by parsing the SYSTEM Registry file before parsing UserAssist. * @returns Array of `UserAssist` entries parsed from a Windows drive letter */ -export function getAltUserassist(drive: string): UserAssist[] { +export function getAltUserassist( + drive: string, + resolve: boolean, +): UserAssist[] { //@ts-ignore: Custom Artemis function - const data: string = Deno.core.ops.get_alt_userassist(drive); + const data: string = Deno.core.ops.get_alt_userassist(drive, resolve); const results: UserAssist[] = JSON.parse(data); return results;