You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

勒索软件攻击后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 ForEach usage: You're mixing up the ForEach keyword (used for collection loops) with ForEach-Object (the pipeline-aware cmdlet). When piping output from Get-ChildItem, you need ForEach-Object (or its alias %).
  • Malformed Get-Item calls: The nested Get-Item blocks with script blocks for LiteralPath are invalid—you don't need to re-fetch the item because Get-ChildItem already returns the directory object (accessible via $_).
  • Missing commas in Select: Your calculated properties in Select-Object aren't separated by commas, which breaks the syntax.
  • Incorrect path construction: When building $StartPath, using $DriveLetter:" can cause issues because $DriveLetter is a PSDrive object, not just a string. Use its Root property instead.
  • Misplaced Export-CSV: The cmdlet is placed inside the pipeline incorrectly, so it never receives the output from Select-Object.
  • Redundant directory checks: Get-ChildItem -Recurse | ?{ $_.PSIsContainer } already filters for directories, so you don't need to re-check PSIsContainer later (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

  1. Drive Handling: We use $drive.Root to get the correct root path of each drive, and add a Test-Path check to skip inaccessible drives (like empty optical drives).
  2. Simplified Directory Fetch: Get-ChildItem -Directory replaces the old filter for cleaner syntax. -ErrorAction SilentlyContinue prevents the script from crashing when it hits folders you don't have permission to read.
  3. ACL Retrieval: We use Get-Acl directly on the directory's FullName instead of the broken DirectoryInfo.GetAccessControl() call—this is more reliable and idiomatic PowerShell.
  4. Nested Loop for Access Rules: Each directory's ACL has multiple permission entries (one per user/group), so we loop through each $accessRule to create a separate CSV row for every entry. This ensures you get a complete audit of all permissions.
  5. Valid Custom Objects: We use [PSCustomObject] to create structured output that works seamlessly with Export-Csv.
  6. Correct CSV Export: Export-Csv is placed at the end of the pipeline, so it receives all the custom objects and writes them to the file. -Force lets 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

火山引擎 最新活动