├── LICENSE.md ├── UsnJrnl2Csv.au3 ├── changelog.txt ├── db-schema-bodyfile.sql ├── db-schema-log2timeline.sql ├── db-schema-usnjrnl.sql ├── import-sql ├── import-csv-bodyfile-usnjrnl.sql ├── import-csv-l2t-usnjrnl.sql └── import-csv-usnjrnl.sql ├── readme-usnjrnl2csv-mysql.txt └── readme.txt /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Joakim Schicht 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /UsnJrnl2Csv.au3: -------------------------------------------------------------------------------- 1 | #Region ;**** Directives created by AutoIt3Wrapper_GUI **** 2 | #AutoIt3Wrapper_Icon=C:\Program Files (x86)\AutoIt3\Icons\au3.ico 3 | #AutoIt3Wrapper_Outfile=UsnJrnl2Csv.exe 4 | #AutoIt3Wrapper_Outfile_x64=UsnJrnl2Csv64.exe 5 | #AutoIt3Wrapper_Compile_Both=y 6 | #AutoIt3Wrapper_UseX64=y 7 | #AutoIt3Wrapper_Change2CUI=y 8 | #AutoIt3Wrapper_Res_Comment=Parser for $UsnJrnl (NTFS) 9 | #AutoIt3Wrapper_Res_Description=Parser for $UsnJrnl (NTFS) 10 | #AutoIt3Wrapper_Res_Fileversion=1.0.0.24 11 | #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker 12 | #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 5 13 | #AutoIt3Wrapper_Run_Au3Stripper=y 14 | #Au3Stripper_Parameters=/sf /sv /rm /pe 15 | #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** 16 | 17 | #Include 18 | #Include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #Include 25 | 26 | Global $UsnJrnlCsv, $UsnJrnlCsvFile, $OutputPath = @ScriptDir, $TargetOutputPath = @ScriptDir, $UsnJrnlSqlFile, $DebugOutFile, $hDebugOutFile 27 | Global $de="|", $PrecisionSeparator=".", $PrecisionSeparator2="", $sOutputFile, $VerboseOn=false, $SurroundingQuotes=True, $PreviousUsn, $DoDefaultAll, $Dol2t, $DoBodyfile 28 | Global $_COMMON_KERNEL32DLL=DllOpen("kernel32.dll"), $File, $MaxPages, $CurrentPage, $WithQuotes, $EncodingWhenOpen=128 29 | Global $ProgressStatus, $ProgressUsnJrnl 30 | Global $begin, $ElapsedTime, $EntryCounter, $DoScanMode1=0, $DoScanMode=0, $DoNormalMode=1, $SectorSize=512, $ExtendedNameCheckChar=1, $ExtendedNameCheckWindows=1, $ExtendedNameCheckAll=1, $ExtendedTimestampCheck=1 31 | Global $tDelta = _WinTime_GetUTCToLocalFileTimeDelta() 32 | Global $DateTimeFormat,$ExampleTimestampVal = "01CD74B3150770B8",$TimestampPrecision=3, $UTCconfig 33 | Global $TimestampErrorVal = "0000-00-00 00:00:00" 34 | Global $USN_Page_Size = 4096, $Remainder="", $nBytes 35 | Global $VerifyFragment=0, $OutFragmentName="OutFragment.bin", $RebuiltFragment, $CleanUp=0 36 | Global $myctredit, $CheckUnicode, $checkl2t, $checkbodyfile, $checkdefaultall, $SeparatorInput, $checkquotes, $CheckExtendedNameCheckChar, $CheckExtendedNameCheckWindows, $CheckExtendedTimestampCheck 37 | Global $CharsToGrabDate, $CharStartTime, $CharsToGrabTime 38 | Global $GlobalStartOffset=0, $StartOffsetInput 39 | 40 | $Progversion = "UsnJrnl2Csv 1.0.0.24" 41 | If $cmdline[0] > 0 Then 42 | $CommandlineMode = True 43 | ConsoleWrite($Progversion & @CRLF) 44 | _GetInputParams() 45 | _Main() 46 | Else 47 | DllCall("kernel32.dll", "bool", "FreeConsole") 48 | $CommandlineMode = False 49 | 50 | $Form = GUICreate($Progversion, 700, 350, -1, -1) 51 | 52 | $LabelTimestampFormat = GUICtrlCreateLabel("Timestamp format:",20,20,90,20) 53 | $ComboTimestampFormat = GUICtrlCreateCombo("", 110, 20, 30, 25) 54 | $LabelTimestampPrecision = GUICtrlCreateLabel("Precision:",150,20,50,20) 55 | $ComboTimestampPrecision = GUICtrlCreateCombo("", 200, 20, 70, 25) 56 | 57 | $LabelPrecisionSeparator = GUICtrlCreateLabel("Precision separator:",280,20,100,20) 58 | $PrecisionSeparatorInput = GUICtrlCreateInput($PrecisionSeparator,380,20,15,20) 59 | $LabelPrecisionSeparator2 = GUICtrlCreateLabel("Precision separator2:",400,20,100,20) 60 | $PrecisionSeparatorInput2 = GUICtrlCreateInput($PrecisionSeparator2,505,20,15,20) 61 | 62 | $InputExampleTimestamp = GUICtrlCreateInput("",340,45,190,20) 63 | GUICtrlSetState($InputExampleTimestamp, $GUI_DISABLE) 64 | 65 | $Label1 = GUICtrlCreateLabel("Set decoded timestamps to specific region:",20,45,230,20) 66 | $Combo2 = GUICtrlCreateCombo("", 230, 45, 85, 25) 67 | 68 | $LabelSeparator = GUICtrlCreateLabel("Set separator:",20,70,70,20) 69 | $SeparatorInput = GUICtrlCreateInput($de,90,70,20,20) 70 | $SeparatorInput2 = GUICtrlCreateInput($de,120,70,30,20) 71 | GUICtrlSetState($SeparatorInput2, $GUI_DISABLE) 72 | $checkquotes = GUICtrlCreateCheckbox("Quotation mark", 180, 70, 90, 20) 73 | GUICtrlSetState($checkquotes, $GUI_UNCHECKED) 74 | $CheckUnicode = GUICtrlCreateCheckbox("Unicode", 180, 90, 60, 20) 75 | GUICtrlSetState($CheckUnicode, $GUI_CHECKED) 76 | 77 | ;$checkl2t = GUICtrlCreateCheckbox("log2timeline", 20, 100, 130, 20) 78 | $checkl2t = GUICtrlCreateRadio("log2timeline", 20, 100, 130, 20) 79 | ;GUICtrlSetState($checkl2t, $GUI_UNCHECKED) 80 | ;GUICtrlSetState($checkl2t, $GUI_DISABLE) 81 | ;$checkbodyfile = GUICtrlCreateCheckbox("bodyfile", 20, 120, 100, 20) 82 | $checkbodyfile = GUICtrlCreateRadio("bodyfile", 20, 120, 100, 20) 83 | ;GUICtrlSetState($checkbodyfile, $GUI_UNCHECKED) 84 | ;GUICtrlSetState($checkbodyfile, $GUI_DISABLE) 85 | ;$checkdefaultall = GUICtrlCreateCheckbox("dump everything", 20, 140, 130, 20) 86 | $checkdefaultall = GUICtrlCreateRadio("dump everything", 20, 140, 110, 20) 87 | ;GUICtrlSetState($checkdefaultall, $GUI_CHECKED) 88 | ;GUICtrlSetState($checkdefaultall, $GUI_DISABLE) 89 | 90 | $LabelBrokenData = GUICtrlCreateLabel("Broken data:",130,120,65,20) 91 | $CheckScanMode = GUICtrlCreateCheckbox("Scan mode", 200, 120, 80, 20) 92 | GUICtrlSetState($CheckScanMode, $GUI_UNCHECKED) 93 | 94 | $LabelBrokenData = GUICtrlCreateLabel("Data validation:",300,75,90,20) 95 | $CheckExtendedNameCheckChar = GUICtrlCreateCheckbox("Filename check Char", 390, 70, 120, 20) 96 | GUICtrlSetState($CheckExtendedNameCheckChar, $GUI_CHECKED) 97 | $CheckExtendedNameCheckWindows = GUICtrlCreateCheckbox("Filename check Windows", 390, 90, 150, 20) 98 | GUICtrlSetState($CheckExtendedNameCheckWindows, $GUI_CHECKED) 99 | $CheckExtendedTimestampCheck = GUICtrlCreateCheckbox("Timestamp check", 390, 110, 120, 20) 100 | GUICtrlSetState($CheckExtendedTimestampCheck, $GUI_CHECKED) 101 | 102 | $LabelUsnPageSize = GUICtrlCreateLabel("USN_PAGE_SIZE:",130,145,100,20) 103 | $UsnPageSizeInput = GUICtrlCreateInput($USN_Page_Size,230,145,40,20) 104 | 105 | $LabelTimestampError = GUICtrlCreateLabel("Timestamp ErrorVal:",290,145,100,20) 106 | $TimestampErrorInput = GUICtrlCreateInput($TimestampErrorVal,390,145,130,20) 107 | 108 | $ButtonOutput = GUICtrlCreateButton("Change Output", 580, 70, 100, 20) 109 | $ButtonInput = GUICtrlCreateButton("Browse $UsnJrnl", 580, 95, 100, 20) 110 | $ButtonStart = GUICtrlCreateButton("Start Parsing", 580, 120, 100, 20) 111 | 112 | $LabelUsnPageSize = GUICtrlCreateLabel("Offset:",525,145,40,20) 113 | $StartOffsetInput = GUICtrlCreateInput(0x0,570,145,120,20) 114 | 115 | $myctredit = GUICtrlCreateEdit("Current output folder: " & $outputpath & @CRLF, 0, 170, 700, 100, BitOR($ES_AUTOVSCROLL, $WS_VSCROLL, $ES_READONLY)) 116 | GUICtrlSetBkColor($myctredit, 0xFFFFFF) 117 | ;_GUICtrlEdit_SetLimitText($myctredit, 128000) 118 | 119 | _InjectTimeZoneInfo() 120 | _InjectTimestampFormat() 121 | _InjectTimestampPrecision() 122 | $PrecisionSeparator = GUICtrlRead($PrecisionSeparatorInput) 123 | $PrecisionSeparator2 = GUICtrlRead($PrecisionSeparatorInput2) 124 | _TranslateTimestamp() 125 | 126 | GUISetState(@SW_SHOW) 127 | 128 | While 1 129 | $nMsg = GUIGetMsg() 130 | Sleep(50) 131 | _TranslateSeparator() 132 | $PrecisionSeparator = GUICtrlRead($PrecisionSeparatorInput) 133 | $PrecisionSeparator2 = GUICtrlRead($PrecisionSeparatorInput2) 134 | _TranslateTimestamp() 135 | Select 136 | Case $nMsg = $ButtonOutput 137 | $TargetOutputPath = FileSelectFolder("Select output folder.", "", 7, $OutputPath) 138 | If Not @error then 139 | _DisplayInfo("New output folder: " & $TargetOutputPath & @CRLF) 140 | Else 141 | $TargetOutputPath = @ScriptDir 142 | EndIf 143 | Case $nMsg = $ButtonInput 144 | $File = FileOpenDialog("Select $UsnJrnl file",@ScriptDir,"All (*.*)") 145 | If Not @error Then _DisplayInfo("Input: " & $File & @CRLF) 146 | Case $nMsg = $ButtonStart 147 | _Main() 148 | GUICtrlSetState($checkl2t, $GUI_UNCHECKED) 149 | GUICtrlSetState($checkbodyfile, $GUI_UNCHECKED) 150 | GUICtrlSetState($checkdefaultall, $GUI_UNCHECKED) 151 | Case $nMsg = $GUI_EVENT_CLOSE 152 | Exit 153 | EndSelect 154 | WEnd 155 | EndIf 156 | 157 | Func _Main() 158 | $EntryCounter=0 159 | GUICtrlSetData($ProgressUsnJrnl, 0) 160 | 161 | If Not $CommandlineMode Then 162 | $CheckUnicode = GUICtrlRead($CheckUnicode) 163 | EndIf 164 | 165 | If $CheckUnicode = 1 Then 166 | $EncodingWhenOpen = BitOR($FO_OVERWRITE, $FO_UTF8) 167 | If Not $CommandlineMode Then _DisplayInfo("UNICODE configured" & @CRLF) 168 | Else 169 | $EncodingWhenOpen = BitOR($FO_OVERWRITE, $FO_ANSI) 170 | If Not $CommandlineMode Then _DisplayInfo("ANSI configured" & @CRLF) 171 | EndIf 172 | 173 | If Not $CommandlineMode Then 174 | If Int(GUICtrlRead($checkl2t) + GUICtrlRead($checkbodyfile) + GUICtrlRead($checkdefaultall)) <> 9 Then 175 | _DisplayInfo("Error: Output format must be set to 1 of the 3 options." & @CRLF) 176 | Return 177 | EndIf 178 | $Dol2t = False 179 | $DoBodyfile = False 180 | $DoDefaultAll = False 181 | If GUICtrlRead($checkl2t) = 1 Then 182 | $Dol2t = True 183 | ElseIf GUICtrlRead($checkbodyfile) = 1 Then 184 | $DoBodyfile = True 185 | ElseIf GUICtrlRead($checkdefaultall) = 1 Then 186 | $DoDefaultAll = True 187 | EndIf 188 | EndIf 189 | 190 | _CreateOutputStructureAndFiles() 191 | 192 | If Not $CommandlineMode Then 193 | If ($DateTimeFormat = 4 Or $DateTimeFormat = 5) And ($Dol2t Or $DoBodyfile) Then 194 | _DisplayInfo("Error: Timestamp format can't be 4 or 5 in combination with OutputFormat log2timeline and bodyfile" & @CRLF) 195 | Return 196 | EndIf 197 | EndIf 198 | 199 | If Not $CommandlineMode Then 200 | $de = GUICtrlRead($SeparatorInput) 201 | Else 202 | $de = $SeparatorInput 203 | EndIf 204 | 205 | If Not $CommandlineMode Then 206 | $GlobalStartOffset = GUICtrlRead($StartOffsetInput) 207 | Else 208 | $GlobalStartOffset = $StartOffsetInput 209 | EndIf 210 | 211 | 212 | If Not $CommandlineMode Then 213 | $TimestampErrorVal = GUICtrlRead($TimestampErrorInput) 214 | Else 215 | $TimestampErrorVal = $TimestampErrorVal 216 | EndIf 217 | 218 | If Not $CommandlineMode Then 219 | $USN_Page_Size = GUICtrlRead($UsnPageSizeInput) 220 | EndIf 221 | If Mod($USN_Page_Size,512) Then 222 | If Not $CommandlineMode Then 223 | _DisplayInfo("Error: USN_PAGE_SIZE must be a multiple of 512" & @CRLF) 224 | _DumpOutput("Error: USN_PAGE_SIZE must be a multiple of 512" & @CRLF) 225 | Return 226 | Else 227 | _DumpOutput("Error: USN_PAGE_SIZE must be a multiple of 512" & @CRLF) 228 | Exit 229 | EndIf 230 | EndIf 231 | 232 | If Not $CommandlineMode Then 233 | $tDelta = _GetUTCRegion(GUICtrlRead($Combo2))-$tDelta 234 | If @error Then 235 | _DisplayInfo("Error: Timezone configuration failed." & @CRLF) 236 | Return 237 | EndIf 238 | $tDelta = $tDelta*-1 ;Since delta is substracted from timestamp later on 239 | EndIf 240 | 241 | If $CommandlineMode Then 242 | $PrecisionSeparator = $PrecisionSeparator 243 | $PrecisionSeparator2 = $PrecisionSeparator2 244 | Else 245 | $PrecisionSeparator = GUICtrlRead($PrecisionSeparatorInput) 246 | $PrecisionSeparator2 = GUICtrlRead($PrecisionSeparatorInput2) 247 | EndIf 248 | If StringLen($PrecisionSeparator) <> 1 Then 249 | If Not $CommandlineMode Then _DisplayInfo("Error: Precision separator not set properly" & @crlf) 250 | _DumpOutput("Error: Precision separator not set properly" & @crlf) 251 | Return 252 | EndIf 253 | 254 | If $CommandlineMode Then 255 | $WithQuotes = $checkquotes 256 | Else 257 | $WithQuotes = GUICtrlRead($checkquotes) 258 | EndIf 259 | 260 | If $WithQuotes = 1 Then 261 | $WithQuotes=1 262 | Else 263 | $WithQuotes=0 264 | EndIf 265 | 266 | If $CommandlineMode Then 267 | $ExtendedNameCheckChar = $CheckExtendedNameCheckChar 268 | Else 269 | $ExtendedNameCheckChar = GUICtrlRead($CheckExtendedNameCheckChar) 270 | EndIf 271 | 272 | If $ExtendedNameCheckChar = 1 Then 273 | $ExtendedNameCheckChar=1 274 | Else 275 | $ExtendedNameCheckChar=0 276 | EndIf 277 | 278 | If $CommandlineMode Then 279 | $ExtendedNameCheckWindows = $CheckExtendedNameCheckWindows 280 | Else 281 | $ExtendedNameCheckWindows = GUICtrlRead($CheckExtendedNameCheckWindows) 282 | EndIf 283 | 284 | If $ExtendedNameCheckWindows = 1 Then 285 | $ExtendedNameCheckWindows=1 286 | Else 287 | $ExtendedNameCheckWindows=0 288 | EndIf 289 | 290 | If $ExtendedNameCheckChar And $ExtendedNameCheckWindows Then 291 | $ExtendedNameCheckAll = 1 292 | Else 293 | $ExtendedNameCheckAll = 0 294 | EndIf 295 | 296 | If $CommandlineMode Then 297 | $ExtendedTimestampCheck = $CheckExtendedTimestampCheck 298 | Else 299 | $ExtendedTimestampCheck = GUICtrlRead($CheckExtendedTimestampCheck) 300 | EndIf 301 | 302 | If $ExtendedTimestampCheck = 1 Then 303 | $ExtendedTimestampCheck=1 304 | Else 305 | $ExtendedTimestampCheck=0 306 | EndIf 307 | 308 | If Not FileExists($File) Then 309 | If Not $CommandlineMode Then _DisplayInfo("Error: No $UsnJrnl chosen for input" & @CRLF) 310 | _DumpOutput("Error: No $UsnJrnl chosen for input" & @CRLF) 311 | Return 312 | EndIf 313 | 314 | _DumpOutput("Using $UsnJrnl: " & $File & @CRLF) 315 | _DumpOutput("Quotes configuration: " & $WithQuotes & @CRLF) 316 | _DumpOutput("USN_PAGE_SIZE: " & $USN_Page_Size & @CRLF) 317 | _DumpOutput("UNICODE configuration: " & $CheckUnicode & @CRLF) 318 | _DumpOutput("Extended timestamp check: " & $ExtendedTimestampCheck & @CRLF) 319 | _DumpOutput("Extended filename check Windows: " & $ExtendedNameCheckWindows & @CRLF) 320 | _DumpOutput("Extended filename check Char: " & $ExtendedNameCheckChar & @CRLF) 321 | _DumpOutput("Start offset: " & $GlobalStartOffset & @CRLF) 322 | 323 | If Not $CommandlineMode Then 324 | If GUICtrlRead($CheckScanMode) = 1 Then 325 | $DoScanMode = 1 326 | $DoNormalMode = 0 327 | EndIf 328 | EndIf 329 | 330 | If $DoScanMode=0 Then 331 | $DoNormalMode=1 332 | EndIf 333 | 334 | _DumpOutput("Normal mode: " & $DoNormalMode & @CRLF) 335 | _DumpOutput("Scan mode: " & $DoScanMode & @CRLF) 336 | 337 | _DumpOutput("Using DateTime format: " & $DateTimeFormat & @CRLF) 338 | _DumpOutput("Using timestamp precision: " & $TimestampPrecision & @CRLF) 339 | _DumpOutput("Timestamps presented in UTC: " & $UTCconfig & @CRLF) 340 | _DumpOutput("Using precision separator: " & $PrecisionSeparator & @CRLF) 341 | ; _DumpOutput("------------------- END CONFIGURATION -----------------------" & @CRLF) 342 | 343 | 344 | _SetDateTimeFormats() 345 | 346 | Local $TSPrecisionFormatTransform = "" 347 | If $TimestampPrecision > 1 Then 348 | $TSPrecisionFormatTransform = $PrecisionSeparator & "%f" 349 | EndIf 350 | 351 | Local $TimestampFormatTransform 352 | If $DoDefaultAll Or $DoBodyfile Then 353 | ;usnrnl or bodyfile table 354 | 355 | Select 356 | Case $DateTimeFormat = 1 357 | $TimestampFormatTransform = "%Y%m%d%H%i%s" & $TSPrecisionFormatTransform 358 | Case $DateTimeFormat = 2 359 | $TimestampFormatTransform = "%m/%d/%Y %H:%i:%s" & $TSPrecisionFormatTransform 360 | Case $DateTimeFormat = 3 361 | $TimestampFormatTransform = "%d/%m/%Y %H:%i:%s" & $TSPrecisionFormatTransform 362 | Case $DateTimeFormat = 4 Or $DateTimeFormat = 5 363 | If $CommandlineMode Then 364 | ConsoleWrite("WARNING: Loading of sql into database with TSFormat 4 or 5 is not yet supported." & @CRLF) 365 | Else 366 | _DumpOutput("WARNING: Loading of sql into database with TSFormat 4 or 5 is not yet supported." & @CRLF) 367 | EndIf 368 | Case $DateTimeFormat = 6 369 | $TimestampFormatTransform = "%Y-%m-%d %H:%i:%s" & $TSPrecisionFormatTransform 370 | EndSelect 371 | _ReplaceStringInFile($UsnJrnlSqlFile, "__TimestampTransformationSyntax__", $TimestampFormatTransform) 372 | EndIf 373 | 374 | Local $DateFormatTransform, $TimeFormatTransform 375 | If $Dol2t Then 376 | ;log2timeline table 377 | Select 378 | Case $DateTimeFormat = 1 379 | $DateFormatTransform = "%Y%m%d" 380 | $TimeFormatTransform = "%H%i%s" 381 | Case $DateTimeFormat = 2 382 | $DateFormatTransform = "%m/%d/%Y" 383 | $TimeFormatTransform = "%H:%i:%s" 384 | Case $DateTimeFormat = 3 385 | $DateFormatTransform = "%d/%m/%Y" 386 | $TimeFormatTransform = "%H:%i:%s" 387 | Case $DateTimeFormat = 4 Or $DateTimeFormat = 5 388 | If $CommandlineMode Then 389 | ConsoleWrite("WARNING: Loading of sql into database with TSFormat 4 or 5 is not yet supported." & @CRLF) 390 | Else 391 | _DumpOutput("WARNING: Loading of sql into database with TSFormat 4 or 5 is not yet supported." & @CRLF) 392 | EndIf 393 | Case $DateTimeFormat = 6 394 | $DateFormatTransform = "%Y-%m-%d" 395 | $TimeFormatTransform = "%H:%i:%s" 396 | EndSelect 397 | _ReplaceStringInFile($UsnJrnlSqlFile, "__DateTransformationSyntax__", $DateFormatTransform) 398 | _ReplaceStringInFile($UsnJrnlSqlFile, "__TimeTransformationSyntax__", $TimeFormatTransform) 399 | EndIf 400 | 401 | $Progress = GUICtrlCreateLabel("Decoding $UsnJrnl info and writing to csv", 10, 280,540,20) 402 | GUICtrlSetFont($Progress, 12) 403 | $ProgressStatus = GUICtrlCreateLabel("", 10, 275, 520, 20) 404 | $ElapsedTime = GUICtrlCreateLabel("", 10, 290, 520, 20) 405 | $ProgressUsnJrnl = GUICtrlCreateProgress(0, 315, 700, 30) 406 | $begin = TimerInit() 407 | 408 | $hFile = _WinAPI_CreateFile("\\.\" & $File,2,2,7) 409 | If $hFile = 0 Then 410 | If Not $CommandlineMode Then _DisplayInfo("Error: Creating handle on file" & @CRLF) 411 | _DumpOutput("Error: Creating handle on file" & @CRLF) 412 | Return 413 | EndIf 414 | 415 | _WriteCSVHeader() 416 | 417 | $InputFileSize = _WinAPI_GetFileSizeEx($hFile) 418 | _DumpOutput("InputFileSize: " & $InputFileSize & " bytes" & @CRLF) 419 | $InputFileSize -= $GlobalStartOffset 420 | 421 | AdlibRegister("_UsnJrnlProgress", 1000) 422 | 423 | Select 424 | 425 | Case $DoNormalMode 426 | $tBuffer = DllStructCreate("byte[" & $USN_Page_Size & "]") 427 | $MaxPages = Ceiling($InputFileSize/$USN_Page_Size) 428 | For $i = 0 To $MaxPages-1 429 | $CurrentPage=$i 430 | _WinAPI_SetFilePointerEx($hFile, $GlobalStartOffset + ($i * $USN_Page_Size), $FILE_BEGIN) 431 | If $i = $MaxPages-1 Then $tBuffer = DllStructCreate("byte[" & $USN_Page_Size & "]") 432 | _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer), $USN_Page_Size, $nBytes) 433 | $RawPage = DllStructGetData($tBuffer, 1) 434 | $EntryCounter += _UsnProcessPage(StringMid($RawPage,3),$i*$USN_Page_Size,0) 435 | If Not Mod($i,1000) Then 436 | FileFlush($UsnJrnlCsv) 437 | EndIf 438 | Next 439 | 440 | Case $DoScanMode 441 | $ChunkSize = $SectorSize*100 442 | $tBuffer = DllStructCreate("byte[" & ($ChunkSize)+$SectorSize & "]") 443 | $MaxPages = Ceiling($InputFileSize/($ChunkSize)) 444 | For $i = 0 To $MaxPages-1 445 | $CurrentPage=$i 446 | _WinAPI_SetFilePointerEx($hFile, $GlobalStartOffset + ($i * $ChunkSize), $FILE_BEGIN) 447 | If $i = $MaxPages-1 Then $tBuffer = DllStructCreate("byte[" & ($ChunkSize)+$SectorSize & "]") 448 | _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer), ($ChunkSize)+$SectorSize, $nBytes) 449 | $RawPage = DllStructGetData($tBuffer, 1) 450 | $EntryCounter += _ScanModeUsnProcessPage2(StringMid($RawPage,3),$i*($ChunkSize),0,$ChunkSize) 451 | If Not Mod($i,1000) Then 452 | FileFlush($UsnJrnlCsv) 453 | EndIf 454 | Next 455 | 456 | EndSelect 457 | 458 | AdlibUnRegister("_UsnJrnlProgress") 459 | $MaxPages = $CurrentPage 460 | _UsnJrnlProgress() 461 | ProgressOff() 462 | 463 | _WinAPI_CloseHandle($hFile) 464 | FileFlush($UsnJrnlCsv) 465 | FileClose($UsnJrnlCsv) 466 | 467 | If $EntryCounter < 1 Then 468 | _DumpOutput("Error: No valid $UsnJrnl entries could be decoded." & @CRLF) 469 | If $CleanUp Then 470 | FileFlush($hDebugOutFile) 471 | FileClose($hDebugOutFile) 472 | FileDelete($UsnJrnlCsvFile) 473 | FileDelete($UsnJrnlSqlFile) 474 | FileDelete($DebugOutFile) 475 | Else 476 | FileMove($UsnJrnlCsvFile,$UsnJrnlCsvFile&".empty",1) 477 | _DumpOutput("Empty output: " & $UsnJrnlCsvFile & " is postfixed with .empty" & @CRLF) 478 | EndIf 479 | If Not $CommandlineMode Then 480 | _DisplayInfo("Error: No valid $UsnJrnl entries could be decoded." & @CRLF) 481 | Return 482 | Else 483 | Exit(1) 484 | EndIf 485 | EndIf 486 | 487 | If Not $CommandlineMode Then _DisplayInfo("Entries parsed: " & $EntryCounter & @CRLF) 488 | _DumpOutput("Entries parsed: " & $EntryCounter & @CRLF) 489 | If Not $CommandlineMode Then _DisplayInfo("Parsing finished in " & _WinAPI_StrFromTimeInterval(TimerDiff($begin)) & @CRLF) 490 | _DumpOutput("Parsing finished in " & _WinAPI_StrFromTimeInterval(TimerDiff($begin)) & @CRLF) 491 | 492 | FileFlush($hDebugOutFile) 493 | FileClose($hDebugOutFile) 494 | 495 | If $CleanUp Then 496 | FileDelete($UsnJrnlCsvFile) 497 | FileDelete($UsnJrnlSqlFile) 498 | FileDelete($DebugOutFile) 499 | EndIf 500 | Return 501 | EndFunc 502 | 503 | Func _UsnDecodeRecord($Record, $OffsetRecord) 504 | Local $DecodeOk=0, $TimestampOk=1 505 | $UsnJrnlRecordLength = StringMid($Record,1,8) 506 | $UsnJrnlRecordLength = Dec(_SwapEndian($UsnJrnlRecordLength),2) 507 | $UsnJrnlMajorVersion = StringMid($Record,9,4) 508 | $UsnJrnlMajorVersion = Dec(_SwapEndian($UsnJrnlMajorVersion),2) 509 | $UsnJrnlMinorVersion = StringMid($Record,13,4) 510 | $UsnJrnlMinorVersion = Dec(_SwapEndian($UsnJrnlMinorVersion),2) 511 | $UsnJrnlFileReferenceNumber = StringMid($Record,17,12) 512 | $UsnJrnlFileReferenceNumber = Dec(_SwapEndian($UsnJrnlFileReferenceNumber),2) 513 | $UsnJrnlMFTReferenceSeqNo = StringMid($Record,29,4) 514 | $UsnJrnlMFTReferenceSeqNo = Dec(_SwapEndian($UsnJrnlMFTReferenceSeqNo),2) 515 | $UsnJrnlParentFileReferenceNumber = StringMid($Record,33,12) 516 | $UsnJrnlParentFileReferenceNumber = Dec(_SwapEndian($UsnJrnlParentFileReferenceNumber),2) 517 | $UsnJrnlParentReferenceSeqNo = StringMid($Record,45,4) 518 | $UsnJrnlParentReferenceSeqNo = Dec(_SwapEndian($UsnJrnlParentReferenceSeqNo),2) 519 | $UsnJrnlUsn = StringMid($Record,49,16) 520 | $UsnJrnlUsn = Dec(_SwapEndian($UsnJrnlUsn),2) 521 | $UsnJrnlTimestamp = StringMid($Record,65,16) 522 | If $ExtendedTimestampCheck Then 523 | $UsnJrnlTimestampTmp = Dec(_SwapEndian($UsnJrnlTimestamp),2) 524 | If $UsnJrnlTimestampTmp < 112589990684262400 Or $UsnJrnlTimestampTmp > 139611588448485376 Then ;14 oktober 1957 - 31 mai 2043 525 | $TimestampOk=0 526 | Else 527 | $TimestampOk=1 528 | EndIf 529 | EndIf 530 | $UsnJrnlTimestamp = _DecodeTimestamp($UsnJrnlTimestamp) 531 | $UsnJrnlReason = StringMid($Record,81,8) 532 | $UsnJrnlReason = _DecodeReasonCodes("0x"&_SwapEndian($UsnJrnlReason)) 533 | $UsnJrnlSourceInfo = StringMid($Record,89,8) 534 | ; $UsnJrnlSourceInfo = _DecodeSourceInfoFlag("0x"&_SwapEndian($UsnJrnlSourceInfo)) 535 | $UsnJrnlSourceInfo = "0x"&_SwapEndian($UsnJrnlSourceInfo) 536 | $UsnJrnlSecurityId = StringMid($Record,97,8) 537 | $UsnJrnlSecurityId = Dec(_SwapEndian($UsnJrnlSecurityId),2) 538 | $UsnJrnlFileAttributes = StringMid($Record,105,8) 539 | $UsnJrnlFileAttributes = _File_Attributes("0x"&_SwapEndian($UsnJrnlFileAttributes)) 540 | $UsnJrnlFileNameLength = StringMid($Record,113,4) 541 | $UsnJrnlFileNameLength = Dec(_SwapEndian($UsnJrnlFileNameLength),2) 542 | ; $UsnJrnlFileNameOffset = StringMid($Record,117,4) 543 | ; $UsnJrnlFileNameOffset = Dec(_SwapEndian($UsnJrnlFileNameOffset),2) 544 | $UsnJrnlFileName = StringMid($Record,121,$UsnJrnlFileNameLength*2) 545 | $UsnJrnlFileName = BinaryToString("0x"&$UsnJrnlFileName,2) 546 | #cs 547 | If $VerboseOn Then 548 | _DumpOutput("$UsnJrnlMajorVersion: " & $UsnJrnlMajorVersion & @CRLF) 549 | _DumpOutput("$UsnJrnlMinorVersion: " & $UsnJrnlMinorVersion & @CRLF) 550 | _DumpOutput("$UsnJrnlFileReferenceNumber: " & $UsnJrnlFileReferenceNumber & @CRLF) 551 | _DumpOutput("$UsnJrnlMFTReferenceSeqNo: " & $UsnJrnlMFTReferenceSeqNo & @CRLF) 552 | _DumpOutput("$UsnJrnlParentFileReferenceNumber: " & $UsnJrnlParentFileReferenceNumber & @CRLF) 553 | _DumpOutput("$UsnJrnlParentReferenceSeqNo: " & $UsnJrnlParentReferenceSeqNo & @CRLF) 554 | _DumpOutput("$UsnJrnlUsn: " & $UsnJrnlUsn & @CRLF) 555 | _DumpOutput("$UsnJrnlTimestamp: " & $UsnJrnlTimestamp & @CRLF) 556 | _DumpOutput("$UsnJrnlReason: " & $UsnJrnlReason & @CRLF) 557 | _DumpOutput("$UsnJrnlSourceInfo: " & $UsnJrnlSourceInfo & @CRLF) 558 | _DumpOutput("$UsnJrnlSecurityId: " & $UsnJrnlSecurityId & @CRLF) 559 | _DumpOutput("$UsnJrnlFileAttributes: " & $UsnJrnlFileAttributes & @CRLF) 560 | _DumpOutput("$UsnJrnlFileName: " & $UsnJrnlFileName & @CRLF) 561 | EndIf 562 | #ce 563 | If $USN_Page_Size > $UsnJrnlRecordLength And Int($UsnJrnlFileReferenceNumber) > 0 And Int($UsnJrnlMFTReferenceSeqNo) > 0 And Int($UsnJrnlParentFileReferenceNumber) > 4 And $UsnJrnlFileNameLength > 0 And $TimestampOk And $UsnJrnlTimestamp <> $TimestampErrorVal Then 564 | $DecodeOk=1 565 | If $VerifyFragment Then 566 | $RebuiltFragment = "0x" & StringMid($Record,1,120 + ($UsnJrnlFileNameLength*2)) 567 | ;ConsoleWrite(_HexEncode($RebuiltFragment) & @CRLF) 568 | _WriteOutputFragment() 569 | If @error Then 570 | If Not $CommandlineMode Then 571 | _DisplayInfo("Output fragment was verified but could not be written to: " & $OutputPath & "\" & $OutFragmentName & @CRLF) 572 | Return SetError(1) 573 | Else 574 | _DumpOutput("Output fragment was verified but could not be written to: " & $OutputPath & "\" & $OutFragmentName & @CRLF) 575 | Exit(4) 576 | EndIf 577 | Else 578 | ConsoleWrite("Output fragment verified and written to: " & $OutputPath & "\" & $OutFragmentName & @CRLF) 579 | EndIf 580 | Else 581 | If $WithQuotes Then 582 | Select 583 | Case $DoDefaultAll 584 | FileWriteLine($UsnJrnlCsv, '"'&$OffsetRecord&'"'&$de&'"'&$UsnJrnlFileName&'"'&$de&'"'&$UsnJrnlUsn&'"'&$de&'"'&$UsnJrnlTimestamp&'"'&$de&'"'&$UsnJrnlReason&'"'&$de&'"'&$UsnJrnlFileReferenceNumber&'"'&$de&'"'&$UsnJrnlMFTReferenceSeqNo&'"'&$de&'"'&$UsnJrnlParentFileReferenceNumber&'"'&$de&'"'&$UsnJrnlParentReferenceSeqNo&'"'&$de&'"'&$UsnJrnlFileAttributes&'"'&$de&'"'&$UsnJrnlMajorVersion&'"'&$de&'"'&$UsnJrnlMinorVersion&'"'&$de&'"'&$UsnJrnlSourceInfo&'"'&$de&'"'&$UsnJrnlSecurityId&'"'&@CRLF) 585 | Case $Dol2t 586 | FileWriteLine($UsnJrnlCsv, '"'&'"'&StringLeft($UsnJrnlTimestamp,$CharsToGrabDate)&'"' & $de & '"'&StringMid($UsnJrnlTimestamp,$CharStartTime,$CharsToGrabTime)&'"' & $de & '"'&$UTCconfig&'"' & $de & '"'&"MACB"&'"' & $de & '"'&"UsnJrnl"&'"' & $de & '"'&"UsnJrnl:J"&'"' & $de & '"'&$UsnJrnlReason&'"' & $de & '""' & $de & '""' & $de & '""' & $de & '""' & $de & '""' & $de & '"'&$UsnJrnlFileName&'"' & $de & '"'&$UsnJrnlFileReferenceNumber&'"' & $de & '"'&"Offset:"&$OffsetRecord&" Usn:"&$UsnJrnlUsn&" MftRef:"&$UsnJrnlFileReferenceNumber&" MftRefSeqNo:"&$UsnJrnlMFTReferenceSeqNo&" ParentMftRef:"&$UsnJrnlParentFileReferenceNumber&" ParentMftRefSeqNo:"&$UsnJrnlParentReferenceSeqNo&" FileAttr:"&$UsnJrnlFileAttributes&'"' & $de & '""' & $de & '""' & @CRLF) 587 | Case $DoBodyfile 588 | FileWriteLine($UsnJrnlCsv, '""' & $de & '"'&$UsnJrnlFileName&'"' & $de & '"'&$UsnJrnlFileReferenceNumber&'"' & $de & '"'&"UsnJrnl"&'"' & $de & '""' & $de & '""' & $de & '""' & $de & '"'&$UsnJrnlTimestamp&'"' & $de & '"'&$UsnJrnlTimestamp&'"' & $de & '"'&$UsnJrnlTimestamp&'"' & $de & '"'&$UsnJrnlTimestamp&'"' & @CRLF) 589 | EndSelect 590 | Else 591 | Select 592 | Case $DoDefaultAll 593 | FileWriteLine($UsnJrnlCsv, $OffsetRecord&$de&$UsnJrnlFileName&$de&$UsnJrnlUsn&$de&$UsnJrnlTimestamp&$de&$UsnJrnlReason&$de&$UsnJrnlFileReferenceNumber&$de&$UsnJrnlMFTReferenceSeqNo&$de&$UsnJrnlParentFileReferenceNumber&$de&$UsnJrnlParentReferenceSeqNo&$de&$UsnJrnlFileAttributes&$de&$UsnJrnlMajorVersion&$de&$UsnJrnlMinorVersion&$de&$UsnJrnlSourceInfo&$de&$UsnJrnlSecurityId&@crlf) 594 | Case $Dol2t 595 | FileWriteLine($UsnJrnlCsv, StringLeft($UsnJrnlTimestamp,$CharsToGrabDate) & $de & StringMid($UsnJrnlTimestamp,$CharStartTime,$CharsToGrabTime) & $de & $UTCconfig & $de & "MACB" & $de & "UsnJrnl" & $de & "UsnJrnl:J" & $de & $UsnJrnlReason & $de & "" & $de & "" & $de & "" & $de & "" & $de & "" & $de & $UsnJrnlFileName & $de & $UsnJrnlFileReferenceNumber & $de & "Offset:"&$OffsetRecord&" Usn:"&$UsnJrnlUsn&" MftRef:"&$UsnJrnlFileReferenceNumber&" MftRefSeqNo:"&$UsnJrnlMFTReferenceSeqNo&" ParentMftRef:"&$UsnJrnlParentFileReferenceNumber&" ParentMftRefSeqNo:"&$UsnJrnlParentReferenceSeqNo&" FileAttr:"&$UsnJrnlFileAttributes & $de & "" & $de & "" & @CRLF) 596 | Case $DoBodyfile 597 | FileWriteLine($UsnJrnlCsv, "" & $de & $UsnJrnlFileName & $de & $UsnJrnlFileReferenceNumber & $de & "UsnJrnl" & $de & "" & $de & "" & $de & "" & $de & $UsnJrnlTimestamp & $de & $UsnJrnlTimestamp & $de & $UsnJrnlTimestamp & $de & $UsnJrnlTimestamp & @CRLF) 598 | EndSelect 599 | EndIf 600 | EndIf 601 | Else 602 | _DumpOutput("Error: Bad entry at offset " & $OffsetRecord & ":" & @CRLF) 603 | ; _DumpOutput(_HexEncode("0x"&$Record) & @CRLF) 604 | EndIf 605 | Return $DecodeOk 606 | EndFunc 607 | 608 | Func _DecodeReasonCodes($USNReasonInput) 609 | ;ntifs.h 610 | Local $USNReasonOutput = "" 611 | If BitAND($USNReasonInput, 0x00008000) Then $USNReasonOutput &= 'BASIC_INFO_CHANGE+' 612 | If BitAND($USNReasonInput, 0x80000000) Then $USNReasonOutput &= 'CLOSE+' 613 | If BitAND($USNReasonInput, 0x00020000) Then $USNReasonOutput &= 'COMPRESSION_CHANGE+' 614 | If BitAND($USNReasonInput, 0x00000002) Then $USNReasonOutput &= 'DATA_EXTEND+' 615 | If BitAND($USNReasonInput, 0x00000001) Then $USNReasonOutput &= 'DATA_OVERWRITE+' 616 | If BitAND($USNReasonInput, 0x00000004) Then $USNReasonOutput &= 'DATA_TRUNCATION+' 617 | If BitAND($USNReasonInput, 0x00000400) Then $USNReasonOutput &= 'EA_CHANGE+' 618 | If BitAND($USNReasonInput, 0x00040000) Then $USNReasonOutput &= 'ENCRYPTION_CHANGE+' 619 | If BitAND($USNReasonInput, 0x00000100) Then $USNReasonOutput &= 'FILE_CREATE+' 620 | If BitAND($USNReasonInput, 0x00000200) Then $USNReasonOutput &= 'FILE_DELETE+' 621 | If BitAND($USNReasonInput, 0x00010000) Then $USNReasonOutput &= 'HARD_LINK_CHANGE+' 622 | If BitAND($USNReasonInput, 0x00004000) Then $USNReasonOutput &= 'INDEXABLE_CHANGE+' 623 | If BitAND($USNReasonInput, 0x00000020) Then $USNReasonOutput &= 'NAMED_DATA_EXTEND+' 624 | If BitAND($USNReasonInput, 0x00000010) Then $USNReasonOutput &= 'NAMED_DATA_OVERWRITE+' 625 | If BitAND($USNReasonInput, 0x00000040) Then $USNReasonOutput &= 'NAMED_DATA_TRUNCATION+' 626 | If BitAND($USNReasonInput, 0x00080000) Then $USNReasonOutput &= 'OBJECT_ID_CHANGE+' 627 | If BitAND($USNReasonInput, 0x00002000) Then $USNReasonOutput &= 'RENAME_NEW_NAME+' 628 | If BitAND($USNReasonInput, 0x00001000) Then $USNReasonOutput &= 'RENAME_OLD_NAME+' 629 | If BitAND($USNReasonInput, 0x00100000) Then $USNReasonOutput &= 'REPARSE_POINT_CHANGE+' 630 | If BitAND($USNReasonInput, 0x00000800) Then $USNReasonOutput &= 'SECURITY_CHANGE+' 631 | If BitAND($USNReasonInput, 0x00200000) Then $USNReasonOutput &= 'STREAM_CHANGE+' 632 | If BitAND($USNReasonInput, 0x00800000) Then $USNReasonOutput &= 'INTEGRITY_CHANGE+' 633 | If BitAND($USNReasonInput, 0x00400000) Then $USNReasonOutput &= 'TRANSACTED_CHANGE+' 634 | If BitAND($USNReasonInput, 0x01000000) Then $USNReasonOutput &= 'DESIRED_STORAGE_CLASS_CHANGE+' 635 | $USNReasonOutput = StringTrimRight($USNReasonOutput, 1) 636 | Return $USNReasonOutput 637 | EndFunc 638 | 639 | Func _File_Attributes($FAInput) 640 | Local $FAOutput = "" 641 | If BitAND($FAInput, 0x0001) Then $FAOutput &= 'read_only+' 642 | If BitAND($FAInput, 0x0002) Then $FAOutput &= 'hidden+' 643 | If BitAND($FAInput, 0x0004) Then $FAOutput &= 'system+' 644 | If BitAND($FAInput, 0x0010) Then $FAOutput &= 'directory+' 645 | If BitAND($FAInput, 0x0020) Then $FAOutput &= 'archive+' 646 | If BitAND($FAInput, 0x0040) Then $FAOutput &= 'device+' 647 | If BitAND($FAInput, 0x0080) Then $FAOutput &= 'normal+' 648 | If BitAND($FAInput, 0x0100) Then $FAOutput &= 'temporary+' 649 | If BitAND($FAInput, 0x0200) Then $FAOutput &= 'sparse_file+' 650 | If BitAND($FAInput, 0x0400) Then $FAOutput &= 'reparse_point+' 651 | If BitAND($FAInput, 0x0800) Then $FAOutput &= 'compressed+' 652 | If BitAND($FAInput, 0x1000) Then $FAOutput &= 'offline+' 653 | If BitAND($FAInput, 0x2000) Then $FAOutput &= 'not_indexed+' 654 | If BitAND($FAInput, 0x4000) Then $FAOutput &= 'encrypted+' 655 | If BitAND($FAInput, 0x8000) Then $FAOutput &= 'integrity_stream+' 656 | If BitAND($FAInput, 0x10000) Then $FAOutput &= 'virtual+' 657 | If BitAND($FAInput, 0x20000) Then $FAOutput &= 'no_scrub_data+' 658 | If BitAND($FAInput, 0x10000000) Then $FAOutput &= 'directory+' 659 | If BitAND($FAInput, 0x20000000) Then $FAOutput &= 'index_view+' 660 | $FAOutput = StringTrimRight($FAOutput, 1) 661 | Return $FAOutput 662 | EndFunc 663 | 664 | Func _DecodeSourceInfoFlag($input) 665 | Select 666 | Case $input = 0x00000001 667 | $ret = "USN_SOURCE_DATA_MANAGEMENT" 668 | Case $input = 0x00000002 669 | $ret = "USN_SOURCE_AUXILIARY_DATA" 670 | Case $input = 0x00000004 671 | $ret = "USN_SOURCE_REPLICATION_MANAGEMENT" 672 | Case $input = 0x00000008 673 | $ret = "USN_SOURCE_CLIENT_REPLICATION_MANAGEMENT" 674 | Case Else 675 | $ret = "EMPTY" 676 | EndSelect 677 | Return $ret 678 | EndFunc 679 | 680 | Func _DecodeTimestamp($StampDecode) 681 | $StampDecode = _SwapEndian($StampDecode) 682 | $StampDecode_tmp = _WinTime_UTCFileTimeToLocalFileTime("0x" & $StampDecode) 683 | $StampDecode = _WinTime_UTCFileTimeFormat(Dec($StampDecode,2) - $tDelta, $DateTimeFormat, $TimestampPrecision) 684 | If @error Then 685 | $StampDecode = $TimestampErrorVal 686 | ElseIf $TimestampPrecision = 3 Then 687 | $StampDecode = $StampDecode & $PrecisionSeparator2 & _FillZero(StringRight($StampDecode_tmp, 4)) 688 | EndIf 689 | Return $StampDecode 690 | EndFunc 691 | 692 | Func _SwapEndian($iHex) 693 | Return StringMid(Binary(Dec($iHex,2)),3, StringLen($iHex)) 694 | EndFunc 695 | 696 | Func _FillZero($inp) 697 | Local $inplen, $out, $tmp = "" 698 | $inplen = StringLen($inp) 699 | For $i = 1 To 4 - $inplen 700 | $tmp &= "0" 701 | Next 702 | $out = $tmp & $inp 703 | Return $out 704 | EndFunc ;==>_FillZero 705 | 706 | Func _HexEncode($bInput) 707 | Local $tInput = DllStructCreate("byte[" & BinaryLen($bInput) & "]") 708 | DllStructSetData($tInput, 1, $bInput) 709 | Local $a_iCall = DllCall("crypt32.dll", "int", "CryptBinaryToString", _ 710 | "ptr", DllStructGetPtr($tInput), _ 711 | "dword", DllStructGetSize($tInput), _ 712 | "dword", 11, _ 713 | "ptr", 0, _ 714 | "dword*", 0) 715 | 716 | If @error Or Not $a_iCall[0] Then 717 | Return SetError(1, 0, "") 718 | EndIf 719 | Local $iSize = $a_iCall[5] 720 | Local $tOut = DllStructCreate("char[" & $iSize & "]") 721 | $a_iCall = DllCall("crypt32.dll", "int", "CryptBinaryToString", _ 722 | "ptr", DllStructGetPtr($tInput), _ 723 | "dword", DllStructGetSize($tInput), _ 724 | "dword", 11, _ 725 | "ptr", DllStructGetPtr($tOut), _ 726 | "dword*", $iSize) 727 | If @error Or Not $a_iCall[0] Then 728 | Return SetError(2, 0, "") 729 | EndIf 730 | Return SetError(0, 0, DllStructGetData($tOut, 1)) 731 | EndFunc 732 | 733 | Func _WinTime_GetUTCToLocalFileTimeDelta() 734 | Local $iUTCFileTime=864000000000 ; exactly 24 hours from the origin (although 12 hours would be more appropriate (max variance = 12)) 735 | $iLocalFileTime=_WinTime_UTCFileTimeToLocalFileTime($iUTCFileTime) 736 | If @error Then Return SetError(@error,@extended,-1) 737 | Return $iLocalFileTime-$iUTCFileTime ; /36000000000 = # hours delta (effectively giving the offset in hours from UTC/GMT) 738 | EndFunc 739 | 740 | Func _WinTime_UTCFileTimeToLocalFileTime($iUTCFileTime) 741 | If $iUTCFileTime<0 Then Return SetError(1,0,-1) 742 | Local $aRet=DllCall($_COMMON_KERNEL32DLL,"bool","FileTimeToLocalFileTime","uint64*",$iUTCFileTime,"uint64*",0) 743 | If @error Then Return SetError(2,@error,-1) 744 | If Not $aRet[0] Then Return SetError(3,0,-1) 745 | Return $aRet[2] 746 | EndFunc 747 | 748 | Func _WinTime_UTCFileTimeFormat($iUTCFileTime,$iFormat=4,$iPrecision=0,$bAMPMConversion=False) 749 | ;~ If $iUTCFileTime<0 Then Return SetError(1,0,"") ; checked in below call 750 | 751 | ; First convert file time (UTC-based file time) to 'local file time' 752 | Local $iLocalFileTime=_WinTime_UTCFileTimeToLocalFileTime($iUTCFileTime) 753 | If @error Then Return SetError(@error,@extended,"") 754 | ; Rare occassion: a filetime near the origin (January 1, 1601!!) is used, 755 | ; causing a negative result (for some timezones). Return as invalid param. 756 | If $iLocalFileTime<0 Then Return SetError(1,0,"") 757 | 758 | ; Then convert file time to a system time array & format & return it 759 | Local $vReturn=_WinTime_LocalFileTimeFormat($iLocalFileTime,$iFormat,$iPrecision,$bAMPMConversion) 760 | Return SetError(@error,@extended,$vReturn) 761 | EndFunc 762 | 763 | Func _WinTime_LocalFileTimeFormat($iLocalFileTime,$iFormat=4,$iPrecision=0,$bAMPMConversion=False) 764 | ;~ If $iLocalFileTime<0 Then Return SetError(1,0,"") ; checked in below call 765 | 766 | ; Convert file time to a system time array & return result 767 | Local $aSysTime=_WinTime_LocalFileTimeToSystemTime($iLocalFileTime) 768 | If @error Then Return SetError(@error,@extended,"") 769 | 770 | ; Return only the SystemTime array? 771 | If $iFormat=0 Then Return $aSysTime 772 | 773 | Local $vReturn=_WinTime_FormatTime($aSysTime[0],$aSysTime[1],$aSysTime[2],$aSysTime[3], _ 774 | $aSysTime[4],$aSysTime[5],$aSysTime[6],$aSysTime[7],$iFormat,$iPrecision,$bAMPMConversion) 775 | Return SetError(@error,@extended,$vReturn) 776 | EndFunc 777 | 778 | Func _WinTime_LocalFileTimeToSystemTime($iLocalFileTime) 779 | Local $aRet,$stSysTime,$aSysTime[8]=[-1,-1,-1,-1,-1,-1,-1,-1] 780 | 781 | ; Negative values unacceptable 782 | If $iLocalFileTime<0 Then Return SetError(1,0,$aSysTime) 783 | 784 | ; SYSTEMTIME structure [Year,Month,DayOfWeek,Day,Hour,Min,Sec,Milliseconds] 785 | $stSysTime=DllStructCreate("ushort[8]") 786 | 787 | $aRet=DllCall($_COMMON_KERNEL32DLL,"bool","FileTimeToSystemTime","uint64*",$iLocalFileTime,"ptr",DllStructGetPtr($stSysTime)) 788 | If @error Then Return SetError(2,@error,$aSysTime) 789 | If Not $aRet[0] Then Return SetError(3,0,$aSysTime) 790 | Dim $aSysTime[8]=[DllStructGetData($stSysTime,1,1),DllStructGetData($stSysTime,1,2),DllStructGetData($stSysTime,1,4),DllStructGetData($stSysTime,1,5), _ 791 | DllStructGetData($stSysTime,1,6),DllStructGetData($stSysTime,1,7),DllStructGetData($stSysTime,1,8),DllStructGetData($stSysTime,1,3)] 792 | Return $aSysTime 793 | EndFunc 794 | 795 | Func _WinTime_FormatTime($iYear,$iMonth,$iDay,$iHour,$iMin,$iSec,$iMilSec,$iDayOfWeek,$iFormat=4,$iPrecision=0,$bAMPMConversion=False) 796 | Local Static $_WT_aMonths[12]=["January","February","March","April","May","June","July","August","September","October","November","December"] 797 | Local Static $_WT_aDays[7]=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"] 798 | 799 | If Not $iFormat Or $iMonth<1 Or $iMonth>12 Or $iDayOfWeek>6 Then Return SetError(1,0,"") 800 | 801 | ; Pad MM,DD,HH,MM,SS,MSMSMSMS as necessary 802 | Local $sMM=StringRight(0&$iMonth,2),$sDD=StringRight(0&$iDay,2),$sMin=StringRight(0&$iMin,2) 803 | ; $sYY = $iYear ; (no padding) 804 | ; [technically Year can be 1-x chars - but this is generally used for 4-digit years. And SystemTime only goes up to 30827/30828] 805 | Local $sHH,$sSS,$sMS,$sAMPM 806 | 807 | ; 'Extra precision 1': +SS (Seconds) 808 | If $iPrecision Then 809 | $sSS=StringRight(0&$iSec,2) 810 | ; 'Extra precision 2': +MSMSMSMS (Milliseconds) 811 | If $iPrecision>1 Then 812 | ; $sMS=StringRight('000'&$iMilSec,4) 813 | $sMS=StringRight('000'&$iMilSec,3);Fixed an erronous 0 in front of the milliseconds 814 | Else 815 | $sMS="" 816 | EndIf 817 | Else 818 | $sSS="" 819 | $sMS="" 820 | EndIf 821 | If $bAMPMConversion Then 822 | If $iHour>11 Then 823 | $sAMPM=" PM" 824 | ; 12 PM will cause 12-12 to equal 0, so avoid the calculation: 825 | If $iHour=12 Then 826 | $sHH="12" 827 | Else 828 | $sHH=StringRight(0&($iHour-12),2) 829 | EndIf 830 | Else 831 | $sAMPM=" AM" 832 | If $iHour Then 833 | $sHH=StringRight(0&$iHour,2) 834 | Else 835 | ; 00 military = 12 AM 836 | $sHH="12" 837 | EndIf 838 | EndIf 839 | Else 840 | $sAMPM="" 841 | $sHH=StringRight(0 & $iHour,2) 842 | EndIf 843 | 844 | Local $sDateTimeStr,$aReturnArray[3] 845 | 846 | ; Return an array? [formatted string + "Month" + "DayOfWeek"] 847 | If BitAND($iFormat,0x10) Then 848 | $aReturnArray[1]=$_WT_aMonths[$iMonth-1] 849 | If $iDayOfWeek>=0 Then 850 | $aReturnArray[2]=$_WT_aDays[$iDayOfWeek] 851 | Else 852 | $aReturnArray[2]="" 853 | EndIf 854 | ; Strip the 'array' bit off (array[1] will now indicate if an array is to be returned) 855 | $iFormat=BitAND($iFormat,0xF) 856 | Else 857 | ; Signal to below that the array isn't to be returned 858 | $aReturnArray[1]="" 859 | EndIf 860 | 861 | ; Prefix with "DayOfWeek "? 862 | If BitAND($iFormat,8) Then 863 | If $iDayOfWeek<0 Then Return SetError(1,0,"") ; invalid 864 | $sDateTimeStr=$_WT_aDays[$iDayOfWeek]&', ' 865 | ; Strip the 'DayOfWeek' bit off 866 | $iFormat=BitAND($iFormat,0x7) 867 | Else 868 | $sDateTimeStr="" 869 | EndIf 870 | 871 | If $iFormat<2 Then 872 | ; Basic String format: YYYYMMDDHHMM[SS[MSMSMSMS[ AM/PM]]] 873 | $sDateTimeStr&=$iYear&$sMM&$sDD&$sHH&$sMin&$sSS&$sMS&$sAMPM 874 | Else 875 | ; one of 4 formats which ends with " HH:MM[:SS[:MSMSMSMS[ AM/PM]]]" 876 | Switch $iFormat 877 | ; /, : Format - MM/DD/YYYY 878 | Case 2 879 | $sDateTimeStr&=$sMM&'/'&$sDD&'/' 880 | ; /, : alt. Format - DD/MM/YYYY 881 | Case 3 882 | $sDateTimeStr&=$sDD&'/'&$sMM&'/' 883 | ; "Month DD, YYYY" format 884 | Case 4 885 | $sDateTimeStr&=$_WT_aMonths[$iMonth-1]&' '&$sDD&', ' 886 | ; "DD Month YYYY" format 887 | Case 5 888 | $sDateTimeStr&=$sDD&' '&$_WT_aMonths[$iMonth-1]&' ' 889 | Case 6 890 | $sDateTimeStr&=$iYear&'-'&$sMM&'-'&$sDD 891 | $iYear='' 892 | Case Else 893 | Return SetError(1,0,"") 894 | EndSwitch 895 | $sDateTimeStr&=$iYear&' '&$sHH&':'&$sMin 896 | If $iPrecision Then 897 | $sDateTimeStr&=':'&$sSS 898 | ; If $iPrecision>1 Then $sDateTimeStr&=':'&$sMS 899 | If $iPrecision>1 Then $sDateTimeStr&=$PrecisionSeparator&$sMS 900 | EndIf 901 | $sDateTimeStr&=$sAMPM 902 | EndIf 903 | If $aReturnArray[1]<>"" Then 904 | $aReturnArray[0]=$sDateTimeStr 905 | Return $aReturnArray 906 | EndIf 907 | Return $sDateTimeStr 908 | EndFunc 909 | 910 | Func _DisplayInfo($DebugInfo) 911 | _GUICtrlEdit_AppendText($myctredit, $DebugInfo) 912 | EndFunc 913 | 914 | Func _DisplayProgress() 915 | ProgressSet(Round((($CurrentPage / $MaxPages) * 100), 2), Round(($CurrentPage / $MaxPages) * 100, 2) & " % finished parsing", "") 916 | EndFunc 917 | 918 | Func _WriteCSVHeader() 919 | If $DoDefaultAll Then 920 | $UsnJrnl_Csv_Header = "Offset"&$de&"FileName"&$de&"USN"&$de&"Timestamp"&$de&"Reason"&$de&"MFTReference"&$de&"MFTReferenceSeqNo"&$de&"MFTParentReference"&$de&"MFTParentReferenceSeqNo"&$de&"FileAttributes"&$de&"MajorVersion"&$de&"MinorVersion"&$de&"SourceInfo"&$de&"SecurityId" 921 | ElseIf $Dol2t Then 922 | $UsnJrnl_Csv_Header = "Date"&$de&"Time"&$de&"Timezone"&$de&"MACB"&$de&"Source"&$de&"SourceType"&$de&"Type"&$de&"User"&$de&"Host"&$de&"Short"&$de&"Desc"&$de&"Version"&$de&"Filename"&$de&"Inode"&$de&"Notes"&$de&"Format"&$de&"Extra" 923 | ElseIf $DoBodyfile Then 924 | $UsnJrnl_Csv_Header = "MD5"&$de&"name"&$de&"inode"&$de&"mode_as_string"&$de&"UID"&$de&"GID"&$de&"size"&$de&"atime"&$de&"mtime"&$de&"ctime"&$de&"crtime" 925 | EndIf 926 | FileWriteLine($UsnJrnlCsv, $UsnJrnl_Csv_Header & @CRLF) 927 | EndFunc 928 | 929 | Func _InjectTimeZoneInfo() 930 | $Regions = "UTC: -12.00|" & _ 931 | "UTC: -11.00|" & _ 932 | "UTC: -10.00|" & _ 933 | "UTC: -9.30|" & _ 934 | "UTC: -9.00|" & _ 935 | "UTC: -8.00|" & _ 936 | "UTC: -7.00|" & _ 937 | "UTC: -6.00|" & _ 938 | "UTC: -5.00|" & _ 939 | "UTC: -4.30|" & _ 940 | "UTC: -4.00|" & _ 941 | "UTC: -3.30|" & _ 942 | "UTC: -3.00|" & _ 943 | "UTC: -2.00|" & _ 944 | "UTC: -1.00|" & _ 945 | "UTC: 0.00|" & _ 946 | "UTC: 1.00|" & _ 947 | "UTC: 2.00|" & _ 948 | "UTC: 3.00|" & _ 949 | "UTC: 3.30|" & _ 950 | "UTC: 4.00|" & _ 951 | "UTC: 4.30|" & _ 952 | "UTC: 5.00|" & _ 953 | "UTC: 5.30|" & _ 954 | "UTC: 5.45|" & _ 955 | "UTC: 6.00|" & _ 956 | "UTC: 6.30|" & _ 957 | "UTC: 7.00|" & _ 958 | "UTC: 8.00|" & _ 959 | "UTC: 8.45|" & _ 960 | "UTC: 9.00|" & _ 961 | "UTC: 9.30|" & _ 962 | "UTC: 10.00|" & _ 963 | "UTC: 10.30|" & _ 964 | "UTC: 11.00|" & _ 965 | "UTC: 11.30|" & _ 966 | "UTC: 12.00|" & _ 967 | "UTC: 12.45|" & _ 968 | "UTC: 13.00|" & _ 969 | "UTC: 14.00|" 970 | GUICtrlSetData($Combo2,$Regions,"UTC: 0.00") 971 | EndFunc 972 | 973 | Func _GetUTCRegion($UTCRegion) 974 | If $UTCRegion = "" Then Return SetError(1,0,0) 975 | 976 | If StringInStr($UTCRegion,"UTC:") Then 977 | $part1 = StringMid($UTCRegion,StringInStr($UTCRegion," ")+1) 978 | Else 979 | $part1 = $UTCRegion 980 | EndIf 981 | $UTCconfig = $part1 982 | If StringRight($part1,2) = "15" Then $part1 = StringReplace($part1,".15",".25") 983 | If StringRight($part1,2) = "30" Then $part1 = StringReplace($part1,".30",".50") 984 | If StringRight($part1,2) = "45" Then $part1 = StringReplace($part1,".45",".75") 985 | $DeltaTest = $part1*36000000000 986 | Return $DeltaTest 987 | EndFunc 988 | 989 | Func _TranslateSeparator() 990 | ; Or do it the other way around to allow setting other trickier separators, like specifying it in hex 991 | GUICtrlSetData($SeparatorInput,StringLeft(GUICtrlRead($SeparatorInput),1)) 992 | GUICtrlSetData($SeparatorInput2,"0x"&Hex(Asc(GUICtrlRead($SeparatorInput)),2)) 993 | EndFunc 994 | 995 | Func _InjectTimestampFormat() 996 | Local $Formats = "1|" & _ 997 | "2|" & _ 998 | "3|" & _ 999 | "4|" & _ 1000 | "5|" & _ 1001 | "6|" 1002 | GUICtrlSetData($ComboTimestampFormat,$Formats,"6") 1003 | EndFunc 1004 | 1005 | Func _InjectTimestampPrecision() 1006 | Local $Precision = "None|" & _ 1007 | "MilliSec|" & _ 1008 | "NanoSec|" 1009 | GUICtrlSetData($ComboTimestampPrecision,$Precision,"NanoSec") 1010 | EndFunc 1011 | 1012 | Func _TranslateTimestamp() 1013 | Local $lPrecision,$lTimestamp,$lTimestampTmp 1014 | $DateTimeFormat = StringLeft(GUICtrlRead($ComboTimestampFormat),1) 1015 | $lPrecision = GUICtrlRead($ComboTimestampPrecision) 1016 | Select 1017 | Case $lPrecision = "None" 1018 | $TimestampPrecision = 1 1019 | Case $lPrecision = "MilliSec" 1020 | $TimestampPrecision = 2 1021 | Case $lPrecision = "NanoSec" 1022 | $TimestampPrecision = 3 1023 | EndSelect 1024 | $lTimestampTmp = _WinTime_UTCFileTimeToLocalFileTime("0x" & $ExampleTimestampVal) 1025 | $lTimestamp = _WinTime_UTCFileTimeFormat(Dec($ExampleTimestampVal,2), $DateTimeFormat, $TimestampPrecision) 1026 | If @error Then 1027 | $lTimestamp = $TimestampErrorVal 1028 | ElseIf $TimestampPrecision = 3 Then 1029 | $lTimestamp = $lTimestamp & $PrecisionSeparator2 & _FillZero(StringRight($lTimestampTmp, 4)) 1030 | EndIf 1031 | GUICtrlSetData($InputExampleTimestamp,$lTimestamp) 1032 | EndFunc 1033 | 1034 | Func _UsnJrnlProgress() 1035 | GUICtrlSetData($ProgressStatus, "Processing UsnJrnl page " & $CurrentPage & " of " & $MaxPages & ", total entries: " & $EntryCounter) 1036 | GUICtrlSetData($ElapsedTime, "Elapsed time = " & _WinAPI_StrFromTimeInterval(TimerDiff($begin))) 1037 | GUICtrlSetData($ProgressUsnJrnl, 100 * $CurrentPage / $MaxPages) 1038 | EndFunc 1039 | 1040 | Func _DumpOutput($text) 1041 | ConsoleWrite($text) 1042 | If $hDebugOutFile Then FileWrite($hDebugOutFile, $text) 1043 | EndFunc 1044 | 1045 | Func _UsnProcessPage($TargetPage,$OffsetFile,$OffsetChunk) 1046 | Local $LocalUsnCounter = 0, $NextOffset = 1, $TotalSizeOfPage = StringLen($TargetPage), $OffsetRecord=0 1047 | Do 1048 | $SizeOfNextUsnRecord = StringMid($TargetPage,$NextOffset,8) 1049 | $SizeOfNextUsnRecord = Dec(_SwapEndian($SizeOfNextUsnRecord),2) 1050 | If $SizeOfNextUsnRecord = 0 Then 1051 | ; _DumpOutput("Zero padding at offset 0x" & Hex(Int($CurrentPage*$USN_Page_Size+(($NextOffset-1)/2))) & @CRLF) 1052 | ExitLoop 1053 | EndIf 1054 | $SizeOfNextUsnRecord = $SizeOfNextUsnRecord*2 1055 | $NextUsnRecord = StringMid($TargetPage,$NextOffset,$SizeOfNextUsnRecord) 1056 | ; $FileNameLength = StringMid($TargetPage,$NextOffset+112,4) 1057 | ; $FileNameLength = Dec(_SwapEndian($FileNameLength),2) 1058 | $OffsetRecord = "0x" & Hex(Int($OffsetFile + ($OffsetChunk + $NextOffset)/2)) 1059 | $LocalUsnCounter += _UsnDecodeRecord($NextUsnRecord, $OffsetRecord) 1060 | $NextOffset+=$SizeOfNextUsnRecord 1061 | Until $NextOffset-$SizeOfNextUsnRecord > $TotalSizeOfPage 1062 | Return $LocalUsnCounter 1063 | EndFunc 1064 | #cs 1065 | Func _ScanModeUsnProcessPage($TargetPage) 1066 | Local $NextOffset = 1, $TotalSizeOfPage = StringLen($TargetPage) 1067 | Do 1068 | $SizeOfNextUsnRecord = StringMid($TargetPage,$NextOffset,8) 1069 | $SizeOfNextUsnRecord = Dec(_SwapEndian($SizeOfNextUsnRecord),2) 1070 | $SizeOfNextUsnRecord = $SizeOfNextUsnRecord*2 1071 | $NextUsnRecord = StringMid($TargetPage,$NextOffset,$SizeOfNextUsnRecord) 1072 | If _ScanModeUsnDecodeRecord($NextUsnRecord) Then 1073 | ; _DumpOutput("Found entry at offset 0x" & Hex(Int($CurrentPage*$USN_Page_Size+(($NextOffset-1)/2))) & @CRLF) 1074 | ; _DumpOutput(_HexEncode("0x"&$NextUsnRecord) & @CRLF) 1075 | Return $NextOffset-1 1076 | Else 1077 | ; _DumpOutput("Bad entry at offset 0x" & Hex(Int($CurrentPage*$USN_Page_Size+(($NextOffset-1)/2))) & @CRLF) 1078 | ; _DumpOutput(_HexEncode("0x"&$NextUsnRecord) & @CRLF) 1079 | $NextOffset+=2 1080 | EndIf 1081 | 1082 | Until $NextOffset >= $TotalSizeOfPage 1083 | Return SetError(1,0,0) 1084 | EndFunc 1085 | #ce 1086 | Func _ScanModeUsnProcessPage2($TargetPage,$OffsetFile,$OffsetChunk,$EndOffset) 1087 | Local $LocalUsnCounter = 0, $NextOffset = 1, $TotalSizeOfPage = StringLen($TargetPage) 1088 | Do 1089 | $SizeOfNextUsnRecord = StringMid($TargetPage,$NextOffset,8) 1090 | $SizeOfNextUsnRecord = Dec(_SwapEndian($SizeOfNextUsnRecord),2) 1091 | $SizeOfNextUsnRecord = $SizeOfNextUsnRecord*2 1092 | $NextUsnRecord = StringMid($TargetPage,$NextOffset,$SizeOfNextUsnRecord) 1093 | If _ScanModeUsnDecodeRecord($NextUsnRecord) Then 1094 | ; _DumpOutput("Found entry at offset 0x" & Hex(Int($CurrentPage*$USN_Page_Size+(($NextOffset-1)/2))) & @CRLF) 1095 | ; _DumpOutput(_HexEncode("0x"&$NextUsnRecord) & @CRLF) 1096 | $OffsetRecord = "0x" & Hex(Int($OffsetFile + ($OffsetChunk + $NextOffset)/2)) 1097 | $LocalUsnCounter += _UsnDecodeRecord($NextUsnRecord, $OffsetRecord) 1098 | $NextOffset+=$SizeOfNextUsnRecord 1099 | ; Return $NextOffset-1 1100 | Else 1101 | ; _DumpOutput("Bad entry at offset 0x" & Hex(Int($CurrentPage*$USN_Page_Size+(($NextOffset-1)/2))) & @CRLF) 1102 | ; _DumpOutput(_HexEncode("0x"&$NextUsnRecord) & @CRLF) 1103 | $NextOffset+=2 1104 | EndIf 1105 | 1106 | Until $NextOffset > $TotalSizeOfPage Or $NextOffset/2 > $EndOffset 1107 | Return $LocalUsnCounter 1108 | EndFunc 1109 | 1110 | Func _ScanModeUsnDecodeRecord($Record) 1111 | $UsnJrnlRecordLength = StringMid($Record,1,8) 1112 | $UsnJrnlRecordLength = Dec(_SwapEndian($UsnJrnlRecordLength),2) 1113 | ; If $UsnJrnlRecordLength > $USN_Page_Size Or $UsnJrnlRecordLength < BinaryLen("0x"&$Record) Then Return SetError(1,0,0) 1114 | If (($UsnJrnlRecordLength > $USN_Page_Size) Or ($UsnJrnlRecordLength > StringLen($Record)/2)) Then Return SetError(1,0,0) 1115 | $UsnJrnlMajorVersion = StringMid($Record,9,4) 1116 | $UsnJrnlMajorVersion = Dec(_SwapEndian($UsnJrnlMajorVersion),2) 1117 | If $UsnJrnlMajorVersion < 2 And $UsnJrnlMajorVersion > 4 Then Return SetError(1,0,0) 1118 | ; $UsnJrnlMinorVersion = StringMid($Record,13,4) 1119 | ; $UsnJrnlMinorVersion = Dec(_SwapEndian($UsnJrnlMinorVersion),2) 1120 | $UsnJrnlFileReferenceNumber = StringMid($Record,17,12) 1121 | $UsnJrnlFileReferenceNumber = Dec(_SwapEndian($UsnJrnlFileReferenceNumber),2) 1122 | If $UsnJrnlFileReferenceNumber = 0 Then Return SetError(1,0,0) 1123 | $UsnJrnlMFTReferenceSeqNo = StringMid($Record,29,4) 1124 | $UsnJrnlMFTReferenceSeqNo = Dec(_SwapEndian($UsnJrnlMFTReferenceSeqNo),2) 1125 | If $UsnJrnlMFTReferenceSeqNo = 0 Then Return SetError(1,0,0) 1126 | $UsnJrnlParentFileReferenceNumber = StringMid($Record,33,12) 1127 | $UsnJrnlParentFileReferenceNumber = Dec(_SwapEndian($UsnJrnlParentFileReferenceNumber),2) 1128 | If $UsnJrnlParentFileReferenceNumber < 5 Then Return SetError(1,0,0) 1129 | $UsnJrnlParentReferenceSeqNo = StringMid($Record,45,4) 1130 | $UsnJrnlParentReferenceSeqNo = Dec(_SwapEndian($UsnJrnlParentReferenceSeqNo),2) 1131 | If $UsnJrnlParentReferenceSeqNo = 0 Then Return SetError(1,0,0) 1132 | $UsnJrnlUsn = StringMid($Record,49,16) 1133 | $UsnJrnlUsn = Dec(_SwapEndian($UsnJrnlUsn),2) 1134 | If $UsnJrnlUsn = 0 Then Return SetError(1,0,0) 1135 | $UsnJrnlTimestamp = StringMid($Record,65,16) 1136 | If $ExtendedTimestampCheck Then 1137 | $UsnJrnlTimestampTmp = Dec(_SwapEndian($UsnJrnlTimestamp),2) 1138 | If $UsnJrnlTimestampTmp < 112589990684262400 Or $UsnJrnlTimestampTmp > 139611588448485376 Then Return SetError(1,0,0) ;14 oktober 1957 - 31 mai 2043 1139 | EndIf 1140 | $UsnJrnlTimestamp = _DecodeTimestamp($UsnJrnlTimestamp) 1141 | If $UsnJrnlTimestamp = $TimestampErrorVal Then Return SetError(1,0,0) 1142 | $UsnJrnlReason = StringMid($Record,81,8) 1143 | $UsnJrnlReason = Dec(_SwapEndian($UsnJrnlReason),2) 1144 | If $UsnJrnlReason = 0 Then Return SetError(1,0,0) 1145 | ; $UsnJrnlSourceInfo = StringMid($Record,89,8) 1146 | ; $UsnJrnlSourceInfo = "0x"&_SwapEndian($UsnJrnlSourceInfo) 1147 | ; $UsnJrnlSecurityId = StringMid($Record,97,8) 1148 | ; $UsnJrnlSecurityId = Dec(_SwapEndian($UsnJrnlSecurityId),2) 1149 | ; $UsnJrnlFileAttributes = StringMid($Record,105,8) 1150 | ; $UsnJrnlFileAttributes = _File_Attributes("0x"&_SwapEndian($UsnJrnlFileAttributes)) 1151 | $UsnJrnlFileNameLength = StringMid($Record,113,4) 1152 | $UsnJrnlFileNameLength = Dec(_SwapEndian($UsnJrnlFileNameLength),2) 1153 | If $UsnJrnlFileNameLength = 0 Then Return SetError(1,0,0) 1154 | $UsnJrnlFileNameOffset = StringMid($Record,117,4) 1155 | $UsnJrnlFileNameOffset = Dec(_SwapEndian($UsnJrnlFileNameOffset),2) 1156 | If $UsnJrnlFileNameOffset <> 60 Then Return SetError(1,0,0) 1157 | $UsnJrnlFileName = StringMid($Record,121,$UsnJrnlFileNameLength*2) 1158 | $NameTest = 1 1159 | Select 1160 | Case $ExtendedNameCheckAll 1161 | ; _DumpOutput("$ExtendedNameCheckAll: " & $ExtendedNameCheckAll & @CRLF) 1162 | $NameTest = _ValidateCharacterAndWindowsFileName($UsnJrnlFileName) 1163 | Case $ExtendedNameCheckChar 1164 | ; _DumpOutput("$ExtendedNameCheckChar: " & $ExtendedNameCheckChar & @CRLF) 1165 | $NameTest = _ValidateCharacter($UsnJrnlFileName) 1166 | Case $ExtendedNameCheckWindows 1167 | ; _DumpOutput("$ExtendedNameCheckWindows: " & $ExtendedNameCheckWindows & @CRLF) 1168 | $NameTest = _ValidateWindowsFileName($UsnJrnlFileName) 1169 | EndSelect 1170 | If Not $NameTest Then Return SetError(1,0,0) 1171 | $UsnJrnlFileName = BinaryToString("0x"&$UsnJrnlFileName,2) 1172 | If @error Or $UsnJrnlFileName = "" Or StringLen($UsnJrnlFileName)>$UsnJrnlRecordLength*2 Or StringLen($UsnJrnlFileName)>255 Then Return SetError(1,0,0) 1173 | #cs 1174 | ; _DumpOutput("$UsnJrnlMajorVersion: " & $UsnJrnlMajorVersion & @CRLF) 1175 | ; _DumpOutput("$UsnJrnlMinorVersion: " & $UsnJrnlMinorVersion & @CRLF) 1176 | _DumpOutput("$UsnJrnlFileReferenceNumber: " & $UsnJrnlFileReferenceNumber & @CRLF) 1177 | _DumpOutput("$UsnJrnlMFTReferenceSeqNo: " & $UsnJrnlMFTReferenceSeqNo & @CRLF) 1178 | _DumpOutput("$UsnJrnlParentFileReferenceNumber: " & $UsnJrnlParentFileReferenceNumber & @CRLF) 1179 | _DumpOutput("$UsnJrnlParentReferenceSeqNo: " & $UsnJrnlParentReferenceSeqNo & @CRLF) 1180 | _DumpOutput("$UsnJrnlUsn: " & $UsnJrnlUsn & @CRLF) 1181 | _DumpOutput("$UsnJrnlTimestamp: " & $UsnJrnlTimestamp & @CRLF) 1182 | ; _DumpOutput("$UsnJrnlReason: " & $UsnJrnlReason & @CRLF) 1183 | ; _DumpOutput("$UsnJrnlSourceInfo: " & $UsnJrnlSourceInfo & @CRLF) 1184 | ; _DumpOutput("$UsnJrnlSecurityId: " & $UsnJrnlSecurityId & @CRLF) 1185 | ; _DumpOutput("$UsnJrnlFileAttributes: " & $UsnJrnlFileAttributes & @CRLF) 1186 | _DumpOutput("$UsnJrnlFileName: " & $UsnJrnlFileName & @CRLF) 1187 | 1188 | _DumpOutput("$UsnJrnlRecordLength: " & $UsnJrnlRecordLength & @CRLF) 1189 | _DumpOutput("StringLen($Record)/2): " & StringLen($Record)/2 & @CRLF) 1190 | _DumpOutput(_HexEncode("0x"&$Record) & @CRLF) 1191 | If $UsnJrnlUsn = 1605548992 Then 1192 | MsgBox(0,"Info","Check output") 1193 | EndIf 1194 | #ce 1195 | Return 1 1196 | EndFunc 1197 | 1198 | Func _GetInputParams() 1199 | Local $TimeZone, $OutputFormat, $ScanMode 1200 | For $i = 1 To $cmdline[0] 1201 | ;ConsoleWrite("Param " & $i & ": " & $cmdline[$i] & @CRLF) 1202 | If StringLeft($cmdline[$i],13) = "/UsnJrnlFile:" Then $File = StringMid($cmdline[$i],14) 1203 | If StringLeft($cmdline[$i],12) = "/OutputPath:" Then $TargetOutputPath = StringMid($cmdline[$i],13) 1204 | If StringLeft($cmdline[$i],10) = "/TimeZone:" Then $TimeZone = StringMid($cmdline[$i],11) 1205 | If StringLeft($cmdline[$i],14) = "/OutputFormat:" Then $OutputFormat = StringMid($cmdline[$i],15) 1206 | If StringLeft($cmdline[$i],11) = "/Separator:" Then $SeparatorInput = StringMid($cmdline[$i],12) 1207 | If StringLeft($cmdline[$i],15) = "/QuotationMark:" Then $checkquotes = StringMid($cmdline[$i],16) 1208 | If StringLeft($cmdline[$i],9) = "/Unicode:" Then $CheckUnicode = StringMid($cmdline[$i],10) 1209 | If StringLeft($cmdline[$i],10) = "/ScanMode:" Then $ScanMode = StringMid($cmdline[$i],11) 1210 | If StringLeft($cmdline[$i],10) = "/TSFormat:" Then $DateTimeFormat = StringMid($cmdline[$i],11) 1211 | If StringLeft($cmdline[$i],13) = "/TSPrecision:" Then $TimestampPrecision = StringMid($cmdline[$i],14) 1212 | If StringLeft($cmdline[$i],22) = "/TSPrecisionSeparator:" Then $PrecisionSeparator = StringMid($cmdline[$i],23) 1213 | If StringLeft($cmdline[$i],23) = "/TSPrecisionSeparator2:" Then $PrecisionSeparator2 = StringMid($cmdline[$i],24) 1214 | If StringLeft($cmdline[$i],12) = "/TSErrorVal:" Then $TimestampErrorVal = StringMid($cmdline[$i],13) 1215 | If StringLeft($cmdline[$i],13) = "/UsnPageSize:" Then $USN_Page_Size = StringMid($cmdline[$i],14) 1216 | If StringLeft($cmdline[$i],18) = "/TestFilenameChar:" Then $CheckExtendedNameCheckChar = StringMid($cmdline[$i],19) 1217 | If StringLeft($cmdline[$i],21) = "/TestFilenameWindows:" Then $CheckExtendedNameCheckWindows = StringMid($cmdline[$i],22) 1218 | If StringLeft($cmdline[$i],15) = "/TestTimestamp:" Then $CheckExtendedTimestampCheck = StringMid($cmdline[$i],16) 1219 | If StringLeft($cmdline[$i],16) = "/VerifyFragment:" Then $VerifyFragment = StringMid($cmdline[$i],17) 1220 | If StringLeft($cmdline[$i],17) = "/OutFragmentName:" Then $OutFragmentName = StringMid($cmdline[$i],18) 1221 | If StringLeft($cmdline[$i],9) = "/CleanUp:" Then $CleanUp = StringMid($cmdline[$i],10) 1222 | If StringLeft($cmdline[$i],13) = "/StartOffset:" Then $StartOffsetInput = StringMid($cmdline[$i],14) 1223 | Next 1224 | 1225 | If StringLen($TargetOutputPath) > 0 Then 1226 | If DirGetSize($TargetOutputPath) = -1 Then 1227 | DirCreate($TargetOutputPath) 1228 | Else 1229 | ConsoleWrite("Warning: Output directory already exist: " & $TargetOutputPath & @CRLF) 1230 | EndIf 1231 | Else 1232 | $TargetOutputPath = @ScriptDir 1233 | EndIf 1234 | 1235 | If StringLen($CheckUnicode) > 0 Then 1236 | If $CheckUnicode <> 0 And $CheckUnicode <> 1 Then 1237 | ConsoleWrite("Error: Incorect Unicode: " & $CheckUnicode & @CRLF) 1238 | Exit(1) 1239 | EndIf 1240 | Else 1241 | $CheckUnicode = 1 1242 | EndIf 1243 | 1244 | If StringLen($CheckExtendedNameCheckChar) > 0 Then 1245 | If $CheckExtendedNameCheckChar <> 0 And $CheckExtendedNameCheckChar <> 1 Then 1246 | ConsoleWrite("Error: Incorect TestFilenameChar: " & $CheckExtendedNameCheckChar & @CRLF) 1247 | Exit(1) 1248 | EndIf 1249 | Else 1250 | $CheckExtendedNameCheckChar = 1 1251 | EndIf 1252 | 1253 | If StringLen($CheckExtendedNameCheckWindows) > 0 Then 1254 | If $CheckExtendedNameCheckWindows <> 0 And $CheckExtendedNameCheckWindows <> 1 Then 1255 | ConsoleWrite("Error: Incorect TestFilenameWindows: " & $CheckExtendedNameCheckWindows & @CRLF) 1256 | Exit(1) 1257 | EndIf 1258 | Else 1259 | $CheckExtendedNameCheckWindows = 1 1260 | EndIf 1261 | 1262 | If StringLen($CheckExtendedTimestampCheck) > 0 Then 1263 | If $CheckExtendedTimestampCheck <> 0 And $CheckExtendedTimestampCheck <> 1 Then 1264 | ConsoleWrite("Error: Incorect TestTimestamp: " & $CheckExtendedTimestampCheck & @CRLF) 1265 | Exit(1) 1266 | EndIf 1267 | Else 1268 | $CheckExtendedTimestampCheck = 1 1269 | EndIf 1270 | 1271 | If StringLen($ScanMode) > 0 Then 1272 | If $ScanMode <> 0 Then 1273 | $ScanMode = 1 1274 | EndIf 1275 | Else 1276 | $ScanMode = 0 1277 | EndIf 1278 | Select 1279 | case $ScanMode = 0 1280 | $DoNormalMode = 1 1281 | $DoScanMode = 0 1282 | case $ScanMode = 1 1283 | $DoNormalMode = 0 1284 | $DoScanMode = 1 1285 | EndSelect 1286 | 1287 | If StringLen($TimeZone) > 0 Then 1288 | Select 1289 | Case $TimeZone = "-12.00" 1290 | Case $TimeZone = "-11.00" 1291 | Case $TimeZone = "-10.00" 1292 | Case $TimeZone = "-9.30" 1293 | Case $TimeZone = "-9.00" 1294 | Case $TimeZone = "-8.00" 1295 | Case $TimeZone = "-7.00" 1296 | Case $TimeZone = "-6.00" 1297 | Case $TimeZone = "-5.00" 1298 | Case $TimeZone = "-4.30" 1299 | Case $TimeZone = "-4.00" 1300 | Case $TimeZone = "-3.30" 1301 | Case $TimeZone = "-3.00" 1302 | Case $TimeZone = "-2.00" 1303 | Case $TimeZone = "-1.00" 1304 | Case $TimeZone = "0.00" 1305 | Case $TimeZone = "1.00" 1306 | Case $TimeZone = "2.00" 1307 | Case $TimeZone = "3.00" 1308 | Case $TimeZone = "3.30" 1309 | Case $TimeZone = "4.00" 1310 | Case $TimeZone = "4.30" 1311 | Case $TimeZone = "5.00" 1312 | Case $TimeZone = "5.30" 1313 | Case $TimeZone = "5.45" 1314 | Case $TimeZone = "6.00" 1315 | Case $TimeZone = "6.30" 1316 | Case $TimeZone = "7.00" 1317 | Case $TimeZone = "8.00" 1318 | Case $TimeZone = "8.45" 1319 | Case $TimeZone = "9.00" 1320 | Case $TimeZone = "9.30" 1321 | Case $TimeZone = "10.00" 1322 | Case $TimeZone = "10.30" 1323 | Case $TimeZone = "11.00" 1324 | Case $TimeZone = "11.30" 1325 | Case $TimeZone = "12.00" 1326 | Case $TimeZone = "12.45" 1327 | Case $TimeZone = "13.00" 1328 | Case $TimeZone = "14.00" 1329 | Case Else 1330 | $TimeZone = "0.00" 1331 | EndSelect 1332 | Else 1333 | $TimeZone = "0.00" 1334 | EndIf 1335 | 1336 | $tDelta = _GetUTCRegion($TimeZone)-$tDelta 1337 | If @error Then 1338 | _DisplayInfo("Error: Timezone configuration failed." & @CRLF) 1339 | Else 1340 | _DisplayInfo("Timestamps presented in UTC: " & $UTCconfig & @CRLF) 1341 | EndIf 1342 | $tDelta = $tDelta*-1 1343 | 1344 | If StringLen($File) > 0 Then 1345 | If Not FileExists($File) Then 1346 | ConsoleWrite("Error input $UsnJrnl file does not exist." & @CRLF) 1347 | Exit(1) 1348 | EndIf 1349 | EndIf 1350 | 1351 | If StringLen($OutputFormat) > 0 Then 1352 | If $OutputFormat = "l2t" Then $Dol2t = True 1353 | If $OutputFormat = "bodyfile" Then $DoBodyfile = True 1354 | If $OutputFormat = "all" Then $DoDefaultAll = True 1355 | If $Dol2t = False And $DoBodyfile = False Then $DoDefaultAll = True 1356 | 1357 | Else 1358 | $DoDefaultAll = True 1359 | EndIf 1360 | 1361 | 1362 | If StringLen($PrecisionSeparator) <> 1 Then $PrecisionSeparator = "." 1363 | If StringLen($SeparatorInput) <> 1 Then $SeparatorInput = "|" 1364 | 1365 | If StringLen($TimestampPrecision) > 0 Then 1366 | Select 1367 | Case $TimestampPrecision = "None" 1368 | ConsoleWrite("Timestamp Precision: " & $TimestampPrecision & @CRLF) 1369 | $TimestampPrecision = 1 1370 | Case $TimestampPrecision = "MilliSec" 1371 | ConsoleWrite("Timestamp Precision: " & $TimestampPrecision & @CRLF) 1372 | $TimestampPrecision = 2 1373 | Case $TimestampPrecision = "NanoSec" 1374 | ConsoleWrite("Timestamp Precision: " & $TimestampPrecision & @CRLF) 1375 | $TimestampPrecision = 3 1376 | EndSelect 1377 | Else 1378 | $TimestampPrecision = 1 1379 | EndIf 1380 | 1381 | If StringLen($DateTimeFormat) > 0 Then 1382 | If $DateTimeFormat <> 1 And $DateTimeFormat <> 2 And $DateTimeFormat <> 3 And $DateTimeFormat <> 4 And $DateTimeFormat <> 5 And $DateTimeFormat <> 6 Then 1383 | $DateTimeFormat = 6 1384 | EndIf 1385 | Else 1386 | $DateTimeFormat = 6 1387 | EndIf 1388 | 1389 | If ($DateTimeFormat = 4 Or $DateTimeFormat = 5) And ($checkl2t + $checkbodyfile > 0) Then 1390 | ConsoleWrite("Error: TSFormat can't be 4 or 5 in combination with OutputFormat l2t and bodyfile" & @CRLF) 1391 | Exit(1) 1392 | EndIf 1393 | 1394 | If StringLen($VerifyFragment) > 0 Then 1395 | If $VerifyFragment <> 1 Then 1396 | $VerifyFragment = 0 1397 | EndIf 1398 | EndIf 1399 | 1400 | If StringLen($OutFragmentName) > 0 Then 1401 | If StringInStr($OutFragmentName,"\") Then 1402 | ConsoleWrite("Error: OutFragmentName must be a filename and not a path." & @CRLF) 1403 | Exit(1) 1404 | EndIf 1405 | EndIf 1406 | 1407 | If StringLen($CleanUp) > 0 Then 1408 | If $CleanUp <> 1 Then 1409 | $CleanUp = 0 1410 | EndIf 1411 | EndIf 1412 | 1413 | If StringLen($StartOffsetInput) > 0 Then 1414 | If StringIsDigit($StartOffsetInput) = 0 Then 1415 | $StartOffsetInput = 0 1416 | Else 1417 | $StartOffsetInput = Number($StartOffsetInput) 1418 | EndIf 1419 | EndIf 1420 | EndFunc 1421 | 1422 | Func _ValidateCharacter($InputString) 1423 | ;ConsoleWrite("$InputString: " & $InputString & @CRLF) 1424 | $StringLength = StringLen($InputString) 1425 | For $i = 1 To $StringLength Step 4 1426 | $TestChunk = StringMid($InputString,$i,4) 1427 | $TestChunk = Dec(_SwapEndian($TestChunk),2) 1428 | If ($TestChunk > 31 And $TestChunk < 256) Then 1429 | ContinueLoop 1430 | Else 1431 | Return 0 1432 | EndIf 1433 | Next 1434 | Return 1 1435 | EndFunc 1436 | 1437 | Func _ValidateWindowsFileName($InputString) 1438 | $StringLength = StringLen($InputString) 1439 | For $i = 1 To $StringLength Step 4 1440 | $TestChunk = StringMid($InputString,$i,4) 1441 | $TestChunk = Dec(_SwapEndian($TestChunk),2) 1442 | If ($TestChunk <> 47 And $TestChunk <> 92 And $TestChunk <> 58 And $TestChunk <> 42 And $TestChunk <> 63 And $TestChunk <> 34 And $TestChunk <> 60 And $TestChunk <> 62) Then 1443 | ContinueLoop 1444 | Else 1445 | Return 0 1446 | EndIf 1447 | Next 1448 | Return 1 1449 | EndFunc 1450 | 1451 | Func _ValidateCharacterAndWindowsFileName($InputString) 1452 | ;ConsoleWrite("$InputString: " & $InputString & @CRLF) 1453 | $StringLength = StringLen($InputString) 1454 | For $i = 1 To $StringLength Step 4 1455 | $TestChunk = StringMid($InputString,$i,4) 1456 | $TestChunk = Dec(_SwapEndian($TestChunk),2) 1457 | If ($TestChunk > 31 And $TestChunk < 256) Then 1458 | If ($TestChunk <> 47 And $TestChunk <> 92 And $TestChunk <> 58 And $TestChunk <> 42 And $TestChunk <> 63 And $TestChunk <> 34 And $TestChunk <> 60 And $TestChunk <> 62) Then 1459 | ContinueLoop 1460 | Else 1461 | Return 0 1462 | EndIf 1463 | ContinueLoop 1464 | Else 1465 | Return 0 1466 | EndIf 1467 | Next 1468 | Return 1 1469 | EndFunc 1470 | 1471 | Func _WriteOutputFragment() 1472 | Local $nBytes, $Offset 1473 | 1474 | $Size = BinaryLen($RebuiltFragment) 1475 | $Size2 = $Size 1476 | If Mod($Size,0x8) Then 1477 | ConsoleWrite("SizeOf $RebuiltFragment: " & $Size & @CRLF) 1478 | While 1 1479 | $RebuiltFragment &= "00" 1480 | $Size2 += 1 1481 | If Mod($Size2,0x8) = 0 Then ExitLoop 1482 | WEnd 1483 | ConsoleWrite("Corrected SizeOf $RebuiltFragment: " & $Size2 & @CRLF) 1484 | EndIf 1485 | 1486 | Local $tBuffer = DllStructCreate("byte[" & $Size2 & "]") 1487 | DllStructSetData($tBuffer,1,$RebuiltFragment) 1488 | If @error Then Return SetError(1) 1489 | Local $OutFile = $OutputPath & "\" & $OutFragmentName 1490 | If Not FileExists($OutFile) Then 1491 | $Offset = 0 1492 | Else 1493 | $Offset = FileGetSize($OutFile) 1494 | EndIf 1495 | Local $hFileOut = _WinAPI_CreateFile("\\.\" & $OutFile,3,6,7) 1496 | If Not $hFileOut Then Return SetError(1) 1497 | _WinAPI_SetFilePointerEx($hFileOut, $Offset, $FILE_BEGIN) 1498 | If Not _WinAPI_WriteFile($hFileOut, DllStructGetPtr($tBuffer), DllStructGetSize($tBuffer), $nBytes) Then Return SetError(1) 1499 | _WinAPI_CloseHandle($hFileOut) 1500 | EndFunc 1501 | 1502 | Func _SetDateTimeFormats() 1503 | Select 1504 | Case $DateTimeFormat = 1 1505 | $CharsToGrabDate = 8 1506 | $CharStartTime = 9 1507 | $CharsToGrabTime = 6 1508 | Case $DateTimeFormat = 2 1509 | $CharsToGrabDate = 10 1510 | $CharStartTime = 11 1511 | $CharsToGrabTime = 8 1512 | Case $DateTimeFormat = 3 1513 | $CharsToGrabDate = 10 1514 | $CharStartTime = 11 1515 | $CharsToGrabTime = 8 1516 | Case $DateTimeFormat = 6 1517 | $CharsToGrabDate = 10 1518 | $CharStartTime = 11 1519 | $CharsToGrabTime = 8 1520 | EndSelect 1521 | EndFunc 1522 | 1523 | Func _CreateOutputStructureAndFiles() 1524 | 1525 | ; Output is already defined either explicitly or else default to current dir. 1526 | 1527 | Local $TimestampStart = @YEAR & "-" & @MON & "-" & @MDAY & "_" & @HOUR & "-" & @MIN & "-" & @SEC 1528 | 1529 | ;$OutputPath = $TargetOutputPath&"\UsnJrnl2Csv_"&$TimestampStart 1530 | $OutputPath = $TargetOutputPath 1531 | If DirCreate($OutputPath) = 0 Then 1532 | ConsoleWrite("Error creating: " & $OutputPath & @CRLF) 1533 | Exit 1534 | EndIf 1535 | 1536 | ;$DebugOutFile = $OutputPath & "\UsnJrnl.log" 1537 | $DebugOutFile = $OutputPath & "\UsnJrnl_"&$TimestampStart&".log" 1538 | $hDebugOutFile = FileOpen($DebugOutFile, $EncodingWhenOpen) 1539 | If @error Then 1540 | ConsoleWrite("Error: Could not create log file" & @CRLF) 1541 | MsgBox(0,"Error","Could not create log file") 1542 | Exit 1543 | EndIf 1544 | 1545 | ;$UsnJrnlCsvFile = $OutputPath & "\UsnJrnl.csv" 1546 | $UsnJrnlCsvFile = $OutputPath & "\UsnJrnl_"&$TimestampStart&".csv" 1547 | $UsnJrnlCsv = FileOpen($UsnJrnlCsvFile, $EncodingWhenOpen) 1548 | If @error Then 1549 | If Not $CommandlineMode Then _DisplayInfo("Error creating: " & $UsnJrnlCsvFile & @CRLF) 1550 | _DumpOutput("Error creating: " & $UsnJrnlCsvFile & @CRLF) 1551 | Return 1552 | EndIf 1553 | 1554 | ;$UsnJrnlSqlFile = $OutputPath & "\UsnJrnl.sql" 1555 | $UsnJrnlSqlFile = $OutputPath & "\UsnJrnl_"&$TimestampStart&".sql" 1556 | Select 1557 | Case $DoDefaultAll 1558 | FileInstall(".\import-sql\import-csv-usnjrnl.sql", $UsnJrnlSqlFile) 1559 | Case $Dol2t 1560 | FileInstall(".\import-sql\import-csv-l2t-usnjrnl.sql", $UsnJrnlSqlFile) 1561 | Case $DoBodyfile 1562 | FileInstall(".\import-sql\import-csv-bodyfile-usnjrnl.sql", $UsnJrnlSqlFile) 1563 | EndSelect 1564 | Local $FixedPath = StringReplace($UsnJrnlCsvFile, "\","\\") 1565 | Sleep(500) 1566 | _ReplaceStringInFile($UsnJrnlSqlFile, "__PathToCsv__", $FixedPath) 1567 | If $CheckUnicode = 1 Then _ReplaceStringInFile($UsnJrnlSqlFile, "latin1", "utf8") 1568 | _ReplaceStringInFile($UsnJrnlSqlFile, "__Separator__", $de) 1569 | 1570 | EndFunc -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | UsnJrnl2Csv Changelog 2 | 3 | 1.0.0.24 4 | Added an optional start offset configuration. 5 | Fixed minor GUI bug. 6 | Various minor changes, reshuffling of code and removing unused code. 7 | Changed license to MIT. 8 | 9 | 1.0.0.23 10 | Added support for new output formats; bodyfile and log2timeline. 11 | Added db schemas for the new output formats. 12 | Fixed bug that prevented sql file from running when timestamp format <> 6. 13 | 14 | 1.0.0.22 15 | Fixed bug that prevented separator to be configured. 16 | 17 | 1.0.0.21 18 | Added missing reason and source codes. 19 | 20 | 1.0.0.20 21 | Moved the import sql files into the new import-sql sub directory so that compilation works with the project as is. 22 | 23 | 1.0.0.19 24 | Recompiled with AutoIt version 3.3.14.2, which fixes certain Windows 10 ui issues. 25 | 26 | 1.0.0.18 27 | Added 3 new parameters. /VerifyFragment:, /OutFragmentName: and /CleanUp:. See readme. 28 | Added additional exit errorlevel for fragment verification mode. 29 | Added postfix of .empty to csv's generated with 0 hits. 30 | 31 | 1.0.0.17 32 | Fixed bug that did not consider /OutputPath: parameter in commandline mode. 33 | Added exit errorlevel to make it suite better with batch scripting. 34 | 35 | 1.0.0.16 36 | Fix that improve processing time for scan mode by roughly 20%. 37 | 38 | 1.0.0.15 39 | Fixed some configuration values not being logged. 40 | Fixed character set in the generated sql to be utf8 when applicable. 41 | Changed Reason column in UsnJrnl table of sql to be VARCHAR(255). 42 | 43 | 1.0.0.14 44 | Split the extended filename check into 2, 1 for valid character and 1 for valid Windows filename character. 45 | Made all 3 extended checks independent on unicode configuration. 46 | Changed default unicode configuration to 1. 47 | Removed previous scan mode 1, and renamed scan mode 2 to just scan mode. 48 | 49 | 1.0.0.13 50 | Added more validation check. 51 | Added support for identifying records spanning across sectors while in scan mode 2. 52 | Deactivated scan mode 1 as it no longer makes any sense to use it. 53 | 54 | 1.0.0.12 55 | Improved record validation for normal mode. 56 | 57 | 1.0.0.11 58 | Added 2 more options for extended checks on filename and timestamp. Used with scan mode. 59 | Fixed a bug where some configurations was not re-applied when program was run multiple times with different settings. 60 | 61 | 1.0.0.10 62 | Suppressed background console when launching gui. 63 | Compiled binaries with latest version 3.3.14.2. 64 | Set default configuration for quotation mark to off. 65 | 66 | 1.0.0.9 67 | Fixed minor bug that caused timestamp precision 2 and timestamp error val not to be re-read at each call to _Main. 68 | 69 | 1.0.0.8 70 | Added command line mode. All configurable option from gui are also exposed on command line. 71 | Changed file encoding to utf8 with BOM, when unicode configured. The previous ucs2 would not import into MySql. 72 | Added auto generated sql file with correct settings for import of csv. 73 | 74 | 1.0.0.7 75 | Added option to specify a second precision separator, to be used as separation between MilliSec and NanoSec. 76 | Added option to specify a custom error value for invalid timestamps, or incorrectly decoded timestamps. 77 | Added 2 sql's for database schema and import of data, along with instructions for how to import the csv into a MySql database. 78 | 79 | 1.0.0.6 80 | Fixed bug that caused scan mode 2 to not rescan damaged data within sector after a valid usn record was found. 81 | 82 | 1.0.0.5. 83 | Added 4 remaining structure members to the output; MajorVersion, MinorVersion, SourceInfo and SecurityId. 84 | Fixed gui to show 100 % when parsing is done. 85 | Added total entries parsed to the gui update. 86 | Implemented a log file for verbose output. 87 | Fixed bug that caused configured UTC configuration to always be 0.00. 88 | Added error checking (data sanity) of parsed entries. 89 | Added optional configuration of USN_PAGE_SIZE. 90 | Aded missing reason code for USN_REASON_TRANSACTED_CHANGE. 91 | Added a field for file offset in output. 92 | Fixed a bug that caused the last record per usn page to sometimes not be processed. 93 | Added 2 options for scan modes for handling damaged input data. 94 | 95 | 1.0.0.4. 96 | Added support for configuring (millisec) precision separator. 97 | 98 | 1.0.0.3. 99 | Added unicode support. 100 | 101 | 1.0.0.2. 102 | Fixed bug that caused not all records to be processed. 103 | 104 | 1.0.0.1. 105 | Fixed a bug with the quotes around values. Added nicer GUI with progressbar. Added more options for outputted timestamps, like UTC region, timestamp format and precision. And configurable separator. 106 | 107 | 1.0.0.0. 108 | Initial version. 109 | -------------------------------------------------------------------------------- /db-schema-bodyfile.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE bodyfile( 3 | `id` INT(11) NOT NULL AUTO_INCREMENT 4 | ,`MD5` VARCHAR(32) NOT NULL 5 | ,`name` TEXT NOT NULL 6 | ,`inode` BIGINT NOT NULL 7 | ,`mode_as_string` MEDIUMTEXT NOT NULL 8 | ,`UID` VARCHAR(64) NOT NULL 9 | ,`GID` VARCHAR(64) NULL 10 | ,`size` BIGINT NULL 11 | ,`atime` DATETIME(6) NOT NULL 12 | ,`mtime` DATETIME(6) NOT NULL 13 | ,`ctime` DATETIME(6) NOT NULL 14 | ,`crtime` DATETIME(6) NOT NULL 15 | ,PRIMARY KEY (Id) 16 | ); -------------------------------------------------------------------------------- /db-schema-log2timeline.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE log2timeline( 3 | `id` INT(11) NOT NULL AUTO_INCREMENT 4 | ,`date` DATE NOT NULL 5 | ,`time` TIME NOT NULL 6 | ,`timezone` VARCHAR(32) NOT NULL 7 | ,`MACB` VARCHAR(8) NOT NULL 8 | ,`source` VARCHAR(128) NOT NULL 9 | ,`sourcetype` VARCHAR(128) NULL 10 | ,`type` VARCHAR(128) NULL 11 | ,`user` VARCHAR(64) NULL 12 | ,`host` VARCHAR(128) NULL 13 | ,`short` VARCHAR(256) NULL 14 | ,`desc` MEDIUMTEXT NULL 15 | ,`version` INT(4) NULL 16 | ,`filename` VARCHAR(256) NULL 17 | ,`inode` BIGINT NOT NULL 18 | ,`notes` VARCHAR(128) NULL 19 | ,`format` VARCHAR(128) NULL 20 | ,`extra` TEXT NULL 21 | ,PRIMARY KEY (Id) 22 | ); -------------------------------------------------------------------------------- /db-schema-usnjrnl.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE usnjrnl( 3 | `Id` INT(11) NOT NULL AUTO_INCREMENT 4 | ,`Offset` VARCHAR(18) NOT NULL 5 | ,`FileName` VARCHAR(255) NOT NULL 6 | ,`USN` BIGINT NOT NULL 7 | ,`Timestamp` DATETIME(6) NOT NULL 8 | ,`Reason` VARCHAR(255) NOT NULL 9 | ,`MFTReference` BIGINT NOT NULL 10 | ,`MFTReferenceSeqNo` INT(5) NOT NULL 11 | ,`MFTParentReference` BIGINT NOT NULL 12 | ,`MFTParentReferenceSeqNo` INT(5) NOT NULL 13 | ,`FileAttributes` VARCHAR(64) NOT NULL 14 | ,`MajorVersion` INT(5) NOT NULL 15 | ,`MinorVersion` INT(5) NOT NULL 16 | ,`SourceInfo` VARCHAR(10) NOT NULL 17 | ,`SecurityId` INT(11) NOT NULL 18 | ,PRIMARY KEY (Id) 19 | ); -------------------------------------------------------------------------------- /import-sql/import-csv-bodyfile-usnjrnl.sql: -------------------------------------------------------------------------------- 1 | LOAD DATA INFILE '__PathToCsv__' IGNORE 2 | INTO TABLE bodyfile 3 | CHARACTER SET 'latin1' 4 | COLUMNS TERMINATED BY '__Separator__' 5 | OPTIONALLY ENCLOSED BY '"' 6 | ESCAPED BY '"' 7 | LINES TERMINATED BY '\n' 8 | IGNORE 1 LINES 9 | (@MD5, @name, @inode, @mode_as_string, @UID, @GID, @size, @atime, @mtime, @ctime, @crtime) 10 | SET 11 | MD5 = nullif(@MD5,''), 12 | `name` = nullif(@name,''), 13 | inode = nullif(@inode,''), 14 | mode_as_string = nullif(@mode_as_string,''), 15 | UID = nullif(@UID,''), 16 | GID = nullif(@GID,''), 17 | `size` = nullif(@size,''), 18 | atime = STR_TO_DATE(@atime, '__TimestampTransformationSyntax__'), 19 | mtime = STR_TO_DATE(@mtime, '__TimestampTransformationSyntax__'), 20 | ctime = STR_TO_DATE(@ctime, '__TimestampTransformationSyntax__'), 21 | crtime = STR_TO_DATE(@crtime, '__TimestampTransformationSyntax__') 22 | ; 23 | 24 | -------------------------------------------------------------------------------- /import-sql/import-csv-l2t-usnjrnl.sql: -------------------------------------------------------------------------------- 1 | LOAD DATA INFILE '__PathToCsv__' IGNORE 2 | INTO TABLE log2timeline 3 | CHARACTER SET 'latin1' 4 | COLUMNS TERMINATED BY '__Separator__' 5 | OPTIONALLY ENCLOSED BY '"' 6 | ESCAPED BY '"' 7 | LINES TERMINATED BY '\n' 8 | IGNORE 1 LINES 9 | (@date, @time, `timezone`, `MACB`, @source, @sourcetype, @type, @user, @host, @short, @desc, @version, @filename, @inode, @notes, @format, @extra) 10 | SET 11 | `date` = STR_TO_DATE(@date, '__DateTransformationSyntax__'), 12 | `time` = STR_TO_DATE(@time, '__TimeTransformationSyntax__'), 13 | source = nullif(@source,''), 14 | sourcetype = nullif(@sourcetype,''), 15 | type = nullif(@type,''), 16 | user = nullif(@user,''), 17 | host = nullif(@host,''), 18 | short = nullif(@short,''), 19 | `desc` = nullif(@desc,''), 20 | version = nullif(@version,''), 21 | filename = nullif(@filename,''), 22 | inode = nullif(@inode,''), 23 | notes = nullif(@notes,''), 24 | format = nullif(@format,''), 25 | extra = nullif(@extra,'') 26 | ; 27 | 28 | -------------------------------------------------------------------------------- /import-sql/import-csv-usnjrnl.sql: -------------------------------------------------------------------------------- 1 | LOAD DATA INFILE "__PathToCsv__" IGNORE 2 | INTO TABLE usnjrnl 3 | CHARACTER SET 'latin1' 4 | COLUMNS TERMINATED BY '__Separator__' 5 | OPTIONALLY ENCLOSED BY '"' 6 | ESCAPED BY '"' 7 | LINES TERMINATED BY '\n' 8 | IGNORE 1 LINES 9 | (`Offset`, `FileName`, @USN, @Timestamp, `Reason`, @MFTReference, @MFTReferenceSeqNo, @MFTParentReference, @MFTParentReferenceSeqNo, `FileAttributes`, @MajorVersion, @MinorVersion, @SourceInfo, @SecurityId) 10 | SET 11 | `Timestamp` = STR_TO_DATE(@Timestamp, '__TimestampTransformationSyntax__'), 12 | USN = nullif(@USN,''), 13 | MFTReference = nullif(@MFTReference,''), 14 | MFTReferenceSeqNo = nullif(@MFTReferenceSeqNo,''), 15 | MFTParentReference = nullif(@MFTParentReference,''), 16 | MFTParentReferenceSeqNo = nullif(@MFTParentReferenceSeqNo,''), 17 | MajorVersion = nullif(@MajorVersion,''), 18 | MinorVersion = nullif(@MinorVersion,''), 19 | SourceInfo = nullif(@SourceInfo,''), 20 | SecurityId = nullif(@SecurityId,'') 21 | ; -------------------------------------------------------------------------------- /readme-usnjrnl2csv-mysql.txt: -------------------------------------------------------------------------------- 1 | As of version 1.0.0.7, the output csv of usnjrnl2csv supports import into MySql/MariaDb database. Attached is the database schema, usnjrnl2csv.sql, which should be used to create the database on MySql 5.6.4 or higher. That version is when precision in the timestamp was added. Earlier versions can be used, but then all DATETIME(6) occurrences in usnjrnl2csv.sql must be replaced with VARCHAR(28). It is important to use timestamp format 6. Precision of MilliSec or NanoSec is optional, but recommended. If NanoSec precision is used, then precision separator 2 must be empty (default value). It is also important to keep the timestamp error value to something valid for MySql, which the default value is. A nice sql client to use is HeidiSql. To import the csv into the database, use the import-csv-usnjrnl.sql or similar, depending on the output format chosen. Simply just run the autogenerated sql that will have all correct settings. Assumption is that database has been created beforehand using the included schema file. 2 | 3 | For manual database creation use following statement: 4 | 5 | CREATE DATABASE IF NOT EXISTS Ntfs 6 | CHARACTER SET 'utf8' 7 | COLLATE 'utf8_general_ci'; 8 | 9 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | Introduction 2 | The journal is a log of changes to files on an NTFS volume. Such changes can for instance be the creation, deletion or modification of files or directories. It is optional to have it on, and can be configured with fsutil.exe on Windows. However, it was not turned on by default until Vista and later. 3 | 4 | Details 5 | The journal, if turned on, can be found in the directory \$Extend and is named $UsnJrnl (this is not visible in explorer as it is part of the system files on NTFS). Actually it is an alternate data stream $J that contains the relevant data. This stream is usually rather large and can be several GB in size. Thus it may take quite some time to process, if filled up. The file is sparse, so preferrably use the ExtractUsnJrnl tool to extract it. 6 | 7 | The structure is well known and very simpel; http://www.microsoft.com/msj/0999/journal/journal.aspx 8 | 9 | The tool supports USN_RECORD_V2 and USN_RECORD_V3, but not USN_RECORD_V4 (introduced in Windows 8.1 and not activated by default.). 10 | 11 | The nice thing about it, is that it contains large amount of historical data. 12 | 13 | From version 1.0.0.5, all structure members were included in the output. 14 | 15 | The USN_PAGE_SIZE is configurable. The default value is 4096, and should be sufficient for most cases. 16 | 17 | Timestamps are written UTC 0.00 by default, but can be configured to anything. The format and precision of the timestamps can also be configured, as well as the millisec/precision separator. See displayed examples in the gui. 18 | 19 | Scan mode 20 | The scan mode option for handling damaged input data, like for instance carved usn records. The default mode is normal mode, which expects a well structured $UsnJrnl file, containing 1 or more usn pages. 21 | It works fine with any damaged data. This option is brute-force-like and will identify any usn record in a chunk of data if it is valid. Usn records can be randomly put within any kind of input data, and still be found. This mode is very slow. 22 | 23 | There still exist some possibility for false positives even though lots of validation checks are present. 3 optional validations tests can be deactivated to improve output or speed. The 2 extended filename checks are slow, but also greatly reduces false positive. The extended timestamp check can also be optionally disable as it will throw an error on validation for timestamps outside the defined range of 14 oktober 1957 - 31 mai 2043. 24 | 25 | Requirements 26 | The journal must have been extracted beforehand by another tool. 27 | 1. Your best and easiest option would be the ExtractUsnJrnl tool: https://github.com/jschicht/ExtractUsnJrnl 28 | 29 | If you know the MFT reference number of the file, you can retrieve the file with these slightly more complicated tools: 30 | 2. NTFS File Extractor; https://github.com/jschicht/NtfsFileExtractor 31 | 3. RawCopy: https://github.com/jschicht/RawCopy 32 | 33 | Command line use 34 | If no parameters are supplied, the GUI will by default launch. Valid switches are: 35 | 36 | Switches: 37 | /UsnJrnlFile: 38 | Input UsnJrnl file ($J stream) extracted. 39 | /OutputPath: 40 | The output path of where to put output. Defaults to program directory. 41 | /TimeZone: 42 | A string value for the timezone. See notes further down for valid values. 43 | /OutputFormat: 44 | The output format of csv. Valid values can be l2t, bodyfile, all. Default is all. 45 | /Separator: 46 | The separator to use in the csv. Default is | 47 | /QuotationMark: 48 | Boolean value for surrounding values in csv with quotes. Default is 0. Can be 0 or 1. 49 | /Unicode: 50 | Boolean value for decoding unicode strings. Default is 1. Can be 0 or 1. 51 | /TSFormat: 52 | An integer from 1 - 6 for specifying the timestamp format. Start the gui to see what they mean. Default is 6. 53 | /TSPrecision: 54 | What precision to use in the timestamp. Valid values are None, MilliSec and NanoSec. Default is NanoSec. 55 | /TSPrecisionSeparator: 56 | The separator to put in the separation of the precision. Default is ".". Start the gui to see what it means. 57 | /TSPrecisionSeparator2: 58 | The separator to put in between MilliSec and NanoSec in the precision of timestamp. Default is empty/nothing. Start the gui to see what it means. 59 | /TSErrorVal: 60 | A custom error value to put with errors in timestamp decode. Default value is '0000-00-00 00:00:00', which is compatible with MySql, and represents and invalid timestamp value for NTFS. 61 | /UsnPageSize: 62 | The size of USN_PAGE_SIZE. Default is 4096, which should work in most cases. 63 | /ScanMode: 64 | Boolean value to activate ScanMode. Default is 0, Normal mode. Can be 0 or 1. See explanation further up. 65 | /TestFilenameChar: 66 | Boolean value to activate extended filename validation for characters outside valid range. Only used with scan mode. Default value is 1. 67 | /TestFilenameWindows: 68 | Boolean value to activate extended filename validation for characters not conforming to Windows valid filenames. Only used with scan mode. Default value is 1. 69 | /TestTimestamp: 70 | Boolean value to activate extended timestamp validation. Default value is 1. Can be 0 or 1. 71 | /VerifyFragment: 72 | Boolean value for activating a simple validation on a fragment only, and not full parser. Can be 0 or 1. Will by default write fixed fragment to OutFragment.bin unless otherwise specified in /OutFragmentName: 73 | /OutFragmentName: 74 | The output filename to write the fixed fragment to, if /VerifyFragment: is set to 1. If omitted, the default filename is OutFragment.bin. 75 | /CleanUp: 76 | Boolean value for cleaning up all output if no entries could be decoded. Default value is 1. Can be 0 or 1. This setting makes the most sense if program is run in loop in batch or similar. 77 | /StartOffset: 78 | An optional integer for offset to start parsing at. Defaults to 0. 79 | 80 | The available TimeZone's to use are: 81 | -12.00 82 | -11.00 83 | -10.00 84 | -9.30 85 | -9.00 86 | -8.00 87 | -7.00 88 | -6.00 89 | -5.00 90 | -4.30 91 | -4.00 92 | -3.30 93 | -3.00 94 | -2.00 95 | -1.00 96 | 0.00 97 | 1.00 98 | 2.00 99 | 3.00 100 | 3.30 101 | 4.00 102 | 4.30 103 | 5.00 104 | 5.30 105 | 5.45 106 | 6.00 107 | 6.30 108 | 7.00 109 | 8.00 110 | 8.45 111 | 9.00 112 | 9.30 113 | 10.00 114 | 10.30 115 | 11.00 116 | 11.30 117 | 12.00 118 | 12.45 119 | 13.00 120 | 14.00 121 | 122 | Error levels 123 | The current exit (error) codes have been implemented in commandline mode, which makes it more suited for batch scripting. 124 | 1. No valid journal entries could be decoded. Empty output. 125 | 4. Failure in writing fixed fragment to output. Validation of fragment succeeded though. 126 | 127 | Thus if you get %ERRORLEVEL% == 1 it means nothing was decoded, and if you get %ERRORLEVEL% == 4 then valid records where detected but could not be written to separate output (only used with /VerifyFragment: and /OutFragmentName:). 128 | 129 | 130 | Examples: 131 | UsnJrnl2Csv.exe /UsnJrnlFile:c:\temp\$UsnJrnl_$J.bin /TimeZone:2.00 /TSFormat:1 /TSPrecision:MilliSec /Unicode:1 132 | UsnJrnl2Csv.exe /UsnJrnlFile:c:\temp\$UsnJrnl_$J.bin /TimeZone:-10.00 /TSFormat:4 /TSPrecision:NanoSec /Unicode:1 133 | UsnJrnl2Csv.exe /UsnJrnlFile:c:\temp\$UsnJrnl_$J.bin /TimeZone:3.00 /TSFormat:1 /TSPrecision:MilliSec 134 | UsnJrnl2Csv.exe /UsnJrnlFile:c:\temp\$UsnJrnl_$J.bin /TSFormat:2 /TSPrecision:None 135 | UsnJrnl2Csv.exe /UsnJrnlFile:c:\temp\$UsnJrnl_$J.bin /OutputPath:c:\temp\UsnJrnlOutput /ScanMode:2 136 | UsnJrnl2Csv.exe /UsnJrnlFile:C:\temp\$UsnJrnl_$J.bin /TSPrecision:NanoSec /ScanMode:1 137 | UsnJrnl2Csv.exe /UsnJrnlFile:C:\temp\$UsnJrnl_$J.bin /TSPrecision:NanoSec /TSFormat:2 /ScanMode:1 /OutputFormat:bodyfile 138 | UsnJrnl2Csv.exe /UsnJrnlFile:C:\temp\fragment.bin /ScanMode:1 /VerifyFragment:1 /OutputPath:e:\UsnJrnlOutput /OutFragmentName:FragmentCollection.bin /CleanUp:1 139 | UsnJrnl2Csv.exe /UsnJrnlFile:e:\UsnJrnlOutput\FragmentCollection.bin /OutputPath:e:\UsnJrnlOutput 140 | 141 | Last example is a basic that uses common defaults that work out just fine in most cases. Also compatible with MySql imports. 142 | 143 | 144 | ToDo 145 | Add support for USN_RECORD_V4. 146 | --------------------------------------------------------------------------------