Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ windows:
go build -o sqlitehunter_compiler.exe ./bin/*.go

compile: FORCE
./sqlitehunter_compiler compile ./definitions/ ./output/SQLiteHunter.yaml --output_zip ./output/SQLiteHunter.zip --index ./docs/content/docs/rules/index.json
go run ./bin/ compile ./definitions/ ./output/SQLiteHunter.yaml --output_zip ./output/SQLiteHunter.zip --index ./docs/content/docs/rules/index.json

golden: compile
./testing/velociraptor.bin --definitions ./output --config ./testing/test.config.yaml golden --env testFiles=`pwd`/test_files ./testing/testcases -v --filter=${GOLDEN}
Expand Down
2 changes: 1 addition & 1 deletion compile/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ func (self *Artifact) BuildIndex() []byte {
})
}

serialized, _ := json.Marshal(defs)
serialized, _ := json.MarshalIndent(defs, " ", " ")
return serialized
}
12 changes: 7 additions & 5 deletions compile/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ description: |
column_types:
- name: Image
type: preview_upload
- name: Payload
type: preview_upload

export: |
LET SPEC <= "{{ .CompressedSpec }}"
Expand Down Expand Up @@ -69,7 +71,7 @@ export: |
then=OSPath =~ get(item=Specs.sources, field=SourceName).filename)

-- Build a regex for all enabled categories.
LET all_categories = SELECT _value
LET all_categories = SELECT if(condition=_value = "All", then=".", else=_value) AS _value
FROM foreach(row=["All"{{ range .Categories }},"{{ . }}"{{ end }}])
WHERE get(field=_value)

Expand Down Expand Up @@ -143,10 +145,10 @@ sources:
// Velociraptor to recreate the entire notebook.
LET ArtifactsWithResults <=
SELECT pathspec(accessor="fs", parse=Data.VFSPath)[4] AS Artifact ,
pathspec(accessor="fs", parse=Data.VFSPath)[-1][:-11] AS Source ,
stat(accessor="fs", filename=Data.VFSPath).Size / 8 AS Records
pathspec(accessor="fs", parse=Data.VFSPath)[-1][:-5] AS Source ,
stat(accessor="fs", filename=Data.VFSPath + ".index").Size / 8 AS Records
FROM enumerate_flow(client_id=ClientId, flow_id=FlowId)
WHERE Type =~ "ResultIndex" AND Records > 0
WHERE Type =~ "Result" AND Records > 0

LET _ <= SELECT notebook_update_cell(notebook_id=NotebookId, type="vql",
input=format(format='''
Expand Down Expand Up @@ -183,7 +185,7 @@ sources:
/*
# {{ $v.Key }}
*/
SELECT * FROM source(Source={{ Quote $v.Key }})
SELECT * FROM source(source={{ Quote $v.Key }})
LIMIT 50
query: |
LET Rows = SELECT * FROM {{ $action }}(SourceName={{ Quote $v.Key }})
Expand Down
80 changes: 80 additions & 0 deletions definitions/Windows_Notification_Service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
Name: Windows WPNDatabase - Notifications
Description: |
Parse the `wpndatabase.db` file

Author: Andrew Rathbun
Email: andrew.d.rathbun@gmail.com
Reference: https://github.com/EricZimmerman/SQLECmd

SQLiteIdentifyQuery: |
SELECT count(*) AS `Check`
FROM sqlite_master
WHERE type='table'
AND (name='Notification' OR
name='HandlerAssets' OR
name='WNSPushChannel' OR
name='TransientTable' OR
name='NotificationData');

SQLiteIdentifyValue: 5

Categories:
- Windows

FilenameRegex: "wpndatabase.db"
Globs:
- C:\Users\*\AppData\Local\Microsoft\Windows\Notifications\wpndatabase.db

Sources:
- name: Notifications
VQL: |
SELECT *, Parent || "" AS Parent,
timestamp(winfiletime= ArrivalTime) AS ArrivalTime,
if(condition= ExpirationTime > 0,
then=timestamp(winfiletime= ExpirationTime),
else='Expired') AS ExpirationTime,
format(format="%02x", args=ActivityId) As ActivityId,
WNSId || "" AS WNSId,

if(condition= WNSCreatedTime > 0,
then=timestamp(winfiletime= WNSCreatedTime),
else='') AS WNSCreatedTime,

if(condition= WNSExpirationTime > 0,
then=timestamp(winfiletime= WNSExpirationTime),
else='') AS WNSExpirationTime,

upload(accessor="data",
file=Payload,
name=format(format="Payload%v.png", args=ID)) AS Payload

FROM Rows

SQL: |
SELECT
Notification.Id AS ID,
Notification.'Order' AS 'Order',
Notification.HandlerId AS HandlerId,
NotificationHandler.PrimaryId AS Application,
NotificationHandler.ParentId AS Parent,
NotificationHandler.HandlerType AS HandlerType,
Notification.Type AS Type,
Notification.Payload AS Payload,
Notification.PayloadType AS PayloadType,
Notification.Tag AS Tag,
Notification."Group" AS "Group",
Notification.ArrivalTime AS ArrivalTime,
Notification.ExpiryTime AS ExpirationTime,
NotificationHandler.CreatedTime AS HandlerCreated,
NotificationHandler.ModifiedTime AS HandlerModified,
NotificationHandler.WNSId AS WNSId,
NotificationHandler.WNFEventName AS WNFEventName,
WNSPushChannel.ChannelId AS ChannelID,
WNSPushChannel.Uri AS URI,
WNSPushChannel.CreatedTime AS WNSCreatedTime,
WNSPushChannel.ExpiryTime AS WNSExpirationTime,
Notification.ActivityId AS ActivityId
FROM Notification
JOIN NotificationHandler ON NotificationHandler.RecordId = Notification.HandlerId
LEFT JOIN WNSPushChannel ON WNSPushChannel.HandlerId = NotificationHandler.RecordId
ORDER BY Id DESC
450 changes: 449 additions & 1 deletion docs/content/docs/rules/index.json

Large diffs are not rendered by default.

147 changes: 97 additions & 50 deletions output/SQLiteHunter.yaml

Large diffs are not rendered by default.

Loading