diff --git a/PowerHuntShares.psm1 b/PowerHuntShares.psm1
index e653062..ed4e4c7 100644
--- a/PowerHuntShares.psm1
+++ b/PowerHuntShares.psm1
@@ -4,7 +4,7 @@
#--------------------------------------
# Author: Scott Sutherland, 2024 NetSPI
# License: 3-clause BSD
-# Version: v1.80
+# Version: v1.85
# References: This script includes custom code and code taken and modified from the open source projects PowerView, Invoke-Ping, and Invoke-Parrell.
function Invoke-HuntSMBShares
{
@@ -165,7 +165,7 @@ function Invoke-HuntSMBShares
[Parameter(Mandatory = $false,
HelpMessage = 'Number of items to sample for summary report.')]
- [int]$SampleSum = 5,
+ [int]$SampleSum = 200,
[Parameter(Mandatory = $false,
HelpMessage = 'Runspace time out.')]
@@ -196,12 +196,8 @@ function Invoke-HuntSMBShares
[int] $DirLevel = 3,
[Parameter(Mandatory = $false,
- HelpMessage = 'Search for common files containing passwords on the c$ shares.')]
- [switch] $FindFiles,
-
- [Parameter(Mandatory = $false,
- HelpMessage = 'Path to file of file paths to search for. One path per line.')]
- [string] $FindFilesList,
+ HelpMessage = 'Path to interesting files template to import file keywords to search for.')]
+ [string] $FileKeywordsPath,
[Parameter(Mandatory = $false,
HelpMessage = 'Do not perform ping scan.')]
@@ -267,6 +263,18 @@ function Invoke-HuntSMBShares
break
}
+ # Check for keyword file path
+ If($FileKeywordsPath){
+
+ if(Test-Path $FileKeywordsPath){
+ #Write-Output " [x]The target directory exists."
+ }else{
+ Write-Output " [x] The $FileKeywordsPath did not exist."
+ Write-Output " [!] Aborting operation."
+ break
+ }
+ }
+
# ----------------------------------------------------------------------
# Import computers from file
# ----------------------------------------------------------------------
@@ -1445,7 +1453,395 @@ function Invoke-HuntSMBShares
#Write-Output " [*][$Time] - Summary report data generated."
#Write-Output " [*][$Time] - $Top5ShareCountTotal of $AllAccessibleSharesCount ($DupPercent) shares are associated with the top 5 share names."
+ # ----------------------------------------------------------------------
+ # Create Interesting Files Table
+ # ----------------------------------------------------------------------
+ Write-Output " [*][$Time] Finding interesting files..."
+
+ # Define common image and other formats to filter out later
+ $ImageFormats = @("*.jpg", "*.jpeg", "*.png", "*.gif", "*.bmp", "*.ico", "*.svg", "*.webp", "*.mif", "*.heic", "*.msi")
+
+ # Create data table to hold interesting file keywords
+ $FileNamePatternsAll = New-Object system.data.datatable
+ $FileNamePatternsAll.Columns.Add("Keyword") | Out-Null # Keyword
+ $FileNamePatternsAll.Columns.Add("Description") | Out-Null # Summary of keyword.
+ $FileNamePatternsAll.Columns.Add("Instructions") | Out-Null # Used to instruct testing how to attack match.
+ $FileNamePatternsAll.Columns.Add("Category") | Out-Null # File name category: Secret (password), sensitive (data), binaries, script, backup, database
+ $FileNamePatternsAll.Columns.Add("SampleRegex") | Out-Null # Used to parse sample data from file matches.
+
+ # Add rows to data table - Sensitive data
+ $FileNamePatternsAll.Rows.Add("*credit*","Credit card number and/or PII.","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*pci*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*social*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*ssn*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("human*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("finance*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("Health*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("Billing*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("patient*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("HR*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*ftp*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*Program Files*","","None.","Sensitive","") | Out-Null
+
+ # Add rows to data table - Files containing passwords
+ $FileNamePatternsAll.Rows.Add("context.xml*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("db2cli.ini*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("ftpd.*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("ftpusers*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("httpd.conf*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("hudson.security.HudsonPrivateSecurityRealm.*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("jboss-cli.xml*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("jboss-logmanager.properties*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("jenkins.model.JenkinsLocationConfiguration.*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("machine.config*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("my.*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("mysql.user*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("nginx.conf*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*ntds.dit*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("pg_hba.conf*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("php.ini*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("putty.reg*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("postgresql.conf*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("SAM","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("SAM-*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("SAM_*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("SYSTEM","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("server.xml*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("shadow*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("standalone.xml*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("tnsnames.ora*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("tomcat-users.xml*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("sitemanager.xml*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("users.*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmx*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmdk*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.nvram*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmsd*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmsn*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmss*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmem*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vhd*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vhdx*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.avhd*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.avhdx*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vsv*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vbox*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vbox-prev*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vdi*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.hdd*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.sav*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.pvm*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.pvs*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.qcow*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.qcow2*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.img*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*vcenter*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*vault*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*DefaultAppPool*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*WinSCP.ini*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.kdbx","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("wp-config.php*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.config","","None.","Secret","") | Out-Null
+
+ # Add rows to data table - Database files
+ $FileNamePatternsAll.Rows.Add("*database*","","None.","Database","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.sql*","","None.","Database","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.sqlite*","","None.","Database","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.idf*","","None.","Database","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.mdf*","","None.","Database","") | Out-Null
+
+ # Add rows to data table - Backup files
+ $FileNamePatternsAll.Rows.Add("*.bak*","","None.","Backup","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.bkf*","","None.","Backup","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*backup*","","None.","Backup","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.tar*","","None.","Backup","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.zip*","","None.","Backup","") | Out-Null
+
+ # Add rows to data table - Scripts
+ $FileNamePatternsAll.Rows.Add("*.ps1*","","None.","Script","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.psm1*","","None.","Script","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.bat*","","None.","Script","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.sh*","","None.","Script","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vbs*","","None.","Script","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.cmd*","","None.","Script","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.wsh*","","None.","Script","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.wsf*","","None.","Script","") | Out-Null
+
+ # Add rows to data table - Binaries
+ $FileNamePatternsAll.Rows.Add("*.dll","","None.","Binaries","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.exe","","None.","Binaries","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.msi","","None.","Binaries","") | Out-Null
+
+ # Use keyword from define file instead
+ if($FileKeywordsPath){
+ $FileNamePatternsAllTest = import-csv "$FileKeywordsPath"
+ $CheckFieldKeyword = $FileNamePatternsAllTest | gm | where name -like "keyword" | select name -ExpandProperty name
+ $CheckFieldCategory = $FileNamePatternsAllTest | gm | where name -like "category" | select name -ExpandProperty name
+ if($CheckFieldKeyword -and $CheckFieldCategory){
+ # File found and columns exist
+ $FileNamePatternsAll = $FileNamePatternsAllTest
+ }else{
+ # File columns do not exist
+ # Do nothing and fail back to hard coded list
+ }
+ }
+
+ # Get unqiue categories
+ $FileNamePatternCategories = $FileNamePatternsAll | select Category -Unique
+ $FileNamePatternCategoriesCount = $FileNamePatternsAll | select Category -Unique | measure | select count -ExpandProperty count
+
+ # Generate chart categories - Individual rows
+ # for each category - "var MyScriptsCount = countStringInDisplayedRows('Scripts');"
+ $ChartCategoryCatVars = $FileNamePatternCategories |
+ foreach{
+ $ChartCatGenCat = $_.category
+ $ChartCatGenVar = "My"+ $ChartCatGenCat + "Count"
+ "var $ChartCatGenVar = countStringInDisplayedRows('$ChartCatGenCat');"
+ }
+ $ChartCategoryCatVarsFlat = $ChartCategoryCatVars -join "`n"
+
+ # Generate chart categories - Category list
+ # once - categories: ['Sensitive', 'Secrets', 'Scripts'],
+ $ChartCategoryCommas = ($FileNamePatternCategories | Select-Object -ExpandProperty category | ForEach-Object { "'$_'" }) -join ", "
+ $ChartCategoryCat = "categories: [$ChartCategoryCommas],"
+
+ # Generate chart categories -
+ # once - data: [MySensitiveCount, MySecretCount, MyScriptsCount]
+ $ChartCategoryCountFormat = ($FileNamePatternCategories | Select-Object -ExpandProperty category | ForEach-Object {"My"+ $_ + "Count"}) -join ", "
+ $ChartCategoryDat = "data: [$ChartCategoryCountFormat]"
+
+ # Get a list of file names from each folder group for the target share name
+ $InterestingFilesAllFileNames = $ExcessiveSharePrivs | select FileList -Unique | foreach {$_.FileList -split "`r`n"} | Where-Object {$_ -ne ''} | foreach {$_.ToLower()}| select -Unique
+
+ # Identify keyword matches in filenames
+ $InterestingFilesAllMatches = New-Object system.data.datatable
+ $InterestingFilesAllMatches.Columns.Add("FileName") | Out-Null
+ $InterestingFilesAllMatches.Columns.Add("Category") | Out-Null
+ $FileNamePatternsAll |
+ foreach {
+ $TargetKeywordValue = $_.Keyword
+ $TargetKeywordCategory = $_.Category
+ $InterestingFilesAllFileNames |
+ foreach {
+
+ if($_ -like "$TargetKeywordValue"){
+
+ # check if file has already been labeled
+ $CheckForFile = $InterestingFilesAllMatches | where Filename -like "$_"
+ if(-not $CheckForFile){
+
+ # Add file
+ $InterestingFilesAllMatches.Rows.Add("$_","$TargetKeywordCategory")| Out-Null
+ }
+ }
+ }
+ }
+
+ # Query for a list of information for each file name match
+ $InterestingFilesAllObjects = $InterestingFilesAllMatches |
+ foreach{
+
+ # Set variables
+ $TargetFileNameValue = $_.FileName
+ $TargetCategoryValue = $_.Category
+
+ # Filter for records with the target file
+ $TargetKeywordMatches = $ExcessiveSharePrivs | where FileList -like "*$TargetFileNameValue*" | select ComputerName,ShareName,SharePath -Unique
+
+ # Extend object to include a unc path to file
+ $TargetKeywordMatches |
+ foreach {
+
+ # Select the propertity and make new ones
+ $TargetKeywordComputer = $_.ComputerName
+ $TargetKeywordShareName = $_.ShareName
+ $TargetKeywordSharePath = $_.SharePath
+ $TargetKeywordUNCPath = "$TargetKeywordSharePath\$TargetFileNameValue"
+ $TargetKeywordCategory = $TargetCategoryValue
+
+ # Create updated object
+ $object = New-Object psobject
+ $object | add-member noteproperty ComputerName $TargetKeywordComputer
+ $object | add-member noteproperty ShareName $TargetKeywordShareName
+ $object | add-member noteproperty SharePath $TargetKeywordSharePath
+ $object | add-member noteproperty UncPath $TargetKeywordUNCPath
+ $object | add-member noteproperty FileName $TargetFileNameValue
+ $object | add-member noteproperty Category $TargetKeywordCategory
+
+ # Return object
+ $object
+ }
+ } | select ComputerName,ShareName,SharePath,UncPath,FileName,Category -Unique
+
+ <#
+
+ # Define list of words associated with sensitive data
+ $FileNamePatternsSecrets = $FileNamePatternsAll | where category -like "*Secret*" | select Keyword -ExpandProperty keyword
+
+ # Define list of words associated with password files
+ $FileNamePatternsData = $FileNamePatternsAll | where category -like "*Sensitive*" | select Keyword -ExpandProperty keyword
+
+ # Get a list of file names from each folder group for the target share name
+ $InterestingFilesAllFileNames = $ExcessiveSharePrivs | select FileList -Unique | foreach {$_.FileList -split "`r`n"} | Where-Object {$_ -ne ''} | foreach {$_.ToLower()}| select -Unique
+
+ # Identify Secrets
+ $InterestingFilesAllSecrets = $FileNamePatternsSecrets |
+ foreach {
+ $TargetSecret = $_
+ $InterestingFilesAllFileNames |
+ foreach {
+ if($_ -like "$TargetSecret"){
+
+ # return file name match
+ $_
+ }
+ }
+ }
+
+ # Create new secret files objects
+ $InterestingFilesAllSecretsObjects = $InterestingFilesAllSecrets |
+ foreach{
+
+ # Set target file
+ $TargetSecretFile = $_
+
+ # Filter for record with the target file
+ $TargetSecretMatches = $ExcessiveSharePrivs | where FileList -like "*$TargetSecretFile*" | select ComputerName,ShareName,SharePath -Unique
+ $TargetSecretMatches |
+ foreach {
+
+ # Select the propertity and make new ones
+ $TargetSecretComputer = $_.ComputerName
+ $TargetSecretShareName = $_.ShareName
+ $TargetSecretSharePath = $_.SharePath
+ $TargetSecretUNCPath = "$TargetSecretSharePath\$TargetSecretFile"
+ $TargetSecretType = "Secrets"
+
+ # Create updated object
+ $object = New-Object psobject
+ $object | add-member noteproperty ComputerName $TargetSecretComputer
+ $object | add-member noteproperty ShareName $TargetSecretShareName
+ $object | add-member noteproperty SharePath $TargetSecretSharePath
+ $object | add-member noteproperty UncPath $TargetSecretUNCPath
+ $object | add-member noteproperty FileName $TargetSecretFile
+ $object | add-member noteproperty DataType $TargetSecretType
+
+ # Return object
+ $object
+ }
+ } | select ComputerName,ShareName,SharePath,UncPath,FileName,DataType -Unique
+
+ # Identify Data
+ $InterestingFilesAllData = $FileNamePatternsData |
+ foreach {
+ $TargetSecret = $_
+ $InterestingFilesAllFileNames |
+ foreach {
+ if($_ -like "$TargetSecret"){
+
+ # return file name match
+ $_
+ }
+ }
+ }
+
+ # Create new data files objects
+ $InterestingFilesAllDataObjects = $InterestingFilesAllData |
+ foreach{
+
+ # Set target file
+ $TargetSecretFile = $_
+
+ # Filter for record with the target file
+ $TargetSecretMatches = $ExcessiveSharePrivs | where FileList -like "*$TargetSecretFile*" | select ComputerName,ShareName,SharePath -Unique
+ $TargetSecretMatches |
+ foreach {
+
+ # Select the propertity and make new ones
+ $TargetSecretComputer = $_.ComputerName
+ $TargetSecretShareName = $_.ShareName
+ $TargetSecretSharePath = $_.SharePath
+ $TargetSecretUNCPath = "$TargetSecretSharePath\$TargetSecretFile"
+ $TargetSecretType = "Sensitive"
+
+ # Create updated object
+ $object = New-Object psobject
+ $object | add-member noteproperty ComputerName $TargetSecretComputer
+ $object | add-member noteproperty ShareName $TargetSecretShareName
+ $object | add-member noteproperty SharePath $TargetSecretSharePath
+ $object | add-member noteproperty UncPath $TargetSecretUNCPath
+ $object | add-member noteproperty FileName $TargetSecretFile
+ $object | add-member noteproperty DataType $TargetSecretType
+
+ # Return object
+ $object
+ }
+ } | select ComputerName,ShareName,SharePath,UncPath,FileName,DataType -Unique
+
+ # Combine objects
+ $InterestingFilesAllObjects = $InterestingFilesAllSecretsObjects + $InterestingFilesAllDataObjects
+
+
+ # Count objects
+ $InterestingFilesAllSecretsFullCount = $InterestingFilesAllSecretsObjects | measure | select count -ExpandProperty count
+ $InterestingFilesAllSecretsFullCountU = $InterestingFilesAllSecretsObjects | select FileName -Unique | measure | select count -ExpandProperty count
+ $InterestingFilesAllDataFullcount = $InterestingFilesAllDataObjects | measure | select count -ExpandProperty count
+ $InterestingFilesAllDataFullcountU = $InterestingFilesAllDataObjects | select FileName -Unique | measure | select count -ExpandProperty count
+ #>
+
+ # Outbout objects to file
+ $InterestingFilesAllObjects | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Interesting-Files.csv"
+
+ # Get order list of interesting file names by count
+ $InterestingFilesAllFilesCount = $InterestingFilesAllObjects | measure | select count -ExpandProperty count
+ $InterestingFilesAllFilesCountU = $InterestingFilesAllObjects | select filename -Unique | measure | select count -ExpandProperty count
+ $InterestingFilesAllFilesGrouped = $InterestingFilesAllObjects | group filename | select count,name | sort count -Descending
+
+ # Generate a row for each one
+ # Headers are Instance Count, FileName, Type, File Paths,Affected Computers, Affected Shares
+ $InterestingFilesAllFilesRows = $InterestingFilesAllFilesGrouped |
+ foreach{
+
+ # Get count
+ $IfFinalCount = $_.count
+
+ # Get File Name
+ $IfFinalName = $_.name
+
+ # Category
+ $IfFinalType = $InterestingFilesAllObjects | Where-Object { $_.FileName -like "$IfFinalName" } | select Category -First 1 -ExpandProperty Category
+
+ # Get File Paths
+ $IfFinalPaths = $InterestingFilesAllObjects | Where-Object { $_.FileName -like "$IfFinalName" } | ForEach-Object { $ASDF = $_.UncPath; "$ASDF
" } | Out-String
+
+ # Get Share Count for Name
+ #