Skip to content

Commit

Permalink
Create TabState.yaml (Velocidex#805)
Browse files Browse the repository at this point in the history
Added TabState artifact to parse notepad TabState.
  • Loading branch information
mgreen27 authored Mar 3, 2024
1 parent 21970e9 commit 4d0dbe0
Showing 1 changed file with 81 additions and 0 deletions.
81 changes: 81 additions & 0 deletions content/exchange/artifacts/TabState.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Windows.Forensics.TabState
author: Matt Green - @mgreen27
description: |
This artifact parses notepad TabState files in available in Windows 11.
In Windows 11, notepad has implemented a feature to repopulate previously
open notepad tabs - both saved and unsaved. This data is stored on disk and
provides an interesting opportunity for DFIR practitioners.
reference:
- https://medium.com/@mahmoudsoheem/new-digital-forensics-artifact-from-windows-notepad-527645906b7b
- https://www.youtube.com/watch?v=zSSBbv2fc2s

type: CLIENT

parameters:
- name: TargetGlob
description: Target glob for notepad TabState bin files.
default: C:\Users\*\AppData\Local\Packages\Microsoft.WindowsNotepad_8wekyb3d8bbwe\LocalState\TabState\*.bin
- name: ContentRegex
description: Content filter regex to select which TabState files return a row.
type: regex
default: .
- name: FilenameRegex
description: Filter regex to select Saved filename path. ```^$``` returns only unsaved files.
type: regex
default: .
- name: UploadFile
description: If selected will upload TabState file.
type: bool

export: |
LET TSProfile = '''[
["TabState", 0, [
["__Magic", 0, "String", {"length": 3, "term_hex" : "FFFFFF" }],
["__Saved", 3, "char"],
["__FileNameSize", 4, "int8"],
["__Filename", 5, "String", {
encoding: "utf8",
length: "x=>x.__FileNameSize * 2",
term_hex : "000000",
}],
["Filename",0,"Value",{"value": "x=>if(condition= x.__Saved > 0, then=utf16(string=x.__Filename),else='')"}],
["__HeaderPrefix", "x=>5 + len(list=x.__Filename)", "String",{"term_hex": "0100", length: 1000, max_length: 1000}],
["__DataOffset",0,"Value",{ "value": "x=>5 + len(list=x.__Filename) + len(list=x.__HeaderPrefix)"}],
["__Data", "x=> x.__DataOffset + 5", "String", {
encoding: "utf8",
length: 100000,
max_length: 100000,
"term_hex" : "000000000000000000000000"
}],
["StateData",0,"Value",{ "value": "x=>utf16(string=x.__Data[:(len(list=x.__Data) - 5)])"}],
]]]'''
sources:
- precondition:
SELECT OS From info() where OS = 'windows'

query: |
LET results = SELECT OSPath, Name,Mtime,Atime,Ctime,Btime,
parse_binary(filename=OSPath,profile=TSProfile,struct='TabState') as Parsed
FROM glob(globs=expand(path=TargetGlob))
WHERE NOT IsDir
AND NOT OSPath =~'''\.(0|1)\.bin$'''
AND Parsed.StateData =~ ContentRegex
AND Parsed.Filename =~ FilenameRegex
SELECT
Name,Mtime,Atime,Ctime,Btime,
Parsed.Filename as SavedFilename,
Parsed.StateData as StateData,
OSPath
FROM if(condition= UploadFile,
then={
SELECT *, upload(file=OSPath) as Upload
FROM results
},
else= results )

0 comments on commit 4d0dbe0

Please sign in to comment.