PSCustomObject - Cycle through hashtable?

Welcome Forums General PowerShell Q&A PSCustomObject - Cycle through hashtable?

This topic contains 7 replies, has 3 voices, and was last updated by

 
Participant
3 months, 1 week ago.

  • Author
    Posts
  • #105764

    Participant
    Points: 2
    Rank: Member

    Hi All,

    I am not sure I am using the right terminology but here goes, I have written a function to retrieve a URL report from VirusTotal, the function I have written converts from the returned JSON to a PSCustomObject and I would like to get a certain element of the output, here is the code so far (I have my own API Key stored in $APIKey):

    function VT-RetrieveReport($URLToSend='https://test.co.uk'){
        $URL = 'http://www.virustotal.com/vtapi/v2/url/report'
        $PostParams = @{apikey="$APIKey";resource="$URLToSend"}
        $TheResponse = Invoke-WebRequest -Uri $URL -Method Post -Body $PostParams | ConvertFrom-Json
        return $TheResponse.Scans
        }
    

    This function returns a list like this:

    ZCloudsec : @{detected=False; result=clean site}
    PhishLabs : @{detected=False; result=unrated site}
    Zerofox : @{detected=True; result=clean site}

    These are note properties of a PSCustomObject, what I would like to do is get the 'detected=False' part of each blacklist name but I do not know how to achieve this, so far I can get the Name property which is just:

    ZCloudsec
    PhishLabs
    Zerofox

    by doing

    VT-RetrieveReport | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
    

    How do I access the key/value pairs of each of the Names? Ideally I would like to throw away any name that is detected=false and just keep the ones that say detected=true, so the output would look something like:

    Zerofox = True

    I hope that explains it, thanks again for any further help

  • #105769

    Participant
    Points: 59
    Rank: Member
    function VT-RetrieveReport($URLToSend='https://test.co.uk'){
        $URL = 'http://www.virustotal.com/vtapi/v2/url/report'
        $PostParams = @{apikey="$APIKey";resource="$URLToSend"}
        $TheResponse = Invoke-WebRequest -Uri $URL -Method Post -Body $PostParams | ConvertFrom-Json
        
        foreach ($BlackList in ($TheResponse.Scans | Get-Member -MemberType NoteProperty).Name) {
            if ($TheResponse.Scans.$BlackList.Detected) {
                [PSCustomObject]@{ $BlackList = $true }
            }
        } 
    }
    
    • #105772

      Participant
      Points: 2
      Rank: Member

      Thanks very much Sam.

  • #105848

    Participant
    Points: 2
    Rank: Member

    Hi again,

    I am trying to improve the function by outputting to a CSV file but I am struggling with the additional fields for the blacklists that show as something is malicious – the additional fields do not show on the CSV file 'Blacklist Name','Detected#,'Reason':

    function VT-RetrieveReport($URLToSend=@('http://test2.co.uk','http://www.test.co.uk','https://test3.co.uk','http://www.test4.co.uk')){
    $URL = 'http://www.virustotal.com/vtapi/v2/url/report'
    $CustomOutput = 
    ForEach ($URLToRetrieveReportFor in $URLToSend) {
            $PostParams = @{apikey="$APIKey";resource="$URLToRetrieveReportFor"}
            $TheResponse = Invoke-WebRequest -Uri $URL -Method Post -Body $PostParams | ConvertFrom-Json
            [hashtable]$ObjectProperty = @{}
            $ObjectProperty.Add('URL',$URLToRetrieveReportFor)
            $ObjectProperty.Add('ScanTime',[datetime]$TheResponse.scan_date)
            $ObjectProperty.Add('Blacklists Checked',$TheResponse.total)
    
        ForEach ($BlackList in ($TheResponse.Scans | Get-Member -MemberType NoteProperty).Name) {
            if ($TheResponse.Scans.$BlackList.Detected) {
                $ObjectProperty.Add('Blacklist Name',$BlackList)
                $ObjectProperty.Add('Detected',$TheResponse.Scans.$BlackList.Detected)
                $ObjectProperty.Add('Reason',$TheResponse.Scans.$BlackList.Result)
                }
                
            }
            New-Object -TypeName PSObject -Property $ObjectProperty 
        }
        $CustomOutput | Export-Csv C:\users\me\desktop\test.csv -Append -NoTypeInformation
    }
    

    Thanks for any further help

  • #105946

    Participant
    Points: 2
    Rank: Member

    Is there a way to run the function, store all of the processing output and then send it to CSV?

    • #105980

      Participant
      Points: 160
      Helping Hand
      Rank: Participant

      Nested objects are nested objects for a reason, so the won't always parse cleanly. Anytime that you are trying to flatten something, you're making assumptions that the data your getting will cooperate. For instance, if there are additional scans or more information in the "Scans", the loop will catch them but I'm not sure it would add that property to the export because it's not in every object.

      My question is why put it into a CSV? You can do a ton of analysis without ever needing to stare at a spreadsheet.

      To answer you last question, Export-CSV will export to a CSV, but it's probably not going to look how you expect.

      "scan_date","total","scans"
      "8/6/2018 9:24:50 AM","3","@{ZCloudsec=System.Collections.Hashtable; PhishLabs=System.Collections.Hashtable; Zerofox=System.Collections.Hashtable}"
      

      You do need to do a parse to make it flat, so here is goes. With out having the JSON and from what you posted, I created a mock object from the response. The key is the hash values are all the same, so you're going to need to do some concatenation to get a unique value for detected and result. Take a look at this code which should get you pretty close to what you are attempting:

      $urls = 'http://test2.co.uk','http://www.test.co.uk','https://test3.co.uk','http://www.test4.co.uk'
      
      foreach ($url in $urls) {
          $theResponse = [pscustomobject]@{
              scan_date = (Get-Date)
              total = 3
              scans = [pscustomobject]@{
                  ZCloudsec = @{detected=$false; result='clean site'}
                  PhishLabs = @{detected=$false; result='unrated site'}
                  Zerofox = @{detected=$true; result='clean site'}
              }
          }
          
          $props = @{}
          $props.Add('Url', $url)
          $props.Add('Scan Time', $theResponse.scan_date)
          $props.Add('Blacklists Checked', $theResponse.total)
      
          foreach ($scan in $theResponse.Scans.PSObject.Properties) {
              foreach ($hash in $scan.Value.GetEnumerator()) {
                  $props.Add(('{0}_{1}' -f $scan.Name, $hash.Name), $hash.Value)
              }
          }
          
          New-Object -TypeName PSObject -Property $props
      }
      

      Output:

      Url                : http://test2.co.uk
      Blacklists Checked : 3
      PhishLabs_detected : False
      Zerofox_result     : clean site
      Zerofox_detected   : True
      Scan Time          : 8/6/2018 9:24:49 AM
      ZCloudsec_detected : False
      ZCloudsec_result   : clean site
      PhishLabs_result   : unrated site
      
      Url                : http://www.test.co.uk
      Blacklists Checked : 3
      PhishLabs_detected : False
      Zerofox_result     : clean site
      Zerofox_detected   : True
      Scan Time          : 8/6/2018 9:24:50 AM
      ZCloudsec_detected : False
      ZCloudsec_result   : clean site
      PhishLabs_result   : unrated site
      
      Url                : https://test3.co.uk
      Blacklists Checked : 3
      PhishLabs_detected : False
      Zerofox_result     : clean site
      Zerofox_detected   : True
      Scan Time          : 8/6/2018 9:24:50 AM
      ZCloudsec_detected : False
      ZCloudsec_result   : clean site
      PhishLabs_result   : unrated site
      
      Url                : http://www.test4.co.uk
      Blacklists Checked : 3
      PhishLabs_detected : False
      Zerofox_result     : clean site
      Zerofox_detected   : True
      Scan Time          : 8/6/2018 9:24:50 AM
      ZCloudsec_detected : False
      ZCloudsec_result   : clean site
      PhishLabs_result   : unrated site
      
    • #107749

      Participant
      Points: 2
      Rank: Member

      Thanks very much Rob, just what I was after.  Things like this really knock confidence when I cannot figure something out for myself.

  • #107764

    Participant
    Points: 160
    Helping Hand
    Rank: Participant

    Your welcome!!  That is what a community is supposed to do, help!!

The topic ‘PSCustomObject - Cycle through hashtable?’ is closed to new replies.