Skip to content

Commit dce5424

Browse files
authored
Added Windows notifications service (#30)
1 parent 6e31e38 commit dce5424

6 files changed

Lines changed: 635 additions & 58 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ windows:
88
go build -o sqlitehunter_compiler.exe ./bin/*.go
99

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

1313
golden: compile
1414
./testing/velociraptor.bin --definitions ./output --config ./testing/test.config.yaml golden --env testFiles=`pwd`/test_files ./testing/testcases -v --filter=${GOLDEN}

compile/artifact.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,6 @@ func (self *Artifact) BuildIndex() []byte {
102102
})
103103
}
104104

105-
serialized, _ := json.Marshal(defs)
105+
serialized, _ := json.MarshalIndent(defs, " ", " ")
106106
return serialized
107107
}

compile/template.yaml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ description: |
2121
column_types:
2222
- name: Image
2323
type: preview_upload
24+
- name: Payload
25+
type: preview_upload
2426

2527
export: |
2628
LET SPEC <= "{{ .CompressedSpec }}"
@@ -69,7 +71,7 @@ export: |
6971
then=OSPath =~ get(item=Specs.sources, field=SourceName).filename)
7072
7173
-- Build a regex for all enabled categories.
72-
LET all_categories = SELECT _value
74+
LET all_categories = SELECT if(condition=_value = "All", then=".", else=_value) AS _value
7375
FROM foreach(row=["All"{{ range .Categories }},"{{ . }}"{{ end }}])
7476
WHERE get(field=_value)
7577
@@ -143,10 +145,10 @@ sources:
143145
// Velociraptor to recreate the entire notebook.
144146
LET ArtifactsWithResults <=
145147
SELECT pathspec(accessor="fs", parse=Data.VFSPath)[4] AS Artifact ,
146-
pathspec(accessor="fs", parse=Data.VFSPath)[-1][:-11] AS Source ,
147-
stat(accessor="fs", filename=Data.VFSPath).Size / 8 AS Records
148+
pathspec(accessor="fs", parse=Data.VFSPath)[-1][:-5] AS Source ,
149+
stat(accessor="fs", filename=Data.VFSPath + ".index").Size / 8 AS Records
148150
FROM enumerate_flow(client_id=ClientId, flow_id=FlowId)
149-
WHERE Type =~ "ResultIndex" AND Records > 0
151+
WHERE Type =~ "Result" AND Records > 0
150152
151153
LET _ <= SELECT notebook_update_cell(notebook_id=NotebookId, type="vql",
152154
input=format(format='''
@@ -183,7 +185,7 @@ sources:
183185
/*
184186
# {{ $v.Key }}
185187
*/
186-
SELECT * FROM source(Source={{ Quote $v.Key }})
188+
SELECT * FROM source(source={{ Quote $v.Key }})
187189
LIMIT 50
188190
query: |
189191
LET Rows = SELECT * FROM {{ $action }}(SourceName={{ Quote $v.Key }})
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
Name: Windows WPNDatabase - Notifications
2+
Description: |
3+
Parse the `wpndatabase.db` file
4+
5+
Author: Andrew Rathbun
6+
Email: andrew.d.rathbun@gmail.com
7+
Reference: https://github.com/EricZimmerman/SQLECmd
8+
9+
SQLiteIdentifyQuery: |
10+
SELECT count(*) AS `Check`
11+
FROM sqlite_master
12+
WHERE type='table'
13+
AND (name='Notification' OR
14+
name='HandlerAssets' OR
15+
name='WNSPushChannel' OR
16+
name='TransientTable' OR
17+
name='NotificationData');
18+
19+
SQLiteIdentifyValue: 5
20+
21+
Categories:
22+
- Windows
23+
24+
FilenameRegex: "wpndatabase.db"
25+
Globs:
26+
- C:\Users\*\AppData\Local\Microsoft\Windows\Notifications\wpndatabase.db
27+
28+
Sources:
29+
- name: Notifications
30+
VQL: |
31+
SELECT *, Parent || "" AS Parent,
32+
timestamp(winfiletime= ArrivalTime) AS ArrivalTime,
33+
if(condition= ExpirationTime > 0,
34+
then=timestamp(winfiletime= ExpirationTime),
35+
else='Expired') AS ExpirationTime,
36+
format(format="%02x", args=ActivityId) As ActivityId,
37+
WNSId || "" AS WNSId,
38+
39+
if(condition= WNSCreatedTime > 0,
40+
then=timestamp(winfiletime= WNSCreatedTime),
41+
else='') AS WNSCreatedTime,
42+
43+
if(condition= WNSExpirationTime > 0,
44+
then=timestamp(winfiletime= WNSExpirationTime),
45+
else='') AS WNSExpirationTime,
46+
47+
upload(accessor="data",
48+
file=Payload,
49+
name=format(format="Payload%v.png", args=ID)) AS Payload
50+
51+
FROM Rows
52+
53+
SQL: |
54+
SELECT
55+
Notification.Id AS ID,
56+
Notification.'Order' AS 'Order',
57+
Notification.HandlerId AS HandlerId,
58+
NotificationHandler.PrimaryId AS Application,
59+
NotificationHandler.ParentId AS Parent,
60+
NotificationHandler.HandlerType AS HandlerType,
61+
Notification.Type AS Type,
62+
Notification.Payload AS Payload,
63+
Notification.PayloadType AS PayloadType,
64+
Notification.Tag AS Tag,
65+
Notification."Group" AS "Group",
66+
Notification.ArrivalTime AS ArrivalTime,
67+
Notification.ExpiryTime AS ExpirationTime,
68+
NotificationHandler.CreatedTime AS HandlerCreated,
69+
NotificationHandler.ModifiedTime AS HandlerModified,
70+
NotificationHandler.WNSId AS WNSId,
71+
NotificationHandler.WNFEventName AS WNFEventName,
72+
WNSPushChannel.ChannelId AS ChannelID,
73+
WNSPushChannel.Uri AS URI,
74+
WNSPushChannel.CreatedTime AS WNSCreatedTime,
75+
WNSPushChannel.ExpiryTime AS WNSExpirationTime,
76+
Notification.ActivityId AS ActivityId
77+
FROM Notification
78+
JOIN NotificationHandler ON NotificationHandler.RecordId = Notification.HandlerId
79+
LEFT JOIN WNSPushChannel ON WNSPushChannel.HandlerId = NotificationHandler.RecordId
80+
ORDER BY Id DESC

docs/content/docs/rules/index.json

Lines changed: 449 additions & 1 deletion
Large diffs are not rendered by default.

output/SQLiteHunter.yaml

Lines changed: 97 additions & 50 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)