Windows Forensic Analysis using PowerShell

Windows Forensic Analysis using PowerShell

As I continue on with my undergrad in Information Assurance, I try to apply techniques and concepts in real-world applications. It helps me “drill” the concepts into my forgetful brain, and because security interests me, I think its fun!

As stated before in my post Controlling/Monitoring Local Admin Rights using PowerShell. PoshSec is seeking to tackle Information Security concerns using PowerShell. What PoshSec hasn’t quite looked at (yet), is Forensic Analysis. Forensics is critical in Information Security because after an intruder gains root access your Windows OS, you need to know basic information like what was accessed? or when?

Or maybe you are on the “other side” and need to cover your tracks. Wouldn’t it be nice to know what Windows Artifacts could be used against you in a forensic investigation if needed?

Whether your interest is Forensics, or Anti-Forensics, my newest script is only a start to a larger forensics project I will be working on with the other million projects I have going!  It is pretty simple right now in its “infancy” stage, but I wanted to put it out there to see if anyone had ideas or would like to help with this project? Essentially, I want to take every Windows Artifact listed in the SANS Windows Artifact Analysis poster and be able to analyze each one, generate a detailed report, and provide the option to “erase your tracks”. SOUNDS COOL RIGHT!

https://blogs.sans.org/computer-forensics/files/2012/06/SANS-Digital-Forensics-and-Incident-Response-Poster-2012.pdf

You can download the source code here:

https://app.box.com/s/z7ozi8cr8feomz2l7ygv

MD5: 82D02FEB39114618EB605B4A4AE18E78

I have not created any help files yet for these CMDLETS but I do plan on completing them and readying this script for distribution in the near future.

Right now, this is what it analyzes…

  • IE Temporary Internet Files
  • IE History
  • IE Cookies
  • Windows Explorer Recent Items
  • Windows Explorer Thumbnail Cache
  • Recycle Bin Items
  • System Temp Files
  • Memory Dump Files
  • Windows System Log Files
  • Windows Error Reports
  • System Font Cache
  • Windows Prefetch Data
  • Windows Search Data
  • Remote Desktop Cache

How it all works.

Get-SecWindowsArtifacts will analyze the host system it is executed on (future script will allow for remote computer analysis)

The console will display a summary of what was analyzed including (filecount, name, and Size in KB)

If the user chooses, a report is created providing detailed information on each collected Windows artifact

Windows Forensic Analysis using PowerShell

Windows Forensic Analysis using PowerShell

You can see here the value of the report, providing detailed information about creation time, last accessed, filenames, locations…etc.

Windows Forensic Analysis using PowerShell

Clear-SecWindowsArtifacts will import the report created, and delete every file from the system.

Windows Forensic Analysis using PowerShell

I know that there are more efficient ways to achieve this, but Its a start…

Get-SecWindowsArtifacts

[code language=”powershell”]
Function Get-SecWindowsArtifacts
{
$ErrorActionPreference = "SilentlyContinue"
$MainArray = @()
$KBSize = "Size (KB)"

#Internet Explorer
Write-Host -ForegroundColor DarkGray "Analyzing Internet Explorer"

#Retrieves Internet Explorer Files and Information
$IETempFiles = Get-ChildItem "$env:LOCALAPPDATAMicrosoftWindowsTemporary Internet Files" -Recurse -Force -Exclude Counters.dat | ?{$_.PSIsContainer -eq $False}
$IETempFilesSum = $IETempFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="IE Temp Files"
Files=$IETempFiles.count
$KBSize=("{0:N2}" -f ($IETempFilesSum.Sum / 1KB))}

#Retrieves Internet Explorer History and Information
$IEHistoryFiles = Get-ChildItem "$env:LOCALAPPDATAMicrosoftWindowsHistory" -Filter container.dat -Recurse -Force
$IEHistoryFilesSum = $IEHistoryFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="IE History Files"
Files=("{0:N0}" -f ($IEHistoryFiles.count))
$KBSize=("{0:N2}" -f ($IEHistoryFilesSum.Sum / 1KB))}

#Retrieves Internet Explorer Cookies and Information
$IECookieFiles = Get-ChildItem "$env:LOCALAPPDATAMicrosoftInternet ExplorerRecoveryLast Active" -Recurse -Force
$IECookieFilesSum = $IECookieFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="IE Cookie Files"
Files=("{0:N0}" -f ($IECookieFiles.count))
$KBSize=("{0:N2}" -f ($IECookieFilesSum.Sum / 1KB))}

#Windows Explorer
Write-Host -ForegroundColor DarkGray "Analyzing Windows Explorer"

