Windows.Forensics.Amcache

The Amcache.hve is a registry artifact that stores metadata used by the OS’s application compatibility infrastructure to record metadata about binaries present on the system. This includes file paths, hashes, timestamps, and install/interaction information for executables and drivers.

NOTE: execution must be corroborated with additional artifacts.


name: Windows.Forensics.Amcache
author: Matthieu Chatelan, Yann Malherbe
description: |
  The Amcache.hve is a registry artifact that stores metadata
  used by the OS’s application compatibility infrastructure to 
  record metadata about binaries present on the system. This 
  includes file paths, hashes, timestamps, and install/interaction 
  information for executables and drivers. 
  
  NOTE: execution must be corroborated with additional artifacts.
  
reference:
    - https://www.ssi.gouv.fr/uploads/2019/01/anssi-coriin_2019-analysis_amcache.pdf
    - https://github.com/libyal/dtformats/blob/main/documentation/AMCache%20file%20(AMCache.hve)%20format.asciidoc

type: CLIENT

precondition: SELECT OS From info() where OS = 'windows'

parameters:
  - name: amCacheGlob
    default: "%SYSTEMROOT%/appcompat/Programs/Amcache.hve"
  - name: NTFS_CACHE_SIZE
    type: int
    default: 1000

  - name: File
    description: Version `From Windows 8/2012 to Windows 10 1709`. This key is constituted of several subkeys where each representing a volume GUID that contains subkeys looking like `Root\File\<GUID>\<MFTId>` 
    type: bool
    default: Y
    
  - name: Programs
    description: Version `From Windows 8/2012 to Windows 10 1709`, This key contains installed programs only in subkeys like `Root\Programs\<AppID>` which contains information about the PE in subkeys.
    type: bool
    default: Y
    
  - name: Generic
    description: Version `From Windows 8 to Windows 10 1507`, The Generic key contains one subkey named 0, which in turn contains one subkey per driver installed on the system. Each of these subkeys is actually named as the SHA-1 of the driver it represents, preceded by ’0000’ like `\Root\Generic\0\0000<SHA1>`
    type: bool
    default: Y
    
  - name: InventoryDriverBinary
    description: Version `From Windows 10 1607`, n this key, each entry is named after the SHA-1 of the driver, preceded by ’0000’, and the subkey representing the drivers.
    type: bool
    default: N
    
  - name: InventoryApplication
    description: Version `From Windows 10 1607`, This key contains the installation of a program and also programs installed via an AppXPackage.
    type: bool
    default: Y
    
  - name: InventoryDeviceContainer
    description: Version `From Windows 10 1607`, records OS devices such as bluetooth, printers, etc. Has links to DevicePnps
    type: bool
    default: N
    
  - name: InventoryDriverPackage
    description: Version `From Windows 10 1607`, records Package information that links to both DeviceContainers and DevicePnPs
    type: bool
    default: N
    
  - name: InventoryApplicationFile
    description: Version `From Windows 10 1607`, records EXE files that are part of a program.
    type: bool
    default: Y
    
  - name: InventoryDevicePnp
    description: Version `From Windows 10 1607`, records Plug and Play (PnP) devices such as bluetooth, USB, etc. More verbose details than those contained in DeviceContainers
    type: bool
    default: N
    
  - name: InventoryApplicationShortcut
    description: Version `From Windows 10 1709`, contains information about LNK files found on the computer in the Start Menu directory
    type: bool
    default: Y  
    
