11# -*- coding: utf-8 -*-
22"""Windows Registry plugin to parse the AMCache.hve Root key."""
33
4+ import re
5+
46from dfdatetime import filetime as dfdatetime_filetime
57from dfdatetime import posix_time as dfdatetime_posix_time
8+ from dfdatetime import time_elements as dfdatetime_time_elements
69
710from dfwinreg import errors as dfwinreg_errors
811
@@ -95,6 +98,14 @@ class AMCachePlugin(interface.WindowsRegistryPlugin):
9598 interface .WindowsRegistryKeyPathFilter ('\\ Root' )])
9699
97100 # Contains: {value name: attribute name}
101+ _APPLICATION_SUB_KEY_VALUES = {
102+ 'LowerCaseLongPath' : 'full_path' ,
103+ 'ProductName' : 'product_name' ,
104+ 'ProductVersion' : 'file_version' ,
105+ 'ProgramId' : 'program_identifier' ,
106+ 'Publisher' : 'company_name' ,
107+ 'Size' : 'file_size' }
108+
98109 _FILE_REFERENCE_KEY_VALUES = {
99110 '0' : 'product_name' ,
100111 '1' : 'company_name' ,
@@ -106,7 +117,7 @@ class AMCachePlugin(interface.WindowsRegistryPlugin):
106117 '100' : 'program_identifier' ,
107118 '101' : 'sha1' }
108119
109- _AMCACHE_COMPILATION_TIME = 'f'
120+ _AMCACHE_LINK_TIME = 'f'
110121 _AMCACHE_FILE_MODIFICATION_TIME = '11'
111122 _AMCACHE_FILE_CREATION_TIME = '12'
112123 _AMCACHE_ENTRY_WRITE_TIME = '17'
@@ -115,6 +126,13 @@ class AMCachePlugin(interface.WindowsRegistryPlugin):
115126
116127 _AMCACHE_P_FILES = 'Files'
117128
129+ # Date and time string formatted as: "MM/DD/YYYY hh:mm:ss"
130+ # for example "04/07/2014 15:18:49"
131+ # TODO: determine if this is true for other locales.
132+ _LINK_DATE_TIME_RE = re .compile (
133+ r'([0-9][0-9])/([0-9][0-9])/([0-9][0-9][0-9][0-9]) '
134+ r'([0-9][0-9]):([0-9][0-9]):([0-9][0-9])' )
135+
118136 _PRODUCT_KEY_VALUES = {
119137 '0' : 'name' ,
120138 '1' : 'version' ,
@@ -126,8 +144,7 @@ class AMCachePlugin(interface.WindowsRegistryPlugin):
126144 'f' : 'product_code' ,
127145 '10' : 'package_code' ,
128146 '11' : 'msi_product_code' ,
129- '12' : 'msi_package_code' ,
130- }
147+ '12' : 'msi_package_code' }
131148
132149 def _GetValueDataAsObject (
133150 self , parser_mediator , key_path , value_name , registry_value ):
@@ -167,6 +184,112 @@ def _GetValueDataAsObject(
167184
168185 return value_object
169186
187+ def _ParseApplicationSubKey (self , parser_mediator , application_sub_key ):
188+ """Parses a Root\\ InventoryApplicationFile\\ %NAME%|%IDENTIFIER% key.
189+
190+ Args:
191+ parser_mediator (ParserMediator): mediates interactions between parsers
192+ and other components, such as storage and dfVFS.
193+ application_sub_key (dfwinreg.WinRegistryKey): application sub key of the
194+ InventoryApplicationFile Windows Registry key.
195+ """
196+ event_data = AMCacheFileEventData ()
197+
198+ for value_name , attribute_name in self ._APPLICATION_SUB_KEY_VALUES .items ():
199+ value = application_sub_key .GetValueByName (value_name )
200+ if value :
201+ value_data = self ._GetValueDataAsObject (
202+ parser_mediator , application_sub_key .path , value_name , value )
203+
204+ setattr (event_data , attribute_name , value_data )
205+
206+ install_date_value = application_sub_key .GetValueByName ('InstallDate' )
207+ if install_date_value :
208+ date_time = self ._ParseDateStringValue (
209+ parser_mediator , application_sub_key .path , install_date_value )
210+ event = time_events .DateTimeValuesEvent (
211+ date_time , definitions .TIME_DESCRIPTION_LINK_TIME )
212+ parser_mediator .ProduceEventWithEventData (event , event_data )
213+
214+ install_date_msi_value = application_sub_key .GetValueByName (
215+ 'InstallDateMsi' )
216+ if install_date_msi_value :
217+ date_time = self ._ParseDateStringValue (
218+ parser_mediator , application_sub_key .path , install_date_msi_value )
219+ event = time_events .DateTimeValuesEvent (
220+ date_time , definitions .TIME_DESCRIPTION_LINK_TIME )
221+ parser_mediator .ProduceEventWithEventData (event , event_data )
222+
223+ link_date_value = application_sub_key .GetValueByName ('LinkDate' )
224+ if link_date_value :
225+ date_time = self ._ParseDateStringValue (
226+ parser_mediator , application_sub_key .path , link_date_value )
227+ event = time_events .DateTimeValuesEvent (
228+ date_time , definitions .TIME_DESCRIPTION_LINK_TIME )
229+ parser_mediator .ProduceEventWithEventData (event , event_data )
230+
231+ def _ParseDateStringValue (self , parser_mediator , key_path , registry_value ):
232+ """Parses a date and time string value.
233+
234+ Args:
235+ parser_mediator (ParserMediator): mediates interactions between parsers
236+ and other components, such as storage and dfvfs.
237+ key_path (str): key path.
238+ registry_value (dfwinreg.WinRegistryValue): Windows Registry value.
239+
240+ Returns:
241+ dfdatetime_time_elements.TimeElements: date and time value or None
242+ if not available.
243+ """
244+ if not registry_value .DataIsString ():
245+ parser_mediator .ProduceExtractionWarning ((
246+ 'unsupported {0:s} with value data type: {1:s} in key: '
247+ '{2:s}' ).format (
248+ registry_value .name , registry_value .data_type_string , key_path ))
249+ return None
250+
251+ date_time_string = registry_value .GetDataAsObject ()
252+ if not date_time_string :
253+ parser_mediator .ProduceExtractionWarning (
254+ 'missing {0:s} value data in key: {1:s}' .format (
255+ registry_value .name , key_path ))
256+ return None
257+
258+ re_match = self ._LINK_DATE_TIME_RE .match (date_time_string )
259+ if not re_match :
260+ parser_mediator .ProduceExtractionWarning (
261+ 'unsupported {0:s} value data: {1!s} in key: {2:s}' .format (
262+ registry_value .name , date_time_string , key_path ))
263+ return None
264+
265+ month , day_of_month , year , hours , minutes , seconds = re_match .groups ()
266+
267+ try :
268+ year = int (year , 10 )
269+ month = int (month , 10 )
270+ day_of_month = int (day_of_month , 10 )
271+ hours = int (hours , 10 )
272+ minutes = int (minutes , 10 )
273+ seconds = int (seconds , 10 )
274+ except (TypeError , ValueError ):
275+ parser_mediator .ProduceExtractionWarning (
276+ 'invalid {0:s} date time value: {1!s} in key: {2:s}' .format (
277+ registry_value .name , date_time_string , key_path ))
278+ return None
279+
280+ time_elements_tuple = (year , month , day_of_month , hours , minutes , seconds )
281+
282+ try :
283+ date_time = dfdatetime_time_elements .TimeElements (
284+ time_elements_tuple = time_elements_tuple )
285+ except ValueError :
286+ parser_mediator .ProduceExtractionWarning (
287+ 'invalid {0:s} date time value: {1!s} in key: {2:s}' .format (
288+ registry_value .name , time_elements_tuple , key_path ))
289+ return None
290+
291+ return date_time
292+
170293 def _ParseFileKey (self , parser_mediator , file_key ):
171294 """Parses a Root\\ File key.
172295
@@ -220,42 +343,54 @@ def _ParseFileReferenceKey(self, parser_mediator, file_reference_key):
220343
221344 setattr (event_data , attribute_name , value_data )
222345
223- amcache_time_value = file_reference_key .GetValueByName (
346+ write_time_value = file_reference_key .GetValueByName (
224347 self ._AMCACHE_ENTRY_WRITE_TIME )
225- if amcache_time_value :
226- timestamp = amcache_time_value .GetDataAsObject ()
227- amcache_time = dfdatetime_filetime .Filetime (timestamp = timestamp )
348+ if write_time_value :
349+ timestamp = write_time_value .GetDataAsObject ()
350+ date_time = dfdatetime_filetime .Filetime (timestamp = timestamp )
228351 event = time_events .DateTimeValuesEvent (
229- amcache_time , definitions .TIME_DESCRIPTION_MODIFICATION )
352+ date_time , definitions .TIME_DESCRIPTION_MODIFICATION )
230353 parser_mediator .ProduceEventWithEventData (event , event_data )
231354
232355 creation_time_value = file_reference_key .GetValueByName (
233356 self ._AMCACHE_FILE_CREATION_TIME )
234357 if creation_time_value :
235358 timestamp = creation_time_value .GetDataAsObject ()
236- creation_time = dfdatetime_filetime .Filetime (timestamp = timestamp )
359+ date_time = dfdatetime_filetime .Filetime (timestamp = timestamp )
237360 event = time_events .DateTimeValuesEvent (
238- creation_time , definitions .TIME_DESCRIPTION_CREATION )
361+ date_time , definitions .TIME_DESCRIPTION_CREATION )
239362 parser_mediator .ProduceEventWithEventData (event , event_data )
240363
241364 modification_time_value = file_reference_key .GetValueByName (
242365 self ._AMCACHE_FILE_MODIFICATION_TIME )
243366 if modification_time_value :
244367 timestamp = modification_time_value .GetDataAsObject ()
245- modification_time = dfdatetime_filetime .Filetime (timestamp = timestamp )
368+ date_time = dfdatetime_filetime .Filetime (timestamp = timestamp )
246369 event = time_events .DateTimeValuesEvent (
247- modification_time , definitions .TIME_DESCRIPTION_MODIFICATION )
370+ date_time , definitions .TIME_DESCRIPTION_MODIFICATION )
248371 parser_mediator .ProduceEventWithEventData (event , event_data )
249372
250- compilation_time_value = file_reference_key .GetValueByName (
251- self ._AMCACHE_COMPILATION_TIME )
252- if compilation_time_value :
253- timestamp = compilation_time_value .GetDataAsObject ()
254- link_time = dfdatetime_posix_time .PosixTime (timestamp = timestamp )
373+ link_time_value = file_reference_key .GetValueByName (self ._AMCACHE_LINK_TIME )
374+ if link_time_value :
375+ timestamp = link_time_value .GetDataAsObject ()
376+ date_time = dfdatetime_posix_time .PosixTime (timestamp = timestamp )
255377 event = time_events .DateTimeValuesEvent (
256- link_time , definitions .TIME_DESCRIPTION_CHANGE )
378+ date_time , definitions .TIME_DESCRIPTION_LINK_TIME )
257379 parser_mediator .ProduceEventWithEventData (event , event_data )
258380
381+ def _ParseInventoryApplicationFileKey (
382+ self , parser_mediator , inventory_application_file_key ):
383+ """Parses a Root\\ InventoryApplicationFile key.
384+
385+ Args:
386+ parser_mediator (ParserMediator): mediates interactions between parsers
387+ and other components, such as storage and dfVFS.
388+ inventory_application_file_key (dfwinreg.WinRegistryKey): the
389+ InventoryApplicationFile Windows Registry key.
390+ """
391+ for application_sub_key in inventory_application_file_key .GetSubkeys ():
392+ self ._ParseApplicationSubKey (parser_mediator , application_sub_key )
393+
259394 def _ParseProgramKey (self , parser_mediator , program_key ):
260395 """Parses a program key (a sub key of Root\\ Programs) for events.
261396
@@ -268,13 +403,11 @@ def _ParseProgramKey(self, parser_mediator, program_key):
268403
269404 for value_name , attribute_name in self ._PRODUCT_KEY_VALUES .items ():
270405 value = program_key .GetValueByName (value_name )
271- if not value :
272- continue
273-
274- value_data = self ._GetValueDataAsObject (
275- parser_mediator , program_key .path , value_name , value )
406+ if value :
407+ value_data = self ._GetValueDataAsObject (
408+ parser_mediator , program_key .path , value_name , value )
276409
277- setattr (event_data , attribute_name , value_data )
410+ setattr (event_data , attribute_name , value_data )
278411
279412 installation_time_value = program_key .GetValueByName (
280413 self ._AMCACHE_P_INSTALLATION_TIME )
@@ -312,6 +445,9 @@ def _ParseRootKey(self, parser_mediator, root_key):
312445 if sub_key .name == 'File' :
313446 self ._ParseFileKey (parser_mediator , sub_key )
314447
448+ elif sub_key .name == 'InventoryApplicationFile' :
449+ self ._ParseInventoryApplicationFileKey (parser_mediator , sub_key )
450+
315451 elif sub_key .name == 'Programs' :
316452 self ._ParseProgramsKey (parser_mediator , sub_key )
317453
@@ -328,7 +464,6 @@ def _ParseSubKey(self, parser_mediator, registry_key):
328464 for sub_key in registry_key .GetSubkeys ():
329465 self ._ParseSubKey (parser_mediator , sub_key )
330466
331-
332467 def ExtractEvents (self , parser_mediator , registry_key , ** kwargs ):
333468 """Extracts events from a Windows Registry key.
334469
0 commit comments