#Retrieves Recent Files and Information
$RecentFiles = Get-ChildItem "$env:APPDATAMicrosoftWindowsRecent" -Recurse -Force | ?{$_.PSIsContainer -eq $False}
$RecentFilesSum = $RecentFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="Recent Files"
Files=("{0:N0}" -f ($RecentFiles.count))
$KBSize=("{0:N2}" -f ($RecentFilesSum.Sum / 1KB))}

#Retrieves Thumbnail Cache Files and Information
$ThumbCacheFiles = Get-ChildItem "$env:LOCALAPPDATAMicrosoftWindowsExplorer" -Filter thumbcache* -Recurse -Force | ?{$_.PSIsContainer -eq $False}
$ThumbCacheFilesSum = $RecentFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="ThumbCache Files"
Files=("{0:N0}" -f ($ThumbCacheFiles.count))
$KBSize=("{0:N2}" -f ($ThumbCacheFilesSum.Sum / 1KB))}

#System
Write-Host -ForegroundColor DarkGray "Analyzing System Files"

#Retrieves System Recycle Bin Files and Information
$RecBinFiles = Get-ChildItem ‘C:$Recycle.Bin’ -Recurse -Force
$RecBinFilesSum = $RecBinFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="Recycle Bin"
Files=("{0:N0}" -f ($RecBinFiles.count))
$KBSize=("{0:N2}" -f ($RecBinFilesSum.Sum / 1KB))}

#Retrieves System Temporary Files and Information
$SysTempFiles = Get-ChildItem "$env:SystemRootTEMP" -Recurse -Force
$SysTempSum = $SysTempFiles | Measure-Object -Property length -Sum
$TempFilesLocal = Get-ChildItem "$env:LOCALAPPDATATemp" -Recurse -Force
$TempFilesLocalSum = $TempFilesLocal | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="System Temp Files"
Files=("{0:N0}" -f ($SysTempFiles.count))
$KBSize=("{0:N2}" -f ($SysTempSum.Sum / 1KB))}
$MainArray += New-Object PSObject -Property @{
Name="User Temp Files"
Files=("{0:N0}" -f ($TempFilesLocal.count))
$KBSize=("{0:N2}" -f ($TempFilesLocalSum.Sum / 1KB))}

#Retrieves System Memory Dump Information
$MemDumpFiles = Get-ChildItem "$env:LOCALAPPDATACrashDumps" -Filter *.dmp -Recurse -Force
$MemDumpSum = $MemDumpFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="Memory Dump Files"
Files=("{0:N0}" -f ($MemDumpFiles.count))
$KBSize=("{0:N2}" -f ($MemDumpSum.Sum / 1KB))}

#Retrieves System Windows Log files and Information
$WinLogFiles = Get-ChildItem "$env:SystemRoot" -Filter *.log -Recurse -Force -Exclude "$env:SystemRootTemp"
$WinLogsSum = $WinLogFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="Windows Log Files"
Files=("{0:N0}" -f ($WinLogFiles.count))
$KBSize=("{0:N2}" -f ($WinLogsSum.Sum / 1KB))}

#Retrieves System Windows Error Reporting
$WinerrFiles = Get-ChildItem "$env:ProgramDataMicrosoftWindowsWER" -Recurse -Force | ?{$_.PSIsContainer -eq $False}
$WinerrSum = $WinerrFiles | Measure-Object -Property length -Sum
$WinerrFilesLocal = Get-ChildItem "$env:LOCALAPPDATAMicrosoftWindowsWER" -Recurse -Force | ?{$_.PSIsContainer -eq $False}
$WinerrSumLocal = $WinerrFilesLocal | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="Windows Error Reporting"
Files=("{0:N0}" -f ($WinerrFiles.count))
$KBSize=("{0:N2}" -f ($WinerrSum.Sum / 1KB))}
$MainArray += New-Object PSObject -Property @{
Name="Windows Error Reporting (Local)"
Files=("{0:N0}" -f ($WinerrFilesLocal.count))
$KBSize=("{0:N2}" -f ($WinerrSumLocal.Sum / 1KB))}

#Retrieves System Font Cache
$FontFiles = Get-ChildItem "$env:SystemRootSystem32" -Filter FNTCACHE.DAT -Force
$FontFilesSum = $FontFiles | Measure-Object -Property length -Sum
$FontFilesLocal = Get-ChildItem "$env:SystemRootServiceProfilesLocalServiceAppDataLocal" -Filter *Cache*.dat -Recurse -Force
$FontFilesSumLocal = $FontFilesLocal | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="System Font Cache"
Files=("{0:N0}" -f ($FontFiles.count))
$KBSize=("{0:N2}" -f ($FontFilesSum.Sum / 1KB))}
$MainArray += New-Object PSObject -Property @{
Name="System Font Cache (Local)"
Files=("{0:N0}" -f ($FontFilesLocal.count))
$KBSize=("{0:N2}" -f ($FontFilesSumLocal.Sum / 1KB))}

