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'
)
})
}
)