55import dataclasses
66import datetime
77import enum
8- import logging
98import itertools
9+ import logging
1010from typing import Dict , Iterable , Iterator , List , Optional , Tuple , Union
1111
1212from volatility3 .framework import interfaces , renderers
@@ -132,6 +132,7 @@ class _AmcacheEntry:
132132 sha1_hash : NullableString = renderers .NotApplicableValue ()
133133 service : NullableString = renderers .NotApplicableValue ()
134134 product_name : NullableString = renderers .NotApplicableValue ()
135+ product_version : NullableString = renderers .NotApplicableValue ()
135136
136137
137138def _entry_sort_key (entry_tuple : Tuple [NullableString , _AmcacheEntry ]) -> str :
@@ -279,34 +280,38 @@ def parse_file_key(
279280 correlating `Root\\ Program` entries, and the second member is the `AmcacheEntry`.
280281 """
281282
283+ val_enum = Win8FileValName
284+
285+ wanted_values = [key .value for key in val_enum ]
286+
282287 for file_entry_key in itertools .chain (
283288 * (key .get_subkeys () for key in file_key .get_subkeys ())
284289 ):
285290 vollog .debug (f"Checking Win8 File key { file_entry_key .get_name ()} " )
286291 values = {
287292 str (value .get_name ()): value
288293 for value in file_entry_key .get_values ()
289- if value .get_name () in [ key . value for key in Win8FileValName ]
294+ if value .get_name () in wanted_values
290295 }
291296
292- program_id = _get_string_value (values , Win8FileValName .ProgramID .value )
293- path = _get_string_value (values , Win8FileValName .Path .value )
294- company = _get_string_value (values , Win8FileValName .Company .value )
297+ program_id = _get_string_value (values , val_enum .ProgramID .value )
298+ path = _get_string_value (values , val_enum .Path .value )
299+ company = _get_string_value (values , val_enum .Company .value )
295300 last_mod_time = _get_datetime_filetime_value (
296- values , Win8FileValName .LastModTime .value
301+ values , val_enum .LastModTime .value
297302 )
298303 last_mod_time_2 = _get_datetime_filetime_value (
299- values , Win8FileValName .LastModTime2 .value
304+ values , val_enum .LastModTime2 .value
300305 )
301306 install_time = _get_datetime_filetime_value (
302- values , Win8FileValName .CreateTime .value
307+ values , val_enum .CreateTime .value
303308 )
304309 compile_time = _get_datetime_utc_epoch_value (
305- values , Win8FileValName .CompileTime .value
310+ values , val_enum .CompileTime .value
306311 )
307- sha1_hash = _get_string_value (values , Win8FileValName .SHA1Hash .value )
312+ sha1_hash = _get_string_value (values , val_enum .SHA1Hash .value )
308313 vollog .debug (f"Found sha1hash { sha1_hash } " )
309- product_name = _get_string_value (values , Win8FileValName .Product .value )
314+ product_name = _get_string_value (values , val_enum .Product .value )
310315
311316 yield program_id , _AmcacheEntry (
312317 AmcacheEntryType .File .name ,
@@ -335,21 +340,24 @@ def parse_programs_key(
335340 :return: An iterator of tuples, where the first member is the program ID string for
336341 correlating `Root\\ File` entries, and the second member is the `AmcacheEntry`.
337342 """
343+ val_enum = Win8ProgramValName
344+
345+ wanted_values = [key .value for key in val_enum ]
338346 for program_key in programs_key .get_subkeys ():
339347 values = {
340348 str (value .get_name ()): value
341349 for value in program_key .get_values ()
342- if value .get_name () in [ key . value for key in Win8ProgramValName ]
350+ if value .get_name () in wanted_values
343351 }
344352 vollog .debug (f"Parsing Win8 Program key { program_key .get_name ()} " )
345353 program_id = program_key .get_name ().strip ().strip ("\u0000 " )
346354
347- product = _get_string_value (values , Win8ProgramValName .Product .value )
348- company = _get_string_value (values , Win8ProgramValName .Publisher .value )
355+ product = _get_string_value (values , val_enum .Product .value )
356+ company = _get_string_value (values , val_enum .Publisher .value )
349357 install_time = _get_datetime_utc_epoch_value (
350- values , Win8ProgramValName .InstallTime .value
358+ values , val_enum .InstallTime .value
351359 )
352- _version = _get_string_value (values , Win8ProgramValName .Version .value )
360+ _version = _get_string_value (values , val_enum .Version .value )
353361
354362 if isinstance (_version , str ):
355363 if isinstance (product , str ):
@@ -378,29 +386,29 @@ def parse_inventory_app_key(
378386 :return: An iterator of tuples, where the first member is the program ID string for
379387 correlating `Root\\ InventoryApplicationFile` entries, and the second member is the `AmcacheEntry`.
380388 """
389+ val_enum = Win10InvAppValName
390+
391+ wanted_values = [key .value for key in val_enum ]
392+
381393 for program_key in inv_app_key .get_subkeys ():
382394 program_id = program_key .get_name ()
383395
384396 values = {
385397 str (value .get_name ()): value
386398 for value in program_key .get_values ()
387- if value .get_name () in [ key . value for key in Win10InvAppValName ]
399+ if value .get_name () in wanted_values
388400 }
389401
390- name = _get_string_value (values , Win10InvAppValName .Name .value )
391- version = _get_string_value (values , Win10InvAppValName .Version .value )
392- publisher = _get_string_value (values , Win10InvAppValName .Publisher .value )
393- path = _get_string_value (values , Win10InvAppValName .RootDirPath .value )
394- install_date = _get_datetime_str_value (
395- values , Win10InvAppValName .InstallDate .value
396- )
402+ name = _get_string_value (values , val_enum .Name .value )
403+ version = _get_string_value (values , val_enum .Version .value )
404+ publisher = _get_string_value (values , val_enum .Publisher .value )
405+ path = _get_string_value (values , val_enum .RootDirPath .value )
406+ install_date = _get_datetime_str_value (values , val_enum .InstallDate .value )
397407 last_mod = conversion .wintime_to_datetime (
398408 program_key .LastWriteTime .QuadPart
399409 )
400410
401411 product : str = name if isinstance (name , str ) else "UNKNOWN" # type: ignore
402- if isinstance (version , str ):
403- product += " " + version
404412
405413 yield program_id .strip ().strip ("\u0000 " ), _AmcacheEntry (
406414 AmcacheEntryType .Program .name ,
@@ -409,6 +417,7 @@ def parse_inventory_app_key(
409417 install_time = install_date ,
410418 product_name = product ,
411419 company = publisher ,
420+ product_version = version ,
412421 )
413422
414423 @classmethod
@@ -422,7 +431,9 @@ def parse_inventory_app_file_key(
422431 with it's parent `InventoryApplication` program entry, and the second member is the `Amcache` entry.
423432 """
424433
425- valName = Win10InvAppFileValName
434+ val_enum = Win10InvAppFileValName
435+
436+ wanted_values = [key .value for key in val_enum ]
426437
427438 for file_key in inv_app_file_key .get_subkeys ():
428439
@@ -433,23 +444,17 @@ def parse_inventory_app_file_key(
433444 values = {
434445 str (value .get_name ()): value
435446 for value in file_key .get_values ()
436- if value .get_name () in [ key . value for key in valName ]
447+ if value .get_name () in wanted_values
437448 }
438449
439450 last_mod = conversion .wintime_to_datetime (file_key .LastWriteTime .QuadPart )
440- path = _get_string_value (values , valName .LowerCaseLongPath .value )
441- linkdate = _get_datetime_str_value (values , valName .LinkDate .value )
442- sha1_hash = _get_string_value (values , valName .FileId .value )
443- publisher = _get_string_value (values , valName .Publisher .value )
444- prod_name = _get_string_value (values , valName .ProductName .value )
445- prod_ver = _get_string_value (values , valName .ProductVersion .value )
446- program_id = _get_string_value (values , valName .ProgramID .value )
447-
448- if isinstance (prod_ver , str ):
449- if isinstance (prod_name , str ):
450- prod_name = f"{ prod_name } { prod_ver } "
451- else :
452- prod_name = f"UNKNOWN { prod_ver } "
451+ path = _get_string_value (values , val_enum .LowerCaseLongPath .value )
452+ linkdate = _get_datetime_str_value (values , val_enum .LinkDate .value )
453+ sha1_hash = _get_string_value (values , val_enum .FileId .value )
454+ publisher = _get_string_value (values , val_enum .Publisher .value )
455+ prod_name = _get_string_value (values , val_enum .ProductName .value )
456+ prod_ver = _get_string_value (values , val_enum .ProductVersion .value )
457+ program_id = _get_string_value (values , val_enum .ProgramID .value )
453458
454459 yield program_id , _AmcacheEntry (
455460 AmcacheEntryType .File .name ,
@@ -463,6 +468,7 @@ def parse_inventory_app_file_key(
463468 else sha1_hash
464469 ),
465470 product_name = prod_name ,
471+ product_version = prod_ver ,
466472 )
467473
468474 @classmethod
@@ -474,34 +480,36 @@ def parse_driver_binary_key(
474480 :param driver_binary_key: The `Root\\ InventoryDriverBinary` registry key
475481 :return: An iterator of `AmcacheEntry`s
476482 """
477- for binary_key in driver_binary_key .get_subkeys ():
483+ val_enum = Win10DriverBinaryValName
484+
485+ wanted_values = [key .value for key in val_enum ]
478486
479- valName = Win10DriverBinaryValName
487+ for binary_key in driver_binary_key . get_subkeys ():
480488
481489 values = {
482490 str (value .get_name ()): value
483491 for value in binary_key .get_values ()
484- if value .get_name () in [ key . value for key in valName ]
492+ if value .get_name () in wanted_values
485493 }
486494
487495 # Depending on the Windows version, the key name will be either the name
488496 # of the driver, or its SHA1 hash.
489497 if "/" in binary_key .get_name ():
490498 driver_name = binary_key .get_name ()
491- sha1_hash = _get_string_value (values , valName .DriverId .name )
499+ sha1_hash = _get_string_value (values , val_enum .DriverId .name )
492500 else :
493501 sha1_hash = binary_key .get_name ()
494- driver_name = _get_string_value (values , valName .DriverName .name )
502+ driver_name = _get_string_value (values , val_enum .DriverName .name )
495503
496504 if isinstance (sha1_hash , str ):
497505 sha1_hash = sha1_hash [4 :] if sha1_hash .startswith ("0000" ) else sha1_hash
498506
499507 company , product , service , last_write_time , driver_timestamp = (
500- _get_string_value (values , valName .DriverCompany .name ),
501- _get_string_value (values , valName .Product .name ),
502- _get_string_value (values , valName .Service .name ),
508+ _get_string_value (values , val_enum .DriverCompany .name ),
509+ _get_string_value (values , val_enum .Product .name ),
510+ _get_string_value (values , val_enum .Service .name ),
503511 conversion .wintime_to_datetime (binary_key .LastWriteTime .QuadPart ),
504- _get_datetime_utc_epoch_value (values , valName .DriverTimeStamp .name ),
512+ _get_datetime_utc_epoch_value (values , val_enum .DriverTimeStamp .name ),
505513 )
506514
507515 yield _AmcacheEntry (
0 commit comments