Skip to content

Commit

Permalink
Updated KapeFiles Targets artifact (Velocidex#1097)
Browse files Browse the repository at this point in the history
Also various cleanups.
  • Loading branch information
scudette authored Jun 8, 2021
1 parent 588fbc3 commit 162a28e
Show file tree
Hide file tree
Showing 8 changed files with 1,229 additions and 1,191 deletions.
69 changes: 35 additions & 34 deletions artifacts/definitions/Windows/Applications/SBECmd.yaml
Original file line number Diff line number Diff line change
@@ -1,45 +1,42 @@
name: Windows.Applications.SBECmd
description: |
Execute Eric Zimmerman's SBECmd and return output for analysis
Objective:
- Find which folders were accessed on the local machine, the network, and/or removable devices. Evidence of previously existing folders after deletion/overwrite. When certain folders were accessed.
- Find which folders were accessed on the local machine, the
network, and/or removable devices. Evidence of previously
existing folders after deletion/overwrite. When certain folders
were accessed.
Interpretation:
- Stores information about which folders were most recently browsed by the user.
- Stores information about which folders were most recently
browsed by the user.
MITRE ATT&CK ID: TA0009 - Collection
author: Eduardo Mattos - @eduardfir

reference:
- https://github.com/EricZimmerman

required_permissions:
- EXECVE

type: CLIENT

tools:
- name: SBECmd
url: https://github.com/Velocidex/Tools/raw/main/SBECmd/ShellBagsExplorer/SBECmd.exe

precondition: SELECT OS From info() where OS = 'windows'

parameters:
- name: tactic
description: ATT&CK tactic
default: collection
type: hidden

- name: userRegex
default: .

- name: UploadFiles
description: "Select to Upload SBECmd Output files."
type: bool

- name: RemovePayload
description: "Select to Remove Payload after execution."
type: bool
Expand All @@ -51,10 +48,10 @@ sources:
LET payload <= SELECT * FROM Artifact.Generic.Utils.FetchBinary(
ToolName="SBECmd", IsExecutable=TRUE)
-- build tempfolder for output
-- build tempfolder for output
LET tempfolder <= tempdir(remove_last=TRUE)
-- get users with profiles
-- get users with profiles
LET UserProfiles = SELECT Uid, Name, Directory, UUID, Mtime
FROM Artifact.Windows.Sys.Users()
WHERE Name =~ userRegex and Directory =~ "Users"
Expand All @@ -78,19 +75,23 @@ sources:
})
- name: Uploads
queries:
- |
SELECT * FROM chain(
a={
SELECT * FROM if(condition=UploadFiles,
then={
SELECT Name, upload(file=FullPath, name=relpath(base=tempfile, path=FullPath)) as FileDetails
FROM glob(globs="/**", root=tempfolder)})
},
b={
SELECT * FROM if(condition=RemovePayload,
then={
SELECT * FROM execve(argv=['powershell','Remove-Item',
payload.FullPath[0],'-Force' ])})
})
WHERE Stdout =~ "SBECmd"
query: |
SELECT * FROM chain(
a={
SELECT * FROM if(
condition=UploadFiles,
then={
SELECT Name, upload(file=FullPath,
name=relpath(base=tempfile, path=FullPath)) as FileDetails
FROM glob(globs="/**", root=tempfolder)
})
},
b={
SELECT * FROM if(
condition=RemovePayload,
then={
SELECT * FROM execve(argv=['powershell','Remove-Item',
payload.FullPath[0],'-Force' ])
})
})
WHERE Stdout =~ "SBECmd"
2,200 changes: 1,101 additions & 1,099 deletions artifacts/definitions/Windows/KapeFiles/Targets.yaml

Large diffs are not rendered by default.

70 changes: 44 additions & 26 deletions artifacts/definitions/Windows/NTFS/I30.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,60 @@ description: |
parameters:
- name: DirectoryGlobs
default: C:\Users\**
default: C:\Users\*

- name: SlackOnly
description: "Select to return only entries from Slack space."
type: bool

precondition:
SELECT * FROM info() where OS = 'windows'
- name: AlsoUpload
description: Select to also upload the raw $I30 stream.
type: bool

sources:
- name: UploadI30Streams
queries:
- LET inodes = SELECT FullPath, Data.mft AS MFT,
precondition:
SELECT * FROM info() where OS = 'windows' AND AlsoUpload

query: |
LET inodes = SELECT FullPath, Data.mft AS MFT,
parse_ntfs(device=FullPath, inode=Data.mft) AS MFTInfo
FROM glob(globs=DirectoryGlobs, accessor="ntfs")
WHERE IsDir and log(message=MFT)
FROM glob(globs=DirectoryGlobs, accessor="ntfs")
WHERE IsDir
- LET upload_streams = SELECT * FROM foreach(
row=MFTInfo.Attributes,
query={
SELECT Type, TypeId, Id, Inode, Size, Name, FullPath,
upload(accessor="mft", file=MFTInfo.Device + Inode,
name=FullPath + "/" + Inode) AS IndexUpload
FROM scope()
WHERE Type =~ "INDEX_"
})
LET upload_streams = SELECT * FROM foreach(
row=MFTInfo.Attributes,
query={
SELECT _value.Type AS Type,
_value.TypeId AS TypeId,
_value.Id AS Id,
_value.Inode AS Inode,
_value.Size AS Size,
_value.Name AS Name,
_value.FullPath AS FullPath,
upload(accessor="mft", file=MFTInfo.Device + _value.Inode,
name=_value.FullPath + "/" + _value.Inode) AS IndexUpload
FROM scope()
WHERE Type =~ "INDEX_"
})
- SELECT * FROM foreach(row=inodes, query=upload_streams)
SELECT * FROM foreach(row=inodes, query=upload_streams)
- name: AnalyzeI30
queries:
- SELECT * FROM foreach(
row=inodes,
query={
SELECT FullPath, Name, NameType, Size, AllocatedSize,
IsSlack, SlackOffset, Mtime, Atime, Ctime, Btime, MFTId
FROM parse_ntfs_i30(device=MFTInfo.Device, inode=MFT)
WHERE IsSlack = true or NOT SlackOnly
})
precondition:
SELECT * FROM info() where OS = 'windows'