#Advanced
Write-Host -ForegroundColor DarkGray "Analysing Windows Prefetch Data"
$PrefetchFiles = Get-ChildItem "$env:SystemRootPrefetch" -Filter *.pf -Recurse -Force
$PrefetchFilesSum = $PrefetchFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="Windows Prefetch Data"
Files=("{0:N0}" -f ($PrefetchFiles.count))
$KBSize=("{0:N2}" -f ($PrefetchFilesSum.Sum / 1KB))}

Write-Host -ForegroundColor DarkGray "Analysing Windows Search Data"
$WinSearch = Get-ChildItem "$env:ProgramDataMicrosoftSearchData" -Filter *.log -Recurse -Force
$WinSearchSum = $WinSearch | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="Windows Search Data"
Files=("{0:N0}" -f ($WinSearch.count))
$KBSize=("{0:N2}" -f ($WinSearchSum.Sum / 1KB))}

Write-Host -ForegroundColor DarkGray "Analysing Remote Desktop Cache"
$RDPFiles = Get-ChildItem "$env:LOCALAPPDATAMicrosoftTerminal Server ClientCache" -Recurse -Force
$RDPFilesSum = $RDPFiles | Measure-Object -Property length -Sum
$MainArray += New-Object PSObject -Property @{
Name="RDP Cache"
Files=("{0:N0}" -f ($RDPFiles.count))
$KBSize=("{0:N2}" -f ($RDPFilesSum.Sum / 1KB))}

#Add up total file sizes
$FinalSize = (

$IETempFilesSum.Sum +
$IEHistoryFilesSum.Sum +
$IECookieFilesSum.Sum +
$RecentFilesSum.Sum +
$ThumbCacheFilesSum.Sum +
$RecBinFilesSum.Sum +
$SysTempSum.Sum +
$SysTempSumLocal.Sum +
$MemDumpSum.Sum +
$WinLogsSum.Sum +
$WinerrSum.Sum +
$WinerrSumLocal.Sum +
$FontFilesSum.Sum +
$FontFilesSumLocal.Sum +
$PrefetchFilesSum.Sum +
$WinSearchSum.Sum +
$RDPFilesSum.Sum
)

#Display Results
$MainArray | Select Files,Name,$KBSize | ft -AutoSize
$FinalSize = "{0:N2}" -f ($FinalSize / 1MB)
Write-Host -ForegroundColor Yellow "$FinalSize MB to be removed. (Approximate Size)"

$title = "Generate Forensic Report"
$message = "Do you want to generate a detailed forensic report of discovered artifacts?"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Generates report"
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Exit"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $message, $options, 0)

switch ($result)
{
0 {
Write-Host -ForegroundColor Cyan "Generating Detailed Forensic Report…"
$PoshSecDir = "C:PoshSecGet-SecWindowsArtifacts"
$check = Test-Path -PathType Container "$PoshSecDirReports"
if($check -eq $false){
New-Item "$PoshSecDirReports" -type Directory -Force
}
$IETempFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Force
$IEHistoryFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$IECookieFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$RecentFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$ThumbCacheFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$RecBinFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$SysTemp | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$SysTempLocal | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$MemDump | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$WinLogs | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$Winerr | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$WinerrLocal | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$FontFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$FontFilesLocal | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$PrefetchFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$WinSearch | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
$RDPFiles | Export-Csv -Path $PoshSecDirReportsGet-SecWindowsArtifacts.CSV -NoTypeInformation -Append
}
1 {Continue}
}

Write-Host -ForegroundColor Green "`n`n`n`nComplete!"

}
[/code]

And after Get-SecWindowsArtifacts generates the report, you can execute…

Clear-SecWindowsArtifacts

[code language=”powershell”]
Function Clear-SecWindowsArtifacts
{
#Get-SecWindowsArtifacts must be executed and report generated before data can be erased.
$SecWindowsArtifactsCSV = Import-CSV "C:PoshSecGet-SecWindowsArtifactsReportsGet-SecWindowsArtifacts.CSV"

$title = "Clear-SecWindowsArtifacts"
$message = "Are you sure you want to delete forensic data?"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Deletes Files"
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Exits"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $message, $options, 0)

switch ($result)
{
0 {
foreach ($file in ($SecWindowsArtifactsCSV.FullName)){
Remove-Item -Verbose -Recurse -Path $file -Force -ErrorAction SilentlyContinue
} #End Of CSV Loop

}
1 {Continue}
}
} # End of Function
[/code]

As always please feel free to subscribe/comment/share

Thanks!

-Bryan

Tags// ,