勒索软件攻击后Windows服务器文件夹权限审计PowerShell脚本嵌套循环故障排查求助
Let's break down what's going wrong with your script and fix it step by step. Your original code has several syntax errors and logical issues that are causing those null value and parameter binding errors.
Key Issues in Your Original Script
- Incorrect
ForEachusage: You're mixing up theForEachkeyword (used for collection loops) withForEach-Object(the pipeline-aware cmdlet). When piping output fromGet-ChildItem, you needForEach-Object(or its alias%). - Malformed
Get-Itemcalls: The nestedGet-Itemblocks with script blocks forLiteralPathare invalid—you don't need to re-fetch the item becauseGet-ChildItemalready returns the directory object (accessible via$_). - Missing commas in
Select: Your calculated properties inSelect-Objectaren't separated by commas, which breaks the syntax. - Incorrect path construction: When building
$StartPath, using$DriveLetter:" can cause issues because$DriveLetteris aPSDriveobject, not just a string. Use itsRootproperty instead. - Misplaced
Export-CSV: The cmdlet is placed inside the pipeline incorrectly, so it never receives the output fromSelect-Object. - Redundant directory checks:
Get-ChildItem -Recurse | ?{ $_.PSIsContainer }already filters for directories, so you don't need to re-checkPSIsContainerlater (though we'll keep clarity in the fixed version).
Fixed PowerShell Script
$ErrorActionPreference = "Continue" $strComputer = $env:ComputerName $colDrives = Get-PSDrive -PSProvider Filesystem # Loop through each filesystem drive foreach ($drive in $colDrives) { # Skip drives that aren't ready (like empty CD-ROMs) if (-not (Test-Path -LiteralPath $drive.Root)) { Write-Warning "Skipping unavailable drive: $($drive.Name)" continue } # Get all directories recursively, fetch their ACLs, and format output Get-ChildItem -LiteralPath $drive.Root -Recurse -Directory -ErrorAction SilentlyContinue | ForEach-Object { $directory = $_ # Get the access control list for the directory $acl = Get-Acl -LiteralPath $directory.FullName # Loop through each access rule in the ACL (one row per permission entry) foreach ($accessRule in $acl.Access) { # Output a custom object with all required audit properties [PSCustomObject]@{ 'Server Name' = $strComputer 'Full Path' = $directory.FullName 'Type' = 'D' # We're only processing directories here 'Owner' = $acl.Owner 'Trustee' = $accessRule.IdentityReference 'Inherited' = $accessRule.IsInherited 'Inheritance Flags' = $accessRule.InheritanceFlags 'Ace Flags' = $accessRule.PropagationFlags 'Ace Type' = $accessRule.AccessControlType 'Access Masks' = $accessRule.FileSystemRights } } } | # Export to CSV (one file per drive, overwrites existing files) Export-Csv -NoTypeInformation -Delimiter "|" -Path "$strComputer`_$($drive.Name).csv" -Force }
What's Fixed & Improved
- Drive Handling: We use
$drive.Rootto get the correct root path of each drive, and add aTest-Pathcheck to skip inaccessible drives (like empty optical drives). - Simplified Directory Fetch:
Get-ChildItem -Directoryreplaces the old filter for cleaner syntax.-ErrorAction SilentlyContinueprevents the script from crashing when it hits folders you don't have permission to read. - ACL Retrieval: We use
Get-Acldirectly on the directory'sFullNameinstead of the brokenDirectoryInfo.GetAccessControl()call—this is more reliable and idiomatic PowerShell. - Nested Loop for Access Rules: Each directory's ACL has multiple permission entries (one per user/group), so we loop through each
$accessRuleto create a separate CSV row for every entry. This ensures you get a complete audit of all permissions. - Valid Custom Objects: We use
[PSCustomObject]to create structured output that works seamlessly withExport-Csv. - Correct CSV Export:
Export-Csvis placed at the end of the pipeline, so it receives all the custom objects and writes them to the file.-Forcelets you overwrite existing audit files if needed.
Testing Tips
- Run PowerShell as Administrator to ensure you have permission to read all directories on the drives.
- The script will create a CSV file for each drive (e.g.,
DESKTOP-ABC123_C.csv) in the directory where you run the script. - Each CSV row represents a single permission entry, making it easy to compare permissions pre- and post-attack.
内容的提问来源于stack exchange,提问作者Taylor Arter




