From ffe0f8b548361ca01fd53d5011eb2c32d88cf450 Mon Sep 17 00:00:00 2001 From: Scott Sutherland Date: Thu, 18 Jul 2024 15:12:08 -0500 Subject: [PATCH] Update PowerHuntShares.psm1 Small sort function update. --- PowerHuntShares.psm1 | 253 ++++++++++++++++++++++--------------------- 1 file changed, 130 insertions(+), 123 deletions(-) diff --git a/PowerHuntShares.psm1 b/PowerHuntShares.psm1 index f3f8f38..171baa6 100644 --- a/PowerHuntShares.psm1 +++ b/PowerHuntShares.psm1 @@ -4,7 +4,7 @@ #-------------------------------------- # Author: Scott Sutherland, 2024 NetSPI # License: 3-clause BSD -# Version: v1.74 +# Version: v1.75 # 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 { @@ -5071,43 +5071,43 @@ This section contains a list of the most common SMB share names. In some cases, - - - - - - -
Share
Count  
Share
Count  
Share Count
is the number of unique shares with
the same name.
Share
Name  
Share
Name  
Share Name
is the name of a
collection of share
with the same name.
Risk
Level  
Risk
Level  
Risk Level
relfects the exposure of credentials and sensitive data.
Share
Similarity  
Share
Similarity  
Share Similarity
scores reflect how likely it is that the shares are related to each other.
Folder
Groups  
Folder
Groups  
Folder Groups
are groups of shares
that have the same
name and file listing.
Common
Files  
Common
Files  
Common Files
are file names that
exist in 10% or more
of the file groups.
Interesting
Files  
Interesting
Files  
{ + const cellA = a.cells[columnIndex].innerText.toLowerCase(); + const cellB = b.cells[columnIndex].innerText.toLowerCase(); - rows.forEach(row => row.classList.add('hidden')); - filteredRows.slice(startIndex, endIndex).forEach(row => row.classList.remove('hidden')); - - updatePagination(filteredRows.length); - updateFilterCounter(filteredRows.length); - - // If the current page has no rows, adjust the current page - if (filteredRows.length === 0 || filteredRows.slice(startIndex, endIndex).length === 0) { - if (currentPage > 1) { - currentPage--; - displayRows(filteredRows); - } - } - } - - function updatePagination(totalRows) { - const pageCount = Math.ceil(totalRows / rowsPerPage); - pagination.innerHTML = ''; - - for (let i = 1; i <= pageCount; i++) { - const pageButton = document.createElement('button'); - pageButton.textContent = i; - pageButton.classList.add('pagination-button'); - if (i === currentPage) pageButton.classList.add('active'); - pageButton.addEventListener('click', () => { - currentPage = i; - applyFiltersAndSort(); - }); - pagination.appendChild(pageButton); - } - } - - // Sorting - function sortTable(n, type = 'number') { - const dir = currentSortColumn === n && currentSortDir === "asc" ? "desc" : "asc"; - currentSortDir = dir; - currentSortColumn = n; - - rows.sort((a, b) => { - const cellA = a.cells[n].innerText.toLowerCase(); - const cellB = b.cells[n].innerText.toLowerCase(); - - if (type === 'number') { - if (!isNaN(parseFloat(cellA)) && !isNaN(parseFloat(cellB))) { - return dir === "asc" ? parseFloat(cellA) - parseFloat(cellB) : parseFloat(cellB) - parseFloat(cellA); - } else if (cellA.includes('%') && cellB.includes('%')) { - const numA = parseFloat(cellA.replace('%', '')); - const numB = parseFloat(cellB.replace('%', '')); - return dir === "asc" ? numA - numB : numB - numA; - } else { - if (cellA < cellB) return dir === "asc" ? -1 : 1; - if (cellA > cellB) return dir === "asc" ? 1 : -1; - return 0; - } + if (dataType === 'number') { + if (!isNaN(parseFloat(cellA)) && !isNaN(parseFloat(cellB))) { + return dir === "asc" ? parseFloat(cellA) - parseFloat(cellB) : parseFloat(cellB) - parseFloat(cellA); + } else if (cellA.includes('%') && cellB.includes('%')) { + const numA = parseFloat(cellA.replace('%', '')); + const numB = parseFloat(cellB.replace('%', '')); + return dir === "asc" ? numA - numB : numB - numA; } else { if (cellA < cellB) return dir === "asc" ? -1 : 1; if (cellA > cellB) return dir === "asc" ? 1 : -1; return 0; } + } else { + if (cellA < cellB) return dir === "asc" ? -1 : 1; + if (cellA > cellB) return dir === "asc" ? 1 : -1; + return 0; + } + }); + + rows.forEach(row => tbody.appendChild(row)); + updateSortIndicators(tableId, columnIndex); + applyFiltersAndSort(tableId, null, null, 'pagination'); + } + + function updateSortIndicators(tableId, columnIndex) { + const table = document.getElementById(tableId); + const headers = table.querySelectorAll("th"); + headers.forEach((th, index) => { + th.classList.remove("asc", "desc"); + if (index === columnIndex) { + th.classList.add(currentSortDir); + } + }); + } + + // Filtering Function + function applyFiltersAndSort(tableId, searchInputId, filterCounterId, paginationId) { + const table = document.getElementById(tableId); + const tbody = table.querySelector('tbody'); + const rows = Array.from(tbody.rows); + const searchInput = document.getElementById(searchInputId); + const filterCounter = document.getElementById(filterCounterId); + const checkboxes = document.querySelectorAll('.filter-checkbox'); + + const filterInputValue = searchInput ? searchInput.value.toLowerCase() : ''; + const checkedFilters = Array.from(checkboxes) + .filter(cb => cb.checked) + .map(cb => cb.name); + + const filteredRows = rows.filter(row => { + const cells = Array.from(row.cells); + const matchesTextFilter = cells.some(cell => cell.innerText.toLowerCase().includes(filterInputValue)); + const matchesCheckboxFilter = checkedFilters.every(filter => row.getAttribute(filter) === "Yes"); + + return matchesTextFilter && matchesCheckboxFilter; + }); + + let maxPage = Math.ceil(filteredRows.length / rowsPerPage) || 1; + if (currentPage > maxPage) { + currentPage = maxPage; + } + + displayRows(tableId, filteredRows, filterCounterId, paginationId); + } + + function updateFilterCounter(filterCounterId, visibleRows) { + const filterCounter = document.getElementById(filterCounterId); + filterCounter.textContent = ``Showing `${visibleRows} row${visibleRows !== 1 ? 's' : ''}``; + } + + // Pagination Functions + function displayRows(tableId, filteredRows, filterCounterId, paginationId) { + const table = document.getElementById(tableId); + const tbody = table.querySelector('tbody'); + const startIndex = (currentPage - 1) * rowsPerPage; + const endIndex = currentPage * rowsPerPage; + + Array.from(tbody.rows).forEach(row => row.classList.add('hidden')); + filteredRows.slice(startIndex, endIndex).forEach(row => row.classList.remove('hidden')); + + updatePagination(paginationId, filteredRows.length); + updateFilterCounter(filterCounterId, filteredRows.length); + + if (filteredRows.length === 0 || filteredRows.slice(startIndex, endIndex).length === 0) { + if (currentPage > 1) { + currentPage--; + displayRows(tableId, filteredRows, filterCounterId, paginationId); + } + } + } + + function updatePagination(paginationId, totalRows) { + const pagination = document.getElementById(paginationId); + const pageCount = Math.ceil(totalRows / rowsPerPage); + pagination.innerHTML = ''; + + for (let i = 1; i <= pageCount; i++) { + const pageButton = document.createElement('button'); + pageButton.textContent = i; + pageButton.classList.add('pagination-button'); + if (i === currentPage) pageButton.classList.add('active'); + pageButton.addEventListener('click', () => { + currentPage = i; + applyFiltersAndSort('sharenametable', 'filterInput', 'filterCounter', paginationId); }); - - const tbody = table.tBodies[0]; - rows.forEach(row => tbody.appendChild(row)); - - updateSortIndicators(n); - applyFiltersAndSort(); + pagination.appendChild(pageButton); } + } - function updateSortIndicators(n) { - const headers = document.querySelectorAll("th"); - headers.forEach((th, index) => { - th.classList.remove("asc", "desc"); - if (index === n) { - th.classList.add(currentSortDir); - } - }); - } + // Example Initialization + document.getElementById('filterInput').addEventListener("keyup", () => applyFiltersAndSort('sharenametable', 'filterInput', 'filterCounter', 'pagination')); + document.querySelectorAll('.filter-checkbox').forEach(checkbox => checkbox.addEventListener('change', () => applyFiltersAndSort('sharenametable', 'filterInput', 'filterCounter', 'pagination'))); - // Filtering - searchInput.addEventListener("keyup", applyFiltersAndSort); - checkboxes.forEach(checkbox => checkbox.addEventListener('change', applyFiltersAndSort)); - - function applyFiltersAndSort() { - const filterInputValue = searchInput.value.toLowerCase(); - const checkedFilters = Array.from(checkboxes) - .filter(cb => cb.checked) - .map(cb => cb.name); - - const filteredRows = rows.filter(row => { - const cells = Array.from(row.cells); - const matchesTextFilter = cells.some(cell => cell.innerText.toLowerCase().includes(filterInputValue)); - const matchesCheckboxFilter = checkedFilters.every(filter => row.getAttribute(filter) === "Yes"); - - return matchesTextFilter && matchesCheckboxFilter; - }); - - // Adjust currentPage if necessary to ensure it is not greater than the number of available pages - let maxPage = Math.ceil(filteredRows.length / rowsPerPage) || 1; - if (currentPage > maxPage) { - currentPage = maxPage; // Set to max page if current is too high - } - - displayRows(filteredRows); - } - - function updateFilterCounter(visibleRows) { - filterCounter.textContent = ```${visibleRows} matches found``; - } - - // Initial call to display rows - applyFiltersAndSort(); + // Initial call to display rows + applyFiltersAndSort('sharenametable', 'filterInput', 'filterCounter', 'pagination');