query: |
LET inodes = SELECT FullPath, Data.mft AS MFT,
parse_ntfs(device=FullPath, inode=Data.mft) AS MFTInfo
FROM glob(globs=DirectoryGlobs, accessor="ntfs")
WHERE IsDir
SELECT * FROM foreach(
row=inodes,
query={
SELECT FullPath, Name, NameType, Size, AllocatedSize,
IsSlack, SlackOffset, Mtime, Atime, Ctime, Btime, MFTId
FROM parse_ntfs_i30(device=MFTInfo.Device, inode=MFT)
WHERE IsSlack = true or NOT SlackOnly
})
45 changes: 18 additions & 27 deletions artifacts/definitions/Windows/Registry/WDigest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@ name: Windows.Registry.WDigest
description: |
Find WDigest registry values on the filesystem.
In order to prevent the “clear-text” password from being placed in LSASS, the following registry key needs to be set to “0” (Digest Disabled):
In order to prevent the “clear-text” password from being placed in
LSASS, the following registry key needs to be set to “0” (Digest
Disabled):
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest “UseLogonCredential”(DWORD)
This registry key is worth monitoring in an environment as an attacker may wish to set it to 1 to enable Digest password support which forces “clear-text” passwords to be placed in LSASS on any version of Windows from Windows 7 / 2008R2 up to Windows 10 / 2012R2. Furthermore, Windows 8.1 / 2012 R2 and newer do not have a “UseLogonCredential” DWORD value, so the key needs to be added. The existence of the key is suspicious, if not expected.
This registry key is worth monitoring in an environment as an
attacker may wish to set it to 1 to enable Digest password support
which forces “clear-text” passwords to be placed in LSASS on any
version of Windows from Windows 7 / 2008R2 up to Windows 10 /
2012R2. Furthermore, Windows 8.1 / 2012 R2 and newer do not have a
“UseLogonCredential” DWORD value, so the key needs to be
added. The existence of the key is suspicious, if not expected.
* ATT&CK tactic: Defense Evasion, Credential Access
* ATT&CK technique: T1112, T1003.001
type: CLIENT

Expand All @@ -16,40 +27,20 @@ precondition:
SELECT * FROM info() where OS = 'windows'

parameters:
- name: tactic
description: ATT&CK tactic
default: Defense Evasion
type: hidden

- name: technique
description: ATT&CK technique
default: T1112
type: hidden

- name: tactic
description: ATT&CK tactic
default: Credential Access
type: hidden

- name: technique
description: ATT&CK technique
default: T1003.001
type: hidden

- name: SearchRegistryGlob
default: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\**
description: Use a glob to define the files that will be searched.

sources:
- query: |
SELECT Name,
FullPath,
Data,
Sys,
SELECT Name,
FullPath,
Data,
Sys,
ModTime as Modified
FROM glob(globs=SearchRegistryGlob, accessor='registry')
WHERE Name =~ "LogonCredential"
column_types:
- name: Modified
type: timestamp
7 changes: 7 additions & 0 deletions gui/velociraptor/src/components/core/paged-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ class VeloPagedTable extends Component {

// When called will cause the table to be recalculated.
refresh: PropTypes.func,

// A version to force refresh of the table.
version: PropTypes.object,
}

state = {
Expand Down Expand Up @@ -124,6 +127,10 @@ class VeloPagedTable extends Component {
}

componentDidUpdate(prevProps, prevState, snapshot) {
if (!_.isEqual(prevProps.version, this.props.version)) {
this.fetchRows();
};

if (!_.isEqual(prevProps.params, this.props.params)) {
this.setState({start_row: 0, toggles: {}, columns: []});
};
Expand Down
9 changes: 9 additions & 0 deletions gui/velociraptor/src/components/flows/flow-logs.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';

import VeloPagedTable from '../core/paged-table.js';
import VeloTimestamp from "../utils/time.js";


function getFlowState(flow) {
return {flow_id: flow.session_id,
total_logs: flow.total_logs};
}


export default class FlowLogs extends React.Component {
static propTypes = {
flow: PropTypes.object,
Expand Down Expand Up @@ -37,6 +45,7 @@ export default class FlowLogs extends React.Component {
flow_id: this.props.flow.session_id,
type: "log",
}}
version={getFlowState(this.props.flow)}
/>
);
}
Expand Down
1 change: 1 addition & 0 deletions gui/velociraptor/src/components/flows/flow-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export default class FlowResults extends React.Component {
<VeloPagedTable
className="col-12"
params={this.state.params}
version={getFlowState(this.props.flow)}
/>
</>
);
Expand Down
Loading

0 comments on commit 162a28e

Please sign in to comment.