sources:
 - name: File
   query: |
      SELECT * FROM if(
        condition=File,
        then={
          SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, 
              query={
                SELECT get(item=scope(), member="100") As ProductId,
                       get(item=scope(), member="101") As SHA1,
                       get(item=scope(), member="15") As FullPath,
                       get(item=scope(), member="11") As ModificationTime,
                       get(item=scope(), member="12") As CreationTime,
                       Key.Mtime as LastModifiedKey
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/File/*/*',
                   accessor='raw_reg'
                )
              }
            )
        }
      ) 
      
 - name: Programs
   query: |
      SELECT * FROM if(
        condition=Programs,
        then={
            SELECT * FROM foreach(
          row={
            SELECT FullPath from glob(globs=expand(path=amCacheGlob))
          }, query={
                SELECT get(item=scope(), member="0") As Name,
                       get(item=scope(), member="1") As Version,
                       get(item=scope(), member="2") As Publisher,
                       get(item=scope(), member="a") As InstallationTime,
                       get(item=scope(), member="b") As UninstallationTime,
                       Key.Mtime as LastModifiedKey
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/Programs/*',
                   accessor='raw_reg'
                )
            })
        }
      ) 
      
 - name: Generic
   query: |
      SELECT * FROM if(
        condition=Generic,
        then={
            SELECT * FROM foreach(
          row={
            SELECT FullPath from glob(globs=expand(path=amCacheGlob))
          }, query={
                SELECT Key.Mtime as LastModifiedKey,
                       Key.OSPath.Path as SHA1
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/Generic/0/*',
                   accessor='raw_reg'
                )
            })
        }
      ) 

 - name: InventoryDriverBinary
   query: |
      SELECT * FROM if(
        condition=InventoryDriverBinary,
        then={
            SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, query={
                SELECT Key.Mtime as Timestamp,
                       DriverName,
                       DriverVersion,
                       Product,
                       ProductVersion,
                       DriverCompany,
                       Service,
                       DriverType,
                       DriverTimeStamp,
                       ImageSize, 
                       substr(str=DriverId, start=4, end=44) AS SHA1,
                       split(string=Key.OSPath.Path,sep='"')[1] as FullPath
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/InventoryDriverBinary/*',
                   accessor='raw_reg'
                )
            })
        }
      ) 

 - name: InventoryApplication
   query: |
      SELECT * FROM if(
        condition=InventoryApplication,
        then={
            SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, query={
                SELECT Key.Mtime as Timestamp,
                       Name,
                       PackageFullName,
                       Version,
                       Publisher,
                       Source AS SourceApp,
                       Type,
                       substr(str=ProgramInstanceId, start=4, end=44) AS SHA1,
                       ManifestPath,
                       InstallDate,
                       Language,
                       UninstallString
                       
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/InventoryApplication/*',
                   accessor='raw_reg'
                )
            })
        }
      )
      
 - name: InventoryDeviceContainer
   query: |
      SELECT * FROM if(
        condition=InventoryDeviceContainer,
        then={
            SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, query={
                SELECT Key.Mtime as Timestamp,
                       ModelName,
                       FriendlyName,
                       ModelNumber,
                       Manufacturer,
                       PrimaryCategory,
                       Categories,
                       ModelId
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/InventoryDeviceContainer/*',
                   accessor='raw_reg'
                )
            })
        }
      )

 - name: InventoryDriverPackage
   query: |
      SELECT * FROM if(
        condition=InventoryDriverPackage,
        then={
            SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, query={
                SELECT Key.Mtime as Timestamp,
                       SYSFILE,
                       Version,
                       Provider,
                       Date,
                       Class,
                       Directory,
                       ClassGuid
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/InventoryDriverPackage/*',
                   accessor='raw_reg'
                )
            })
        }
      )

 - name: InventoryApplicationFile
   query: |
      SELECT * FROM if(
        condition=InventoryApplicationFile,
        then={
            SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, query={
                SELECT Key.Mtime as Timestamp,
                       Name,
                       ProductName,
                       ProductVersion,
                       Size,
                       Usn,
                       substr(str=FileId, start=4, end=44) AS SHA1,
                       LowerCaseLongPath AS FullPath,
                       OriginalFileName,
                       BinaryType,
                       LinkDate,
                       AppxPackageFullName
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/InventoryApplicationFile/*',
                   accessor='raw_reg'
                )
            })
        }
      )
      
 - name: InventoryDevicePnp
   query: |
      SELECT * FROM if(
        condition=InventoryDevicePnp,
        then={
            SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, query={
                SELECT Key.Mtime as Timestamp,
                       DriverName,
                       Enumerator,
                       Model,
                       Manufacturer,
                       Description,
                       InstallDate,
                       ParentId,
                       MatchingId
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/InventoryDevicePnp/*',
                   accessor='raw_reg'
                )
            })
        }
      )
      
 - name: InventoryApplicationShortcut
   query: |
      SELECT * FROM if(
        condition=InventoryApplicationShortcut,
        then={
            SELECT * FROM foreach(
              row={
                SELECT FullPath from glob(globs=expand(path=amCacheGlob))
              }, query={
                SELECT Key.Mtime as Timestamp,
                       ShortcutPath
                FROM read_reg_key(
                   root=pathspec(DelegatePath=FullPath),
                   globs='/Root/InventoryApplicationShortcut/*',
                   accessor='raw_reg'
                )
            })
        }
      )