diff --git a/artemis-docs/docs/API/Artifacts/windows.md b/artemis-docs/docs/API/Artifacts/windows.md index a0e5704c..4a2d234d 100644 --- a/artemis-docs/docs/API/Artifacts/windows.md +++ b/artemis-docs/docs/API/Artifacts/windows.md @@ -109,7 +109,7 @@ Parse RecycleBin file at provided path. | ----- | ------ | ------------------------ | | path | string | Path to RecycleBin file. | -### getRegistry(path) -> Registry[] | WindowsError +### getRegistry(path) -> RegistryData | WindowsError Parse Registry file at provided path. diff --git a/artemis-docs/docs/API/Helper/network.md b/artemis-docs/docs/API/Helper/network.md index bbe1684c..964b892f 100644 --- a/artemis-docs/docs/API/Helper/network.md +++ b/artemis-docs/docs/API/Helper/network.md @@ -8,20 +8,17 @@ The artemis API allows a user to make HTTP network requests using the [reqwest](https://docs.rs/reqwest/latest/reqwest/index.html) crate. It can be used to interact with external services or services that expose an API. -### request(url, protocol, body, headers) -> ClientResponse | HttpError +### request(client, body) -> ClientResponse | HttpError Make a very simple GET or POST request to the provided URL. You may specify an -optional body or headers. By default headers will use -`Content-Type: application/json`. +optional body. The body must be in raw bytes if provided. This function is async -| Param | Type | Description | -| -------- | ---------------------------- | -------------------------------------------------------------------- | -| url | string | URL to target | -| protocol | Protocol | Protocol to use. Currently only GET or POST | -| body | Uint8Array | Optional body to send with request | -| headers | Record<string, string> | Optional headers to use. Default is `Content-Type: application/json` | +| Param | Type | Description | +| ------ | ------------- | ---------------------------------- | +| client | ClientRequest | ClientRequest object | +| body | Uint8Array | Optional body to send with request | ### VirusTotal Class diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/amcache.md b/artemis-docs/docs/Artifacts/Windows Artfacts/amcache.md index 9eccc99b..ebea3ba8 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/amcache.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/amcache.md @@ -10,11 +10,15 @@ keywords: Windows `Amcache` stores metadata related to execution of Windows applications. Data is stored in the `C:\Windows\appcompat\Programs\Amcache.hve` Registry file. This Registry file also contains other metadata such as OS, hardware, and -application info. However, artemis will only collect data related to the -execution of Windows applications. +application info. However, the Amcache artifact will only collect data related +to the possible execution of Windows applications. -The `Registry` artifact may be used if you want to collect the full `Registry` -data from `Amcache.hve`. +* While an entry in Amcache often implies the application was +executed, Windows may pre-populate Amcache with entries based on a user +browsing to a directory that contains an application. + +You can use the [Registry](./registry.md) artifact to parse the Amcache file if +you want to view other metadata such as OS, hardware, more. Other Parsers: @@ -59,8 +63,8 @@ An array of `Amcache` entries ```typescript export interface Amcache { - /**Timestamp when the application was first executed in UNIXEPOCH seconds */ - first_execution: number; + /**Last modified time for Registry key in UNIXEPOCH seconds */ + last_modified: number; /**Path to application */ path: string; /**Name of application */ diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/rawfiles.md b/artemis-docs/docs/Artifacts/Windows Artfacts/rawfiles.md index 755949e2..03b065d7 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/rawfiles.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/rawfiles.md @@ -127,7 +127,7 @@ export interface RawFileInfo { /**Parent MFT reference for entry */ parent_mft_references: number; /**Attributes associated with entry */ - attributess: string[]; + attributes: string[]; /**MD5 of file. Optional */ md5: string; /**SHA1 of file. Optional */ @@ -146,7 +146,7 @@ export interface RawFileInfo { sid: number; /**SID string associated with entry*/ user_sid: string; - /**Group SID associated with enry */ + /**Group SID associated with entry */ group_sid: string; /**Drive letter */ drive: string; diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/shimdb.md b/artemis-docs/docs/Artifacts/Windows Artfacts/shimdb.md index 268e4fd7..7c9bcc34 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/shimdb.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/shimdb.md @@ -66,7 +66,7 @@ export interface Shimdb { /** * SDB files are composed of `TAGS`. There are multiple types of `TAGS` * `data` have `TAGS` that can be represented via a JSON object - * `list_data` have `TAGS` that can be rerpesented as an array of JSON objects + * `list_data` have `TAGS` that can be represented as an array of JSON objects * * Example: * ``` @@ -116,7 +116,7 @@ export interface DatabaseData { * The SDB file may contain additional metadata information * May include additional `TAGS` */ - additional_metdata: Record; + additional_metadata: Record; /**Array of `TAGS` associated with the SDB file */ list_data: TagData[]; } diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/srum.md b/artemis-docs/docs/Artifacts/Windows Artfacts/srum.md index 49d6d05d..1ff2f332 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/srum.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/srum.md @@ -133,7 +133,7 @@ export interface ApplicationTimeline { comp_rendered_timeline: number; /**Comp dirtied value for entry */ comp_dirtied_timeline: number; - /**Comp propaged value for entry */ + /**Comp propagated value for entry */ comp_propagated_timeline: number; /**Audio input value for entry */ audio_in_timeline: number; @@ -153,7 +153,7 @@ export interface ApplicationTimeline { psm_foreground_s: number; /**User input seconds count */ user_input_s: number; - /**Comp rendered seconds countr */ + /**Comp rendered seconds count */ comp_rendered_s: number; /**Comp dirtied seconds count */ comp_dirtied_s: number; @@ -191,7 +191,7 @@ export interface ApplicationTimeline { display_required_timeline: number; /**Keyboard input timeline value for entry */ keyboard_input_timeline: number; - /**Keybouard input seconds count */ + /**Keyboard input seconds count */ keyboard_input_s: number; /**Mouse input seconds count */ mouse_input_s: number; @@ -224,7 +224,7 @@ export interface AppVfu { ```typescript /** - * SRUM table associated witn EnergyInfo `{DA73FB89-2BEA-4DDC-86B8-6E048C6DA477}` + * SRUM table associated with EnergyInfo `{DA73FB89-2BEA-4DDC-86B8-6E048C6DA477}` */ export interface EnergyInfo { /**ID in for row in the ESE table */ @@ -235,7 +235,7 @@ export interface EnergyInfo { app_id: string; /**SID associated with the application process */ user_id: string; - /**Base64 encoded binary data associated witn EnegyInfo entry */ + /**Base64 encoded binary data associated with EnergyInfo entry */ binary_data: string; } ``` @@ -287,7 +287,7 @@ export interface NetworkInfo { interface_luid: number; /**L2 profile ID associated with entry */ l2_profile_id: number; - /**L2 profiel flags associated with entry */ + /**L2 profile flags associated with entry */ l2_profile_flags: number; /**Bytes sent associated with entry */ bytes_sent: number; diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/tasks.md b/artemis-docs/docs/Artifacts/Windows Artfacts/tasks.md index f1c84d3e..e23d3229 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/tasks.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/tasks.md @@ -68,6 +68,17 @@ export interface TaskData { jobs: TaskJob[]; } +/** + * JSON representation of the Task XML schema. + * Most of the schema is Optional. Only `Actions` is required + */ +export interface TaskData { + /**Array of `TaskXml` parsed XML files */ + tasks: TaskXml[]; + /**Array of `TaskJob` parsed Job files */ + jobs: TaskJob[]; +} + /** * JSON representation of the Task XML schema. * Most of the schema is Optional. Only `Actions` is required @@ -99,7 +110,7 @@ export interface TaskJob { error_retry_count: number; /**Error retry interval for the Task */ error_retry_interval: number; - /**Idle deadlin for Task */ + /**Idle deadline for Task */ idle_deadline: number; /**Idle wait for Task */ idle_wait: number; @@ -127,7 +138,7 @@ export interface TaskJob { author: string; /**Comments associated with Task */ comments: string; - /**Base64 encoded User data associatd with Task */ + /**Base64 encoded User data associated with Task */ user_data: string; /**Start Error associated with Task */ start_error: number; @@ -185,7 +196,7 @@ interface RegistrationInfo { interface Triggers { /**Boot triggers for Task */ boot: BootTrigger[]; - /**Regirstration triggers for Task. Format is exactly same as BootTriger*/ + /**Registration triggers for Task. Format is exactly same as BootTrigger*/ registration: BootTrigger[]; /**Idle triggers for Task */ idle: IdleTrigger[]; @@ -199,7 +210,7 @@ interface Triggers { session: SessionTrigger[]; /**Calendar triggers for Task */ calendar: CalendarTrigger[]; - /**Windows Notifications triggers for Trask */ + /**Windows Notifications triggers for Task */ wnf: WnfTrigger[]; } @@ -383,7 +394,7 @@ interface ByMonthDayWeek { * Settings determine how to run Task Actions */ interface Settings { - /**Start Task on demans */ + /**Start Task on demand */ allow_start_on_demand?: boolean; /**Restart if fails */ restart_on_failure?: RestartType; @@ -393,12 +404,12 @@ interface Settings { disallow_start_if_on_batteries?: boolean; /**Stop Task if going on battery power */ stop_if_going_on_batteries?: boolean; - /**Task can be terminated if time limts exceeded */ + /**Task can be terminated if time limits exceeded */ allow_hard_terminate?: boolean; /**If scheduled time is missed, Task may be started */ start_when_available?: boolean; /**Run based on network profile name */ - newtork_profile_name?: string; + network_profile_name?: string; /**Run only if network connection available */ run_only_if_network_available?: boolean; /**Wake system from standby or hibernate to run */ @@ -413,7 +424,7 @@ interface Settings { idle_settings?: IdleSettings; /**Network settings to run */ network_settings?: NetworkSettings; - /**Taks execution time limit */ + /**Task execution time limit */ execution_time_limit?: string; /**Task Priority. Lowest is 1. Highest is 10 */ priority?: number; @@ -423,8 +434,8 @@ interface Settings { use_unified_scheduling_engine?: boolean; /**Task is disabled on Remote App Sessions */ disallow_start_on_remote_app_session?: boolean; - /**Options to run Task during system maintence periods */ - maintence_settings?: MaintenceSettings; + /**Options to run Task during system maintenance periods */ + maintenance?: MaintenanceSettings; /**Task disabled on next OS startup */ volatile?: boolean; } @@ -464,14 +475,14 @@ interface NetworkSettings { } /** - * Maintence options + * Maintenance options */ -interface MaintenceSettings { - /**Duration of maintence */ +interface MaintenanceSettings { + /**Duration of maintenance */ period: string; /**Deadline for Task to run */ deadline?: string; - /**Task can run idependently of other Tasks with `MaintenceSettings` */ + /**Task can run independently of other Tasks with `MaintenanceSettings` */ exclusive?: boolean; } @@ -491,7 +502,7 @@ interface Principals { run_level?: string; /**Process Token SID associated with Task */ process_token_sid_type?: string; - /**Array of privlege value */ + /**Array of privileges value */ required_privileges?: string[]; /**Unique user selected ID */ id_attribute?: string; @@ -517,7 +528,7 @@ interface Actions { interface ExecType { /**Command to execute */ command: string; - /**Arguements for command */ + /**Arguments for command */ arguments?: string; /**Path to a directory */ working_directory?: string; diff --git a/artemis-docs/docs/Artifacts/Windows Artfacts/wmipersist.md b/artemis-docs/docs/Artifacts/Windows Artfacts/wmipersist.md index 16a12b0b..b2e63e28 100644 --- a/artemis-docs/docs/Artifacts/Windows Artfacts/wmipersist.md +++ b/artemis-docs/docs/Artifacts/Windows Artfacts/wmipersist.md @@ -93,7 +93,7 @@ export interface EventLogConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Event category */ @@ -125,7 +125,7 @@ export interface ActiveScriptConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**How many seconds to wait until process is killed. Zero (0) means process will not be killed */ @@ -147,7 +147,7 @@ export interface CommandLineConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Specifies command to execute */ @@ -174,7 +174,7 @@ export interface CommandLineConsumer { KillTimeout: number; /**Priority of process threads */ Priority: number; - /**Determinse if process is launched with interactive WinStation or default WinStation */ + /**Determines if process is launched with interactive WinStation or default WinStation */ RunInteractively: boolean; /**Determines Window show state */ ShowWindowCommand: number; @@ -209,7 +209,7 @@ export interface LogFileConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Whether log file is Unicode or multibyte code file */ @@ -229,7 +229,7 @@ export interface SmtpConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Addresses to send email (BCC) */ @@ -251,4 +251,5 @@ export interface SmtpConsumer { /**Addresses to send email to */ ToLine: string; } + ``` diff --git a/artemis-docs/package-lock.json b/artemis-docs/package-lock.json index 96feb0fe..d9d846a9 100644 --- a/artemis-docs/package-lock.json +++ b/artemis-docs/package-lock.json @@ -8,9 +8,9 @@ "name": "artemis-docs", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.1.1", - "@docusaurus/preset-classic": "^3.1.1", - "@docusaurus/theme-mermaid": "^3.1.1", + "@docusaurus/core": "^3.2.0", + "@docusaurus/preset-classic": "^3.2.0", + "@docusaurus/theme-mermaid": "^3.2.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.1.0", @@ -18,7 +18,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.1.1", + "@docusaurus/module-type-aliases": "^3.2.0", "@tsconfig/docusaurus": "^2.0.2", "typescript": "~5.2.2" }, @@ -68,74 +68,74 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz", - "integrity": "sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.2.tgz", + "integrity": "sha512-PvRQdCmtiU22dw9ZcTJkrVKgNBVAxKgD0/cfiqyxhA5+PHzA2WDt6jOmZ9QASkeM2BpyzClJb/Wr1yt2/t78Kw==", "dependencies": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.2" } }, "node_modules/@algolia/cache-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.1.tgz", - "integrity": "sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA==" + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.2.tgz", + "integrity": "sha512-OUK/6mqr6CQWxzl/QY0/mwhlGvS6fMtvEPyn/7AHUx96NjqDA4X4+Ju7aXFQKh+m3jW9VPB0B9xvEQgyAnRPNw==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz", - "integrity": "sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.2.tgz", + "integrity": "sha512-rfbi/SnhEa3MmlqQvgYz/9NNJ156NkU6xFxjbxBtLWnHbpj+qnlMoKd+amoiacHRITpajg6zYbLM9dnaD3Bczw==", "dependencies": { - "@algolia/cache-common": "4.22.1" + "@algolia/cache-common": "4.23.2" } }, "node_modules/@algolia/client-account": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.1.tgz", - "integrity": "sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.2.tgz", + "integrity": "sha512-VbrOCLIN/5I7iIdskSoSw3uOUPF516k4SjDD4Qz3BFwa3of7D9A0lzBMAvQEJJEPHWdVraBJlGgdJq/ttmquJQ==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-analytics": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.1.tgz", - "integrity": "sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.2.tgz", + "integrity": "sha512-lLj7irsAztGhMoEx/SwKd1cwLY6Daf1Q5f2AOsZacpppSvuFvuBrmkzT7pap1OD/OePjLKxicJS8wNA0+zKtuw==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.1.tgz", - "integrity": "sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.2.tgz", + "integrity": "sha512-Q2K1FRJBern8kIfZ0EqPvUr3V29ICxCm/q42zInV+VJRjldAD9oTsMGwqUQ26GFMdFYmqkEfCbY4VGAiQhh22g==", "dependencies": { - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-personalization": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.1.tgz", - "integrity": "sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.2.tgz", + "integrity": "sha512-vwPsgnCGhUcHhhQG5IM27z8q7dWrN9itjdvgA6uKf2e9r7vB+WXt4OocK0CeoYQt3OGEAExryzsB8DWqdMK5wg==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-search": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.1.tgz", - "integrity": "sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.2.tgz", + "integrity": "sha512-CxSB29OVGSE7l/iyoHvamMonzq7Ev8lnk/OkzleODZ1iBcCs3JC/XgTIKzN/4RSTrJ9QybsnlrN/bYCGufo7qw==", "dependencies": { - "@algolia/client-common": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/transporter": "4.22.1" + "@algolia/client-common": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/events": { @@ -144,47 +144,65 @@ "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" }, "node_modules/@algolia/logger-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.1.tgz", - "integrity": "sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg==" + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.2.tgz", + "integrity": "sha512-jGM49Q7626cXZ7qRAWXn0jDlzvoA1FvN4rKTi1g0hxKsTTSReyYk0i1ADWjChDPl3Q+nSDhJuosM2bBUAay7xw==" }, "node_modules/@algolia/logger-console": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.1.tgz", - "integrity": "sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.2.tgz", + "integrity": "sha512-oo+lnxxEmlhTBTFZ3fGz1O8PJ+G+8FiAoMY2Qo3Q4w23xocQev6KqDTA1JQAGPDxAewNA2VBwWOsVXeXFjrI/Q==", "dependencies": { - "@algolia/logger-common": "4.22.1" + "@algolia/logger-common": "4.23.2" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.2.tgz", + "integrity": "sha512-Q75CjnzRCDzgIlgWfPnkLtrfF4t82JCirhalXkSSwe/c1GH5pWh4xUyDOR3KTMo+YxxX3zTlrL/FjHmUJEWEcg==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.2", + "@algolia/cache-common": "4.23.2", + "@algolia/cache-in-memory": "4.23.2", + "@algolia/client-common": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/logger-common": "4.23.2", + "@algolia/logger-console": "4.23.2", + "@algolia/requester-browser-xhr": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/requester-node-http": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz", - "integrity": "sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.2.tgz", + "integrity": "sha512-TO9wLlp8+rvW9LnIfyHsu8mNAMYrqNdQ0oLF6eTWFxXfxG3k8F/Bh7nFYGk2rFAYty4Fw4XUtrv/YjeNDtM5og==", "dependencies": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.2" } }, "node_modules/@algolia/requester-common": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.1.tgz", - "integrity": "sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg==" + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.2.tgz", + "integrity": "sha512-3EfpBS0Hri0lGDB5H/BocLt7Vkop0bTTLVUBB844HH6tVycwShmsV6bDR7yXbQvFP1uNpgePRD3cdBCjeHmk6Q==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz", - "integrity": "sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.2.tgz", + "integrity": "sha512-SVzgkZM/malo+2SB0NWDXpnT7nO5IZwuDTaaH6SjLeOHcya1o56LSWXk+3F3rNLz2GVH+I/rpYKiqmHhSOjerw==", "dependencies": { - "@algolia/requester-common": "4.22.1" + "@algolia/requester-common": "4.23.2" } }, "node_modules/@algolia/transporter": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.1.tgz", - "integrity": "sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.2.tgz", + "integrity": "sha512-GY3aGKBy+8AK4vZh8sfkatDciDVKad5rTY2S10Aefyjh7e7UGBP4zigf42qVXwU8VOPwi7l/L7OACGMOFcjB0Q==", "dependencies": { - "@algolia/cache-common": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/requester-common": "4.22.1" + "@algolia/cache-common": "4.23.2", + "@algolia/logger-common": "4.23.2", + "@algolia/requester-common": "4.23.2" } }, "node_modules/@ampproject/remapping": { @@ -2133,18 +2151,18 @@ } }, "node_modules/@docsearch/css": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.2.tgz", - "integrity": "sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==" + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==" }, "node_modules/@docsearch/react": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.2.tgz", - "integrity": "sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", "dependencies": { "@algolia/autocomplete-core": "1.9.3", "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.5.2", + "@docsearch/css": "3.6.0", "algoliasearch": "^4.19.1" }, "peerDependencies": { @@ -2169,9 +2187,9 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.1.1.tgz", - "integrity": "sha512-2nQfKFcf+MLEM7JXsXwQxPOmQAR6ytKMZVSx7tVi9HEm9WtfwBH1fp6bn8Gj4zLUhjWKCLoysQ9/Wm+EZCQ4yQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.2.0.tgz", + "integrity": "sha512-WTO6vW4404nhTmK9NL+95nd13I1JveFwZ8iOBYxb4xt+N2S3KzY+mm+1YtWw2vV37FbYfH+w+KrlrRaWuy5Hzw==", "dependencies": { "@babel/core": "^7.23.3", "@babel/generator": "^7.23.3", @@ -2183,14 +2201,13 @@ "@babel/runtime": "^7.22.6", "@babel/runtime-corejs3": "^7.22.6", "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.1.1", - "@docusaurus/logger": "3.1.1", - "@docusaurus/mdx-loader": "3.1.1", + "@docusaurus/cssnano-preset": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-common": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", - "@slorber/static-site-generator-webpack-plugin": "^4.0.7", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@svgr/webpack": "^6.5.1", "autoprefixer": "^10.4.14", "babel-loader": "^9.1.3", @@ -2211,6 +2228,7 @@ "detect-port": "^1.5.1", "escape-html": "^1.0.3", "eta": "^2.2.0", + "eval": "^0.1.8", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "html-minifier-terser": "^7.2.0", @@ -2219,6 +2237,7 @@ "leven": "^3.1.0", "lodash": "^4.17.21", "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", "postcss": "^8.4.26", "postcss-loader": "^7.3.3", "prompts": "^2.4.2", @@ -2255,9 +2274,9 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.1.1.tgz", - "integrity": "sha512-LnoIDjJWbirdbVZDMq+4hwmrTl2yHDnBf9MLG9qyExeAE3ac35s4yUhJI8yyTCdixzNfKit4cbXblzzqMu4+8g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.2.0.tgz", + "integrity": "sha512-H88RXGUia7r/VF3XfyoA4kbwgpUZcKsObF6VvwBOP91EdArTf6lnHbJ/x8Ca79KS/zf98qaWyBGzW+5ez58Iyw==", "dependencies": { "cssnano-preset-advanced": "^5.3.10", "postcss": "^8.4.26", @@ -2269,9 +2288,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.1.1.tgz", - "integrity": "sha512-BjkNDpQzewcTnST8trx4idSoAla6zZ3w22NqM/UMcFtvYJgmoE4layuTzlfql3VFPNuivvj7BOExa/+21y4X2Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.2.0.tgz", + "integrity": "sha512-Z1R1NcOGXZ8CkIJSvjvyxnuDDSlx/+1xlh20iVTw1DZRjonFmI3T3tTgk40YpXyWUYQpIgAoqqPMpuseMMdgRQ==", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.6.0" @@ -2281,15 +2300,13 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.1.1.tgz", - "integrity": "sha512-xN2IccH9+sv7TmxwsDJNS97BHdmlqWwho+kIVY4tcCXkp+k4QuzvWBeunIMzeayY4Fu13A6sAjHGv5qm72KyGA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.2.0.tgz", + "integrity": "sha512-JtkI5o6R/rJSr1Y23cHKz085aBJCvJw3AYHihJ7r+mBX+O8EuQIynG0e6/XpbSCpr7Ino0U50UtxaXcEbFwg9Q==", "dependencies": { - "@babel/parser": "^7.22.7", - "@babel/traverse": "^7.22.8", - "@docusaurus/logger": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "@docusaurus/logger": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -2321,12 +2338,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.1.1.tgz", - "integrity": "sha512-xBJyx0TMfAfVZ9ZeIOb1awdXgR4YJMocIEzTps91rq+hJDFJgJaylDtmoRhUxkwuYmNK1GJpW95b7DLztSBJ3A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.2.0.tgz", + "integrity": "sha512-jRSp9YkvBwwNz6Xgy0RJPsnie+Ebb//gy7GdbkJ2pW2gvvlYKGib2+jSF0pfIzvyZLulfCynS1KQdvDKdSl8zQ==", "dependencies": { "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "3.1.1", + "@docusaurus/types": "3.2.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2340,17 +2357,17 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.1.1.tgz", - "integrity": "sha512-ew/3VtVoG3emoAKmoZl7oKe1zdFOsI0NbcHS26kIxt2Z8vcXKCUgK9jJJrz0TbOipyETPhqwq4nbitrY3baibg==", - "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/logger": "3.1.1", - "@docusaurus/mdx-loader": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-common": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.2.0.tgz", + "integrity": "sha512-MABqwjSicyHmYEfQueMthPCz18JkVxhK3EGhXTSRWwReAZ0UTuw9pG6+Wo+uXAugDaIcJH28rVZSwTDINPm2bw==", + "dependencies": { + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", @@ -2371,17 +2388,18 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.1.1.tgz", - "integrity": "sha512-lhFq4E874zw0UOH7ujzxnCayOyAt0f9YPVYSb9ohxrdCM8B4szxitUw9rIX4V9JLLHVoqIJb6k+lJJ1jrcGJ0A==", - "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/logger": "3.1.1", - "@docusaurus/mdx-loader": "3.1.1", - "@docusaurus/module-type-aliases": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.2.0.tgz", + "integrity": "sha512-uuqhahmsBnirxOz+SXksnWt7+wc+iN4ntxNRH48BUgo7QRNLATWjHCgI8t6zrMJxK4o+QL9DhLaPDlFHs91B3Q==", + "dependencies": { + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -2400,15 +2418,15 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.1.1.tgz", - "integrity": "sha512-NQHncNRAJbyLtgTim9GlEnNYsFhuCxaCNkMwikuxLTiGIPH7r/jpb7O3f3jUMYMebZZZrDq5S7om9a6rvB/YCA==", - "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/mdx-loader": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.2.0.tgz", + "integrity": "sha512-4ofAN7JDsdb4tODO9OIrizWY5DmEJXr0eu+UDIkLqGP+gXXTahJZv8h2mlxO+lPXGXRCVBOfA14OG1hOYJVPwA==", + "dependencies": { + "@docusaurus/core": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -2422,13 +2440,13 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.1.1.tgz", - "integrity": "sha512-xWeMkueM9wE/8LVvl4+Qf1WqwXmreMjI5Kgr7GYCDoJ8zu4kD+KaMhrh7py7MNM38IFvU1RfrGKacCEe2DRRfQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.2.0.tgz", + "integrity": "sha512-p6WxtO5XZGz66y6QNQtCJwBefq4S6/w75XaXVvH1/2P9uaijvF7R+Cm2EWQZ5WsvA5wl//DFWblyDHRyVC207Q==", "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils": "3.1.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", "fs-extra": "^11.1.1", "react-json-view-lite": "^1.2.0", "tslib": "^2.6.0" @@ -2442,13 +2460,13 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.1.1.tgz", - "integrity": "sha512-+q2UpWTqVi8GdlLoSlD5bS/YpxW+QMoBwrPrUH/NpvpuOi0Of7MTotsQf9JWd3hymZxl2uu1o3PIrbpxfeDFDQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.2.0.tgz", + "integrity": "sha512-//TepJTEyAZSvBwHKEbXHu9xT/VkK3wUil2ZakKvQZYfUC01uWn6A1E3toa8R7WhCy1xPUeIukqmJy1Clg8njQ==", "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "tslib": "^2.6.0" }, "engines": { @@ -2460,13 +2478,13 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.1.1.tgz", - "integrity": "sha512-0mMPiBBlQ5LFHTtjxuvt/6yzh8v7OxLi3CbeEsxXZpUzcKO/GC7UA1VOWUoBeQzQL508J12HTAlR3IBU9OofSw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.2.0.tgz", + "integrity": "sha512-3s6zxlaMMb87MW2Rxy6EnSRDs0WDEQPuHilZZH402C8kOrUnIwlhlfjWZ4ZyLDziGl/Eec/DvD0PVqj0qHRomA==", "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -2479,13 +2497,13 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.1.1.tgz", - "integrity": "sha512-d07bsrMLdDIryDtY17DgqYUbjkswZQr8cLWl4tzXrt5OR/T/zxC1SYKajzB3fd87zTu5W5klV5GmUwcNSMXQXA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.2.0.tgz", + "integrity": "sha512-rAKtsJ11vPHA7dTAqWCgyIy7AyFRF/lpI77Zd/4HKgqcIvIayVBvL3QtelhUazfYTLTH6ls6kQ9wjMcIFxRiGg==", "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "tslib": "^2.6.0" }, "engines": { @@ -2497,16 +2515,16 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.1.1.tgz", - "integrity": "sha512-iJ4hCaMmDaUqRv131XJdt/C/jJQx8UreDWTRqZKtNydvZVh/o4yXGRRFOplea1D9b/zpwL1Y+ZDwX7xMhIOTmg==", - "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/logger": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-common": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.2.0.tgz", + "integrity": "sha512-gnWDFt6MStjLkdtt63Lzc+14EPSd8B6mzJGJp9GQMvWDUoMAUijUqpVIHYQq+DPMcI4PJZ5I2nsl5XFf1vOldA==", + "dependencies": { + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -2520,23 +2538,23 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.1.1.tgz", - "integrity": "sha512-jG4ys/hWYf69iaN/xOmF+3kjs4Nnz1Ay3CjFLDtYa8KdxbmUhArA9HmP26ru5N0wbVWhY+6kmpYhTJpez5wTyg==", - "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/plugin-content-blog": "3.1.1", - "@docusaurus/plugin-content-docs": "3.1.1", - "@docusaurus/plugin-content-pages": "3.1.1", - "@docusaurus/plugin-debug": "3.1.1", - "@docusaurus/plugin-google-analytics": "3.1.1", - "@docusaurus/plugin-google-gtag": "3.1.1", - "@docusaurus/plugin-google-tag-manager": "3.1.1", - "@docusaurus/plugin-sitemap": "3.1.1", - "@docusaurus/theme-classic": "3.1.1", - "@docusaurus/theme-common": "3.1.1", - "@docusaurus/theme-search-algolia": "3.1.1", - "@docusaurus/types": "3.1.1" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.2.0.tgz", + "integrity": "sha512-t7tXyk8kUgT7hUqEOgSJnPs+Foem9ucuan/a9QVYaVFCDjp92Sb2FpCY8bVasAokYCjodYe2LfpAoSCj5YDYWg==", + "dependencies": { + "@docusaurus/core": "3.2.0", + "@docusaurus/plugin-content-blog": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/plugin-content-pages": "3.2.0", + "@docusaurus/plugin-debug": "3.2.0", + "@docusaurus/plugin-google-analytics": "3.2.0", + "@docusaurus/plugin-google-gtag": "3.2.0", + "@docusaurus/plugin-google-tag-manager": "3.2.0", + "@docusaurus/plugin-sitemap": "3.2.0", + "@docusaurus/theme-classic": "3.2.0", + "@docusaurus/theme-common": "3.2.0", + "@docusaurus/theme-search-algolia": "3.2.0", + "@docusaurus/types": "3.2.0" }, "engines": { "node": ">=18.0" @@ -2559,22 +2577,22 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.1.1.tgz", - "integrity": "sha512-GiPE/jbWM8Qv1A14lk6s9fhc0LhPEQ00eIczRO4QL2nAQJZXkjPG6zaVx+1cZxPFWbAsqSjKe2lqkwF3fGkQ7Q==", - "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/mdx-loader": "3.1.1", - "@docusaurus/module-type-aliases": "3.1.1", - "@docusaurus/plugin-content-blog": "3.1.1", - "@docusaurus/plugin-content-docs": "3.1.1", - "@docusaurus/plugin-content-pages": "3.1.1", - "@docusaurus/theme-common": "3.1.1", - "@docusaurus/theme-translations": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-common": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.2.0.tgz", + "integrity": "sha512-4oSO5BQOJ5ja7WYdL6jK1n4J96tp+VJHamdwao6Ea252sA3W3vvR0otTflG4p4XVjNZH6hlPQoi5lKW0HeRgfQ==", + "dependencies": { + "@docusaurus/core": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/plugin-content-blog": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/plugin-content-pages": "3.2.0", + "@docusaurus/theme-common": "3.2.0", + "@docusaurus/theme-translations": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", @@ -2598,17 +2616,17 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.1.1.tgz", - "integrity": "sha512-38urZfeMhN70YaXkwIGXmcUcv2CEYK/2l4b05GkJPrbEbgpsIZM3Xc+Js2ehBGGZmfZq8GjjQ5RNQYG+MYzCYg==", - "dependencies": { - "@docusaurus/mdx-loader": "3.1.1", - "@docusaurus/module-type-aliases": "3.1.1", - "@docusaurus/plugin-content-blog": "3.1.1", - "@docusaurus/plugin-content-docs": "3.1.1", - "@docusaurus/plugin-content-pages": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-common": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.2.0.tgz", + "integrity": "sha512-sFbw9XviNJJ+760kAcZCQMQ3jkNIznGqa6MQ70E5BnbP+ja36kGgPOfjcsvAcNey1H1Rkhh3p2Mhf4HVLdKVVw==", + "dependencies": { + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/plugin-content-blog": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/plugin-content-pages": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2627,15 +2645,15 @@ } }, "node_modules/@docusaurus/theme-mermaid": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.1.1.tgz", - "integrity": "sha512-O6u9/7QX/ZapV4HJJSzNs0Jir1KA/LRLORWYeDvbGswqZNusj6q4iLELrKIClysJ3PB3zWUzyKtI/wjIKiV1vA==", - "dependencies": { - "@docusaurus/core": "3.1.1", - "@docusaurus/module-type-aliases": "3.1.1", - "@docusaurus/theme-common": "3.1.1", - "@docusaurus/types": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.2.0.tgz", + "integrity": "sha512-PvN6K6m3JaM9cr9oSPyba6OlwAiSfBzqQtNqdgPFDjakKuT4kj6JODfExi+HKtWuxayOVRQlRl7zTnWxM4sTVw==", + "dependencies": { + "@docusaurus/core": "3.2.0", + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/theme-common": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "mermaid": "^10.4.0", "tslib": "^2.6.0" }, @@ -2648,18 +2666,18 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.1.1.tgz", - "integrity": "sha512-tBH9VY5EpRctVdaAhT+b1BY8y5dyHVZGFXyCHgTrvcXQy5CV4q7serEX7U3SveNT9zksmchPyct6i1sFDC4Z5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.2.0.tgz", + "integrity": "sha512-PgvF4qHoqJp8+GfqClUbTF/zYNOsz4De251IuzXon7+7FAXwvb2qmYtA2nEwyMbB7faKOz33Pxzv+y+153KS/g==", "dependencies": { "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.1.1", - "@docusaurus/logger": "3.1.1", - "@docusaurus/plugin-content-docs": "3.1.1", - "@docusaurus/theme-common": "3.1.1", - "@docusaurus/theme-translations": "3.1.1", - "@docusaurus/utils": "3.1.1", - "@docusaurus/utils-validation": "3.1.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/theme-common": "3.2.0", + "@docusaurus/theme-translations": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "algoliasearch": "^4.18.0", "algoliasearch-helper": "^3.13.3", "clsx": "^2.0.0", @@ -2678,9 +2696,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.1.1.tgz", - "integrity": "sha512-xvWQFwjxHphpJq5fgk37FXCDdAa2o+r7FX8IpMg+bGZBNXyWBu3MjZ+G4+eUVNpDhVinTc+j6ucL0Ain5KCGrg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.2.0.tgz", + "integrity": "sha512-VXzZJBuyVEmwUYyud+7IgJQEBRM6R2u/s10Rp3DOP19CBQxeKgHYTKkKhFtDeKMHDassb665kjgOi0YlJfUT6w==", "dependencies": { "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -2690,9 +2708,9 @@ } }, "node_modules/@docusaurus/types": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.1.1.tgz", - "integrity": "sha512-grBqOLnubUecgKFXN9q3uit2HFbCxTWX4Fam3ZFbMN0sWX9wOcDoA7lwdX/8AmeL20Oc4kQvWVgNrsT8bKRvzg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.2.0.tgz", + "integrity": "sha512-uG3FfTkkkbZIPPNYx6xRfZHKeGyRd/inIT1cqvYt1FobFLd+7WhRXrSBqwJ9JajJjEAjNioRMVFgGofGf/Wdww==", "dependencies": { "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", @@ -2710,11 +2728,12 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.1.1.tgz", - "integrity": "sha512-ZJfJa5cJQtRYtqijsPEnAZoduW6sjAQ7ZCWSZavLcV10Fw0Z3gSaPKA/B4micvj2afRZ4gZxT7KfYqe5H8Cetg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.2.0.tgz", + "integrity": "sha512-3rgrE7iL60yV2JQivlcoxUNNTK2APmn+OHLUmTvX2pueIM8DEOCEFHpJO4MiWjFO7V/Wq3iA/W1M03JnjdugVw==", "dependencies": { - "@docusaurus/logger": "3.1.1", + "@docusaurus/logger": "3.2.0", + "@docusaurus/utils-common": "3.2.0", "@svgr/webpack": "^6.5.1", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", @@ -2726,6 +2745,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "micromatch": "^4.0.5", + "prompts": "^2.4.2", "resolve-pathname": "^3.0.0", "shelljs": "^0.8.5", "tslib": "^2.6.0", @@ -2745,9 +2765,9 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.1.1.tgz", - "integrity": "sha512-eGne3olsIoNfPug5ixjepZAIxeYFzHHnor55Wb2P57jNbtVaFvij/T+MS8U0dtZRFi50QU+UPmRrXdVUM8uyMg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.2.0.tgz", + "integrity": "sha512-WEQT5L2lT/tBQgDRgeZQAIi9YJBrwEILb1BuObQn1St3T/4K1gx5fWwOT8qdLOov296XLd1FQg9Ywu27aE9svw==", "dependencies": { "tslib": "^2.6.0" }, @@ -2764,12 +2784,13 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.1.1.tgz", - "integrity": "sha512-KlY4P9YVDnwL+nExvlIpu79abfEv6ZCHuOX4ZQ+gtip+Wxj0daccdReIWWtqxM/Fb5Cz1nQvUCc7VEtT8IBUAA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.2.0.tgz", + "integrity": "sha512-rCzMTqwNrBrEOyU8EaD1fYWdig4TDhfj+YLqB8DY68VUAqSIgbY+yshpqFKB0bznFYNBJbn0bGpvVuImQOa/vA==", "dependencies": { - "@docusaurus/logger": "3.1.1", - "@docusaurus/utils": "3.1.1", + "@docusaurus/logger": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", "tslib": "^2.6.0" @@ -2876,9 +2897,9 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "node_modules/@mdx-js/mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.0.tgz", - "integrity": "sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", @@ -3043,19 +3064,6 @@ "micromark-util-symbol": "^1.0.1" } }, - "node_modules/@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", - "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", - "dependencies": { - "eval": "^0.1.8", - "p-map": "^4.0.0", - "webpack-sources": "^3.2.2" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", @@ -3416,9 +3424,9 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/estree-jsx": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.4.tgz", - "integrity": "sha512-5idy3hvI9lAMqsyilBM+N+boaCf1MgoefbDxN6KEO5aK17TOHwFAYT9sjxzeKAiIWRUBgLxmZ9mPcnzZXtTcRQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "dependencies": { "@types/estree": "*" } @@ -3969,30 +3977,31 @@ } }, "node_modules/algoliasearch": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", - "integrity": "sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg==", - "dependencies": { - "@algolia/cache-browser-local-storage": "4.22.1", - "@algolia/cache-common": "4.22.1", - "@algolia/cache-in-memory": "4.22.1", - "@algolia/client-account": "4.22.1", - "@algolia/client-analytics": "4.22.1", - "@algolia/client-common": "4.22.1", - "@algolia/client-personalization": "4.22.1", - "@algolia/client-search": "4.22.1", - "@algolia/logger-common": "4.22.1", - "@algolia/logger-console": "4.22.1", - "@algolia/requester-browser-xhr": "4.22.1", - "@algolia/requester-common": "4.22.1", - "@algolia/requester-node-http": "4.22.1", - "@algolia/transporter": "4.22.1" + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.2.tgz", + "integrity": "sha512-8aCl055IsokLuPU8BzLjwzXjb7ty9TPcUFFOk0pYOwsE5DMVhE3kwCMFtsCFKcnoPZK7oObm+H5mbnSO/9ioxQ==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.2", + "@algolia/cache-common": "4.23.2", + "@algolia/cache-in-memory": "4.23.2", + "@algolia/client-account": "4.23.2", + "@algolia/client-analytics": "4.23.2", + "@algolia/client-common": "4.23.2", + "@algolia/client-personalization": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/logger-common": "4.23.2", + "@algolia/logger-console": "4.23.2", + "@algolia/recommend": "4.23.2", + "@algolia/requester-browser-xhr": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/requester-node-http": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/algoliasearch-helper": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.16.2.tgz", - "integrity": "sha512-Yl/Gu5Cq4Z5s/AJ0jR37OPI1H3+z7PHz657ibyaXgMOaWvPlZ3OACN13N+7HCLPUlB0BN+8BtmrG/CqTilowBA==", + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.16.3.tgz", + "integrity": "sha512-1OuJT6sONAa9PxcOmWo5WCAT3jQSpCR9/m5Azujja7nhUQwAUDvaaAYrcmUySsrvHh74usZHbE3jFfGnWtZj8w==", "dependencies": { "@algolia/events": "^4.0.1" }, @@ -4111,9 +4120,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", "funding": [ { "type": "opencollective", @@ -4129,8 +4138,8 @@ } ], "dependencies": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -4250,12 +4259,12 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -4263,7 +4272,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -4360,9 +4369,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -4378,8 +4387,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -4440,14 +4449,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -4496,9 +4506,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001584", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", - "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", "funding": [ { "type": "opencollective", @@ -4951,9 +4961,9 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -6231,9 +6241,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.659", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.659.tgz", - "integrity": "sha512-sRJ3nV3HowrYpBtPF9bASQV7OW49IgZC01Xiq43WfSE3RTCkK0/JidoCmR73Hyc1mN+l/H4Yqx0eNiomvExFZg==" + "version": "1.4.722", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.722.tgz", + "integrity": "sha512-5nLE0TWFFpZ80Crhtp4pIp8LXCztjYX41yUcV6b+bKR2PqzjskTMOOlBi1VjBHlvHwS+4gar7kNKOrsbsewEZQ==" }, "node_modules/elkjs": { "version": "0.9.1", @@ -6306,6 +6316,17 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -6566,16 +6587,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -6886,9 +6907,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -7554,16 +7575,16 @@ } }, "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.2.tgz", - "integrity": "sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==" + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" }, "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.5.tgz", - "integrity": "sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", "dependencies": { - "inline-style-parser": "0.2.2" + "inline-style-parser": "0.2.3" } }, "node_modules/hast-util-to-parse5": { @@ -8421,9 +8442,9 @@ } }, "node_modules/joi": { - "version": "17.12.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.1.tgz", - "integrity": "sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ==", + "version": "17.12.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.2.tgz", + "integrity": "sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==", "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", @@ -8975,9 +8996,9 @@ } }, "node_modules/mdast-util-mdx-jsx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.0.0.tgz", - "integrity": "sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", @@ -12754,9 +12775,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -12981,9 +13002,9 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-json-view-lite": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.2.1.tgz", - "integrity": "sha512-Itc0g86fytOmKZoIoJyGgvNqohWSbh3NXIKNgH6W6FT9PC1ck4xas1tT3Rr/b3UlFXyA9Jjaw9QSXdZy2JwGMQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.3.0.tgz", + "integrity": "sha512-aN1biKC5v4DQkmQBlZjuMFR09MKZGMPtIg+cut8zEeg2HXd6gl2gRy0n4HMacHf0dznQgo0SVXN7eT8zV3hEuQ==", "engines": { "node": ">=14" }, @@ -13292,9 +13313,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.0.tgz", - "integrity": "sha512-O7yfjuC6ra3NHPbRVxfflafAj3LTwx3b73aBvkEFU5z4PsD6FD4vrqJAkE5iNGLz71GdjXfgRqm3SQ0h0VuE7g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" @@ -13983,11 +14004,11 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -15358,9 +15379,9 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", diff --git a/artemis-docs/package.json b/artemis-docs/package.json index 4c19150f..22568388 100644 --- a/artemis-docs/package.json +++ b/artemis-docs/package.json @@ -15,9 +15,9 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "^3.1.1", - "@docusaurus/preset-classic": "^3.1.1", - "@docusaurus/theme-mermaid": "^3.1.1", + "@docusaurus/core": "^3.2.0", + "@docusaurus/preset-classic": "^3.2.0", + "@docusaurus/theme-mermaid": "^3.2.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.1.0", @@ -25,7 +25,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.1.1", + "@docusaurus/module-type-aliases": "^3.2.0", "@tsconfig/docusaurus": "^2.0.2", "typescript": "~5.2.2" }, diff --git a/mod.ts b/mod.ts index d33a6178..609ff581 100644 --- a/mod.ts +++ b/mod.ts @@ -19,10 +19,17 @@ export { getLaunchdAgents, getLaunchdDaemons } from "./src/macos/launchd.ts"; export { getGroups, getUsers } from "./src/macos/accounts.ts"; export { getExecpolicy } from "./src/macos/execpolicy.ts"; export { getFsevents } from "./src/macos/fsevents.ts"; -export { getHomebrewInfo, getCasks, getPackages } from "./src/macos/homebrew.ts"; +export { + getHomebrewInfo, + getCasks, + getPackages, +} from "./src/macos/homebrew.ts"; export { getMacho } from "./src/macos/macho.ts"; export { getPlist } from "./src/macos/plist.ts"; -export { getUnifiedLog, setupUnifiedLogParser } from "./src/macos/unifiedlogs.ts"; +export { + getUnifiedLog, + setupUnifiedLogParser, +} from "./src/macos/unifiedlogs.ts"; export { getSafariDownloads, getSafariHistory, @@ -93,7 +100,7 @@ export { querySqlite } from "./src/applications/sqlite.ts"; /** * Windows exported functions */ -export { getAltAmcache, getAmcache } from "./src/windows/amache.ts"; +export { getAltAmcache, getAmcache } from "./src/windows/amcache.ts"; export { getBits, getBitsPath } from "./src/windows/bits.ts"; export { getEventlogs } from "./src/windows/eventlogs.ts"; export { readAdsData, readRawFile } from "./src/windows/ntfs.ts"; @@ -123,8 +130,9 @@ export { getServiceFile, getServices } from "./src/windows/services.ts"; export { getJumplistPath, getJumplists } from "./src/windows/jumplists.ts"; export { getRecycleBin, getRecycleBinFile } from "./src/windows/recyclebin.ts"; export { getChocolateyInfo } from "./src/windows/chocolatey.ts"; -export { logons } from "./src/windows/eventlogs/logons.ts"; +export { logonsWindows } from "./src/windows/eventlogs/logons.ts"; export { getShellItem } from "./src/windows/shellitems.ts"; export { userAccessLog } from "./src/windows/ese/ual.ts"; export { parseTable } from "./src/windows/ese.ts"; -export { updateHistory } from "./src/windows/ese/updates.ts"; \ No newline at end of file +export { updateHistory } from "./src/windows/ese/updates.ts"; +export { getWmiPersist } from "./src/windows/wmi.ts"; diff --git a/src/http/client.ts b/src/http/client.ts index 36e1076d..a31e6c37 100644 --- a/src/http/client.ts +++ b/src/http/client.ts @@ -4,29 +4,63 @@ export enum Protocol { GET = "GET", POST = "POST", } + +export enum BodyType { + FORM = "form", + NORMAL = "", +} + +/** + * Interface used to make a HTTP request to a URL + */ +export interface ClientRequest { + /**HTTP URL to send request to */ + url: string; + /**GET or POST protocol */ + protocol: Protocol; + /**Headers to send in request. Default is content-type/json */ + headers?: Record; + /**Request body type */ + body_type?: BodyType; + /**Follow HTTP redirects */ + follow_redirects?: boolean; + /**Verify SSL certs */ + verify_ssl?: boolean; +} + /** * A simple HTTP client that can be used to make network requests. The Rust crate [reqwest](https://docs.rs/reqwest/latest/reqwest/index.html) is used to make the request. - * @param url Target URL to send request to - * @param protocol Target `Protocol` to use for request + * @param request `ClientRequest` object used to send HTTP requests * @param body Optional request body to send. Must be in raw bytes. - * @param headers Optional headers associated with request. Default is `application/json` * @returns `ClientResponse` data or Error */ export async function request( - url: string, - protocol: Protocol, + js_request: ClientRequest, body: Uint8Array = new Uint8Array(0), - headers: Record = { "Content-Type": "application/json" }, ): Promise { + // Check if optional settings were not enabled + if (js_request.headers === undefined) { + js_request.headers = { "Content-Type": "application/json" }; + } + if (js_request.body_type === undefined) { + js_request.body_type = BodyType.NORMAL; + } + if (js_request.follow_redirects === undefined) { + js_request.follow_redirects = true; + } + if (js_request.verify_ssl === undefined) { + js_request.verify_ssl = true; + } + try { //@ts-ignore: Custom Artemis function - const result = await http.send(url, protocol, headers, body); + const result = await http.send(JSON.stringify(js_request), body); const res: ClientResponse = JSON.parse(result); return res; } catch (err) { return new HttpError( "REQUEST_ERROR", - `failed to make ${protocol} request to ${url}: ${err}`, + `failed to make ${js_request.protocol} request to ${js_request.url}: ${err}`, ); } } diff --git a/src/http/vt.ts b/src/http/vt.ts index 5253282f..60f9bcb1 100644 --- a/src/http/vt.ts +++ b/src/http/vt.ts @@ -1,6 +1,6 @@ import { VTResponse } from "../../types/http/vt.ts"; import { extractUtf8String } from "../encoding/strings.ts"; -import { Protocol, request } from "./client.ts"; +import { ClientRequest, Protocol, request } from "./client.ts"; import { ErrorName, HttpError } from "./errors.ts"; /** @@ -10,7 +10,7 @@ import { ErrorName, HttpError } from "./errors.ts"; * Your key or IP will be **blocked** if you do! */ export class VirusTotal { - key: string; + private key: string; /** * Provide the VT API key for you account @@ -63,12 +63,13 @@ export class VirusTotal { "x-apikey": this.key, }; - const response = await request( + const client: ClientRequest = { url, - Protocol.GET, - new Uint8Array(0), + protocol: Protocol.GET, headers, - ); + }; + + const response = await request(client); if (response instanceof HttpError) { response.name = err; return response; diff --git a/src/images/icns.ts b/src/images/icns.ts index 2eaee59e..5fe9f006 100644 --- a/src/images/icns.ts +++ b/src/images/icns.ts @@ -1,4 +1,4 @@ -import { Icon, OSType } from "../../types/images/icns.d.ts"; +import { Icon, OSType } from "../../types/images/icns.ts"; import { encode, extractUtf8String } from "../encoding/mod.ts"; import { Endian } from "../nom/helpers.ts"; import { nomUnsignedFourBytes, take } from "../nom/mod.ts"; diff --git a/src/linux/elf.ts b/src/linux/elf.ts index b4a89414..13a61f69 100644 --- a/src/linux/elf.ts +++ b/src/linux/elf.ts @@ -1,4 +1,4 @@ -import { ElfInfo } from "../../types/linux/elf.d.ts"; +import { ElfInfo } from "../../types/linux/elf.ts"; import { LinuxError } from "./errors.ts"; /** diff --git a/src/macos/accounts.ts b/src/macos/accounts.ts index cd54b5fa..c13586ad 100644 --- a/src/macos/accounts.ts +++ b/src/macos/accounts.ts @@ -1,4 +1,4 @@ -import { Groups, Users } from "../../types/macos/accounts.d.ts"; +import { Groups, Users } from "../../types/macos/accounts.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/macos/emond.ts b/src/macos/emond.ts index f5c10216..7fb9116a 100644 --- a/src/macos/emond.ts +++ b/src/macos/emond.ts @@ -1,4 +1,4 @@ -import { Emond } from "../../types/macos/emond.d.ts"; +import { Emond } from "../../types/macos/emond.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/macos/execpolicy.ts b/src/macos/execpolicy.ts index f331b5d7..acd9e212 100644 --- a/src/macos/execpolicy.ts +++ b/src/macos/execpolicy.ts @@ -1,4 +1,4 @@ -import { ExecPolicy } from "../../types/macos/execpolicy.d.ts"; +import { ExecPolicy } from "../../types/macos/execpolicy.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/macos/fsevents.ts b/src/macos/fsevents.ts index 8887b858..35799daa 100644 --- a/src/macos/fsevents.ts +++ b/src/macos/fsevents.ts @@ -1,4 +1,4 @@ -import { Fsevents } from "../../types/macos/fsevents.d.ts"; +import { Fsevents } from "../../types/macos/fsevents.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/macos/homebrew.ts b/src/macos/homebrew.ts index 4713d4dc..94d09843 100644 --- a/src/macos/homebrew.ts +++ b/src/macos/homebrew.ts @@ -183,7 +183,7 @@ function parseRuby(path: string): HomebrewFormula | FileError { return rubyText; } - const descriptoin = rubyText.match(desc); + const description = rubyText.match(desc); const receipt: HomebrewFormula = { description: "", homepage: "", @@ -193,8 +193,8 @@ function parseRuby(path: string): HomebrewFormula | FileError { formulaPath: path, version: "", }; - if (typeof descriptoin?.[0] === "string") { - receipt.description = descriptoin?.[0].replaceAll('"', ""); + if (typeof description?.[0] === "string") { + receipt.description = description?.[0].replaceAll('"', ""); } const homepage = rubyText.match(homepage_reg); diff --git a/src/macos/launchd.ts b/src/macos/launchd.ts index 7bde5a51..aaefb297 100644 --- a/src/macos/launchd.ts +++ b/src/macos/launchd.ts @@ -1,4 +1,4 @@ -import { Launchd } from "../../types/macos/launchd.d.ts"; +import { Launchd } from "../../types/macos/launchd.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/macos/loginitems.ts b/src/macos/loginitems.ts index 995de873..45f24183 100644 --- a/src/macos/loginitems.ts +++ b/src/macos/loginitems.ts @@ -1,4 +1,4 @@ -import { LoginItems } from "../../types/macos/loginitems.d.ts"; +import { LoginItems } from "../../types/macos/loginitems.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/macos/macho.ts b/src/macos/macho.ts index 6e0af838..23faafe9 100644 --- a/src/macos/macho.ts +++ b/src/macos/macho.ts @@ -1,4 +1,4 @@ -import { MachoInfo } from "../../types/macos/macho.d.ts"; +import { MachoInfo } from "../../types/macos/macho.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/macos/plist/xprotect.ts b/src/macos/plist/xprotect.ts index a269b047..58a72398 100644 --- a/src/macos/plist/xprotect.ts +++ b/src/macos/plist/xprotect.ts @@ -39,9 +39,7 @@ export function getXprotectDefinitions( ); } - console.log(entries); - - return []; + return entries; } /** diff --git a/src/macos/safari.ts b/src/macos/safari.ts index e5f1945b..b5efdd05 100644 --- a/src/macos/safari.ts +++ b/src/macos/safari.ts @@ -3,7 +3,7 @@ import { RawSafariHistory, SafariDownloads, SafariHistory, -} from "../../types/macos/safari.d.ts"; +} from "../../types/macos/safari.ts"; import { MacosError } from "./errors.ts"; /** diff --git a/src/system/memory.ts b/src/system/memory.ts index 11acbda6..8a1231f1 100644 --- a/src/system/memory.ts +++ b/src/system/memory.ts @@ -1,4 +1,5 @@ import { Memory } from "../../types/system/systeminfo.d.ts"; +import { ProcessInfo } from "../../types/system/processes.ts"; /** * Function to get memory information @@ -6,15 +7,11 @@ import { Memory } from "../../types/system/systeminfo.d.ts"; */ export function memory(): Memory { //@ts-ignore: Custom Artemis function - const data: string = system.memory(); + const data = system.memory(); const mem: Memory = JSON.parse(data); return mem; } -import { LinuxProcessInfo } from "../../types/linux/processes.d.ts"; -import { MacosProcessInfo } from "../../types/macos/processes.d.ts"; -import { WindowsProcessInfo } from "../../types/windows/processes.d.ts"; - /** * Function to pull a process listing from system * @param md5 MD5 hash the process binary. Default is false @@ -28,7 +25,7 @@ export function processListing( sha1 = false, sha256 = false, binary = false, -): LinuxProcessInfo[] | WindowsProcessInfo[] | MacosProcessInfo[] { +): ProcessInfo[] { const hashes = { md5, sha1, @@ -39,7 +36,7 @@ export function processListing( JSON.stringify(hashes), binary, ); - const proc_array = JSON.parse(data); + const proc_array: ProcessInfo[] = JSON.parse(data); return proc_array; } diff --git a/src/time/conversion.ts b/src/time/conversion.ts index fb050c8a..fbaf2bbb 100644 --- a/src/time/conversion.ts +++ b/src/time/conversion.ts @@ -73,3 +73,45 @@ export function fatToUnixEpoch(fattime: Uint8Array): number { const data: bigint = time.fattime_utc_to_unixepoch(fattime); return Number(data); } + +/** + * Function to convert UNIXEPOCH times to ISO8601 + * @param timestamp Data timestamp. Should be UNIXEPOCH. Duration should either: Seconds, Milliseconds, Microseconds, or nanoseconds + * @returns ISO8601 timestamp + */ +export function unixEpochToISO(timestamp: number | bigint): string { + if (timestamp === 0 || timestamp === 0n) { + return new Date(Number(timestamp)).toISOString(); + } + const milliseconds_len = 13; + + const milliseconds = 1000; + if ( + typeof timestamp === "number" && + timestamp.toString().length < milliseconds_len + ) { + const js_date = new Date(timestamp * milliseconds); + return js_date.toISOString(); + } + const microseconds_len = 16; + const nanoseconds_len = 19; + if (timestamp.toString().length === milliseconds_len) { + return new Date(Number(timestamp)).toISOString(); + } + + if (timestamp.toString().length === microseconds_len) { + const milli_time = BigInt(timestamp) / BigInt(milliseconds); + return new Date(Number(milli_time)).toISOString(); + } + + if (timestamp.toString().length === nanoseconds_len) { + const milli_time = BigInt(timestamp) / BigInt(milliseconds * milliseconds); + return new Date(Number(milli_time)).toISOString(); + } + + console.warn( + `Received very large number: ${timestamp}. Converting to max Number type value`, + ); + const milli_time = BigInt(timestamp) / BigInt(milliseconds); + return new Date(Number(milli_time)).toISOString(); +} diff --git a/src/timesketch/artifacts/files.ts b/src/timesketch/artifacts/files.ts new file mode 100644 index 00000000..b05d2bf5 --- /dev/null +++ b/src/timesketch/artifacts/files.ts @@ -0,0 +1,88 @@ +import { MacosFileInfo } from "../../../types/macos/files.ts"; +import { WindowsFileInfo } from "../../../types/windows/files.ts"; +import { LinuxFileInfo } from "../../../types/linux/files.ts"; + +import { TimesketchTimeline } from "../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../time/conversion.ts"; + +/** + * Function to timeline filesystem info + * @param data Array of `MacosFileInfo[] | WindowsFileInfo[] | LinuxFileInfo[]` + * @param is_windows Specify if filelisting is from Windows + * @returns Array `TimesketchTimeline` of files + */ +export function timelineFiles( + data: MacosFileInfo[] | WindowsFileInfo[] | LinuxFileInfo[], + is_windows: boolean, +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: "", + timestamp_desc: "", + message: `${item.full_path}`, + hash: item.md5, + user: item.uid.toString(), + artifact: "Files", + data_type: "system:fs:file", + _raw: "", + }; + + entry = { ...entry, ...item }; + + // Extract each unique timestamp to their own entry + const time_entries = extractApiTimes(item, is_windows); + for (const time_entry of time_entries) { + entry.datetime = unixEpochToISO(time_entry.datetime); + entry.timestamp_desc = time_entry.desc; + entries.push(Object.assign({}, entry)); + } + } + + return entries; +} + +interface TimeEntries { + datetime: number; + desc: string; +} + +/** + * Function to extract timestamps from file info + * @param entry A file info object. Can be `MacosFileInfo` or `WindowsFileInfo` or `LinuxFileInfo` + * @returns Array of `TimeEntries` + */ +function extractApiTimes( + entry: MacosFileInfo | WindowsFileInfo | LinuxFileInfo, + is_windows: boolean, +): TimeEntries[] { + const check_times: Record = {}; + const entries: TimeEntries[] = []; + + check_times[entry.created] = "Created"; + check_times[entry.modified] === undefined + ? (check_times[entry.modified] = "Modified") + : (check_times[entry.modified] = `${check_times[entry.modified]} Modified`); + + // Currently Rust does not support Changed timestamps on Windows :( + if (!is_windows) { + check_times[entry.changed] === undefined + ? (check_times[entry.changed] = "Changed") + : (check_times[entry.changed] = `${check_times[entry.changed]} Changed`); + } + + check_times[entry.accessed] === undefined + ? (check_times[entry.accessed] = "Accessed") + : (check_times[entry.accessed] = `${check_times[entry.accessed]} Accessed`); + + for (const value in check_times) { + const entry: TimeEntries = { + datetime: Number(value), + desc: check_times[value], + }; + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/emond.ts b/src/timesketch/artifacts/macos/emond.ts new file mode 100644 index 00000000..5c4c27ae --- /dev/null +++ b/src/timesketch/artifacts/macos/emond.ts @@ -0,0 +1,26 @@ +import { Emond } from "../../../../types/macos/emond.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; + +/** + * Function to timeline Emond. (This artifact has no timestamp) + * @param data Array of `Emond` + * @returns Array `TimesketchTimeline` of Emond + */ +export function timelineEmond(data: Emond[]): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: data[i].name, + data_type: "macos:emond:entry", + artifact: "Emond", + }; + entry = { ...entry, ...data[i] }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/execpolicy.ts b/src/timesketch/artifacts/macos/execpolicy.ts new file mode 100644 index 00000000..d81e1b8b --- /dev/null +++ b/src/timesketch/artifacts/macos/execpolicy.ts @@ -0,0 +1,37 @@ +import { ExecPolicy } from "../../../../types/macos/execpolicy.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline execpolicy + * @param data Array of `ExecPolicy` + * @returns Array `TimesketchTimeline` of LoginItems + */ +export function timelineExecpolicy(data: ExecPolicy[]): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.executable_timestamp), + timestamp_desc: "ExecPolicy Entry Created", + message: item.file_identifier, + artifact: "ExecPolicy", + data_type: "macos:sqlite:execpolicy:entry", + }; + entry = { ...entry, ...item }; + entry["executable_timestamp"] = unixEpochToISO(item.executable_timestamp); + entry["executable_measurements_v2_timestamp"] = unixEpochToISO( + item.executable_measurements_v2_timestamp, + ); + entry["reported_timstamp"] = unixEpochToISO(item.reported_timstamp); + entry["mod_time"] = unixEpochToISO(item.mod_time); + entry["policy_scan_cache_timestamp"] = unixEpochToISO( + item.policy_scan_cache_timestamp, + ); + entry["revocation_check_time"] = unixEpochToISO(item.revocation_check_time); + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/fsevents.ts b/src/timesketch/artifacts/macos/fsevents.ts new file mode 100644 index 00000000..dc4dadd8 --- /dev/null +++ b/src/timesketch/artifacts/macos/fsevents.ts @@ -0,0 +1,26 @@ +import { Fsevents } from "../../../../types/macos/fsevents.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; + +/** + * Function to timeline fsevents. (This artifact has no timestamp) + * @param data Array of `Fsevents` + * @returns Array `TimesketchTimeline` of Fsevents + */ +export function timelineFsevents(data: Fsevents[]): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: data[i].path, + data_type: "macos:fsevents:entry", + artifact: "FsEvents", + }; + entry = { ...entry, ...data[i] }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/groups.ts b/src/timesketch/artifacts/macos/groups.ts new file mode 100644 index 00000000..5c04d4c1 --- /dev/null +++ b/src/timesketch/artifacts/macos/groups.ts @@ -0,0 +1,26 @@ +import { Groups } from "../../../../types/macos/accounts.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; + +/** + * Function to timeline macos Groups + * @param data Array of `Groups` + * @returns Array `TimesketchTimeline` of Groups + */ +export function timelineGroupsMacos(data: Groups[]): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: item.name.join(""), + artifact: "Groups", + data_type: "macos:plist:accounts:group", + }; + entry = { ...entry, ...item }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/homebrew.ts b/src/timesketch/artifacts/macos/homebrew.ts new file mode 100644 index 00000000..908d1fc9 --- /dev/null +++ b/src/timesketch/artifacts/macos/homebrew.ts @@ -0,0 +1,30 @@ +import { HomebrewReceipt } from "../../../../types/macos/homebrew.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Homebrew Packages info + * @param data Array of `HomebrewReceipt` + * @returns Array `TimesketchTimeline` of HomebrewReceipt + */ +export function timelineHomebrew( + data: HomebrewReceipt[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.installTime), + timestamp_desc: "Homebrew Package Installed", + message: `${item.name} - ${item.description}`, + data_type: "macos:homebrew:package", + artifact: "HomebrewPackages", + }; + + entry = { ...entry, ...item }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/launchd.ts b/src/timesketch/artifacts/macos/launchd.ts new file mode 100644 index 00000000..3f7c247f --- /dev/null +++ b/src/timesketch/artifacts/macos/launchd.ts @@ -0,0 +1,29 @@ +import { Launchd } from "../../../../types/macos/launchd.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; + +/** + * Function to timeline Launchd. (This artifact has no timestamp) + * @param data Array of `Launchd` + * @param include_raw Include raw data in timeline entry + * @returns Array `TimesketchTimeline` of Launchd + */ +export function timelineLaunchd( + data: Launchd[], +): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + const entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: data[i].plist_path, + data_type: "macos:plist:launchd:entry", + artifact: "Launchd", + _raw: JSON.stringify(data[i]), + }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/loginitems.ts b/src/timesketch/artifacts/macos/loginitems.ts new file mode 100644 index 00000000..b000b4cd --- /dev/null +++ b/src/timesketch/artifacts/macos/loginitems.ts @@ -0,0 +1,31 @@ +import { LoginItems } from "../../../../types/macos/loginitems.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline loginitems + * @param data Array of `LoginItems` + * @returns Array `TimesketchTimeline` of LoginItems + */ +export function timelineLoginItems( + data: LoginItems[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.created), + timestamp_desc: "LoginItem Created", + message: item.path.length != 0 + ? `${item.volume_url}${item.path.join("/")}` + : `${item.app_binary}`, + artifact: "LoginItems", + data_type: "macos:plist:loginitems:entry", + }; + entry = { ...entry, ...item }; + entry["volume_created"] = unixEpochToISO(item.volume_created); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/safari.ts b/src/timesketch/artifacts/macos/safari.ts new file mode 100644 index 00000000..9aa2f4fe --- /dev/null +++ b/src/timesketch/artifacts/macos/safari.ts @@ -0,0 +1,72 @@ +import { + SafariDownloads, + SafariHistory, +} from "../../../../types/macos/safari.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Safari History + * @param data Array of `SafariHistory` + * @returns Array `TimesketchTimeline` of SafariHistory + */ +export function timelineSafariHistory( + data: SafariHistory[], +): TimesketchTimeline[] { + const entries = []; + + for (const value of data) { + for (let i = 0; i < value.history.length; i++) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(value.history[i].visit_time), + timestamp_desc: "Safari Visit Time", + message: `${value.history[i].url} - ${value.history[i].title}`, + data_type: "macos:safari:history", + artifact: "SafariHistory", + }; + entry = { ...entry, ...data[i] }; + entry["visit_time"] = unixEpochToISO(value.history[i].visit_time); + entries.push(entry); + } + } + return entries; +} + +/** + * Function to timeline Safari Downloads + * @param data Array of `SafariDownloads` + * @returns Array `TimesketchTimeline` of SafariDownloads + */ +export function timelineSafariDownloads( + data: SafariDownloads[], +): TimesketchTimeline[] { + const entries = []; + + for (const value of data) { + for (let i = 0; i < value.downloads.length; i++) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(value.downloads[i].created), + timestamp_desc: "Safari Download File Created", + message: `${value.downloads[i].source_url} - ${ + value.downloads[i].download_path + }`, + data_type: "macos:safari:downloads", + artifact: "SafariDownloads", + }; + entry = { ...entry, ...data[i] }; + entry["created"] = unixEpochToISO(value.downloads[i].created); + entry["download_entry_date"] = unixEpochToISO( + value.downloads[i].download_entry_date, + ); + entry["download_entry_finish"] = unixEpochToISO( + value.downloads[i].download_entry_finish, + ); + entry["volume_created"] = unixEpochToISO( + value.downloads[i].volume_created, + ); + + entries.push(entry); + } + } + return entries; +} diff --git a/src/timesketch/artifacts/macos/spotlight.ts b/src/timesketch/artifacts/macos/spotlight.ts new file mode 100644 index 00000000..b768ca25 --- /dev/null +++ b/src/timesketch/artifacts/macos/spotlight.ts @@ -0,0 +1,30 @@ +import { Spotlight } from "../../../../types/macos/spotlight.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline macos users + * @param data `Spotlight` object + * @returns Array `TimesketchTimeline` of Spotlight + */ +export function timelineSpotlight( + data: Spotlight[], +): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(data[i].last_updated), + timestamp_desc: "Spotlight Entry Last Updated", + message: data[i].values["_kMDItemFileName"]?.value as string ?? + `Inode: ${data[i].inode}`, + artifact: "Spotlight", + data_type: "macos:spotlight:entry", + }; + entry = { ...entry, ...data[i] }; + entry["last_updated"] = unixEpochToISO(data[i].last_updated); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/unifiedlogs.ts b/src/timesketch/artifacts/macos/unifiedlogs.ts new file mode 100644 index 00000000..8458b3f6 --- /dev/null +++ b/src/timesketch/artifacts/macos/unifiedlogs.ts @@ -0,0 +1,30 @@ +import { UnifiedLog } from "../../../../types/macos/unifiedlogs.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline unifiedlogs + * @param data Array of `UnifiedLog` + * @returns Array `TimesketchTimeline` of UnifiedLog + */ +export function timelineUnifiedLogs( + data: UnifiedLog[], +): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(data[i].time), + timestamp_desc: "UnifiedLog Entry Created", + message: "", + artifact: "UnifiedLogs", + data_type: "macos:unifiedlog:event", + }; + + entry = { ...entry, ...data[i] }; + entry["time"] = unixEpochToISO(data[i].time); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/macos/users.ts b/src/timesketch/artifacts/macos/users.ts new file mode 100644 index 00000000..5b537ad7 --- /dev/null +++ b/src/timesketch/artifacts/macos/users.ts @@ -0,0 +1,29 @@ +import { Users } from "../../../../types/macos/accounts.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline macos users + * @param data Array of `Users` + * @returns Array `TimesketchTimeline` of Users + */ +export function timelineUsersMacos( + data: Users[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.account_created), + timestamp_desc: "User Created", + message: item.home_path.join(" "), + artifact: "Users", + data_type: "macos:plist:accounts:user", + }; + entry = { ...entry, ...item }; + entry["account_created"] = unixEpochToISO(item.account_created); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/processes.ts b/src/timesketch/artifacts/processes.ts new file mode 100644 index 00000000..43851f42 --- /dev/null +++ b/src/timesketch/artifacts/processes.ts @@ -0,0 +1,30 @@ +import { ProcessInfo } from "../../../types/system/processes.ts"; +import { TimesketchTimeline } from "../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../time/conversion.ts"; + +/** + * Function to timeline process info + * @param data Array of `ProcessInfo` + * @returns Array `TimesketchTimeline` of processes + */ +export function timelineProcesses( + data: ProcessInfo[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.start_time), + timestamp_desc: "ProcessStart", + message: `${item.full_path} ${item.arguments}`, + artifact: "Processes", + data_type: "system:processes:process", + }; + + entry = { ...entry, ...item }; + entry["start_time"] = unixEpochToISO(item.start_time); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/amcache.ts b/src/timesketch/artifacts/windows/amcache.ts new file mode 100644 index 00000000..d197e258 --- /dev/null +++ b/src/timesketch/artifacts/windows/amcache.ts @@ -0,0 +1,30 @@ +import { Amcache } from "../../../../types/windows/amcache.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Amcache + * @param data Array of `Amcache` + * @returns Array `TimesketchTimeline` of Amcache + */ +export function timelineAmcache( + data: Amcache[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.last_modified), + timestamp_desc: "Amcache Registry Last Modified", + message: item.path, + artifact: "Amcache", + data_type: "windows:registry:amcache:entry", + }; + + entry = { ...entry, ...item }; + entry["last_modified"] = unixEpochToISO(item.last_modified); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/bits.ts b/src/timesketch/artifacts/windows/bits.ts new file mode 100644 index 00000000..ce206a81 --- /dev/null +++ b/src/timesketch/artifacts/windows/bits.ts @@ -0,0 +1,111 @@ +import { Bits } from "../../../../types/windows/bits.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; +import { BitsInfo } from "../../../../types/windows/bits.ts"; +import { Jobs } from "../../../../types/windows/bits.ts"; + +/** + * Function to timeline BITS + * @param data Array of `Bits` + * @returns Array `TimesketchTimeline` of BITS + */ +export function timelineBits( + data: Bits, +): TimesketchTimeline[] { + const entries = []; + + for (const item of data.bits) { + let entry: TimesketchTimeline = { + datetime: "", + timestamp_desc: "", + message: `Job: ${item.job_name} - Target Path: ${item.target_path}`, + artifact: "BITS", + data_type: "windows:ese:bits:entry", + }; + + entry = { ...entry, ...item }; + // Extract each unique timestamp to their own entry + const time_entries = extractTimes(item); + for (const time_entry of time_entries) { + entry.datetime = unixEpochToISO(time_entry.datetime); + entry.timestamp_desc = time_entry.desc; + entries.push(Object.assign({}, entry)); + } + } + + for (const item of data.carved_jobs) { + let entry: TimesketchTimeline = { + datetime: "", + timestamp_desc: "", + message: `Job: ${item.job_name} - Target Path: ${item.target_path}`, + artifact: "BITS Carved Job", + data_type: "windows:ese:bits:carve:job", + }; + entry = { ...entry, ...item }; + + // Extract each unique timestamp to their own entry + const time_entries = extractTimes(item); + for (const time_entry of time_entries) { + entry.datetime = unixEpochToISO(time_entry.datetime); + entry.timestamp_desc = `Carved ${time_entry.desc}`; + entries.push(Object.assign({}, entry)); + } + } + + for (const item of data.carved_files) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "Carved BITS File", + message: `File: ${item.full_path} - URL: ${item.url}`, + artifact: "BITS Carved File", + data_type: "windows:ese:bits:carve:file", + }; + entry = { ...entry, ...item }; + + entries.push(entry); + } + + return entries; +} + +interface TimeEntries { + datetime: number; + desc: string; +} + +/** + * Function to extract timestamps from BITS + * @param entry A `BitsInfo` or `Jobs` object + * @returns Array of `TimeEntries` + */ +function extractTimes(entry: BitsInfo | Jobs): TimeEntries[] { + const entries: TimeEntries[] = []; + const check_times: Record = {}; + + check_times[entry.created] = "BITS Created"; + check_times[entry.modified] === undefined + ? (check_times[entry.modified] = "BITS Modified") + : (check_times[entry.modified] = `${check_times[entry.modified]} Modified`); + + check_times[entry.expiration] === undefined + ? (check_times[entry.expiration] = "BITS Expired") + : (check_times[entry.expiration] = `${ + check_times[entry.expiration] + } Expired`); + + check_times[entry.completed] === undefined + ? (check_times[entry.completed] = "BITS Completed") + : (check_times[entry.completed] = `${ + check_times[entry.completed] + } Completed`); + + for (const value in check_times) { + const entry: TimeEntries = { + datetime: Number(value), + desc: check_times[value], + }; + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/eventlogs.ts b/src/timesketch/artifacts/windows/eventlogs.ts new file mode 100644 index 00000000..089e9a72 --- /dev/null +++ b/src/timesketch/artifacts/windows/eventlogs.ts @@ -0,0 +1,70 @@ +import { EventLogRecord } from "../../../../types/windows/eventlogs.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline EventLogs + * @param data Array of `EventLogRecord` + * @returns Array `TimesketchTimeline` of EventLogRecord + */ +export function timelineEventLogs( + data: EventLogRecord[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + const entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.timestamp), + timestamp_desc: "EventLog Generated", + message: "", + artifact: "EventLog", + data_type: "windows:eventlogs:entry", + _raw: JSON.stringify(item), + }; + + const value_data = item.data["Event"] as Record< + string, + Record> | null> + >; + + entry["event_id"] = JSON.stringify(value_data["System"]["EventID"]); + if (value_data["System"]["Provider"] != null) { + const provider = + value_data["System"]["Provider"]["#attributes"] as Record< + string, + string + >; + + entry["provider"] = provider["Name"]; + } + + entry["channel"] = value_data["System"]["Channel"]; + entry["computer"] = value_data["System"]["Computer"]; + if (value_data["System"]["Security"] != null) { + const user = value_data["System"]["Security"]["#attributes"] as Record< + string, + string + >; + entry["user"] = user["UserID"]; + } + let event_message = `EventID: ${entry["event_id"]} -- `; + + for (const event_data in value_data["EventData"]) { + event_message += `${event_data}: ${ + JSON.stringify(value_data["EventData"][event_data]) + } `; + } + + for (const event_data in value_data["UserData"]) { + event_message += `${event_data}: ${ + JSON.stringify(value_data["UserData"][event_data]) + } `; + } + + entry.message = event_message; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/eventlogs/logons.ts b/src/timesketch/artifacts/windows/eventlogs/logons.ts new file mode 100644 index 00000000..dffeebdc --- /dev/null +++ b/src/timesketch/artifacts/windows/eventlogs/logons.ts @@ -0,0 +1,36 @@ +import { LogonsWindows } from "../../../../../types/windows/eventlogs/logons.ts"; +import { TimesketchTimeline } from "../../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../../time/conversion.ts"; + +/** + * Function to timeline Windows Logons + * @param data Array of `LogonsWindows` + * @returns Array `TimesketchTimeline` of LogonsWindows + */ +export function timelineLogonsWindows( + data: LogonsWindows[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.logoff_time), + timestamp_desc: "Windows Logoff", + message: `Logoff for: ${item.account_domain}\\${item.account_name}`, + artifact: "Windows Logons", + data_type: "windows:eventlogs:logons:entry", + }; + + entry = { ...entry, ...item }; + entry["logon_time"] = unixEpochToISO(item.logon_time); + entry["logoff_time"] = unixEpochToISO(item.logoff_time); + + entries.push(Object.assign({}, entry)); + entry.datetime = unixEpochToISO(item.logon_time); + entry.timestamp_desc = "Windows Logon"; + entry.message = `Logon for: ${item.account_domain}\\${item.account_name}`; + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/jumplists.ts b/src/timesketch/artifacts/windows/jumplists.ts new file mode 100644 index 00000000..b2222f54 --- /dev/null +++ b/src/timesketch/artifacts/windows/jumplists.ts @@ -0,0 +1,46 @@ +import { Jumplists } from "../../../../types/windows/jumplists.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; +import { extractShortcutTimes } from "./shortcuts.ts"; + +/** + * Function to timeline Jumplists + * @param data Array of `Jumplists` + * @returns Array `TimesketchTimeline` of Jumplists + */ +export function timelineJumplists( + data: Jumplists[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + const entry: TimesketchTimeline = { + datetime: unixEpochToISO(item?.jumplist_metadata.modified), + timestamp_desc: "Jumplist Modified", + message: item.lnk_info.path, + artifact: "Jumplist", + data_type: "windows:jumplist:entry", + _raw: JSON.stringify(item), + }; + + if (entry.message === "" && item.jumplist_metadata.path === "") { + let message = ""; + for (const shell of item.lnk_info.shellitems) { + message += `${shell.value}\\`; + } + entry.message = message; + } else if (entry.message === "") { + entry.message = item.jumplist_metadata.path; + } + + // Extract each unique timestamp to their own entry + const time_entries = extractShortcutTimes(item.lnk_info); + for (const time_entry of time_entries) { + entry.datetime = unixEpochToISO(time_entry.datetime); + entry.timestamp_desc = time_entry.desc; + entries.push(Object.assign({}, entry)); + } + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/ntfs.ts b/src/timesketch/artifacts/windows/ntfs.ts new file mode 100644 index 00000000..c9680aa7 --- /dev/null +++ b/src/timesketch/artifacts/windows/ntfs.ts @@ -0,0 +1,107 @@ +import { unixEpochToISO } from "../../../time/conversion.ts"; +import { RawFileInfo } from "../../../../types/windows/ntfs.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; + +/** + * Function to timeline filesystem info + * @param data Array of `MacosFileInfo[] | WindowsFileInfo[] | LinuxFileInfo[]` + * @returns Array `TimesketchTimeline` of files + */ +export function timelineRawFiles(data: RawFileInfo[]): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: "", + timestamp_desc: "", + message: `${item.full_path}`, + artifact: "RawFiles", + data_type: "fs::ntfs:file", + }; + + entry = { ...entry, ...item }; + entry["created"] = unixEpochToISO(item.created); + entry["modified"] = unixEpochToISO(item.modified); + entry["accessed"] = unixEpochToISO(item.accessed); + entry["changed"] = unixEpochToISO(item.created); + + entry["filename_created"] = unixEpochToISO(item.filename_created); + entry["filename_modified"] = unixEpochToISO(item.filename_modified); + entry["filename_accessed"] = unixEpochToISO(item.filename_accessed); + entry["filename_changed"] = unixEpochToISO(item.filename_changed); + + entry["binary_info"] = JSON.stringify(item.binary_info); + + // Extract each unique timestamp to their own entry + const time_entries = extractRawTimes(item); + for (const time_entry of time_entries) { + entry.datetime = unixEpochToISO(time_entry.datetime); + entry.timestamp_desc = time_entry.desc; + entries.push(Object.assign({}, entry)); + } + } + + return entries; +} + +interface TimeEntries { + datetime: number; + desc: string; +} + +/** + * Function to extract timestamps from file info + * @param entry A `RawFileInfo` object + * @returns Array of `TimeEntries` + */ +function extractRawTimes(entry: RawFileInfo): TimeEntries[] { + const entries: TimeEntries[] = []; + const check_times: Record = {}; + + check_times[entry.created] = "Created"; + check_times[entry.modified] === undefined + ? (check_times[entry.modified] = "Modified") + : (check_times[entry.modified] = `${check_times[entry.modified]} Modified`); + + check_times[entry.changed] === undefined + ? (check_times[entry.changed] = "Changed") + : (check_times[entry.changed] = `${check_times[entry.changed]} Changed`); + + check_times[entry.accessed] === undefined + ? (check_times[entry.accessed] = "Accessed") + : (check_times[entry.accessed] = `${check_times[entry.accessed]} Accessed`); + + check_times[entry.filename_created] === undefined + ? (check_times[entry.filename_created] = "FilenameCreated") + : (check_times[entry.filename_created] = `${ + check_times[entry.filename_created] + } FilenameCreated`); + + check_times[entry.filename_modified] === undefined + ? (check_times[entry.filename_modified] = "FilenameModified") + : (check_times[entry.filename_modified] = `${ + check_times[entry.filename_modified] + } FilenameModified`); + + check_times[entry.filename_accessed] === undefined + ? (check_times[entry.filename_accessed] = "FilenameAccessed") + : (check_times[entry.filename_accessed] = `${ + check_times[entry.filename_accessed] + } FilenameAccessed`); + + check_times[entry.filename_changed] === undefined + ? (check_times[entry.filename_changed] = "FilenameChanged") + : (check_times[entry.filename_changed] = `${ + check_times[entry.filename_changed] + } FilenameChanged`); + + for (const value in check_times) { + const entry: TimeEntries = { + datetime: Number(value), + desc: check_times[value], + }; + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/prefetch.ts b/src/timesketch/artifacts/windows/prefetch.ts new file mode 100644 index 00000000..95e1cc2c --- /dev/null +++ b/src/timesketch/artifacts/windows/prefetch.ts @@ -0,0 +1,35 @@ +import { Prefetch } from "../../../../types/windows/prefetch.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Prefetch + * @param data Array of `Prefetch` + * @returns Array `TimesketchTimeline` of Prefetch + */ +export function timelinePrefetch( + data: Prefetch[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.last_run_time), + timestamp_desc: "Prefetch Last Execution", + message: item.path, + artifact: "Prefetch", + data_type: "windows:prefetch:execution", + }; + entry = { ...entry, ...item }; + + entries.push(entry); + for (let i = 0; i < item.all_run_times.length; i++) { + const old_run = Object.assign({}, entry); + old_run.datetime = unixEpochToISO(item.all_run_times[i]); + old_run.timestamp_desc = "Prefetch Execution"; + entries.push(old_run); + } + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/recyclebin.ts b/src/timesketch/artifacts/windows/recyclebin.ts new file mode 100644 index 00000000..0d3f2559 --- /dev/null +++ b/src/timesketch/artifacts/windows/recyclebin.ts @@ -0,0 +1,30 @@ +import { RecycleBin } from "../../../../types/windows/recyclebin.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline RecycleBin + * @param data Array of `RecycleBin` + * @returns Array `TimesketchTimeline` of RecycleBin + */ +export function timelineRecycleBin( + data: RecycleBin[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.deleted), + timestamp_desc: "RecycleBin File Deleted", + message: item.full_path, + artifact: "RecycleBin", + data_type: "windows:recyclebin:file", + }; + + entry = { ...entry, ...item }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/registry.ts b/src/timesketch/artifacts/windows/registry.ts new file mode 100644 index 00000000..7c05b184 --- /dev/null +++ b/src/timesketch/artifacts/windows/registry.ts @@ -0,0 +1,39 @@ +import { RegistryData } from "../../../../types/windows/registry.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline RegistryData + * @param data `RegistryData` object + * @returns Array `TimesketchTimeline` of RegistryData + */ +export function timelineRegistry(data: RegistryData): TimesketchTimeline[] { + const entries = []; + + for (const item of data.registry_entries) { + const entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.last_modified), + timestamp_desc: "Registry Last Modified", + message: "", + artifact: "Registry", + data_type: "windows:registry:key", + }; + entry["registry_path"] = data.registry_path; + entry["registry_file"] = data.registry_file; + entry["depth"] = item.depth; + entry["key"] = item.key; + entry["path"] = item.path; + entry["name"] = item.name; + entry["security_offset"] = item.security_offset; + for (const value of item.values) { + entry.message = `${item.path} | Value: ${value.value}`; + entry["value"] = value.value; + entry["data"] = value.data; + entry["reg_data_type"] = value.data_type; + + entries.push(Object.assign({}, entry)); + } + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/search.ts b/src/timesketch/artifacts/windows/search.ts new file mode 100644 index 00000000..ac13862b --- /dev/null +++ b/src/timesketch/artifacts/windows/search.ts @@ -0,0 +1,28 @@ +import { SearchEntry } from "../../../../types/windows/search.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Windows Search + * @param data Array of `SearchEntry` + * @returns Array `TimesketchTimeline` of Search + */ +export function timelineSearch(data: SearchEntry[]): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(data[i].last_modified), + timestamp_desc: "Search Entry Last Modified", + message: data[i].entry, + artifact: "Search", + data_type: "windows:ese:search:entry", + }; + + entry = { ...entry, ...data[i].properties }; + entry["last_modified"] = unixEpochToISO(data[i].last_modified); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/services.ts b/src/timesketch/artifacts/windows/services.ts new file mode 100644 index 00000000..b011ebbc --- /dev/null +++ b/src/timesketch/artifacts/windows/services.ts @@ -0,0 +1,25 @@ +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { Services } from "../../../../types/windows/services.ts"; + +/** + * Function to timeline Services + * @param data Array of `Services` + * @returns Array `TimesketchTimeline` of Services + */ +export function timelineServices(data: Services[]): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: `Service Name: ${item.name} | ${item.path}`, + artifact: "Service", + data_type: "windows:registry:services:entry", + }; + entry = { ...entry, ...item }; + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/shellbags.ts b/src/timesketch/artifacts/windows/shellbags.ts new file mode 100644 index 00000000..c58a923b --- /dev/null +++ b/src/timesketch/artifacts/windows/shellbags.ts @@ -0,0 +1,30 @@ +import { Shellbags } from "../../../../types/windows/shellbags.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Shellbags + * @param data Array of `Shellbags` + * @returns Array `TimesketchTimeline` of Shellbags + */ +export function timelineShellbags(data: Shellbags[]): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.reg_modified), + timestamp_desc: "Registry Last Modified", + message: item.path, + artifact: "Shellbags", + data_type: "windows:registry:shellbags:item", + }; + entry = { ...entry, ...item }; + entry["created"] = unixEpochToISO(item.created); + entry["modified"] = unixEpochToISO(item.modified); + entry["accessed"] = unixEpochToISO(item.accessed); + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/shimcache.ts b/src/timesketch/artifacts/windows/shimcache.ts new file mode 100644 index 00000000..a9de2cf7 --- /dev/null +++ b/src/timesketch/artifacts/windows/shimcache.ts @@ -0,0 +1,29 @@ +import { Shimcache } from "../../../../types/windows/shimcache.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Shimcache + * @param data Array of `Shimcache` + * @returns Array `TimesketchTimeline` of Shimcache + */ +export function timelineShimcache( + data: Shimcache[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.last_modified), + timestamp_desc: "Shimcache Last Modified", + message: item.path, + artifact: "Shimcache", + data_type: "windows:registry:shimcache:entry", + }; + entry = { ...entry, ...item }; + entry["last_modified"] = unixEpochToISO(item.last_modified); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/shimdb.ts b/src/timesketch/artifacts/windows/shimdb.ts new file mode 100644 index 00000000..2b7ca0de --- /dev/null +++ b/src/timesketch/artifacts/windows/shimdb.ts @@ -0,0 +1,50 @@ +import { Shimdb } from "../../../../types/windows/shimdb.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Shimdb + * @param data Array of `Shimdb` + * @returns Array `TimesketchTimeline` of Shimdb + */ +export function timelineShimdb( + data: Shimdb[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + const entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.db_data.compile_time), + timestamp_desc: "Shim Compile Time", + message: "", + artifact: "Shimdb", + data_type: "windows:shimdb:entry", + }; + + // If we include Indexes, memory usage will explode (~2GB) and crash the JS stack. Indexes primarily contain base64 binary data. There's nothing parsable in it + // This likely only affects sysmain.sdb due to the large number of Shims. We could split this into separate entries if needed + // Custom Shims would likely be unaffected + // entry["indexes"] = JSON.stringify(item.indexes); + + entry["sdb_version"] = item.db_data.sdb_version; + entry["compile_time"] = item.db_data.compile_time; + entry["compiler_version"] = item.db_data.compiler_version; + entry["name"] = item.db_data.name; + entry["platform"] = item.db_data.platform; + entry["database_id"] = item.db_data.database_id; + entry["additional_metadata"] = JSON.stringify( + item.db_data.additional_metadata, + ); + + // If we parsed the sysmain.sdb file. This will be a lot of data + for (let i = 0; i < item.db_data.list_data.length; i++) { + entry.message = `${item.sdb_path} | Shim Tag Name: ${ + item.db_data.list_data[i].data["TAG_NAME"] + }`; + entry["tag_info"] = JSON.stringify(item.db_data.list_data[i]); + entries.push(Object.assign({}, entry)); + } + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/shortcuts.ts b/src/timesketch/artifacts/windows/shortcuts.ts new file mode 100644 index 00000000..b0d0b684 --- /dev/null +++ b/src/timesketch/artifacts/windows/shortcuts.ts @@ -0,0 +1,68 @@ +import { Shortcut } from "../../../../types/windows/shortcuts.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Shortcut + * @param data Array of `Shortcut` + * @returns Array `TimesketchTimeline` of Shortcut + */ +export function timelineShortcuts( + data: Shortcut[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: item.path, + artifact: "Shortcut", + data_type: "windows:shortcut:lnk", + }; + + if (entry.message === "") { + for (const shell of item.shellitems) { + entry.message += `${shell.value}\\`; + } + } + + entry = { ...entry, ...item }; + // Extract each unique timestamp to their own entry + const time_entries = extractShortcutTimes(item); + for (const time_entry of time_entries) { + entry.datetime = unixEpochToISO(time_entry.datetime); + entry.timestamp_desc = time_entry.desc; + entries.push(Object.assign({}, entry)); + } + } + + return entries; +} + +interface TimeEntries { + datetime: number; + desc: string; +} +export function extractShortcutTimes(entry: Shortcut): TimeEntries[] { + const entries: TimeEntries[] = []; + const check_times: Record = {}; + + check_times[entry.created] = "Shortcut Target Created"; + check_times[entry.modified] === undefined + ? (check_times[entry.modified] = "Shortcut Target Modified") + : (check_times[entry.modified] = `${check_times[entry.modified]} Modified`); + + check_times[entry.accessed] === undefined + ? (check_times[entry.accessed] = "Shortcut Target Accessed") + : (check_times[entry.accessed] = `${check_times[entry.accessed]} Accessed`); + + for (const value in check_times) { + const entry: TimeEntries = { + datetime: Number(value), + desc: check_times[value], + }; + entries.push(entry); + } + return entries; +} diff --git a/src/timesketch/artifacts/windows/srum.ts b/src/timesketch/artifacts/windows/srum.ts new file mode 100644 index 00000000..6d5b452e --- /dev/null +++ b/src/timesketch/artifacts/windows/srum.ts @@ -0,0 +1,83 @@ +import { + ApplicationInfo, + ApplicationTimeline, + AppVfu, + EnergyInfo, + EnergyUsage, + NetworkConnectivityInfo, + NetworkInfo, + NotificationInfo, +} from "../../../../types/windows/srum.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Windows Search + * @param data Array of `SearchEntry` + * @returns Array `TimesketchTimeline` of Search + */ +export function timelineSrum( + data: + | ApplicationInfo[] + | ApplicationTimeline[] + | AppVfu[] + | EnergyInfo[] + | EnergyUsage[] + | NetworkInfo[] + | NetworkConnectivityInfo[] + | NotificationInfo[], +): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(data[i].timestamp), + timestamp_desc: "SRUM Table Update", + message: data[i].app_id, + artifact: "", + data_type: "", + }; + + entry = { ...entry, ...data[i] }; + if (entry["facetime"] != undefined) { + entry.artifact = "Windows SRUM Application Info"; + entry.data_type = "windows:ese:srum:application_info:entry"; + } else if (entry["cycles_wob"] != undefined) { + entry.artifact = "Windows SRUM Application Timeline"; + entry.data_type = "windows:ese:srum:application_timeline:entry"; + } else if (entry["start_time"] != undefined) { + entry.artifact = "Windows SRUM App VFU"; + entry.data_type = "windows:ese:srum:app_vfu:entry"; + entry["start_time"] = unixEpochToISO((data[i] as AppVfu).start_time); + entry["end_time"] = unixEpochToISO((data[i] as AppVfu).end_time); + } else if (entry["binary_data"] != undefined) { + entry.artifact = "Windows SRUM Energy Info"; + entry.data_type = "windows:ese:srum:energy_info:entry"; + } else if (entry["event_timestamp"] != undefined) { + entry.artifact = "Windows SRUM Energy Usage"; + entry.data_type = "windows:ese:srum:energy_usage:entry"; + entry["event_timestamp"] = unixEpochToISO( + (data[i] as EnergyUsage).event_timestamp, + ); + } else if (entry["bytes_sent"] != undefined) { + entry.artifact = "Windows SRUM Network Info"; + entry.data_type = "windows:ese:srum:network_info:entry"; + } else if (entry["connected_time"] != undefined) { + entry.artifact = "Windows SRUM Network Connectivity"; + entry.data_type = "windows:ese:srum:network_connectivity:entry"; + entry["connect_start_time"] = unixEpochToISO( + (data[i] as NetworkConnectivityInfo).connect_start_time, + ); + } else if (entry["notification_type"] != undefined) { + entry.artifact = "Windows SRUM Notification Info"; + entry.data_type = "windows:ese:srum:notification_info:entry"; + } + + // Timestamp is a reserved word for Timesketch. So we will rename to srum_timestamp + delete entry["timestamp"]; + entry["srum_timestamp"] = unixEpochToISO(data[i].timestamp); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/tasks.ts b/src/timesketch/artifacts/windows/tasks.ts new file mode 100644 index 00000000..735bed80 --- /dev/null +++ b/src/timesketch/artifacts/windows/tasks.ts @@ -0,0 +1,49 @@ +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { TaskData } from "../../../../types/windows/tasks.ts"; + +/** + * Function to timeline Amcache + * @param data Array of `Amcache` + * @returns Array `TimesketchTimeline` of Amcache + */ +export function timelineTasks(data: TaskData): TimesketchTimeline[] { + const entries = []; + + for (const item of data.tasks) { + const entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: item.path, + hash: "", + user: "", + artifact: "Schedule Task", + data_type: "windows:tasks:xml:entry", + _raw: "", + }; + + entry["registration_info"] = item.registrationInfo; + entry["triggers"] = item.triggers; + entry["settings"] = item.settings; + entry["data"] = item.data; + entry["principals"] = item.principals; + entry["actions"] = item.actions; + + entries.push(entry); + } + + for (const item of data.jobs) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: item.path, + artifact: "Schedule Task", + data_type: "windows:tasks:jobs:entry", + }; + + entry = { ...entry, ...item }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/userassist.ts b/src/timesketch/artifacts/windows/userassist.ts new file mode 100644 index 00000000..990291fe --- /dev/null +++ b/src/timesketch/artifacts/windows/userassist.ts @@ -0,0 +1,32 @@ +import { UserAssist } from "../../../../types/windows/userassist.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline UserAssist + * @param data Array of `UserAssist` + * @param include_raw Include raw data in timeline entry + * @returns Array `TimesketchTimeline` of UserAssist + */ +export function timelineUserAssist( + data: UserAssist[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.last_execution), + timestamp_desc: "Userassist Last Execution", + message: item.path, + artifact: "UserAssist", + data_type: "windows:registry:userassist:entry", + }; + + entry = { ...entry, ...item }; + entry["last_execution"] = unixEpochToISO(item.last_execution); + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/users.ts b/src/timesketch/artifacts/windows/users.ts new file mode 100644 index 00000000..bc4a996d --- /dev/null +++ b/src/timesketch/artifacts/windows/users.ts @@ -0,0 +1,32 @@ +import { UserInfo } from "../../../../types/windows/users.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline Windows Users + * @param data Array of `UserInfo` + * @returns Array `TimesketchTimeline` of UserInfo + */ +export function timelineUsersWindows( + data: UserInfo[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(item.last_logon), + timestamp_desc: "User Last Logon", + message: item.username, + artifact: "Windows User", + data_type: "windows:registry:users:entry", + }; + + entry = { ...entry, ...item }; + entry["password_last_set"] = unixEpochToISO(item.password_last_set); + entry["last_password_failure"] = unixEpochToISO(item.last_password_failure); + entry["last_logon"] = unixEpochToISO(item.last_logon); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/usnjrnl.ts b/src/timesketch/artifacts/windows/usnjrnl.ts new file mode 100644 index 00000000..807988a5 --- /dev/null +++ b/src/timesketch/artifacts/windows/usnjrnl.ts @@ -0,0 +1,30 @@ +import { UsnJrnl } from "../../../../types/windows/usnjrnl.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; +import { unixEpochToISO } from "../../../time/conversion.ts"; + +/** + * Function to timeline UsnJrnl + * @param data Array of `UsnJrnl` + * @returns Array `TimesketchTimeline` of UsnJrnl + */ +export function timelineUsnJrnl( + data: UsnJrnl[], +): TimesketchTimeline[] { + const entries = []; + + for (let i = 0; i < data.length; i++) { + let entry: TimesketchTimeline = { + datetime: unixEpochToISO(data[i].update_time), + timestamp_desc: `UsnJrnl ${data[i].update_reason}`, + message: data[i].full_path, + artifact: "UsnJrnl", + data_type: "fs:ntfs:usnjrnl:entry", + }; + + entry = { ...entry, ...data[i] }; + entry["update_time"] = unixEpochToISO(data[i].update_time); + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/artifacts/windows/wmi.ts b/src/timesketch/artifacts/windows/wmi.ts new file mode 100644 index 00000000..66f46212 --- /dev/null +++ b/src/timesketch/artifacts/windows/wmi.ts @@ -0,0 +1,29 @@ +import { WmiPersist } from "../../../../types/windows/wmi.ts"; +import { TimesketchTimeline } from "../../../../types/timesketch/timeline.ts"; + +/** + * Function to timeline WMI Persistence + * @param data Array of `WmiPersist` + * @returns Array `TimesketchTimeline` of WmiPersist + */ +export function timelineWmiPersist( + data: WmiPersist[], +): TimesketchTimeline[] { + const entries = []; + + for (const item of data) { + let entry: TimesketchTimeline = { + datetime: "1601-01-01T00:00:00.000Z", + timestamp_desc: "N/A", + message: item.consumer, + artifact: "WMI Persist", + data_type: "windows:wmi:persistence:entry", + }; + + entry = { ...entry, ...item }; + + entries.push(entry); + } + + return entries; +} diff --git a/src/timesketch/client.ts b/src/timesketch/client.ts new file mode 100644 index 00000000..8f33e9bc --- /dev/null +++ b/src/timesketch/client.ts @@ -0,0 +1,341 @@ +import { TimesketchAuth } from "../../types/timesketch/client.ts"; +import { TimesketchError } from "./error.ts"; +import { BodyType, ClientRequest, Protocol, request } from "../http/client.ts"; +import { HttpError } from "../http/errors.ts"; +import { extractUtf8String } from "../encoding/strings.ts"; +import { + TimesketchArtifact, + TimesketchTimeline, +} from "../../types/timesketch/timeline.ts"; +import { encodeBytes } from "../encoding/bytes.ts"; +import { timelineArtifact } from "./timeline.ts"; +import { TimelineResponse } from "../../types/timesketch/client.ts"; + +export class Timesketch { + private timesketch_auth: TimesketchAuth; + private token: string; + private cookie: string; + private timeline_name; + private opensearch_index: string; + private verify_ssl: boolean; + + /** + * @param auth `TimesketchAuth` object used to authenticate to Timesketch + * @param name The name that should used for the timeline. If none is provided the artifact name will be used. It is **recommended** to provide a name (ex: the hostname) + * @param index The OpenSearch index that should be used when uploading data. If none is provided a new index will be created + * @param verify_ssl Boolean value to determine if artemis should verify SSL certs. Set to false if you use self-signed certs + */ + constructor(auth: TimesketchAuth, name = "", index = "", verify_ssl = true) { + this.timesketch_auth = auth; + this.token = ""; + this.cookie = ""; + this.timeline_name = name; + this.opensearch_index = index; + this.verify_ssl = verify_ssl; + } + + /** + * Function to timeline and upload data to Timesketch + * @param data Artifact data to Timeline. Must be the type specified by `artifact` + * @param artifact The artifact type that should be timeline + * @returns A `TimesketchError` if the data cannot be timeline or if it failed to upload to Timesketch + */ + public async timelineAndUpload( + data: unknown, + artifact: TimesketchArtifact, + ): Promise { + const timeline_data = timelineArtifact(data, artifact); + if (timeline_data instanceof TimesketchError) { + return timeline_data; + } + + if (timeline_data.length === 0) { + return new TimesketchError(`ARTIFACT`, `zero values for ${artifact}`); + } + + // If no token or cookie. We need to logon! + if (this.token === "" || this.cookie === "") { + const status = await this.authTimesketch(); + if (status instanceof TimesketchError) { + return status; + } + } + + if (this.timesketch_auth.sketch_id === undefined) { + await this.createSketch(artifact); + } + + // Verify user provived a valid Sketch ID + const id_status = await this.verifySketchId(); + if (id_status instanceof TimesketchError) { + return id_status; + } + + return await this.uploadTimeline(timeline_data, artifact); + } + + /** + * Function to upload timeline data to Timesketch + * @param data Array of `TimesketchTimeline` + * @param artifact `TimesketchArtifact` enum + * @returns A `TimesketchError` if data cannot be uploaded. + */ + private async uploadTimeline( + data: TimesketchTimeline[], + artifact: TimesketchArtifact, + ): Promise { + if (this.timeline_name === "") { + this.timeline_name = artifact; + } + + const entries_strings = []; + // We have to convert the TimesketchTimeline object to a string :/ + for (let i = 0; i < data.length; i++) { + entries_strings.push(JSON.stringify(data[i])); + } + + const headers = { + "X-Csrftoken": this.token, + Cookie: this.cookie, + }; + + const client: ClientRequest = { + url: `${this.timesketch_auth.url}/api/v1/upload/`, + protocol: Protocol.POST, + headers, + body_type: BodyType.FORM, + verify_ssl: this.verify_ssl, + }; + + const chunk_size = 10000; + // Split data into chunks so Timesketch does not keel over + for (let i = 0; i < entries_strings.length; i += chunk_size) { + const chunk = entries_strings.slice(i, i + chunk_size); + // From: https://github.com/google/timesketch/blob/3c781e6bde4398e24cba7dd41c4f87ba4d6e5394/importer_client/python/timesketch_import_client/importer.py#L249 + const post_data: Record = { + name: this.timeline_name, + sketch_id: this.timesketch_auth.sketch_id, + data_label: artifact, + enable_stream: false, + provider: "artemis", + events: chunk.join("\n"), + }; + + if (this.opensearch_index != "") { + post_data["index_name"] = this.opensearch_index; + } + + const bytes = encodeBytes(JSON.stringify(post_data)); + const response = await request(client, bytes); + if (response instanceof HttpError) { + return new TimesketchError( + `UPLOAD`, + `failed to upload to Timesketch ${response}`, + ); + } + + if (response.status != 201) { + return new TimesketchError( + `UPLOAD`, + `non-201 response for uploading data ${ + extractUtf8String( + new Uint8Array(response.body), + ) + }`, + ); + } + + const task_info: TimelineResponse = JSON.parse( + extractUtf8String(new Uint8Array(response.body)), + ); + + // Try to get the OpenSearch Index from the upload response + if (this.opensearch_index === "") { + this.opensearch_index = + task_info.objects.at(0)?.searchindex.index_name ?? ""; + } + } + } + + /** + * Function to create a sketch + * @param artifact The artifact used to name the sketch if a name is not provided + * @returns A `TimesketchError` if a sketch cannot be created + */ + private async createSketch( + artifact: TimesketchArtifact, + ): Promise { + if (this.timesketch_auth.sketch_name === undefined) { + this.timesketch_auth.sketch_name = artifact; + } + + const headers = { + "X-Csrftoken": this.token, + Cookie: this.cookie, + "Content-Type": "application/json", + }; + + const client: ClientRequest = { + url: `${this.timesketch_auth.url}/api/v1/sketches/`, + protocol: Protocol.POST, + headers, + }; + + const body = { + "name": this.timesketch_auth.sketch_name, + "description": `Timeline for ${this.timesketch_auth.sketch_name}`, + }; + const bytes = encodeBytes(JSON.stringify(body)); + const response = await request(client, bytes); + if (response instanceof HttpError) { + return new TimesketchError( + `SKETCH_ID`, + `failed to create sketch ${this.timesketch_auth.sketch_name}: ${response}`, + ); + } + + const result = extractUtf8String(new Uint8Array(response.body)); + const sketch_object = JSON.parse(result); + const objects_value = sketch_object["objects"]; + if (objects_value === undefined) { + return new TimesketchError( + `SKETCH_ID`, + `failed no objects in sketch response: ${response}`, + ); + } + this.timesketch_auth.sketch_id = objects_value.at(0)["id"]; + } + + /** + * Function to verify if provided Sketch ID exists + * @returns `TimesketchError` if we cannot verify the Sketch ID + */ + private async verifySketchId(): Promise { + const headers = { + "X-Csrftoken": this.token, + Cookie: this.cookie, + }; + + const client: ClientRequest = { + url: + `${this.timesketch_auth.url}/api/v1/sketches/${this.timesketch_auth.sketch_id}/`, + protocol: Protocol.GET, + headers, + verify_ssl: this.verify_ssl, + }; + + const response = await request(client); + if (response instanceof HttpError) { + return new TimesketchError( + `SKETCH_ID`, + `failed to verify Sketch ID ${this.timesketch_auth.sketch_id} ${response}`, + ); + } + + if (response.status != 200) { + return new TimesketchError( + `SKETCH_ID`, + `non-200 response for verifying Sketch ID ${ + extractUtf8String( + new Uint8Array(response.body), + ) + }`, + ); + } + const id_text = extractUtf8String(new Uint8Array(response.body)); + const id_info = JSON.parse(id_text); + if (id_info["objects"].length === 0) { + return new TimesketchError( + `SKETCH_ID`, + `no Sketch ID associated ${this.timesketch_auth.sketch_id}: ${id_text}`, + ); + } + } + + /** + * Function to authenticate to Timesketch + * @returns `TimesketchError` if authentication failed + */ + private async authTimesketch(): Promise { + const client: ClientRequest = { + url: `${this.timesketch_auth.url}/login/`, + protocol: Protocol.GET, + verify_ssl: this.verify_ssl, + }; + const response = await request(client); + if (response instanceof HttpError) { + return new TimesketchError( + `AUTH`, + `failed to start auth to Timesketch ${response}`, + ); + } + + const body_text = extractUtf8String(new Uint8Array(response.body)); + // I hope they don't change this much... + const value_regex = /value=".*"/m; + const value_token = body_text.match(value_regex); + + // Extract the CSRF Token + if (typeof value_token?.[0] === "string" && value_token?.[0].length > 50) { + this.token = value_token?.[0] + .replaceAll("value=", "") + .replaceAll('"', ""); + } + + // Also need first cookie + this.cookie = response.headers["set-cookie"].split(";").at(0) ?? ""; + if (this.cookie === "") { + return new TimesketchError( + `AUTH`, + `failed to get Cookie for logon ${response.headers}`, + ); + } + + // We should be able to auth to Timesketch now! + const form = { + username: this.timesketch_auth.username, + password: this.timesketch_auth.password, + csrf_token: this.token, + }; + const headers = { + "Content-Type": "application/x-www-form-urlencoded", + referer: this.timesketch_auth.url, + Cookie: this.cookie, + }; + const form_string = JSON.stringify(form); + const bytes = encodeBytes(form_string); + + client.headers = headers; + client.body_type = BodyType.FORM; + client.follow_redirects = false; + client.protocol = Protocol.POST; + // Logon but do not follow the redirect. We need one more cookie + const auth_response = await request(client, bytes); + if (auth_response instanceof HttpError) { + return new TimesketchError( + `AUTH`, + `failed to logon and auth to Timesketch ${auth_response}`, + ); + } + + if (auth_response.status != 302) { + return new TimesketchError( + `AUTH`, + `non-302 response for auth to Timesketch ${ + extractUtf8String( + new Uint8Array(auth_response.body), + ) + }`, + ); + } + + // Update the cookie so we remain authenticated + this.cookie = auth_response.headers["set-cookie"].split(";").at(0) ?? ""; + if (this.cookie === "") { + return new TimesketchError( + `AUTH`, + `failed to get last Cookie for logon ${auth_response.headers}`, + ); + } + } +} diff --git a/src/timesketch/error.ts b/src/timesketch/error.ts new file mode 100644 index 00000000..87a88524 --- /dev/null +++ b/src/timesketch/error.ts @@ -0,0 +1,11 @@ +import { ErrorBase } from "../utils/error.ts"; + +export type ErrorName = + | "UPLOAD" + | "TIMELINE" + | "OUTPUT" + | "ARTIFACT" + | "AUTH" + | "SKETCH_ID"; + +export class TimesketchError extends ErrorBase {} diff --git a/src/timesketch/timeline.ts b/src/timesketch/timeline.ts new file mode 100644 index 00000000..8b140eda --- /dev/null +++ b/src/timesketch/timeline.ts @@ -0,0 +1,203 @@ +import { + TimesketchArtifact, + TimesketchTimeline, +} from "../../types/timesketch/timeline.ts"; +import { TimesketchError } from "./error.ts"; +import { ProcessInfo } from "../../types/system/processes.ts"; +import { LoginItems } from "../../types/macos/loginitems.ts"; +import { UnifiedLog } from "../../types/macos/unifiedlogs.ts"; +import { HomebrewReceipt } from "../../types/macos/homebrew.ts"; +import { Fsevents } from "../../types/macos/fsevents.ts"; +import { Groups, Users } from "../../types/macos/accounts.ts"; +import { ExecPolicy } from "../../types/macos/execpolicy.ts"; +import { MacosFileInfo } from "../../types/macos/files.ts"; +import { WindowsFileInfo } from "../../types/windows/files.ts"; +import { LinuxFileInfo } from "../../types/linux/files.ts"; +import { SafariDownloads, SafariHistory } from "../../types/macos/safari.ts"; +import { Launchd } from "../../types/macos/launchd.ts"; +import { Emond } from "../../types/macos/emond.ts"; +import { Spotlight } from "../../types/macos/spotlight.ts"; +import { Prefetch } from "../../types/windows/prefetch.ts"; +import { Amcache } from "../../types/windows/amcache.ts"; +import { Shimcache } from "../../types/windows/shimcache.ts"; +import { Bits } from "../../types/windows/bits.ts"; +import { EventLogRecord } from "../../types/windows/eventlogs.ts"; +import { Jumplists } from "../../types/windows/jumplists.ts"; +import { Shortcut } from "../../types/windows/shortcuts.ts"; +import { RecycleBin } from "../../types/windows/recyclebin.ts"; +import { RegistryData } from "../../types/windows/registry.ts"; +import { Services } from "../../types/windows/services.ts"; +import { Shellbags } from "../../types/windows/shellbags.ts"; +import { RawFileInfo } from "../../types/windows/ntfs.ts"; +import { Shimdb } from "../../types/windows/shimdb.ts"; +import { + ApplicationInfo, + ApplicationTimeline, + AppVfu, + EnergyInfo, + EnergyUsage, + NetworkConnectivityInfo, + NetworkInfo, + NotificationInfo, +} from "../../types/windows/srum.ts"; +import { SearchEntry } from "../../types/windows/search.ts"; +import { TaskData } from "../../types/windows/tasks.ts"; +import { UserAssist } from "../../types/windows/userassist.ts"; +import { UserInfo } from "../../types/windows/users.ts"; +import { UsnJrnl } from "../../types/windows/usnjrnl.ts"; +import { WmiPersist } from "../../types/windows/wmi.ts"; +import { LogonsWindows } from "../../types/windows/eventlogs/logons.ts"; + +/** + * macOS artifact timelines + */ +import { timelineLoginItems } from "./artifacts/macos/loginitems.ts"; +import { timelineUnifiedLogs } from "./artifacts/macos/unifiedlogs.ts"; +import { timelineHomebrew } from "./artifacts/macos/homebrew.ts"; +import { timelineFsevents } from "./artifacts/macos/fsevents.ts"; +import { timelineUsersMacos } from "./artifacts/macos/users.ts"; +import { timelineGroupsMacos } from "./artifacts/macos/groups.ts"; +import { timelineExecpolicy } from "./artifacts/macos/execpolicy.ts"; +import { + timelineSafariDownloads, + timelineSafariHistory, +} from "./artifacts/macos/safari.ts"; +import { timelineLaunchd } from "./artifacts/macos/launchd.ts"; +import { timelineSpotlight } from "./artifacts/macos/spotlight.ts"; +import { timelineEmond } from "./artifacts/macos/emond.ts"; + +/** + * Cross platform artifact timelines + */ +import { timelineProcesses } from "./artifacts/processes.ts"; +import { timelineFiles } from "./artifacts/files.ts"; + +/** + * Windows artifact timelines + */ +import { timelineAmcache } from "./artifacts/windows/amcache.ts"; +import { timelineShimcache } from "./artifacts/windows/shimcache.ts"; +import { timelinePrefetch } from "./artifacts/windows/prefetch.ts"; +import { timelineBits } from "./artifacts/windows/bits.ts"; +import { timelineEventLogs } from "./artifacts/windows/eventlogs.ts"; +import { timelineJumplists } from "./artifacts/windows/jumplists.ts"; +import { timelineShortcuts } from "./artifacts/windows/shortcuts.ts"; +import { timelineRecycleBin } from "./artifacts/windows/recyclebin.ts"; +import { timelineRegistry } from "./artifacts/windows/registry.ts"; +import { timelineShellbags } from "./artifacts/windows/shellbags.ts"; +import { timelineServices } from "./artifacts/windows/services.ts"; +import { timelineRawFiles } from "./artifacts/windows/ntfs.ts"; +import { timelineShimdb } from "./artifacts/windows/shimdb.ts"; +import { timelineSearch } from "./artifacts/windows/search.ts"; +import { timelineSrum } from "./artifacts/windows/srum.ts"; +import { timelineTasks } from "./artifacts/windows/tasks.ts"; +import { timelineUserAssist } from "./artifacts/windows/userassist.ts"; +import { timelineUsersWindows } from "./artifacts/windows/users.ts"; +import { timelineUsnJrnl } from "./artifacts/windows/usnjrnl.ts"; +import { timelineWmiPersist } from "./artifacts/windows/wmi.ts"; +import { timelineLogonsWindows } from "./artifacts/windows/eventlogs/logons.ts"; + +/** + * Function to timeline artifacts parsed by artemis + * @param data Artifact data to timeline. Must be a supported artifact defined by `TimesketchArtifact` + * @param artifact A `TimesketchArtifact` artifact to timeline + * @returns Array of `TimesketchTimeline` or `TimesketchError` + */ +export function timelineArtifact( + data: unknown, + artifact: TimesketchArtifact, +): TimesketchTimeline[] | TimesketchError { + switch (artifact) { + case TimesketchArtifact.PROCESSESS: + return timelineProcesses(data as ProcessInfo[]); + case TimesketchArtifact.LOGINITEMS: + return timelineLoginItems(data as LoginItems[]); + case TimesketchArtifact.SUDOLOGS_MACOS: + case TimesketchArtifact.UNIFIEDLOGS: + return timelineUnifiedLogs(data as UnifiedLog[]); + case TimesketchArtifact.HOMEBREW: + return timelineHomebrew(data as HomebrewReceipt[]); + case TimesketchArtifact.FSEVENTS: + return timelineFsevents(data as Fsevents[]); + case TimesketchArtifact.USERS_MACOS: + return timelineUsersMacos(data as Users[]); + case TimesketchArtifact.GROUPS_MACOS: + return timelineGroupsMacos(data as Groups[]); + case TimesketchArtifact.EXECPOLICY: + return timelineExecpolicy(data as ExecPolicy[]); + case TimesketchArtifact.FILES: + return timelineFiles( + data as MacosFileInfo[] | LinuxFileInfo[], + false, + ); + case TimesketchArtifact.FILES_WINDOWS: + return timelineFiles( + data as WindowsFileInfo[], + true, + ); + case TimesketchArtifact.EMOND: + return timelineEmond(data as Emond[]); + case TimesketchArtifact.SPOTLIGHT: + return timelineSpotlight(data as Spotlight[]); + case TimesketchArtifact.LAUNCHD: + return timelineLaunchd(data as Launchd[]); + case TimesketchArtifact.SAFARI_DOWNLOADS: + return timelineSafariDownloads(data as SafariDownloads[]); + case TimesketchArtifact.SAFARI_HISTORY: + return timelineSafariHistory(data as SafariHistory[]); + case TimesketchArtifact.AMCACHE: + return timelineAmcache(data as Amcache[]); + case TimesketchArtifact.SHIMCACHE: + return timelineShimcache(data as Shimcache[]); + case TimesketchArtifact.PREFETCH: + return timelinePrefetch(data as Prefetch[]); + case TimesketchArtifact.BITS: + return timelineBits(data as Bits); + case TimesketchArtifact.EVENTLOGS: + return timelineEventLogs(data as EventLogRecord[]); + case TimesketchArtifact.JUMPLISTS: + return timelineJumplists(data as Jumplists[]); + case TimesketchArtifact.SHORTCUTS: + return timelineShortcuts(data as Shortcut[]); + case TimesketchArtifact.RECYCLEBIN: + return timelineRecycleBin(data as RecycleBin[]); + case TimesketchArtifact.REGISTRY: + return timelineRegistry(data as RegistryData); + case TimesketchArtifact.SHELLBAGS: + return timelineShellbags(data as Shellbags[]); + case TimesketchArtifact.SERVICES: + return timelineServices(data as Services[]); + case TimesketchArtifact.RAWFILES: + return timelineRawFiles(data as RawFileInfo[]); + case TimesketchArtifact.SHIMDB: + return timelineShimdb(data as Shimdb[]); + case TimesketchArtifact.SRUM: + return timelineSrum( + data as + | ApplicationInfo[] + | ApplicationTimeline[] + | AppVfu[] + | EnergyInfo[] + | EnergyUsage[] + | NetworkInfo[] + | NetworkConnectivityInfo[] + | NotificationInfo[], + ); + case TimesketchArtifact.SEARCH: + return timelineSearch(data as SearchEntry[]); + case TimesketchArtifact.TASKS: + return timelineTasks(data as TaskData); + case TimesketchArtifact.USERASSIST: + return timelineUserAssist(data as UserAssist[]); + case TimesketchArtifact.USERS_WINDOWS: + return timelineUsersWindows(data as UserInfo[]); + case TimesketchArtifact.USNJRNL: + return timelineUsnJrnl(data as UsnJrnl[]); + case TimesketchArtifact.WMIPERSIST: + return timelineWmiPersist(data as WmiPersist[]); + case TimesketchArtifact.LOGONS_WINDOWS: + return timelineLogonsWindows(data as LogonsWindows[]); + default: + return new TimesketchError(`ARTIFACT`, `unknown artifact ${artifact}`); + } +} diff --git a/src/windows/amache.ts b/src/windows/amcache.ts similarity index 94% rename from src/windows/amache.ts rename to src/windows/amcache.ts index 66beab72..cf99636a 100644 --- a/src/windows/amache.ts +++ b/src/windows/amcache.ts @@ -1,4 +1,4 @@ -import { Amcache } from "../../types/windows/amcache.d.ts"; +import { Amcache } from "../../types/windows/amcache.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/bits.ts b/src/windows/bits.ts index 52a075a0..d762c904 100644 --- a/src/windows/bits.ts +++ b/src/windows/bits.ts @@ -1,4 +1,4 @@ -import { Bits } from "../../types/windows/bits.d.ts"; +import { Bits } from "../../types/windows/bits.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/eventlogs.ts b/src/windows/eventlogs.ts index 46a9afe9..f380a6d6 100644 --- a/src/windows/eventlogs.ts +++ b/src/windows/eventlogs.ts @@ -1,4 +1,4 @@ -import { EventLogRecord } from "../../types/windows/eventlogs.d.ts"; +import { EventLogRecord } from "../../types/windows/eventlogs.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/eventlogs/logons.ts b/src/windows/eventlogs/logons.ts index 30d2186d..412ea3c8 100644 --- a/src/windows/eventlogs/logons.ts +++ b/src/windows/eventlogs/logons.ts @@ -1,5 +1,5 @@ import { - Logons, + LogonsWindows, LogonType, Raw4624Logons, Raw4634Logoffs, @@ -12,7 +12,7 @@ import { getEventlogs } from "../eventlogs.ts"; * @param path Path to Security.evtx file * @returns Array of `Logon` entries */ -export function logons(path: string): Logons[] | WindowsError { +export function logonsWindows(path: string): LogonsWindows[] | WindowsError { const recordsData = getEventlogs(path); if (recordsData instanceof WindowsError) { return new WindowsError( @@ -31,7 +31,7 @@ export function logons(path: string): Logons[] | WindowsError { for (const record of records) { // Parse Logon entries if (record.data.Event.System.EventID === logon_eid && isLogon(record)) { - const entry: Logons = { + const entry: LogonsWindows = { logon_type: checkLogonType(record.data.Event.EventData.LogonType), sid: record.data.Event.EventData.TargetUserSid, account_name: record.data.Event.EventData.TargetUserName, diff --git a/src/windows/jumplists.ts b/src/windows/jumplists.ts index ff106ede..9b914ab5 100644 --- a/src/windows/jumplists.ts +++ b/src/windows/jumplists.ts @@ -1,4 +1,4 @@ -import { Jumplists } from "../../types/windows/jumplists.d.ts"; +import { Jumplists } from "../../types/windows/jumplists.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/pe.ts b/src/windows/pe.ts index 4ca4cede..5e8d525a 100644 --- a/src/windows/pe.ts +++ b/src/windows/pe.ts @@ -1,4 +1,4 @@ -import { PeInfo } from "../../types/windows/pe.d.ts"; +import { PeInfo } from "../../types/windows/pe.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/prefetch.ts b/src/windows/prefetch.ts index 46297e28..e46b650f 100644 --- a/src/windows/prefetch.ts +++ b/src/windows/prefetch.ts @@ -1,4 +1,4 @@ -import { Prefetch } from "../../types/windows/prefetch.d.ts"; +import { Prefetch } from "../../types/windows/prefetch.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/recyclebin.ts b/src/windows/recyclebin.ts index 65c4ce5a..77077b5c 100644 --- a/src/windows/recyclebin.ts +++ b/src/windows/recyclebin.ts @@ -1,9 +1,8 @@ -import { RecycleBin } from "../../types/windows/recyclebin.d.ts"; +import { RecycleBin } from "../../types/windows/recyclebin.ts"; import { WindowsError } from "./errors.ts"; /** - * Function to parse Recycle Bin files at either `SystemDrive` or an alternative drive - * @param drive Optional altertnative drive. Will use the `SystemDrive` by default (typically C) + * Function to parse Recycle Bin files at `SystemDrive` * @returns Array of `RecycleBin` entries or `WindowsError` */ export function getRecycleBin(): RecycleBin[] | WindowsError { diff --git a/src/windows/registry.ts b/src/windows/registry.ts index cb1d86b9..fe623420 100644 --- a/src/windows/registry.ts +++ b/src/windows/registry.ts @@ -1,18 +1,32 @@ -import { Registry, SecurityKey } from "../../types/windows/registry.d.ts"; +import { + Registry, + RegistryData, + SecurityKey, +} from "../../types/windows/registry.ts"; import { WindowsError } from "./errors.ts"; /** * Function to parse a `Registry` file * @param path Full path to a `Registry` file - * @returns Array of `Registry` entries or `WindowsError` + * @returns `RegistryData` object or `WindowsError` */ -export function getRegistry(path: string): Registry[] | WindowsError { +export function getRegistry(path: string): RegistryData | WindowsError { try { //@ts-ignore: Custom Artemis function const data: string = Deno.core.ops.get_registry(path); const results: Registry[] = JSON.parse(data); - return results; + const reg: RegistryData = { + registry_path: path, + registry_file: "", + registry_entries: results, + }; + if (path.includes("\\")) { + reg.registry_file = path.split("\\").pop() ?? ""; + } else { + reg.registry_file = path.split("/").pop() ?? ""; + } + return reg; } catch (err) { return new WindowsError( "REGISTRY", diff --git a/src/windows/registry/mru/common.ts b/src/windows/registry/mru/common.ts index e332c514..84a67ee0 100644 --- a/src/windows/registry/mru/common.ts +++ b/src/windows/registry/mru/common.ts @@ -3,7 +3,7 @@ * https://www.magnetforensics.com/blog/what-is-mru-most-recently-used/ */ -import { Registry } from "../../../../types/windows/registry.d.ts"; +import { Registry } from "../../../../types/windows/registry.ts"; import { MruValues } from "../../../../types/windows/registry/recently_used.ts"; import { ShellItems } from "../../../../types/windows/shellitems.ts"; import { decode } from "../../../encoding/base64.ts"; diff --git a/src/windows/registry/mru/recent_docs.ts b/src/windows/registry/mru/recent_docs.ts index 09499a7c..a662f906 100644 --- a/src/windows/registry/mru/recent_docs.ts +++ b/src/windows/registry/mru/recent_docs.ts @@ -1,4 +1,4 @@ -import { Registry } from "../../../../types/windows/registry.d.ts"; +import { Registry } from "../../../../types/windows/registry.ts"; import { MruValues } from "../../../../types/windows/registry/recently_used.ts"; import { ShellItems } from "../../../../types/windows/shellitems.ts"; import { decode } from "../../../encoding/base64.ts"; diff --git a/src/windows/search.ts b/src/windows/search.ts index 3085db7b..9a7f0d50 100644 --- a/src/windows/search.ts +++ b/src/windows/search.ts @@ -1,4 +1,4 @@ -import { SearchEntry } from "../../types/windows/search.d.ts"; +import { SearchEntry } from "../../types/windows/search.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/services.ts b/src/windows/services.ts index 9b81b2d1..3928ecac 100644 --- a/src/windows/services.ts +++ b/src/windows/services.ts @@ -1,4 +1,4 @@ -import { Services } from "../../types/windows/services.d.ts"; +import { Services } from "../../types/windows/services.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/shimcache.ts b/src/windows/shimcache.ts index 3f0f4177..a262d64c 100644 --- a/src/windows/shimcache.ts +++ b/src/windows/shimcache.ts @@ -1,4 +1,4 @@ -import { Shimcache } from "../../types/windows/shimcache.d.ts"; +import { Shimcache } from "../../types/windows/shimcache.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/shimdb.ts b/src/windows/shimdb.ts index cad9e7b5..ee34d820 100644 --- a/src/windows/shimdb.ts +++ b/src/windows/shimdb.ts @@ -1,4 +1,4 @@ -import { Shimdb } from "../../types/windows/shimdb.d.ts"; +import { Shimdb } from "../../types/windows/shimdb.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/shortcuts.ts b/src/windows/shortcuts.ts index 66b98ccd..4313ce7f 100644 --- a/src/windows/shortcuts.ts +++ b/src/windows/shortcuts.ts @@ -1,4 +1,4 @@ -import { Shortcut } from "../../types/windows/shortcuts.d.ts"; +import { Shortcut } from "../../types/windows/shortcuts.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/srum.ts b/src/windows/srum.ts index 7eb3dab7..b9cdbe7a 100644 --- a/src/windows/srum.ts +++ b/src/windows/srum.ts @@ -7,7 +7,7 @@ import { NetworkConnectivityInfo, NetworkInfo, NotificationInfo, -} from "../../types/windows/srum.d.ts"; +} from "../../types/windows/srum.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/tasks.ts b/src/windows/tasks.ts index 83f04c67..405e342a 100644 --- a/src/windows/tasks.ts +++ b/src/windows/tasks.ts @@ -1,4 +1,4 @@ -import { TaskData, TaskJob, TaskXml } from "../../types/windows/tasks.d.ts"; +import { TaskData, TaskJob, TaskXml } from "../../types/windows/tasks.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/userassist.ts b/src/windows/userassist.ts index 7ce42a1b..c70d6603 100644 --- a/src/windows/userassist.ts +++ b/src/windows/userassist.ts @@ -1,4 +1,4 @@ -import { UserAssist } from "../../types/windows/userassist.d.ts"; +import { UserAssist } from "../../types/windows/userassist.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/users.ts b/src/windows/users.ts index 959a0f45..5293e01f 100644 --- a/src/windows/users.ts +++ b/src/windows/users.ts @@ -1,4 +1,4 @@ -import { UserInfo } from "../../types/windows/users.d.ts"; +import { UserInfo } from "../../types/windows/users.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/src/windows/usnjrnl.ts b/src/windows/usnjrnl.ts index 8e4d7de4..b8d1bc42 100644 --- a/src/windows/usnjrnl.ts +++ b/src/windows/usnjrnl.ts @@ -1,4 +1,4 @@ -import { UsnJrnl } from "../../types/windows/usnjrnl.d.ts"; +import { UsnJrnl } from "../../types/windows/usnjrnl.ts"; import { WindowsError } from "./errors.ts"; /** diff --git a/types/images/icns.d.ts b/types/images/icns.ts similarity index 97% rename from types/images/icns.d.ts rename to types/images/icns.ts index 7d2b1064..8a001abf 100644 --- a/types/images/icns.d.ts +++ b/types/images/icns.ts @@ -1,4 +1,4 @@ -interface Icon { +export interface Icon { /**Size in pixels. Ex: 128x128 */ size: number; /**Base64 encoded */ diff --git a/types/linux/elf.d.ts b/types/linux/elf.ts similarity index 100% rename from types/linux/elf.d.ts rename to types/linux/elf.ts diff --git a/types/linux/file.d.ts b/types/linux/files.ts similarity index 94% rename from types/linux/file.d.ts rename to types/linux/files.ts index f7a00f7f..2c696ec5 100644 --- a/types/linux/file.d.ts +++ b/types/linux/files.ts @@ -1,11 +1,11 @@ -import { ElfInfo } from "./elf.d.ts"; +import { ElfInfo } from "./elf.ts"; /** * `LinuxFileInfo` is an interface containing metadata on Linux files and directories. * `Artemis` uses the `walkdir` crate to walk the file system. * It does not parse the raw filesystem */ -export interface WindowsFileInfo { +export interface LinuxFileInfo { /**Full path to file or directory */ full_path: string; /**Directory path */ diff --git a/types/linux/journal.d.ts b/types/linux/journal.d.ts index c06a959f..b6c7308a 100644 --- a/types/linux/journal.d.ts +++ b/types/linux/journal.d.ts @@ -57,9 +57,9 @@ export interface Journal { /**Runtime scope associated with entry */ runtime_scope: string; /**Trused Timestamp associated with entry in UNIXEPOCH microseconds */ - source_realtime: number; + source_realtime: bigint; /**Timestamp associated with entry in UNIXEPOCH microseconds */ - realtime: number; + realtime: bigint; /**How entry was received by the Journal service */ transport: string; /**Journal message entry */ diff --git a/types/linux/processes.d.ts b/types/linux/processes.d.ts deleted file mode 100644 index 7ca78533..00000000 --- a/types/linux/processes.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ElfInfo } from "./elf.d.ts"; - -/** - * `LinuxProcessInfo` is an interface containing metadata on Linux processes. - * `artemis` uses the `sysinfo` crate to pull process information - */ -export interface LinuxProcessInfo { - /**Full path to the process binary */ - full_path: string; - /**Name of process */ - name: string; - /**Path to process binary */ - path: string; - /** Process ID */ - pid: number; - /** Parent Process ID */ - ppid: number; - /**Environment variables associated with process */ - environment: string; - /**Status of the process */ - status: string; - /**Process arguments */ - arguments: string; - /**Process memory usage */ - memory_usage: number; - /**Process virtual memory usage */ - virtual_memory_usage: number; - /**Process start time */ - start_time: number; - /** User ID associated with process */ - uid: string; - /**Group ID associated with process */ - gid: string; - /**MD5 hash of process binary */ - md5: string; - /**SHA1 hash of process binary */ - sha1: string; - /**SHA256 hash of process binary */ - sha256: string; - /**ELF metadata asssociated with process binary */ - binary_info: ElfInfo[]; -} diff --git a/types/macos/accounts.d.ts b/types/macos/accounts.ts similarity index 100% rename from types/macos/accounts.d.ts rename to types/macos/accounts.ts diff --git a/types/macos/emond.d.ts b/types/macos/emond.ts similarity index 99% rename from types/macos/emond.d.ts rename to types/macos/emond.ts index 2d879d0e..b44b8694 100644 --- a/types/macos/emond.d.ts +++ b/types/macos/emond.ts @@ -15,7 +15,7 @@ export interface Emond { /**Event types associated with the rule */ event_types: string[]; /**Start time of the rule */ - start_tiem: string; + start_time: string; /**If partial criteria match should trigger the rule */ allow_partial_criterion_match: boolean; /**Array of commad actions if rule is triggered */ diff --git a/types/macos/execpolicy.d.ts b/types/macos/execpolicy.ts similarity index 100% rename from types/macos/execpolicy.d.ts rename to types/macos/execpolicy.ts diff --git a/types/macos/files.d.ts b/types/macos/files.ts similarity index 96% rename from types/macos/files.d.ts rename to types/macos/files.ts index 763642d7..b840f883 100644 --- a/types/macos/files.d.ts +++ b/types/macos/files.ts @@ -1,4 +1,4 @@ -import { MachoInfo } from "./macho.d.ts"; +import { MachoInfo } from "./macho.ts"; /** * `MacosFileInfo` is an interface containing metadata on macOS files and directories. diff --git a/types/macos/fsevents.d.ts b/types/macos/fsevents.ts similarity index 100% rename from types/macos/fsevents.d.ts rename to types/macos/fsevents.ts diff --git a/types/macos/launchd.d.ts b/types/macos/launchd.ts similarity index 100% rename from types/macos/launchd.d.ts rename to types/macos/launchd.ts diff --git a/types/macos/loginitems.d.ts b/types/macos/loginitems.ts similarity index 100% rename from types/macos/loginitems.d.ts rename to types/macos/loginitems.ts diff --git a/types/macos/macho.d.ts b/types/macos/macho.ts similarity index 100% rename from types/macos/macho.d.ts rename to types/macos/macho.ts diff --git a/types/macos/processes.d.ts b/types/macos/processes.d.ts deleted file mode 100644 index 3b0fd72c..00000000 --- a/types/macos/processes.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { MachoInfo } from "./macho.d.ts"; - -/** - * `MacosProcessInfo` is an interface containing metadata on macOS processes. - * `artemis` uses the `sysinfo` crate to pull process information - */ -export interface MacosProcessInfo { - /**Full path to the process binary */ - full_path: string; - /**Name of process */ - name: string; - /**Path to process binary */ - path: string; - /** Process ID */ - pid: number; - /** Parent Process ID */ - ppid: number; - /**Environment variables associated with process */ - environment: string; - /**Status of the process */ - status: string; - /**Process arguments */ - arguments: string; - /**Process memory usage */ - memory_usage: number; - /**Process virtual memory usage */ - virtual_memory_usage: number; - /**Process start time */ - start_time: number; - /** User ID associated with process */ - uid: string; - /**Group ID associated with process */ - gid: string; - /**MD5 hash of process binary */ - md5: string; - /**SHA1 hash of process binary */ - sha1: string; - /**SHA256 hash of process binary */ - sha256: string; - /**MACHO metadata asssociated with process binary */ - binary_info: MachoInfo[]; -} diff --git a/types/macos/safari.d.ts b/types/macos/safari.ts similarity index 100% rename from types/macos/safari.d.ts rename to types/macos/safari.ts diff --git a/types/macos/spotlight.ts b/types/macos/spotlight.ts index d4725505..997cfbf4 100644 --- a/types/macos/spotlight.ts +++ b/types/macos/spotlight.ts @@ -22,7 +22,7 @@ export interface Spotlight { /**Last time Spotlight entry was updated in UNIXEPOCH **microseconds** */ last_updated: bigint; /**Array of properties associated with the entry */ - values: Record[]; + values: Record; /**Location of the Spotlight database that was parsed */ directory: string; } diff --git a/types/macos/unifiedlogs.ts b/types/macos/unifiedlogs.ts index 53ec5dfe..0864070b 100644 --- a/types/macos/unifiedlogs.ts +++ b/types/macos/unifiedlogs.ts @@ -25,7 +25,7 @@ export interface UnifiedLog { /**UUID of library associated with the log entry */ library_uuid: string; /**UNIXEPOCH timestamp of log entry in nanoseconds */ - time: number; + time: bigint; /**Log entry event type */ event_type: string; /**Log entry log type */ diff --git a/types/system/processes.ts b/types/system/processes.ts new file mode 100644 index 00000000..936ad763 --- /dev/null +++ b/types/system/processes.ts @@ -0,0 +1,43 @@ +import { ElfInfo } from "../linux/elf.ts"; +import { MachoInfo } from "../macos/macho.ts"; +import { PeInfo } from "../windows/pe.ts"; + +/** + * `ProcessInfo` is an interface containing metadata on system processes. + */ +export interface ProcessInfo { + /**Full path to the process binary */ + full_path: string; + /**Name of process */ + name: string; + /**Path to process binary */ + path: string; + /** Process ID */ + pid: number; + /** Parent Process ID */ + ppid: number; + /**Environment variables associated with process */ + environment: string; + /**Status of the process */ + status: string; + /**Process arguments */ + arguments: string; + /**Process memory usage */ + memory_usage: number; + /**Process virtual memory usage */ + virtual_memory_usage: number; + /**Process start time in UNIXEPOCH seconds*/ + start_time: number; + /** User ID associated with process */ + uid: string; + /**Group ID associated with process */ + gid: string; + /**MD5 hash of process binary */ + md5: string; + /**SHA1 hash of process binary */ + sha1: string; + /**SHA256 hash of process binary */ + sha256: string; + /**Binary metadata asssociated with process binary */ + binary_info: PeInfo[] | MachoInfo[] | ElfInfo[]; +} diff --git a/types/timesketch/client.ts b/types/timesketch/client.ts new file mode 100644 index 00000000..2b4b6c6c --- /dev/null +++ b/types/timesketch/client.ts @@ -0,0 +1,52 @@ +/** + * Minimum data needed to authenticate to Timesketch + */ +export interface TimesketchAuth { + /**URL to Timesketch istance */ + url: string; + /**Username for instance */ + username: string; + /**Password for username if using `TimesketchAuthType.CREDS` */ + password: string; + /**If using self-signed cert you may want to disable SSL verification */ + verify_url: boolean; + /**Auth to Timesketch. Currently on creds are supported */ + auth_type: TimesketchAuthType; + /**ID associated with the Sketch that artemis should upload data to. If **undefined** a new Sketch will be created */ + sketch_id?: number; + /**Name that should be used for a new Sketch. If **undefined** the artifact will be used for the name */ + sketch_name?: string; +} + +export enum TimesketchAuthType { + CREDS, +} + +/** + * Basic response object from uploading Timeline + */ +export interface TimelineResponse { + meta: { + task_id: string; + }; + objects: ResponseObject[]; +} + +/** + * Basic Response object from uploading timeline + */ +interface ResponseObject { + color: string; + created_at: string; + description: string; + id: number; + name: string; + searchindex: { + created_at: string; + description: string; + name: string; + index_name: string; + label_string: string; + status: Record; + }; +} \ No newline at end of file diff --git a/types/timesketch/timeline.ts b/types/timesketch/timeline.ts new file mode 100644 index 00000000..8c7ccda1 --- /dev/null +++ b/types/timesketch/timeline.ts @@ -0,0 +1,64 @@ +/** + * Timeline interface for uploading data to TimeSketch + */ +export interface TimesketchTimeline { + /** **Required by Timeskech** ISO8601 timestamp format: YYYY-MM-DD HH:mm:ss. All times are in UTC */ + datetime: string; + /** **Required by Timeskech** Description of the timestamp. Ex: FileCreated */ + timestamp_desc: string; + /** **Required by Timeskech** Timeline message data */ + message: string; + /**The type of artifact that was timelined */ + artifact: string; + /** + * Artifact data type. Based on plaso definition + * (its kind of freeform, https://github.com/log2timeline/plaso/blob/main/docs/sources/user/Scribbles-about-events.md). + * Looks like: `source:artifact:artifact:data`. With first artifact most generic and second one more specific + * :artifact: can be nested. Ex: `windows:registry:explorer:programcache` + */ + data_type: string; + /**Include any other valid JSON data */ + [ key: string ]: unknown; +} + +export enum TimesketchArtifact { + PROCESSESS = "processes", + LOGINITEMS = "loginitems", + UNIFIEDLOGS = "unifiedlogs", + HOMEBREW = "homebrew", + FSEVENTS = "fsevents", + USERS_MACOS = "users-macos", + GROUPS_MACOS = "groups-macos", + EXECPOLICY = "execpolicy", + /**Use `FILES_WINDOWS` for Windows filelistings */ + FILES = "files", + /**Use `FILES` for macOS or Linux filelistings */ + FILES_WINDOWS = "files", + SUDOLOGS_MACOS = "sudologs-macos", + EMOND = "emond", + SPOTLIGHT = "spotlight", + LAUNCHD = "launchd", + SAFARI_DOWNLOADS = "safari-downloads", + SAFARI_HISTORY = "safari-history", + AMCACHE = "amcache", + SHIMCACHE = "shimcache", + PREFETCH = "prefetch", + BITS = "bits", + EVENTLOGS = "eventlogs", + JUMPLISTS = "jumplists", + SHORTCUTS = "shortcuts", + RECYCLEBIN = "recyclebin", + REGISTRY = "registry", + SHELLBAGS = "shellbags", + SERVICES = "services", + RAWFILES = "rawfiles", + SHIMDB = "shimdb", + SRUM = "srum", + SEARCH = "search", + TASKS = "tasks", + USERASSIST = "userassist", + USERS_WINDOWS = "users-windows", + USNJRNL = "usnjrnl", + WMIPERSIST = "wmipersist", + LOGONS_WINDOWS = "logons-windows", +} diff --git a/types/windows/acls.d.ts b/types/windows/acls.ts similarity index 97% rename from types/windows/acls.d.ts rename to types/windows/acls.ts index da62fa0f..c3e3e498 100644 --- a/types/windows/acls.d.ts +++ b/types/windows/acls.ts @@ -24,7 +24,7 @@ export interface AccessControl { /** * Metadata associated with Security Descriptor information */ -interface Descriptor { +export interface Descriptor { /**Control flags associated with the data */ control_flags: string[]; /**SACL info associated with the data */ diff --git a/types/windows/amcache.d.ts b/types/windows/amcache.ts similarity index 93% rename from types/windows/amcache.d.ts rename to types/windows/amcache.ts index 843ac517..0fdb5c83 100644 --- a/types/windows/amcache.d.ts +++ b/types/windows/amcache.ts @@ -7,8 +7,8 @@ * - https://www.ssi.gouv.fr/uploads/2019/01/anssi-coriin_2019-analysis_amcache.pdf */ export interface Amcache { - /**Timestamp when the application was first executed in UNIXEPOCH seconds */ - first_execution: number; + /**Last modified time for Registry key in UNIXEPOCH seconds */ + last_modified: number; /**Path to application */ path: string; /**Name of application */ diff --git a/types/windows/bits.d.ts b/types/windows/bits.ts similarity index 96% rename from types/windows/bits.d.ts rename to types/windows/bits.ts index 0f3080e1..6b8a9e61 100644 --- a/types/windows/bits.d.ts +++ b/types/windows/bits.ts @@ -1,4 +1,4 @@ -import { AccessControl } from "./acls.d.ts"; +import { AccessControl } from "./acls.ts"; /** * Windows Background Intelligent Transfer Service (`BITS`) is a service that allows applications and users to register jobs to upload/download files. @@ -30,6 +30,8 @@ export interface BitsInfo { file_id: string; /**SID associated with the Job */ owner_sid: string; + /**Username associated with SID */ + username: string; /**Timestamp when the Job was created in UNIXEPOCH seconds */ created: number; /**Timestamp when the Job was modified in UNIXEPOCH seconds */ @@ -100,6 +102,8 @@ export interface Jobs { file_id: string; /**SID associated with the Job */ owner_sid: string; + /**Username associated with SID */ + username: string; /**Timestamp when the Job was created in UNIXEPOCH seconds */ created: number; /**Timestamp when the Job was modified in UNIXEPOCH seconds */ diff --git a/types/windows/eventlogs.d.ts b/types/windows/eventlogs.ts similarity index 100% rename from types/windows/eventlogs.d.ts rename to types/windows/eventlogs.ts diff --git a/types/windows/eventlogs/logons.ts b/types/windows/eventlogs/logons.ts index 17484470..1f772da3 100644 --- a/types/windows/eventlogs/logons.ts +++ b/types/windows/eventlogs/logons.ts @@ -1,4 +1,4 @@ -export interface Logons { +export interface LogonsWindows { logon_type: LogonType; sid: string; account_name: string; diff --git a/types/windows/files.d.ts b/types/windows/files.ts similarity index 97% rename from types/windows/files.d.ts rename to types/windows/files.ts index 4853d73a..4a60227d 100644 --- a/types/windows/files.d.ts +++ b/types/windows/files.ts @@ -1,4 +1,4 @@ -import { PeInfo } from "./pe.d.ts"; +import { PeInfo } from "./pe.ts"; /** * `WindowsFileInfo` is an interface containing metadata on Windows files and directories. diff --git a/types/windows/jumplists.d.ts b/types/windows/jumplists.ts similarity index 97% rename from types/windows/jumplists.d.ts rename to types/windows/jumplists.ts index 99d5d876..aae2e948 100644 --- a/types/windows/jumplists.d.ts +++ b/types/windows/jumplists.ts @@ -1,4 +1,4 @@ -import { Shortcut } from "./shortcuts.d.ts"; +import { Shortcut } from "./shortcuts.ts"; /** * Windows `Jumplists` files track opened files via applications in the Taskbar or Start Menu diff --git a/types/windows/ntfs.d.ts b/types/windows/ntfs.ts similarity index 96% rename from types/windows/ntfs.d.ts rename to types/windows/ntfs.ts index 30c76c5c..7f6ee1d6 100644 --- a/types/windows/ntfs.d.ts +++ b/types/windows/ntfs.ts @@ -1,4 +1,4 @@ -import { PeInfo } from "./pe.d.ts"; +import { PeInfo } from "./pe.ts"; /** * Windows NTFS is the default filesystem on Windows devices. @@ -47,7 +47,7 @@ export interface RawFileInfo { /**Parent MFT reference for entry */ parent_mft_references: number; /**Attributes associated with entry */ - attributess: string[]; + attributes: string[]; /**MD5 of file. Optional */ md5: string; /**SHA1 of file. Optional */ @@ -66,7 +66,7 @@ export interface RawFileInfo { sid: number; /**SID string associated with entry*/ user_sid: string; - /**Group SID associated with enry */ + /**Group SID associated with entry */ group_sid: string; /**Drive letter */ drive: string; diff --git a/types/windows/pe.d.ts b/types/windows/pe.ts similarity index 100% rename from types/windows/pe.d.ts rename to types/windows/pe.ts diff --git a/types/windows/prefetch.d.ts b/types/windows/prefetch.ts similarity index 100% rename from types/windows/prefetch.d.ts rename to types/windows/prefetch.ts diff --git a/types/windows/processes.d.ts b/types/windows/processes.d.ts deleted file mode 100644 index b45f920e..00000000 --- a/types/windows/processes.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { PeInfo } from "./pe.d.ts"; - -/** - * `WindowsProcessInfo` is an interface containing metadata on Windows processes. - * `artemis` uses the `sysinfo` crate to pull process information. - */ -export interface WindowsProcessInfo { - /**Full path to the process binary */ - full_path: string; - /**Name of process */ - name: string; - /**Path to process binary */ - path: string; - /** Process ID */ - pid: number; - /** Parent Process ID */ - ppid: number; - /**Environment variables associated with process */ - environment: string; - /**Status of the process */ - status: string; - /**Process arguments */ - arguments: string; - /**Process memory usage */ - memory_usage: number; - /**Process virtual memory usage */ - virtual_memory_usage: number; - /**Process start time in UNIXEPOCH seconds*/ - start_time: number; - /** User ID associated with process */ - uid: string; - /**Group ID associated with process */ - gid: string; - /**MD5 hash of process binary */ - md5: string; - /**SHA1 hash of process binary */ - sha1: string; - /**SHA256 hash of process binary */ - sha256: string; - /**PE metadata asssociated with process binary */ - binary_info: PeInfo[]; -} diff --git a/types/windows/recyclebin.d.ts b/types/windows/recyclebin.ts similarity index 100% rename from types/windows/recyclebin.d.ts rename to types/windows/recyclebin.ts diff --git a/types/windows/registry.d.ts b/types/windows/registry.ts similarity index 96% rename from types/windows/registry.d.ts rename to types/windows/registry.ts index 9953b87d..f577c7c5 100644 --- a/types/windows/registry.d.ts +++ b/types/windows/registry.ts @@ -1,4 +1,4 @@ -import { Descriptor } from "./acls.d.ts"; +import { Descriptor } from "./acls.ts"; /** * Windows `Registry` is a collection of binary files that store Windows configuration settings and OS information. @@ -79,7 +79,7 @@ export interface Value { /** * Security Key data associated with a Registry Key */ -interface SecurityKey { +export interface SecurityKey { /**Number of references to the key */ reference_count: number; /**Permissions and ACLs associated with the key */ diff --git a/types/windows/search.d.ts b/types/windows/search.ts similarity index 100% rename from types/windows/search.d.ts rename to types/windows/search.ts diff --git a/types/windows/services.d.ts b/types/windows/services.ts similarity index 100% rename from types/windows/services.d.ts rename to types/windows/services.ts diff --git a/types/windows/shellbags.ts b/types/windows/shellbags.ts index c7899c0b..cefdc0e5 100644 --- a/types/windows/shellbags.ts +++ b/types/windows/shellbags.ts @@ -8,11 +8,11 @@ export interface Shellbags { /**Reconstructed directory path */ path: string; - /**FAT created timestamp. Only applicable for Directory `shell_type` */ + /**FAT created timestamp in UNIXEPOCH. Only applicable for Directory `shell_type` */ created: number; - /**FAT modified timestamp. Only applicable for Directory `shell_type` */ + /**FAT modified timestamp in UNIXEPOCH. Only applicable for Directory `shell_type` */ modified: number; - /**FAT modified timestamp. Only applicable for Directory `shell_type` */ + /**FAT modified timestamp in UNIXEPOCH. Only applicable for Directory `shell_type` */ accessed: number; /**Entry number in MFT. Only applicable for Directory `shell_type` */ mft_entry: number; diff --git a/types/windows/shimcache.d.ts b/types/windows/shimcache.ts similarity index 100% rename from types/windows/shimcache.d.ts rename to types/windows/shimcache.ts diff --git a/types/windows/shimdb.d.ts b/types/windows/shimdb.ts similarity index 92% rename from types/windows/shimdb.d.ts rename to types/windows/shimdb.ts index d0a71ac3..5afb10e5 100644 --- a/types/windows/shimdb.d.ts +++ b/types/windows/shimdb.ts @@ -1,5 +1,5 @@ /** - * Windows Shimdatabase (ShimDB) can be used by Windows applications to provided compatability between Windows versions. + * Windows Shimdatabase (ShimDB) can be used by Windows applications to provided compatibility between Windows versions. * It does this via `shims` that are inserted into the application that modifies function calls. * Malicious custom shims can be created as a form of persistence. * @@ -19,7 +19,7 @@ export interface Shimdb { /** * SDB files are composed of `TAGS`. There are multiple types of `TAGS` * `data` have `TAGS` that can be represented via a JSON object - * `list_data` have `TAGS` that can be rerpesented as an array of JSON objects + * `list_data` have `TAGS` that can be represented as an array of JSON objects * * Example: * ``` @@ -69,7 +69,7 @@ export interface DatabaseData { * The SDB file may contain additional metadata information * May include additional `TAGS` */ - additional_metdata: Record; + additional_metadata: Record; /**Array of `TAGS` associated with the SDB file */ list_data: TagData[]; } diff --git a/types/windows/shortcuts.d.ts b/types/windows/shortcuts.ts similarity index 100% rename from types/windows/shortcuts.d.ts rename to types/windows/shortcuts.ts diff --git a/types/windows/srum.d.ts b/types/windows/srum.ts similarity index 96% rename from types/windows/srum.d.ts rename to types/windows/srum.ts index 82988ae6..4ba5f378 100644 --- a/types/windows/srum.d.ts +++ b/types/windows/srum.ts @@ -84,7 +84,7 @@ export interface ApplicationTimeline { comp_rendered_timeline: number; /**Comp dirtied value for entry */ comp_dirtied_timeline: number; - /**Comp propaged value for entry */ + /**Comp propagated value for entry */ comp_propagated_timeline: number; /**Audio input value for entry */ audio_in_timeline: number; @@ -104,7 +104,7 @@ export interface ApplicationTimeline { psm_foreground_s: number; /**User input seconds count */ user_input_s: number; - /**Comp rendered seconds countr */ + /**Comp rendered seconds count */ comp_rendered_s: number; /**Comp dirtied seconds count */ comp_dirtied_s: number; @@ -142,7 +142,7 @@ export interface ApplicationTimeline { display_required_timeline: number; /**Keyboard input timeline value for entry */ keyboard_input_timeline: number; - /**Keybouard input seconds count */ + /**Keyboard input seconds count */ keyboard_input_s: number; /**Mouse input seconds count */ mouse_input_s: number; @@ -171,7 +171,7 @@ export interface AppVfu { } /** - * SRUM table associated witn EnergyInfo `{DA73FB89-2BEA-4DDC-86B8-6E048C6DA477}` + * SRUM table associated with EnergyInfo `{DA73FB89-2BEA-4DDC-86B8-6E048C6DA477}` */ export interface EnergyInfo { /**ID in for row in the ESE table */ @@ -182,7 +182,7 @@ export interface EnergyInfo { app_id: string; /**SID associated with the application process */ user_id: string; - /**Base64 encoded binary data associated witn EnegyInfo entry */ + /**Base64 encoded binary data associated with EnergyInfo entry */ binary_data: string; } @@ -230,7 +230,7 @@ export interface NetworkInfo { interface_luid: number; /**L2 profile ID associated with entry */ l2_profile_id: number; - /**L2 profiel flags associated with entry */ + /**L2 profile flags associated with entry */ l2_profile_flags: number; /**Bytes sent associated with entry */ bytes_sent: number; diff --git a/types/windows/tasks.d.ts b/types/windows/tasks.ts similarity index 94% rename from types/windows/tasks.d.ts rename to types/windows/tasks.ts index 97864f30..24169bf6 100644 --- a/types/windows/tasks.d.ts +++ b/types/windows/tasks.ts @@ -47,7 +47,7 @@ export interface TaskJob { error_retry_count: number; /**Error retry interval for the Task */ error_retry_interval: number; - /**Idle deadlin for Task */ + /**Idle deadline for Task */ idle_deadline: number; /**Idle wait for Task */ idle_wait: number; @@ -75,7 +75,7 @@ export interface TaskJob { author: string; /**Comments associated with Task */ comments: string; - /**Base64 encoded User data associatd with Task */ + /**Base64 encoded User data associated with Task */ user_data: string; /**Start Error associated with Task */ start_error: number; @@ -133,7 +133,7 @@ interface RegistrationInfo { interface Triggers { /**Boot triggers for Task */ boot: BootTrigger[]; - /**Regirstration triggers for Task. Format is exactly same as BootTriger*/ + /**Registration triggers for Task. Format is exactly same as BootTrigger*/ registration: BootTrigger[]; /**Idle triggers for Task */ idle: IdleTrigger[]; @@ -147,7 +147,7 @@ interface Triggers { session: SessionTrigger[]; /**Calendar triggers for Task */ calendar: CalendarTrigger[]; - /**Windows Notifications triggers for Trask */ + /**Windows Notifications triggers for Task */ wnf: WnfTrigger[]; } @@ -331,7 +331,7 @@ interface ByMonthDayWeek { * Settings determine how to run Task Actions */ interface Settings { - /**Start Task on demans */ + /**Start Task on demand */ allow_start_on_demand?: boolean; /**Restart if fails */ restart_on_failure?: RestartType; @@ -341,12 +341,12 @@ interface Settings { disallow_start_if_on_batteries?: boolean; /**Stop Task if going on battery power */ stop_if_going_on_batteries?: boolean; - /**Task can be terminated if time limts exceeded */ + /**Task can be terminated if time limits exceeded */ allow_hard_terminate?: boolean; /**If scheduled time is missed, Task may be started */ start_when_available?: boolean; /**Run based on network profile name */ - newtork_profile_name?: string; + network_profile_name?: string; /**Run only if network connection available */ run_only_if_network_available?: boolean; /**Wake system from standby or hibernate to run */ @@ -361,7 +361,7 @@ interface Settings { idle_settings?: IdleSettings; /**Network settings to run */ network_settings?: NetworkSettings; - /**Taks execution time limit */ + /**Task execution time limit */ execution_time_limit?: string; /**Task Priority. Lowest is 1. Highest is 10 */ priority?: number; @@ -371,8 +371,8 @@ interface Settings { use_unified_scheduling_engine?: boolean; /**Task is disabled on Remote App Sessions */ disallow_start_on_remote_app_session?: boolean; - /**Options to run Task during system maintence periods */ - maintence_settings?: MaintenceSettings; + /**Options to run Task during system maintenance periods */ + maintenance?: MaintenanceSettings; /**Task disabled on next OS startup */ volatile?: boolean; } @@ -412,14 +412,14 @@ interface NetworkSettings { } /** - * Maintence options + * Maintenance options */ -interface MaintenceSettings { - /**Duration of maintence */ +interface MaintenanceSettings { + /**Duration of maintenance */ period: string; /**Deadline for Task to run */ deadline?: string; - /**Task can run idependently of other Tasks with `MaintenceSettings` */ + /**Task can run independently of other Tasks with `MaintenanceSettings` */ exclusive?: boolean; } @@ -439,7 +439,7 @@ interface Principals { run_level?: string; /**Process Token SID associated with Task */ process_token_sid_type?: string; - /**Array of privlege value */ + /**Array of privileges value */ required_privileges?: string[]; /**Unique user selected ID */ id_attribute?: string; @@ -465,7 +465,7 @@ interface Actions { interface ExecType { /**Command to execute */ command: string; - /**Arguements for command */ + /**Arguments for command */ arguments?: string; /**Path to a directory */ working_directory?: string; diff --git a/types/windows/userassist.d.ts b/types/windows/userassist.ts similarity index 100% rename from types/windows/userassist.d.ts rename to types/windows/userassist.ts diff --git a/types/windows/users.d.ts b/types/windows/users.ts similarity index 94% rename from types/windows/users.d.ts rename to types/windows/users.ts index 18fce2b6..90372e22 100644 --- a/types/windows/users.d.ts +++ b/types/windows/users.ts @@ -2,7 +2,7 @@ * Parse the SAM Registry file and get user info */ export interface UserInfo { - /**Last logon for account */ + /**Last logon for account in UNIXEPOCH seconds */ last_logon: number; /**Time when password last set in UNIXEPOCH seconds */ password_last_set: number; diff --git a/types/windows/usnjrnl.d.ts b/types/windows/usnjrnl.ts similarity index 100% rename from types/windows/usnjrnl.d.ts rename to types/windows/usnjrnl.ts diff --git a/types/windows/wmi.ts b/types/windows/wmi.ts index 6f7a3e77..48a2dec4 100644 --- a/types/windows/wmi.ts +++ b/types/windows/wmi.ts @@ -42,7 +42,7 @@ export interface EventLogConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Event category */ @@ -74,7 +74,7 @@ export interface ActiveScriptConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**How many seconds to wait until process is killed. Zero (0) means process will not be killed */ @@ -96,7 +96,7 @@ export interface CommandLineConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Specifies command to execute */ @@ -123,7 +123,7 @@ export interface CommandLineConsumer { KillTimeout: number; /**Priority of process threads */ Priority: number; - /**Determinse if process is launched with interactive WinStation or default WinStation */ + /**Determines if process is launched with interactive WinStation or default WinStation */ RunInteractively: boolean; /**Determines Window show state */ ShowWindowCommand: number; @@ -158,7 +158,7 @@ export interface LogFileConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Whether log file is Unicode or multibyte code file */ @@ -178,7 +178,7 @@ export interface SmtpConsumer { /**Name of system where WMI sends events */ MachineName: string; /**Max queue for consumer in bytes */ - MaxmiumQueueSize: number; + MaximumQueueSize: number; /**Unique ID for consumer */ Name: string; /**Addresses to send email (BCC) */