This artifact returns any binaries in the Windows/spool/drivers/** folders with an untrusted Authenticode entry.
It can be used to hunt for dll files droped during exploitation of CVE-2021-1675 - PrintNightmare.
To query all attached ntfs drives: check the AllDrives switch.
I have added several filters to uplift search capabilities from the original MFT artifact. Due to the multi-drive features, the MFTPath will output the MFT path of the entry.
Available filters include:
name: Windows.Detection.PrintNightmare
author: "Matt Green - @mgreen27"
description: |
This artifact returns any binaries in the Windows/spool/drivers/**
folders with an untrusted Authenticode entry.
It can be used to hunt for dll files droped during exploitation of
CVE-2021-1675 - PrintNightmare.
To query all attached ntfs drives: check the AllDrives switch.
I have added several filters to uplift search capabilities from the
original MFT artifact. Due to the multi-drive features, the MFTPath
will output the MFT path of the entry.
Available filters include:
- FullPath regex
- FileName regex
- Time bounds to select files with a timestamp within time ranges
- FileSize bounds
![Sample output](https://github.com/mgreen27/velociraptor-docs/raw/patch-5/content/exchange/artifacts/PrintNightmare.png)
parameters:
- name: MFTFilename
default: "C:/$MFT"
- name: Accessor
default: ntfs
type: hidden
- name: PathRegex
description: "Regex search over FullPath."
default: Windows/System32/spool/drivers
- name: FileRegex
description: "Regex search over File Name"
default: .
- name: AllAuthenticode
type: bool
description: "Show all binaries despite Authenticode trusted status (default shows only untrusted)."
- name: DateAfter
type: timestamp
description: "search for events after this date. YYYY-MM-DDTmm:hh:ssZ"
- name: DateBefore
type: timestamp
description: "search for events before this date. YYYY-MM-DDTmm:hh:ssZ"
- name: SizeMax
type: int64
description: "Entries in the MFT under this size in bytes."
- name: SizeMin
type: int64
description: "Entries in the MFT over this size in bytes."
- name: AllDrives
type: bool
description: "Select MFT search on all attached ntfs drives."
sources:
- query: |
-- time testing
LET time_test(stamp) =
if(condition= DateBefore AND DateAfter,
then= stamp < DateBefore AND stamp > DateAfter,
else=
if(condition=DateBefore,
then= stamp < DateBefore,
else=
if(condition= DateAfter,
then= stamp > DateAfter,
else= True
)))
-- find all ntfs drives
LET ntfs_drives = SELECT FullPath + '/$MFT'as Path
FROM glob(globs="/*", accessor="ntfs")
-- function returning MFT entries
LET mftsearch(MFTPath) = SELECT
split(sep='\\$',string=MFTPath)[0] + FullPath as FullPath,
InUse,FileName,FileSize,
dict(
Created0x10 = Created0x10,
LastModified0x10 = LastModified0x10,
LastRecordChange0x10 = LastRecordChange0x10,
LastAccess0x10 = LastAccess0x10
) as SI,
dict(
Created0x30 = Created0x10,
LastModified0x30 = LastModified0x10,
LastRecordChange0x30 = LastRecordChange0x10,
LastAccess0x30 = LastAccess0x10
) as FN
FROM parse_mft(filename=MFTPath, accessor=Accessor)
WHERE NOT IsDir
AND FullPath =~ PathRegex
AND FileName =~ FileRegex
AND if(condition=SizeMax,
then=FileSize < atoi(string=SizeMax),
else=TRUE)
AND if(condition=SizeMin,
then=FileSize > atoi(string=SizeMin),
else=TRUE)
AND
( time_test(stamp=Created0x10)
OR time_test(stamp=Created0x30)
OR time_test(stamp=LastModified0x10)
OR time_test(stamp=LastModified0x30)
OR time_test(stamp=LastRecordChange0x10)
OR time_test(stamp=LastRecordChange0x30)
OR time_test(stamp=LastAccess0x10)
OR time_test(stamp=LastAccess0x30))
-- include all attached drives
LET all_drives = SELECT * FROM foreach(row=ntfs_drives,
query={
SELECT *
FROM mftsearch(MFTPath=Path)
WHERE log(message="Processing " + Path)
})
-- return rows
SELECT *,
parse_pe(file=FullPath) as PE,
authenticode(filename=FullPath) as Authenticode,
hash(path=FullPath) as Hash
FROM if(condition=AllDrives,
then= all_drives,
else= {
SELECT * FROM mftsearch(MFTPath=MFTFilename)
})
WHERE PE
AND if(condition=AllAuthenticode,
then=TRUE,
else= NOT Authenticode.Trusted = 'trusted')