1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """ Shimcache plugin.
24
25 This code is based on work by:
26
27 # Authors:
28 # Volatility Plugin Development
29 # * Fred House - Mandiant, a FireEye Company
30 # Twitter: @0xF2EDCA5A
31 #
32 # Windows Shimcache Analysis
33 # * Andrew Davis - Mandiant, a FireEye Company
34 # * Claudiu Teodorescu - FireEye Inc.
35 # - Twitter: @cteo1
36
37 https://github.com/fireeye/Volatility-Plugins.git
38
39 and the paper:
40 https://www.fireeye.com/blog/threat-research/2015/10/shim_shady_live_inv/shim-shady-part-2.html
41 """
42 import itertools
43
44 from rekall import plugin
45 from rekall.plugins.windows import common
46
47
48
49 shimcache_xp_x86 = {
50 "SHIM_CACHE_HEADER": [None, {
51 "Magic": [0, ["unsigned int"]],
52 "MaxEntries": [0x4, ["unsigned int"]],
53 "TotalEntries": [0x8, ["unsigned int"]],
54
55 "LRU": [0x10, ["Array", dict(
56 target="unsigned int",
57 count=lambda x: x.TotalEntries
58 )]],
59
60 "Entries": [0x190, ["Array", dict(
61 count=lambda x: x.TotalEntries,
62 target="SHIM_CACHE_ENTRY",
63 )]],
64 }],
65
66 "SHIM_CACHE_ENTRY" : [0x228, {
67 "Path" : [0x0, ["UnicodeString", dict(length=0x208)]],
68 "LastModified" : [0x210, ["WinFileTime"]],
69 "FileSize": [0x218, ["long long"]],
70 "LastUpdate" : [0x220, ["WinFileTime"]],
71 }],
72 }
73
74 shimcache_win7_x64 = {
75 "SHIM_CACHE_ENTRY": [None, {
76 "ListEntry" : [0x0, ["_LIST_ENTRY"]],
77 "Path" : [0x10, ["_UNICODE_STRING"]],
78 "LastModified": [0x20, ["WinFileTime"]],
79 "InsertFlags": [0x28, ["unsigned int"]],
80 "ShimFlags": [0x2c, ["unsigned int"]],
81 "BlobSize": [0x30, ["unsigned long long"]],
82 "BlobBuffer" : [0x38, ["unsigned long"]],
83 }],
84 }
85
86 shimcache_win7_x86 = {
87 "SHIM_CACHE_ENTRY": [None, {
88 "ListEntry" :[0x0, ["_LIST_ENTRY"]],
89 "Path" : [0x08, ["_UNICODE_STRING"]],
90 "LastModified" : [0x10, ["WinFileTime"]],
91 "InsertFlags": [0x18, ["unsigned int"]],
92 "ShimFlags": [0x1c, ["unsigned int"]],
93 "BlobSize": [0x20, ["unsigned long long"]],
94 "BlobBuffer" : [0x24, ["unsigned long"]],
95 }],
96 }
97
98 shimcache_win8_x64 = {
99 "SHIM_CACHE_ENTRY_DETAIL": [None, {
100 "LastModified": [0x0, ["WinFileTime"]],
101 "InsertFlags": [0x08, ["unsigned int"]],
102 "ShimFlags": [0x0c, ["unsigned int"]],
103 "BlobSize": [0x10, ["unsigned long long"]],
104 "Padding": [0x18, ["unsigned long long"]],
105 "BlobBuffer": [0x20, ["unsigned long long"]],
106 }],
107
108 "SHIM_CACHE_ENTRY": [None, {
109 "ListEntry" : [0x0, ["_LIST_ENTRY"]],
110 "Path": [0x18, ["_UNICODE_STRING"]],
111 "ListEntryDetail": [0x38, ["Pointer", dict(
112 target="SHIM_CACHE_ENTRY_DETAIL"
113 )]],
114 }],
115 }
116
117 shimcache_win8_x86 = {
118 "SHIM_CACHE_ENTRY_DETAIL": [None, {
119 "LastModified": [0x0, ["WinFileTime"]],
120 "InsertFlags": [0x08, ["unsigned int"]],
121 "ShimFlags": [0x0c, ["unsigned int"]],
122 "BlobSize": [0x10, ["unsigned long"]],
123 "BlobBuffer": [0x14, ["unsigned long"]],
124 }],
125
126 "SHIM_CACHE_ENTRY": [None, {
127 "ListEntry": [0x0, ["_LIST_ENTRY"]],
128 "Path": [0x10, ["_UNICODE_STRING"]],
129 "ListEntryDetail": [0x20, ["Pointer", dict(
130 target="SHIM_CACHE_ENTRY_DETAIL"
131 )]],
132 }],
133 }
134
135 shimcache_win10_x86 = {
136 "SHIM_CACHE_ENTRY": [None, {
137 "ListEntry" : [0x0, ["_LIST_ENTRY"]],
138 "Path": [0xc, ["_UNICODE_STRING"]],
139 "ListEntryDetail" : [0x14, ["Pointer", dict(
140 target="SHIM_CACHE_ENTRY_DETAIL"
141 )]],
142 }],
143
144 "SHIM_CACHE_ENTRY_DETAIL" : [None, {
145 "LastModified": [0x08, ["WinFileTime"]],
146 "BlobSize": [0x10, ["unsigned long"]],
147 "BlobBuffer": [0x14, ["unsigned long long"]],
148 }],
149
150 "SHIM_CACHE_HANDLE": [0x10, {
151 "eresource": [0x0, ["Pointer", dict(target="_ERESOURCE")]],
152 "avl_table": [0x8, ["Pointer", dict(target="_RTL_AVL_TABLE")]],
153 }],
154 }
155
156 shimcache_win10_x64 = {
157 "SHIM_CACHE_ENTRY": [None, {
158 "ListEntry" : [0x0, ["_LIST_ENTRY"]],
159 "Path": [0x18, ["_UNICODE_STRING"]],
160 "ListEntryDetail" : [0x28, ["Pointer", dict(
161 target="SHIM_CACHE_ENTRY_DETAIL"
162 )]],
163 }],
164
165 "SHIM_CACHE_ENTRY_DETAIL" : [None, {
166 "LastModified": [0x08, ["WinFileTime"]],
167 "BlobSize": [0x10, ["unsigned long"]],
168 "BlobBuffer": [0x18, ["unsigned long long"]],
169 }],
170
171 "SHIM_CACHE_HANDLE": [0x10, {
172 "eresource": [0x0, ["Pointer", dict(target="_ERESOURCE")]],
173 "avl_table": [0x8, ["Pointer", dict(target="_RTL_AVL_TABLE")]],
174 }],
175 }
176
177
216
217
219 """Extract the Application Compatibility Shim Cache from kernel memory."""
220
221 name = "shimcachemem"
222
223 table_header = [
224 dict(name="Shim", style="address"),
225 dict(name="last_mod", width=30),
226 dict(name="last_update", hidden=True),
227 dict(name="size", width=10),
228 dict(name="Path")
229 ]
230
232 """Fetch the shimcache from XP.
233
234 According to the paper, on XP the cache is in shared memory inside the
235 process winlogon.exe. The cache begins with a header and a magic value
236 of 0xDEADBEEF.
237
238 For some reason the algorithm explained in the paper seems unnecessarily
239 complex. In Rekall we just search for a handle to the ShimCacheMemory
240 section object and use it.
241 """
242 for row in self.session.plugins.handles(proc_regex="winlogon",
243 object_types="Section"):
244 if "ShimSharedMemory" in row["details"]:
245
246 section = row["_OBJECT_HEADER"].Object
247
248
249 process_owner = section.Segment.u1.CreatingProcess.deref()
250 va = section.Segment.u2.FirstMappedVa.v()
251
252 if unicode(process_owner.name).lower() != u"winlogon.exe":
253 continue
254
255
256 with self.session.plugins.cc() as cc:
257 cc.SwitchProcessContext(process_owner)
258
259 header = self.profile.SHIM_CACHE_HEADER(va)
260 return header.Entries
261
262 return []
263
265 seen = set()
266 for node in avl_table.BalancedRoot.traverse_children():
267 entry = node.payload("SHIM_CACHE_ENTRY")
268 if entry.obj_offset in seen:
269 continue
270
271 seen.add(entry.obj_offset)
272 yield entry
273
274
275 for subentry in entry.ListEntry.list_of_type(
276 "SHIM_CACHE_ENTRY", "ListEntry"):
277 if subentry.obj_offset in seen:
278 continue
279
280 seen.add(subentry.obj_offset)
281 yield subentry
282
287
295
303
311
334