Skip to content

Commit f753569

Browse files
authored
Add RDPCache parser to RDPCache artifact (#50) (#3651)
* Add RDPCache parser to RDPCache artifact
1 parent 52d59c1 commit f753569

File tree

1 file changed

+139
-14
lines changed

1 file changed

+139
-14
lines changed
Lines changed: 139 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
name: Windows.Forensics.RDPCache
22
author: Matt Green - @mgreen27
33
description: |
4-
This artifact views and enables simplified upload of RDP
5-
cache files.
6-
7-
Filters include User regex to target a user and Accessor to target
8-
vss via ntfs_vss.
9-
10-
Best combined with:
11-
12-
- Windows.EventLogs.RDPAuth to collect RDP focused event logs.
13-
- Windows.Registry.RDP to collect user RDP mru and server info
4+
This artifact parses, views and enables simplified upload of RDP
5+
cache files.
6+
7+
By default the artifact will parse .BIN RDPcache files.
8+
9+
Filters include User regex to target a user and Accessor to target
10+
vss via ntfs_vss.
11+
12+
Best combined with:
13+
14+
- Windows.EventLogs.RDPAuth to collect RDP focused event logs.
15+
- Windows.Registry.RDP to collect user RDP mru and server info
1416
1517
reference:
1618
- https://github.com/ANSSI-FR/bmc-tools
@@ -25,18 +27,141 @@ parameters:
2527
default: .
2628
description: Regex filter of user to target. StartOf(^) and EndOf($)) regex may behave unexpectanly.
2729
type: regex
30+
- name: ParseCache
31+
description: If selected will parse .BIN RDPcache files.
32+
type: bool
33+
- name: Workers
34+
default: 100
35+
type: int
36+
description: Number of workers to use for ParseCache
2837
- name: UploadRDPCache
38+
description: If selected will upload raw cache files. Can be used for offline processing/preservation.
2939
type: bool
3040

