From 4d0dbe0bd889bf0dcec17c4c61d55ba8aca0f882 Mon Sep 17 00:00:00 2001 From: Matthew Green Date: Sun, 3 Mar 2024 23:31:27 +1100 Subject: [PATCH] Create TabState.yaml (#805) Added TabState artifact to parse notepad TabState. --- content/exchange/artifacts/TabState.yaml | 81 ++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 content/exchange/artifacts/TabState.yaml diff --git a/content/exchange/artifacts/TabState.yaml b/content/exchange/artifacts/TabState.yaml new file mode 100644 index 00000000000..c67a229b1dd --- /dev/null +++ b/content/exchange/artifacts/TabState.yaml @@ -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 ) +