1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 from rekall import kb
23 from rekall import obj
24 from rekall.plugins.overlays.windows import pe_vtypes
25 from rekall.plugins.windows.gui import constants
26 from rekall.plugins.windows.gui.vtypes import xp
27 from rekall_lib import utils
28
29
30 win32k_overlay = {
31 '_RTL_ATOM_TABLE_ENTRY': [None, {
32 'Name': [None, ['UnicodeString', dict(
33 encoding='utf16',
34 length=lambda x: x.NameLength * 2)]],
35
36 'ReferenceCount': lambda x: (x.m("ReferenceCount") or
37 x.m("Reference.ReferenceCount")),
38
39 'Pinned': lambda x: x.m("Flags") == 1 or x.m("Reference.Flags") == 1,
40 }],
41
42 'tagWINDOWSTATION': [None, {
43 'pGlobalAtomTable': [None, ['Pointer', dict(
44 target="_RTL_ATOM_TABLE"
45 )]],
46
47 'pClipBase': [None, ["Pointer", dict(
48 target="Array",
49 target_args=dict(
50 target='tagCLIP',
51 count=lambda x: x.cNumClipFormats
52 )
53 )]],
54 }],
55
56 'tagDESKTOP': [None, {
57 'pheapDesktop': [None, ['Pointer', dict(
58 target="_HEAP"
59 )]],
60 }],
61
62 'tagSHAREDINFO': [None, {
63 'aheList': [None, ['Pointer', dict(
64 target='Array',
65 target_args=dict(
66 target="_HANDLEENTRY",
67 count=lambda x: x.psi.cHandleEntries,
68 )
69 )]],
70 }],
71
72 '_HEAD': [None, {
73 'h': [None, ['unsigned int']],
74 }],
75
76 "tagTHREADINFO": [None, {
77 "pEThread": [None, ["Pointer", dict(
78 target="_ETHREAD")]],
79 }],
80
81 "tagHOOK": [None, {
82 "flags": [None, ["Flags", dict(
83 bitmap=utils.MaskMapFromDefines(
84 """
85 // 9/18/2011
86 // http://forum.sysinternals.com/enumerate-windows-hooks_topic23877.html#122641
87 #define HF_GLOBAL 0x0001
88 #define HF_ANSI 0x0002
89 #define HF_NEEDHC_SKIP 0x0004
90 #define HF_HUNG 0x0008
91 #define HF_HOOKFAULTED 0x0010
92 #define HF_NOPLAYBACKDELAY 0x0020
93 #define HF_WX86KNOWINDOWLL 0x0040
94 #define HF_DESTROYED 0x0080
95 // mask for valid flags
96 #define HF_VALID 0x00FF
97 """))
98 ]],
99 }],
100
101 "_HANDLEENTRY": [None, {
102 "pOwner": [None, ["Pointer", dict(
103 target="tagTHREADINFO")]],
104
105 "bFlags": [None, ["Flags", dict(
106 target="byte",
107 bitmap=utils.MaskMapFromDefines("""
108 // 8/17/2011
109 // http://www.reactos.org/wiki/Techwiki:Win32k/HANDLEENTRY
110 // HANDLEENTRY.bFlags
111 #define HANDLEF_DESTROY 0x01
112 #define HANDLEF_INDESTROY 0x02
113 #define HANDLEF_INWAITFORDEATH 0x04
114 #define HANDLEF_FINALDESTROY 0x08
115 #define HANDLEF_MARKED_OK 0x10
116 #define HANDLEF_GRANTED 0x20
117 // mask for valid flags
118 #define HANDLEF_VALID 0x3F
119 """),
120 )]],
121
122 'bType': [None, ['Enumeration', dict(
123 target='unsigned char',
124 choices=constants.HANDLE_TYPE_ENUM,
125 )]],
126 }],
127
128 '_THRDESKHEAD': [None, {
129 "h": [None, ["unsigned int"]],
130 }],
131 }
132
133
134
135
136 win32k_undocumented_AMD64 = {
137
138
139
140
141
142
143
144 '_RTL_ATOM_TABLE': [None, {
145
146
147
148
149
150
151
152
153
154
155 'NumberOfBuckets': lambda x: 0x35,
156
157
158 'Buckets': [0x20, ['Array', dict(
159 count=lambda x: x.NumberOfBuckets,
160 max_count=100,
161 target="Pointer",
162 target_args=dict(
163 target='_RTL_ATOM_TABLE_ENTRY')
164 )]],
165 }],
166
167 'tagEVENTHOOK' : [0x60, {
168 'phkNext' : [0x18, ['Pointer', dict(
169 target='tagEVENTHOOK'
170 )]],
171 'eventMin' : [0x20, ['Enumeration', dict(
172 target='unsigned long',
173 choices=constants.EVENT_ID_ENUM)]],
174
175 'eventMax' : [0x24, ['Enumeration', dict(
176 target='unsigned long',
177 choices=constants.EVENT_ID_ENUM)]],
178
179 'dwFlags' : [0x28, ['unsigned long']],
180 'idProcess' : [0x2C, ['unsigned long']],
181 'idThread' : [0x30, ['unsigned long']],
182 'offPfn' : [0x40, ['Pointer', dict(target="Void")]],
183 'ihmod' : [0x48, ['long']],
184 }],
185
186 'tagHANDLETYPEINFO' : [16, {
187 'fnDestroy' : [0, ['Pointer', dict(
188 target="Function"
189 )]],
190 'dwAllocTag' : [8, ['String', dict(length=4)]],
191 'bObjectCreateFlags' : [12, ['Flags', dict(
192 target='unsigned char',
193 bitmap={
194 'OCF_THREADOWNED': 0,
195 'OCF_PROCESSOWNED': 1,
196 'OCF_MARKPROCESS': 2,
197 'OCF_USEPOOLQUOTA': 3,
198 'OCF_DESKTOPHEAP': 4,
199 'OCF_USEPOOLIFNODESKTOP': 5,
200 'OCF_SHAREDHEAP': 6,
201 'OCF_VARIABLESIZE': 7}
202 )]],
203 }],
204
205 'tagCLIPDATA' : [None, {
206 'cbData' : [0x08, ['unsigned int']],
207 'abData' : [0x0C, ['Array', dict(
208 count=lambda x: x.cbData,
209 target='unsigned char')]],
210 }],
211 }
212
213 win32k_undocumented_I386 = {
214 '_RTL_ATOM_TABLE': [None, {
215 'NumberOfBuckets': [0xC, ['unsigned long']],
216 'Buckets': [0x10, ['Array', dict(
217 count=lambda x: x.NumberOfBuckets,
218 max_count=100,
219 target="Pointer",
220 target_args=dict(
221 target='_RTL_ATOM_TABLE_ENTRY')
222 )]],
223 }],
224
225 'tagEVENTHOOK' : [0x30, {
226 'phkNext' : [0xC, ['Pointer', dict(
227 target='tagEVENTHOOK'
228 )]],
229 'eventMin' : [0x10, ['Enumeration', dict(
230 target='unsigned long',
231 choices=constants.EVENT_ID_ENUM)]],
232
233 'eventMax' : [0x14, ['Enumeration', dict(
234 target='unsigned long',
235 choices=constants.EVENT_ID_ENUM)]],
236
237 'dwFlags' : [0x18, ['unsigned long']],
238 'idProcess' : [0x1C, ['unsigned long']],
239 'idThread' : [0x20, ['unsigned long']],
240 'offPfn' : [0x24, ['Pointer', dict(target="Void")]],
241 'ihmod' : [0x28, ['long']],
242 }],
243
244 'tagHANDLETYPEINFO' : [12, {
245 'fnDestroy' : [0, ['Pointer', dict(
246 target="Function"
247 )]],
248 'dwAllocTag' : [4, ['String', dict(length=4)]],
249 'bObjectCreateFlags' : [8, ['Flags', dict(
250 target='unsigned char',
251 bitmap={
252 'OCF_THREADOWNED': 0,
253 'OCF_PROCESSOWNED': 1,
254 'OCF_MARKPROCESS': 2,
255 'OCF_USEPOOLQUOTA': 3,
256 'OCF_DESKTOPHEAP': 4,
257 'OCF_USEPOOLIFNODESKTOP': 5,
258 'OCF_SHAREDHEAP': 6,
259 'OCF_VARIABLESIZE': 7}
260 )]],
261 }],
262 'tagCLIPDATA' : [None, {
263 'cbData' : [0x08, ['unsigned int']],
264 'abData' : [0x0C, ['Array', dict(
265 count=lambda x: x.cbData,
266 target='unsigned char')]],
267 }],
268 }
272 """A class for session spaces"""
273
275 """Generator for processes in this session.
276
277 A process is always associated with exactly
278 one session.
279 """
280 for p in self.ProcessList.list_of_type(
281 "_EPROCESS", "SessionProcessLinks"):
282 yield p
283
284 @utils.safe_property
286 """Get the base address of the win32k.sys as mapped
287 into this session's memory.
288
289 Since win32k.sys is always the first image to be
290 mapped, we can just grab the first list entry."""
291
292
293
294 try:
295 return list(self.images())[0].Address
296 except IndexError:
297 return obj.NoneObject("No images mapped in this session")
298
300 """Generator for images (modules) loaded into
301 this session's space"""
302 for i in self.ImageList.list_of_type("_IMAGE_ENTRY_IN_SESSION", "Link"):
303 yield i
304
306 """Get the win32k.sys section as an array of
307 32-bit unsigned longs.
308
309 @param sec_name: name of the PE section in win32k.sys
310 to search for.
311
312 @returns all chunks on a 4-byte boundary.
313 """
314
315
316
317
318 section_base = self.Win32KBase
319 section_size = 0x500000
320
321 dos_header = self.obj_profile._IMAGE_DOS_HEADER(
322 offset=self.Win32KBase, vm=self.obj_vm)
323
324 for section in dos_header.NTHeader.Sections:
325 if section.Name == sec_name:
326 section_base = section.VirtualAddress
327 section_size = section.Misc.VirtualSize / 4
328 break
329
330
331 return self.obj_profile.Array(targetType="unsigned long",
332 offset=section_base,
333 count=section_size, vm=self.obj_vm)
334
336 """Find this session's gahti.
337
338 This can potentially be much faster by searching for
339 '\0' * sizeof(tagHANDLETYPEINFO) instead
340 of moving on a dword aligned boundary through
341 the section.
342 """
343
344 for chunk in self._section_chunks(".rdata"):
345 if not chunk.is_valid():
346 continue
347
348 gahti = obj.Object("gahti", offset=chunk.obj_offset,
349 vm=self.obj_vm)
350
351
352
353
354
355
356 if (gahti.types[0].fnDestroy == 0 and
357 str(gahti.types[0].dwAllocTag) == '' and
358 gahti.types[0].bObjectCreateFlags == 0 and
359 str(gahti.types[1].dwAllocTag) == "Uswd"):
360 return gahti
361
362 return obj.NoneObject("Cannot find win32k!_gahti")
363
364
365 -class _HANDLEENTRY(obj.Struct):
366 """A for USER handle entries"""
367
369 """Reference the object this handle represents.
370
371 If the object's type is not in our map, we don't know
372 what type of object to instantiate so its filled with
373 obj.NoneObject() instead.
374 """
375
376 object_map = dict(
377 TYPE_WINDOW="tagWND",
378 TYPE_HOOK="tagHOOK",
379 TYPE_CLIPDATA="tagCLIPDATA",
380 TYPE_WINEVENTHOOK="tagEVENTHOOK",
381 TYPE_TIMER="tagTIMER",
382 )
383
384 object_type = object_map.get(str(self.bType))
385 if object_type is None:
386 return obj.NoneObject("Cannot reference object type")
387
388 return self.obj_profile.Object(
389 object_type, offset=self.phead, vm=self.obj_vm)
390
391 @utils.safe_property
393 """Check if the handle has been freed"""
394 return str(self.bType) == "TYPE_FREE"
395
396 @utils.safe_property
397 - def ThreadOwned(self):
398 """Handles of these types are always thread owned"""
399 return str(self.bType) in [
400 'TYPE_WINDOW', 'TYPE_SETWINDOWPOS', 'TYPE_HOOK',
401 'TYPE_DDEACCESS', 'TYPE_DDECONV', 'TYPE_DDEXACT',
402 'TYPE_WINEVENTHOOK', 'TYPE_INPUTCONTEXT', 'TYPE_HIDDATA',
403 'TYPE_TOUCH', 'TYPE_GESTURE']
404 @utils.safe_property
405 - def ProcessOwned(self):
406 """Handles of these types are always process owned"""
407 return str(self.bType) in [
408 'TYPE_MENU', 'TYPE_CURSOR', 'TYPE_TIMER',
409 'TYPE_CALLPROC', 'TYPE_ACCELTABLE']
410
411 @utils.safe_property
413 """Return the ETHREAD if its thread owned"""
414 if self.ThreadOwned:
415 return self.pOwner.\
416 dereference_as("tagTHREADINFO").\
417 pEThread.dereference()
418 return obj.NoneObject("Cannot find thread")
419
420 @utils.safe_property
422 """Return the _EPROCESS if its process or thread owned"""
423 if self.ProcessOwned:
424 return (self.pOwner.
425 dereference_as("tagPROCESSINFO").
426 Process.dereference())
427
428 elif self.ThreadOwned:
429 return (
430 self.m("pOwner.pEThread.ThreadsProcess").deref() or
431 self.pOwner.ppi.Process.dereference() or
432 self.pOwner.pEThread.Tcb.Process.dereference_as(
433 "_EPROCESS"))
434
435 return obj.NoneObject("Cannot find process")
436
439 """A class for Windowstation objects"""
440
444
445 @utils.safe_property
447 """The EPROCESS of the last registered clipboard viewer"""
448 return self.m("spwndClipViewer.head.pti.ppi.Process")
449
450 @utils.safe_property
452 """Check if a window station is interactive"""
453 return not self.dwWSF_Flags & 4
454
455 @utils.safe_property
457 """Get the window station name.
458
459 Since window stations are securable objects, and are managed by the same
460 object manager as processes, threads, etc, there is an object header
461 which stores the name.
462 """
463 object_hdr = self.obj_session.profile._OBJECT_HEADER(
464 vm=self.obj_vm,
465 offset=self.obj_offset - self.obj_session.profile.get_obj_offset(
466 '_OBJECT_HEADER', 'Body')
467 )
468
469 return object_hdr.NameInfo.Name
470
472 """A generator that yields the window station's desktops"""
473 return self.rpdeskList.walk_list("rpdeskNext")
474
477 """A class for Desktop objects"""
478
481
482 @utils.safe_property
484 """Returns this desktop's parent window station"""
485 return self.rpwinstaParent.dereference()
486
487 @utils.safe_property
489 """Returns the desktop info object"""
490 return self.pDeskInfo.dereference()
491
493 """Generator for _EPROCESS objects attached to this desktop"""
494 for ti in self.PtiList.list_of_type("tagTHREADINFO", "PtiLink"):
495 yield ti
496
506
507 - def windows(self, win, filter=lambda x: True, level=0):
508 """Traverses windows in their Z order, bottom to top.
509
510 @param win: an HWND to start. Usually this is the desktop
511 window currently in focus.
512
513 @param filter: a callable (usually lambda) to use for filtering
514 the results. See below for examples:
515
516 # only print subclassed windows
517 filter = lambda x : x.lpfnWndProc == x.pcls.lpfnWndProc
518
519 # only print processes named csrss.exe
520 filter = lambda x : str(x.head.pti.ppi.Process.ImageFileName).lower() \
521 == "csrss.exe" if x.head.pti.ppi else False
522
523 # only print processes by pid
524 filter = lambda x : x.head.pti.pEThread.Cid.UniqueThread == 0x1020
525
526 # only print visible windows
527 filter = lambda x : 'WS_VISIBLE' not in x.get_flags()
528 """
529 seen = set()
530 wins = []
531 cur = win
532 while cur.is_valid() and cur.v() != 0:
533 if cur in seen:
534 break
535 seen.add(cur)
536 wins.append(cur)
537 cur = cur.spwndNext.dereference()
538 while wins:
539 cur = wins.pop()
540 if not filter(cur):
541 continue
542
543 yield cur, level
544
545 if cur.spwndChild.is_valid() and cur.spwndChild.v() != 0:
546 for info in self.windows(
547 cur.spwndChild, filter=filter, level=level+1):
548 yield info
549
551 """Generator for the desktop heaps"""
552 for segment in self.pheapDesktop.Heap.segments():
553 for entry in segment.heap_entries():
554 yield entry
555
557 """Generator for next desktops in the list"""
558
559
560 yield self
561
562 nextdesk = self.rpdeskNext.dereference(vm=vm)
563 while nextdesk.is_valid() and nextdesk.v() != 0:
564 yield nextdesk
565 nextdesk = nextdesk.rpdeskNext.dereference(vm=vm)
566
568 """A class for window structures"""
569
570 @utils.safe_property
572 """Check if this window listens to clipboard changes"""
573 return self.bClipboardListener.v()
574
575 @utils.safe_property
577 """The class atom for this window"""
578 return self.pcls.atomClassName
579
580 @utils.safe_property
582 """The window's super class"""
583 return self.pcls.atomNVClassName
584
585 @utils.safe_property
587 """The EPROCESS that owns the window"""
588 return self.head.pti.ppi.Process.dereference()
589
590 @utils.safe_property
592 """The ETHREAD that owns the window"""
593 return self.head.pti.pEThread.dereference()
594
595 @utils.safe_property
597 """Is this window visible on the desktop"""
598 return 'WS_VISIBLE' in self.style
599
601
602 if flags.has_key(member):
603 return flags[member]
604
605 return ','.join([n for (n, v) in flags.items() if member & v == v])
606
607 @utils.safe_property
611
612 @utils.safe_property
617
619 """A class for window rects"""
620
622 """Return a tuple of the rect's coordinates"""
623 return (self.left, self.top, self.right, self.bottom)
624
626 """A class for clipboard objects"""
627
629 """Format the clipboard data as a string.
630
631 @param fmt: the clipboard format.
632
633 Note: we cannot simply override __str__ for this
634 purpose, because the clipboard format is not a member
635 of (or in a parent-child relationship with) the
636 tagCLIPDATA structure, so we must pass it in as
637 an argument.
638 """
639
640 if fmt == "CF_UNICODETEXT":
641 encoding = "utf16"
642 else:
643 encoding = "utf8"
644
645 return obj.String(
646 offset=self.abData.obj_offset,
647 vm=self.obj_vm, encoding=encoding,
648 length=self.cbData)
649
651 """Format the clipboard contents as a hexdump"""
652 data = ''.join([chr(c) for c in self.abData])
653 return "".join(["{0:#x} {1:<48} {2}\n".format(
654 self.abData.obj_offset + o, h, ''.join(c))
655 for o, h, c in utils.Hexdump(data)])
656
659 """A class for thread information objects"""
660
662 """Generator for tagHOOK info."""
663 fsHooks = self.fsHooks
664
665 for pos, (name, value) in enumerate(constants.MESSAGE_TYPES):
666
667 if fsHooks & (1 << value + 1):
668 for hook in self.aphkStart[pos].walk_list("phkNext"):
669 yield name, hook
670
673 """A class for event hooks"""
674
675 @utils.safe_property
677 """Event hook flags need special handling so we can't use vtypes"""
678
679
680 f = self.m('dwFlags') >> 1
681
682 flags = [
683 name for (val, name) in constants.EVENT_FLAGS.items() if f & val]
684
685 return '|'.join(flags)
686
688 """A class for atom tables"""
689
691 """Give ourselves an atom cache for quick lookups"""
692 self.atom_cache = {}
693 super(_RTL_ATOM_TABLE, self).__init__(**kwargs)
694
696 """Check for validity based on the atom table signature
697 and the maximum allowed number of buckets"""
698 return (super(_RTL_ATOM_TABLE, self).is_valid() and
699 self.Signature == 0x6d6f7441 and
700 self.NumberOfBuckets < 0xFFFF)
701
702 - def atoms(self, vm=None):
703 """Carve all atoms out of this atom table"""
704 for bucket in self.Buckets:
705 for entry in bucket.deref(vm=vm).walk_list("HashLink"):
706 if entry.Atom < 0xf000:
707 yield entry
708
709 - def find_atom(self, atom_to_find, use_cache=False):
710 """Find an atom by its ID.
711
712 @param atom_to_find: the atom ID (ushort) to find
713
714 @returns an _RTL_ATOM_TALE_ENTRY object
715 """
716 atom_to_find = int(atom_to_find)
717 not_found = obj.NoneObject("Atom not found")
718
719
720 if use_cache:
721 if self.atom_cache:
722 return self.atom_cache.get(atom_to_find, not_found)
723
724
725 self.atom_cache = dict(
726 (int(atom.Atom), atom) for atom in self.atoms())
727
728 return self.atom_cache.get(atom_to_find, not_found)
729 else:
730
731
732 for atom in self.atoms():
733 if atom.Atom == atom_to_find:
734 return atom
735
736 return not_found
737
738
739 -class _RTL_ATOM_TABLE_ENTRY(obj.Struct):
740 """A class for atom table entries"""
741
742 - def is_string_atom(self):
743 """Returns True if the atom is a string atom
744 based on its atom ID.
745
746 A string atom has ID 0xC000 - 0xFFFF
747 """
748 return self.Atom >= 0xC000 and self.Atom <= 0xFFFF
749
750 - def is_valid(self):
751 """Perform some sanity checks on the Atom"""
752 if not super(_RTL_ATOM_TABLE_ENTRY, self).is_valid():
753 return False
754
755
756 if self.Flags not in (0, 1):
757 return False
758
759 return self.NameLength <= 255
760
763 """A mixin which loads the relevant win32k profile."""
764
765 @classmethod
766 - def args(cls, parser):
770
772 """Returns true if the profile is a valid win32k one."""
773 return profile.get_constant("grpWinStaList")
774
775 - def __init__(self, win32k_profile=None, **kwargs):
789
790
791 -class Win32k(pe_vtypes.BasicPEProfile):
792 """A profile for the Win32 GUI system."""
793
794 guessed_types = False
795
796 @staticmethod
798
799
800
801
802 arch = profile.metadata("arch")
803 if arch == "AMD64":
804 exempler = ("win32k/GUID/"
805 "99227A2085CE41969CD5A06F7CC20F522")
806 else:
807 exempler = ("win32k/GUID/"
808 "18EB20F5448A47F5B850023FEE0B24D62")
809
810 result = profile.session.LoadProfile(exempler)
811 if result == None:
812 raise RuntimeError("Unable to load exempler profile %s" % exempler)
813
814 return result
815
816 @classmethod
818 super(Win32k, cls).Initialize(profile)
819
820
821 profile.merge(profile.session.profile)
822
823
824
825 profile.add_constants(dict(PoolTag_WindowStation="Win\xe4",
826 PoolTag_Atom="AtmT"))
827
828 profile.add_classes({
829 'tagWINDOWSTATION': tagWINDOWSTATION,
830 'tagDESKTOP': tagDESKTOP,
831 '_RTL_ATOM_TABLE': _RTL_ATOM_TABLE,
832 '_RTL_ATOM_TABLE_ENTRY': _RTL_ATOM_TABLE_ENTRY,
833 'tagTHREADINFO': tagTHREADINFO,
834 'tagWND': tagWND,
835 '_HANDLEENTRY': _HANDLEENTRY,
836 'tagEVENTHOOK': tagEVENTHOOK,
837 'tagRECT': tagRECT,
838 'tagCLIPDATA': tagCLIPDATA,
839 })
840
841 profile.add_overlay(win32k_overlay)
842 if profile.metadata("arch") == "AMD64":
843 profile.add_overlay(win32k_undocumented_AMD64)
844 else:
845 profile.add_overlay(win32k_undocumented_I386)
846
847 exempler = None
848 required_types = ["tagWINDOWSTATION", "tagDESKTOP", "tagTHREADINFO",
849 "tagWND", "tagDESKTOPINFO", "tagPROCESSINFO",
850 "tagSHAREDINFO", "_HANDLEENTRY", "_HEAD", "tagHOOK",
851 "_THRDESKHEAD", "_WNDMSG", "tagSERVERINFO"]
852 for item in required_types:
853 if not profile.has_type(item):
854
855
856
857 profile.guessed_types = True
858 if exempler is None:
859 win7_profile = cls._LoadExempler(profile)
860
861 profile.vtypes[item] = win7_profile.vtypes[item]
862
863
864 version = profile.metadata('version')
865 arch = profile.metadata("arch")
866
867 if version < 6.0:
868 if arch == "I386":
869 profile.add_types(xp.vtypes_xp_32)
870 else:
871 profile.add_types(xp.vtypes_xp_64)
872
873 if profile.guessed_types:
874 profile.session.logging.debug(
875 "Win32k profile is incomplete - attempting autodetection.")
876
877 profile.add_overlay(
878 profile.session.plugins.win32k_autodetect().GetWin32kOverlay(
879 profile))
880
881
882 return profile
883
884
885 if version.startswith("6.1"):
886 from rekall.plugins.windows.gui.vtypes import win7
887
888 profile = win7.Win32GUIWin7.modify(profile)
889 else:
890 profile = xp.XP2003x86BaseVTypes.modify(profile)
891
892
893
894 profile.add_overlay({
895 'gahti': [None, {
896 'types': [0, ['Array', dict(
897 count=num_handles,
898 target='tagHANDLETYPEINFO')]],
899 }],
900
901 'tagWIN32HEAP': [None, {
902 'Heap': [0, ['_HEAP']],
903 }],
904 'tagCLIPDATA' : [None, {
905 'cbData' : [0x08, ['unsigned int']],
906 'abData' : [0x0C, ['Array', dict(
907 count=lambda x: x.cbData,
908 target='unsigned char')]],
909 }],
910 })
911
912
913
914 if architecture == "AMD64":
915 profile.add_overlay({
916 '_RTL_ATOM_TABLE': [None, {
917 'NumberOfBuckets': [0x18, ['unsigned long']],
918 'Buckets': [0x20, ['Array', dict(
919 count=lambda x: x.NumBuckets,
920 target="Pointer",
921 target_args=dict(
922 target='_RTL_ATOM_TABLE_ENTRY')
923 )]],
924 }],
925
926 'tagCLIPDATA' : [None, {
927 'cbData' : [0x10, None],
928 'abData' : [0x14, None],
929 }],
930 'tagEVENTHOOK' : [0x60, {
931 'phkNext' : [0x18, None],
932 'eventMin' : [0x20, None],
933 'eventMax' : [0x24, None],
934 'dwFlags' : [0x28, None],
935 'idProcess' : [0x2C, None],
936 'idThread' : [0x30, None],
937 'offPfn' : [0x40, None],
938 'ihmod' : [0x48, None],
939 }],
940 'tagHANDLETYPEINFO' : [16, {
941 'dwAllocTag' : [8, None],
942 'bObjectCreateFlags' : [12, None],
943 }],
944 })
945
946
947 if architecture == "I386" and version[:2] == (5, 1):
948 profile.add_overlay({
949 '_MM_SESSION_SPACE': [None, {
950
951 'ResidentProcessCount': [0x248, ['long']],
952 }]})
953
954 return profile
955
958 """Guess the version of win32k.sys from the index.
959
960 NOTE: Win32k needs special attention because it is often not easily
961 detected.
962 """
963 name = "win32k_profile"
964
970