diff --git a/Scripts/Analyze-HuntSMBShares.ps1 b/Scripts/Analyze-HuntSMBShares.ps1
index a14f9e3..23d4122 100644
--- a/Scripts/Analyze-HuntSMBShares.ps1
+++ b/Scripts/Analyze-HuntSMBShares.ps1
@@ -5,7 +5,7 @@
#--------------------------------------
# Author: Scott Sutherland, 2024 NetSPI
# License: 3-clause BSD
-# Version: v1.40
+# Version: v1.45
# References: This script includes custom code and code taken and modified from the open source projects PowerView, Invoke-Ping, and Invoke-Parrell.
function Analyze-HuntSMBShares
{
@@ -1821,18 +1821,10 @@ function Analyze-HuntSMBShares
Below is a summary of number of share ACLs by risk level and a summary of file name counts that may contain passwords, sensitive data, or result in remote code execution. Click the titles for more detail.
@@ -5214,7 +5196,7 @@ This section contains a list of the most common SMB share names. In some cases,
iTHD/4Hv7s1i9NTblIwDvS+2PbHOBDYBVoN2/4+tu3WCeB/Bq60jr/WBOY+SW90tPARMLQNXFx3NHkPuNwBRp50yZAcyU9TKBaB9zP6pjwwfAv0r7m9tfdx+gBkqavlG+DgEIiUKHvd49193b39e6bd3w/VdnLO67/jCAAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0
SU1FB+gHDA40BpbiKy8AAAEjSURBVBjTXZAxS4JhFIWfe5XqA6NIBSvK1pak2tqjvb8Q/oUImgPnqL/R7tbYVPCtUb46iKYoSUGK3tvQK0hnu889HO49Uq1eyOXVtRby+Q1VrSBSBpaBMRDMLG2GMLi/uzV5fXvPFIvFHRE5A0qAAVMgCyjQNbN6v99vyfBzVFTVc2ArprWAHrAJbANLQNts9qCqWom
JAB/u9uzuPXd/AjqRl1T1QIEyIBGuiuiJiJwCGeArcgHZy8Zn5loHcsBL5IWF3bLGOxf1DUxEZP+feazgAfAF+OOOAGuxDQB396BmloJ3F8w5EXbjOXN1zCzVZggDM68D7dhxEttJ/mZvu1u92QyDzGw25fDoeJQkK0FExiAKTIAhkJrZY2g0urXajf0CiVl4icFa+XEAAAAASUVORK5CYII=" />Interesting Files are filenames that may be sensitive.
-
+
@@ -5298,16 +5280,14 @@ Folder groups are SMB shares that contain the exact same file listing. Each file
Loading...
-
+
-
Unique Share Name Count
-
Affected Share Count
+
Unique Share Names
+
Share Count
File Group
File Count
-
Affected Computers
-
Affected Shares
-
Affected ACLs
+
Affected ACLs
@@ -5871,6 +5851,7 @@ const ChartDashboardRiskOptions = {
const ChartDashboardRisk = new ApexCharts(document.querySelector("#ChartDashboardRisk"), ChartDashboardRiskOptions);
ChartDashboardRisk.render();
+
// --------------------------
// Function to support collapsing and expanding sections
// --------------------------
@@ -5882,10 +5863,18 @@ for (i = 0; i < coll.length; i++) {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.maxHeight){
+
content.style.maxHeight = null;
+
+ // Adjust width
+ content.style.width = 0;
+
} else {
content.style.Height = content.scrollHeight + "px";
content.style.maxHeight = "100%";
+
+ // Adjust width
+ content.style.width = "auto";
}
});
}
@@ -5893,9 +5882,10 @@ for (i = 0; i < coll.length; i++) {
function toggleDiv(TargetObjectId) {
var content = document.getElementById(TargetObjectId);
if (content.style.display === "none") {
- content.style.display = "block";
+ content.style.display = "block";
} else {
- content.style.display = "none";
+ content.style.display = "none";
+ content.style.width = 0;
}
}
@@ -5975,7 +5965,7 @@ const chartOptions = {
},
plotOptions: {
bar: {
- borderRadius: 4,
+ borderRadius: 0,
horizontal: false,
colors: {
ranges: [{
@@ -6239,24 +6229,38 @@ applyFiltersAndSort('InterestingFileTable', 'filterInputIF', 'filterCounterIF',
// CSV export function
function extractAndDownloadCSV(tableId, columnIndex) {
- const regex = /\\\\[^\s\\]+\\[^\s\\]+\\[^\s\\]+/g; // UNC path regex
+ // Regex to match \\server\share, \\server\share folder, and \\server\share\file.ext formats, allowing spaces
+ const regex = /\\\\[^\\\s]+\\[^\\]+(?:\\[^\\]*)*/g;
const uncPaths = [];
- // Loop through each filtered row
- currentFilteredRows.forEach(row => {
+ // Get the table element by ID
+ const table = document.getElementById(tableId);
+
+ // Determine rows to process: filtered rows or all rows if no filter is applied
+ const rowsToProcess = currentFilteredRows.length > 0 ? currentFilteredRows : Array.from(table.rows);
+
+ // Loop through each row to process
+ rowsToProcess.forEach(row => {
const cells = row.getElementsByTagName('td');
if (cells[columnIndex]) {
- const cellValue = cells[columnIndex].innerText;
- const matches = cellValue.match(regex);
- if (matches) {
- uncPaths.push(...matches);
+ // Get the div with class 'content' inside the cell
+ const contentDiv = cells[columnIndex].querySelector('.content');
+ if (contentDiv) {
+ const cellValue = contentDiv.innerText;
+ const matches = cellValue.match(regex);
+ if (matches) {
+ uncPaths.push(...matches);
+ }
}
}
});
+ // Remove empty or whitespace-only entries
+ const cleanUncPaths = uncPaths.map(path => path.trim()).filter(path => path.length > 0);
+
// Generate CSV content
let csvContent = 'data:text/csv;charset=utf-8,';
- csvContent += uncPaths.join('\n');
+ csvContent += cleanUncPaths.join('\n');
// Create a link to download the CSV file
const encodedUri = encodeURI(csvContent);
@@ -6291,6 +6295,7 @@ function extractAndDownloadCSV(tableId, columnIndex) {
"@
$NewHtmlReport | Out-File "$OutputDirectory\Summary-Report-$TargetDomain.html"
+$Time = Get-Date -UFormat "%m/%d/%Y %R"
Write-Output " [*][$Time] - Done."
Write-Output ""
Write-Output ""