1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """Autodetect struct layout of various Win32k GUI structs.
20
21 Many win32k structs are undocumented (i.e. are not present in pdb
22 symbols). These structures do change a lot between versions of windows. This
23 module autodetects the struct layout using various heuristics.
24 """
25 import re
26
27 from rekall.plugins.windows import common
28
29
31 """Automatically detect win32k struct layout."""
32
33 name = "win32k_autodetect"
34
35 table_header = [
36 dict(name="divider", type="Divider"),
37 dict(name="field", width=20),
38 dict(name="offset", style="address"),
39 dict(name="definition")
40 ]
41
42
57
87
95
96 - def _Match(self, regex, info):
97 for item in info:
98 if re.match(regex, item):
99 return True
100
101 - def _AddField(self, regex, info, field_name, fields, description):
107
109 """Derive the tagWINDOWSTATION overlay."""
110 fields = {}
111 offset = self.wndstation()
112
113 required_fields = set([
114 "rpwinstaNext", "rpdeskList", "pGlobalAtomTable"])
115
116 stations = set()
117
118 while not offset == None and offset not in stations:
119 stations.add(offset)
120
121 self.session.logging.debug("Checking tagWINDOWSTATION at %#x",
122 offset)
123 for o, info in self.analyze_struct.GuessMembers(offset, size=0x200):
124 if self._AddField(
125 "Tag:Win", info, "rpwinstaNext", fields,
126 [o, ["Pointer", dict(
127 target="tagWINDOWSTATION"
128 )]]):
129 continue
130
131 elif self._AddField(
132 "Tag:Des", info, "rpdeskList", fields,
133 [o, ["Pointer", dict(
134 target="tagDESKTOP"
135 )]]):
136 continue
137
138 elif self._AddField(
139 "Tag:AtmT", info, "pGlobalAtomTable", fields,
140 [o, ["Pointer", dict(
141 target="_RTL_ATOM_TABLE"
142 )]]):
143 continue
144
145 elif self._AddField(
146 "Const:win32k!gTerm", info, "pTerm", fields,
147 [o, ["Pointer", dict(
148 target="tagTERMINAL"
149 )]]):
150 continue
151
152 else:
153 self.session.logging.debug(
154 "Unhandled field %#x, %s" % (o, info))
155 continue
156
157
158
159 self.temp_profile.add_overlay(overlay)
160
161 offset = self.temp_profile.tagWINDOWSTATION(offset).rpwinstaNext
162
163
164 if required_fields.issubset(fields):
165 overlay["tagWINDOWSTATION"][1].update(fields)
166 return overlay
167
168 self.session.logging.debug(
169 "tagWINDOWSTATION: Missing required fields %s",
170 required_fields.difference(fields))
171
172 raise RuntimeError("Unable to guess tagWINDOWSTATION")
173
175 fields = {}
176 required_fields = set([
177 "rpdeskNext", "rpwinstaParent", "hsectionDesktop"])
178
179
180 desktops = set()
181
182 offset = self.wndstation().rpdeskList.v()
183
184 while not offset == None and offset not in desktops:
185 self.session.logging.debug("Checking tagDESKTOP at %#x", offset)
186 desktops.add(offset)
187
188 for o, info in self.analyze_struct.GuessMembers(
189 offset, search=0x400):
190
191 if self._AddField("Tag:Des", info, "rpdeskNext", fields,
192 [o, ["Pointer", dict(
193 target="tagDESKTOP"
194 )]]):
195 continue
196
197 elif self._AddField("Tag:Win", info, "rpwinstaParent", fields,
198 [o, ["Pointer", dict(
199 target="tagWINDOWSTATION"
200 )]]):
201 continue
202
203 elif self._AddField("Tag:Sec", info, "hsectionDesktop", fields,
204 [o, ["Pointer", dict(
205 target="_SECTION_OBJECT"
206 )]]):
207 continue
208
209
210 elif ("_LIST_ENTRY" in info and
211 self._AddField("Tag:Usti", info, "PtiList", fields,
212 [o, ["_LIST_ENTRY"]])):
213 continue
214
215
216 elif ("_LIST_ENTRY" in info and not self._Match("Tag:", info)
217 and self._AddField(
218 "ProcessBilled:", info, "PtiList", fields,
219 [o, ["_LIST_ENTRY"]])):
220 continue
221
222 else:
223 self.session.logging.debug(
224 "Unhandled field %#x %s" % (o, info))
225 continue
226
227
228
229 self.temp_profile.add_overlay(overlay)
230
231 offset = self.temp_profile.tagDESKTOP(offset).rpdeskNext
232
233
234 if required_fields.issubset(fields):
235 overlay["tagDESKTOP"][1].update(fields)
236 return overlay
237
238 self.session.logging.debug(
239 "tagDESKTOP: Missing required fields %s",
240 required_fields.difference(fields))
241
242 raise RuntimeError("Unable to guess tagDESKTOP")
243
245 """Checks if a pointer points to tagPROCESSINFO."""
246 pointer = self.profile.Pointer(offset)
247 pool = self.analyze_struct.SearchForPoolHeader(pointer.v())
248 if pool.Tag == "Uspi":
249 return True
250
251
252 if pool.Tag in ["Usti"]:
253 return False
254
255
256
257 if pool.m("ProcessBilled").Peb:
258 return True
259
260 return False
261
263 self.session.logging.debug("Checking tagTHREADINFO at %#x", offset)
264 for o, info in self.analyze_struct.GuessMembers(
265 offset, size=0x400, search=0x600):
266
267 if self._AddField("Tag:Thr", info, "pEThread", fields,
268 [o, ["Pointer", dict(
269 target="_ETHREAD"
270 )]]):
271 continue
272
273 elif self._AddField("Tag:Usqu", info, "pq", fields,
274 [o, ["Pointer", dict(
275 target="tagQ"
276 )]]):
277 continue
278
279 elif self._AddField("Tag:Uskb", info, "spklActive", fields,
280 [o, ["Pointer", dict(
281 target="tagKL"
282 )]]):
283 continue
284
285 elif self._AddField("Tag:Des", info, "rpdesk", fields,
286 [o, ["Pointer", dict(
287 target="tagDESKTOP"
288 )]]):
289 continue
290
291 elif ("_LIST_ENTRY" in info and
292 self._AddField("Tag:Usti", info, "GdiTmpTgoList", fields,
293 [o, ["_LIST_ENTRY"]])):
294 continue
295
296 elif (self._Check_tagPROCESSINFO(offset + o) and
297 self._AddField(".", info, "ppi", fields,
298 [o, ["Pointer", dict(
299 target="tagPROCESSINFO"
300 )]])):
301 continue
302
303 else:
304 self.session.logging.debug("Unhandled field %#x %s" % (o, info))
305 continue
306
308 fields = {}
309 required_fields = set([
310 "pEThread", "pq", "spklActive", "rpdesk", "PtiLink", "ppi"
311 ])
312
313
314 thread_infos = set()
315 for wndstation in self.wndstation().rpwinstaNext.walk_list(
316 "rpwinstaNext"):
317 for desktop in wndstation.rpdeskList.walk_list("rpdeskNext"):
318 thread_info_pool = self.analyze_struct.SearchForPoolHeader(
319 desktop.PtiList.Flink.v(), search=0x600)
320
321 if thread_info_pool and thread_info_pool not in thread_infos:
322 thread_infos.add(thread_info_pool)
323
324
325 PtiLink_offset = (desktop.PtiList.Flink.v() -
326 thread_info_pool.obj_end)
327 fields["PtiLink"] = [PtiLink_offset, ["_LIST_ENTRY"]]
328
329 self._AnalyzeTagTHREADINFO(thread_info_pool.obj_end, fields)
330 self.temp_profile.add_overlay(overlay)
331
332
333 if required_fields.issubset(fields):
334 overlay["tagTHREADINFO"][1].update(fields)
335 return overlay
336
337 self.session.logging.debug(
338 "tagTHREADINFO: Missing required fields %s",
339 required_fields.difference(fields))
340
341 raise RuntimeError("Unable to guess tagTHREADINFO")
342