自定义 PSObject 返回数组而不是 Object 属性

Custom PSObject is returning Array instead of the Object properties

我很难弄清楚这段代码在哪里出错,以及为什么 Select-Object 没有返回所需的 object 属性作为输出。非常感谢对这里发生的事情的任何输入,或任何潜在的修复。

我通过(单独的)处理程序脚本从 Sysmon 日志中收集所有唯一的 sha256 哈希值,然后处理程序脚本针对这些哈希值执行下面的 script/code。此处理程序脚本运行下面看到的代码,然后将其输出 (script.ps1 | export-csv) 通过管道传输到 Export-Csv 函数中。但是,我在我的 csv 输出中得到了每个 object 的数组,而不是带有列 headers 和所需 object 属性的格式化 CSV 文件。

为了完整起见,运行此(下面的代码)脚本的处理程序脚本。ps1 文件是 Kansa

# VirusTotal API Key 
$apikeyVirusTotal = "ABC123MyFreeVirusTotalAPIKey" 

$hashArray = @() #Array to hold multiple objects 

# VirusTotal Function - API/URI 
Function SubmitVirusTotalURL($hash) {
    Write-Host "Sleeping to avoid rate control."
    Start-Sleep -Seconds 16
    Write-Verbose "Checking VirusTotal: $hash"    
    $response = Invoke-WebRequest -Uri "https://www.virustotal.com/vtapi/v2/file/report?apikey=$apikeyVirusTotal&resource=$hash" | ConvertFrom-Json
    return $response
}

# Import the CSV File and assign it to the variable $CSV
$CSV = Import-Csv -Path ".\test.csv"
#For each line in CSV get the column name value   
foreach ($line in $CSV){
    $hashCount = $line.ct 
    $hash = $line.sha256
    IF($hashCount -lt 2 -and (-not ([string]::IsNullOrEmpty($hash)))){
        $httpResponse = SubmitVirusTotalURL($hash)        
        #create a custom object to hold VT data
        $obj = [PSCustomObject]@{
            'hash' = $hash 
            'sha256'   = $httpResponse.sha256
            'Detections' = $httpResponse.positives
            'TotalScanners' = $httpResponse.total
            'VTReport' = $httpResponse.permalink
        }
        $hashArray += $obj
    }
}
$hashArray

样本输入文件test.csv:

ct, sha256
3, A3CFFBD12ACDB85D24A13E3976B8795C5611DA05C2017755D87B5ECE38D50806
3, 0CD2F3CF62B768F4036605665E6DD888F431B8FEBDA77D07E852F12523072FFC
4, 405F03534BE8B45185695F68DEB47D4DAF04DCD6DF9D351CA6831D3721B1EFC4
1, FAKEHA534BE8B45185695F68DEB47D4DAF04DCD6DF9D351CA6831D3721B1EFC4

这会生成一个包含如下输出的 csv 文件:

@{Sha256=0cd2f3cf62b768f4036605665e6dd888f431b8febda77d07e852f12523072ffc    Detections=0    TotalScanners=72    VTReport=https://www.virustotal.com/gui/file/0cd2f3cf62b768f4036605665e6dd888f431b8febda77d07e852f12523072ffc/detection/f-0cd2f3cf62b768f4036605665e6dd888f431b8febda77d07e852f12523072ffc-1589711909}
@{Sha256=7edc950ecfbbb043a62f31f01be2710892bb34455dd7ea435ce1346873d3f36f    Detections=0    TotalScanners=69    VTReport=https://www.virustotal.com/gui/file/7edc950ecfbbb043a62f31f01be2710892bb34455dd7ea435ce1346873d3f36f/detection/f-7edc950ecfbbb043a62f31f01be2710892bb34455dd7ea435ce1346873d3f36f-1572295279}
@{Sha256=8eaa83ed280a3d7d4f8dd3e4f8cbc28cb7fc74947cfca133fb627db0bc767f30    Detections=0    TotalScanners=71    VTReport=https://www.virustotal.com/gui/file/8eaa83ed280a3d7d4f8dd3e4f8cbc28cb7fc74947cfca133fb627db0bc767f30/detection/f-8eaa83ed280a3d7d4f8dd3e4f8cbc28cb7fc74947cfca133fb627db0bc767f30-1569383486}
@{Sha256=e871e48f75b213a51cf13a3a397c1b31b10b516cb4cfb5f0682c85387d3c5ed9    Detections=0    TotalScanners=72    VTReport=https://www.virustotal.com/gui/file/e871e48f75b213a51cf13a3a397c1b31b10b516cb4cfb5f0682c85387d3c5ed9/detection/f-e871e48f75b213a51cf13a3a397c1b31b10b516cb4cfb5f0682c85387d3c5ed9-1587296148}

为了增加我的困惑,我创建了一个功能几乎相同的测试脚本,减去 sha256Array @() 的添加并且我能够毫无问题地将输出传输到 Format-Table。

这里发生了什么?为什么使用如此相似的代码会得到两种不同类型的输出,我该如何纠正这些问题?

正如上面的所有评论,避免构建您现在正在做的方式:

删除这一行:

$hashArray = @() #Array to hold multiple objects 

现在使用:

#For each line in CSV get the column name value   
$CSV | ForEach-Object {
    $hashCount = $_.ct 
    $hash = $_.sha256
    If($hashCount -lt 2 -and (-not ([string]::IsNullOrEmpty($hash)))){
        $httpResponse = SubmitVirusTotalURL($hash)        
        #create a custom object to hold VT data
        [PSCustomObject]@{
            'hash' = $hash 
            'sha256'   = $httpResponse.sha256
            'Detections' = $httpResponse.positives
            'TotalScanners' = $httpResponse.total
            'VTReport' = $httpResponse.permalink
        }
    }
}

如上所述,如果它正在转换为字符串值,那么问题在于您如何将 $hasharray 传输到 csv。您可以直接通过管道传输到 csv 或保存在变量中以检查对象:

$hasharray = $CSV | ForEach-Object {
    $hashCount = $_.ct 
    $hash = $_.sha256
    If($hashCount -lt 2 -and (-not ([string]::IsNullOrEmpty($hash)))){
        $httpResponse = SubmitVirusTotalURL($hash)        
        #create a custom object to hold VT data
        [PSCustomObject]@{
            'hash' = $hash 
            'sha256'   = $httpResponse.sha256
            'Detections' = $httpResponse.positives
            'TotalScanners' = $httpResponse.total
            'VTReport' = $httpResponse.permalink
        }
    }
}
$hasharray | Export-Csv -Path 'pathtocsv\csvname.csv' -NoTypeInformation