3141
sources:
32-
- query: |
42+
- name: TargetFiles
43+
description: RDP BitmapCache files in scope.
44+
query: |
3345
LET results = SELECT OSPath, Size, Mtime, Atime, Ctime, Btime
3446
FROM glob(globs=RDPCacheGlob,accessor=Accessor)
3547
WHERE OSPath =~ UserRegex
36-
48+
3749
LET upload_results = SELECT *, upload(file=OSPath) as CacheUpload
3850
FROM results
39-
51+
4052
SELECT * FROM if(condition= UploadRDPCache,
4153
then= upload_results,
42-
else= results )
54+
else= results )
55+
56+
- name: Parsed
57+
description: Parsed RDP BitmapCache files.
58+
query: |
59+
LET PROFILE = '''[
60+
["BIN_CONTAINER", 0, [
61+
[Magic, 0, String, {length: 8, term_hex : "FFFFFF" }],
62+
[Version, 8, uint32],
63+
[CachedFiles, 12, Array, {
64+
"type": "rgb32b",
65+
"count": 10000,
66+
"max_count": 2000,
67+
"sentinel": "x=>x.__Size < 15",
68+
}],
69+
]],
70+
["rgb32b","x=>x.__Size",[
71+
[__key1, 0, uint32],
72+
[__key1, 4, uint32],
73+
["Width", 8, "uint16"],
74+
["Height", 10, "uint16"],
75+
[DataLength, 0, Value,{ value: "x=> 4 * x.Width * x.Height"}],
76+
[DataOffset, 0, Value,{ "value": "x=>x.StartOf + 12"}],
77+
["__Size", 0, Value,{ "value": "x=>x.DataLength + 12"}],
78+
["Index", 0, Value,{ "value": "x=>count() - 1 "}],
79+
]]]'''
80+
81+
LET parse_rgb32b(data) = SELECT
82+
_value as Offset,
83+
_value + 3 as EndOffset,
84+
len(list=data) as Length,
85+
data[(_value):(_value + 3)] + unhex(string="FF") as Buffer
86+
FROM range(step=4,end=len(list=data))
87+
88+
LET fix_bmp(data) = SELECT
89+
_value as Offset,
90+
_value + 255 as EndOffset,
91+
join(array=data[ (_value):(_value + 256 ) ],sep='') as Buffer
92+
FROM range(step=256, end= len(list=data) )
93+
ORDER BY Offset DESC
94+
95+
LET parse_container = SELECT * OSPath,Name,Size as FileSize,
96+
read_file(filename=OSPath,length=12) as Header,
97+
parse_binary(filename=OSPath,profile=PROFILE,struct='BIN_CONTAINER') as Parsed
98+
FROM foreach(row={
99+
SELECT * FROM glob(globs=RDPCacheGlob,accessor=Accessor)
100+
WHERE OSPath =~ '\.bin$'
101+
AND OSPath =~ UserRegex
102+
AND NOT IsDir
103+
})
104+
105+
LET find_index_differential = SELECT *, 0 - Parsed.CachedFiles.Index[0] as IndexDif
106+
FROM parse_container
107+
108+
LET parse_cache = SELECT * FROM foreach(row=find_index_differential, query={
109+
SELECT OSPath, IndexDif,
110+
OSPath.Dirname + ( OSPath.Basename + '_' + format(format='%04v',args= Index + IndexDif ) + '.bmp' ) as BmpName,
111+
FileSize,Header,Width,Height,DataLength,DataOffset
112+
FROM foreach(row=Parsed.CachedFiles)
113+
})
114+
115+
LET extract_data = SELECT *
116+
FROM foreach(row=parse_cache,query={
117+
SELECT
118+
OSPath,BmpName,FileSize,Header,Width,Height,DataLength,DataOffset,
119+
join(array=parse_rgb32b(data=read_file(filename=OSPath,offset=DataOffset,length=DataLength)).Buffer,sep='') as Data
120+
FROM scope()
121+
}, workers=Workers)
122+
123+
-- change endianess for unint32
124+
LET pack_lt_l(data) = unhex(string=join(array=[
125+
format(format='%02x',args=unhex(string=format(format='%08x',args=data))[3]),
126+
format(format='%02x',args=unhex(string=format(format='%08x',args=data))[2]),
127+
format(format='%02x',args=unhex(string=format(format='%08x',args=data))[1]),
128+
format(format='%02x',args=unhex(string=format(format='%08x',args=data))[0])
129+
],sep=''))
130+
131+
-- build bmp file, adding appropriate header
132+
LET build_bmp(data,width,height) = join(array=[
133+
"BM",
134+
pack_lt_l(data=len(list=data) + 122),
135+
unhex(string="000000007A0000006C000000"),
136+
pack_lt_l(data=width),
137+
pack_lt_l(data=height),
138+
unhex(string="0100200003000000"),
139+
pack_lt_l(data=len(list=data)),
140+
unhex(string="000000000000000000000000000000000000FF0000FF0000FF000000000000FF"),
141+
" niW",
142+
unhex(string="00" * 36),
143+
unhex(string="000000000000000000000000"),
144+
data
145+
], sep='')
146+
147+
SELECT * FROM if(condition= ParseCache,
148+
then={
149+
SELECT
150+
BmpName, Header, Width, Height, DataLength, DataOffset,
151+
upload(
152+
file=build_bmp(data=join(array=fix_bmp(data=Data).Buffer,sep=''),
153+
width=Width, height=Height),
154+
name=BmpName,
155+
accessor='data' ) as BmpUpload,
156+
OSPath as SourceFile
157+
FROM extract_data
158+
ORDER BY BmpName
159+
},
160+
else= Null )
161+
162+
163+
column_types:
164+
- name: BmpUpload
165+
type: upload_preview
166+
- name: CacheUpload
167+
type: upload_preview

0 commit comments

Comments
 (0)