While reading the following article on Didier Steven’s blog, http://blog.didierstevens.com/2012/10/01/searching-for-that-adobe-cert/, I’ve noticed a screenshot where VirusTotal detection results are reported. He also mentioned that we can actually search virustotal and points to his page http://blog.didierstevens.com/2012/05/21/searching-with-virustotal/ where he says:
Did you know that you can search VirusTotal? You don’t have to submit a file, but you can search for the report of a file has been submitted before. You use a cryptographic hash (MD5, SHA1, SHA256) to identify the file.
If I go to this page https://www.virustotal.com/#search and submit for example the SHA1 of the C:\Windows\SysWOW64\ntoskrnl.exe of my Windows 7 x64 SP1 (en-US) computer
I’ve got the following results:
With the following sample code, I can get the same returned as a powershell object:
$checksum = "4988e05aaae2fa035b8199295be7d4cf5527e4cb" $res = (Invoke-WebRequest -Uri 'https://www.virustotal.com/search/' -Method Post -Body "query=$checksum") $page = Invoke-WebRequest -Method GET -Uri $res.BaseResponse.ResponseUri.OriginalString $obj = New-Object -TypeName PSObject ($page.AllElements | ? { ($_.TagName -eq 'TBODY') -and ($_.outerHTML -match "$checksum") }).OuterText -split "`n" | % { $obj | Add-Member -MemberType NoteProperty -Name ($_ -split ":")[0] -Value (-join($_ -split ":" )[1..($_ -split ":" ).count]) } $obj
Cool, isn’t it ? Wait, there’s more. There are more detailed tabs.
We can access these tabs this way:
$page.AllElements.FindById('antivirus-results').outerHTML $page.AllElements.FindById('behavioural-info').outerHTML $page.AllElements.FindById('additional-info').outerHTML
Here’s the function that parses 2 of the 3 tabs. Parsing behavioural-info is a hassle..
# Requires -Version 3.0 Function Test-VTresults { [CmdletBinding()] param( [Parameter(Mandatory,ValueFromPipeline)] [string[]]$CheckSum ) Begin { $URI = 'https://www.virustotal.com/search/' } Process { if ($CheckSum) { $CheckSum | ForEach-Object -Process { Write-Verbose -Message "Dealing with $_" $res = (Invoke-WebRequest -Uri $URI -Method Post -Body "query=$_") $page = Invoke-WebRequest -Method GET -Uri $res.BaseResponse.ResponseUri.OriginalString # Main tab $obj = New-Object -TypeName PSObject ($page.AllElements | Where-Object { ($_.TagName -eq 'TBODY') -and ($_.outertext -match 'Detection\sratio') } ).OuterText -split "`n" | ForEach-Object -Process { $obj | Add-Member -MemberType NoteProperty -Name ($_ -split ":")[0] -Value (-join($_ -split ":" )[1..($_ -split ":" ).count]) } # Analysis tab $count = 0 $analysisar = @() $AVName = $DetectionDate = $DetectionRate = $null ([regex]'<TD(>|(\sclass=text\-red>))(?<ID>.*)</TD>').Matches( $page.AllElements.FindById('antivirus-results').outerHTML) | ForEach-Object -Process { $count++ switch ((@($_.Groups))[-1]) { {$_ -match '\d{8}'} { $DetectionDate = $_ ; break} {$_ -match '^\-$'}{ $DetectionRate = '-' ; break } {$_ -match '.*'} { if ($count -eq 1) { $AVName = $_ } else { $DetectionRate = $_ } ; break } } if ($count -eq 3) { $count = 0 $analysisar += New-Object -TypeName PSObject -Property @{ Update = $DetectionDate Result = $DetectionRate Antivirus = $AVName } } } # Add the analysis results array as a single property $obj | Add-Member -MemberType NoteProperty -Name Analysis -Value $analysisar if ($page.AllElements.FindById('additional-info')) { $locations = $string = $null # Identify indexes where the H5 tag is located $locations = ([regex]'<H5>').Matches($page.AllElements.FindById('additional-info').outerHTML).Index if ($locations) { $additionalinfoar = @() # Last item and content,...</LI> is missing at the end of each line for easy parsing 😦 # $string = $page.AllElements.FindById('additional-info').outerHTML.Substring($locations[-1]) for ($i = 0 ; $i -le ($locations.Count-2) ; $i++) { # Define the string between two H5 tags $string = $page.AllElements.FindById('additional-info').outerHTML.Substring($locations[$i],($locations[$i+1]-$locations[$i])) # Split this new string switch -Regex ($string) { # Case 1 '<H5>(?<Tool>.*)</H5>(?<text>.*)</TD></TR>' { $additionalinfoar += New-Object -TypeName PSObject -Property @{ Item = ([regex]'<H5>(?<Item>.*)</H5>(?<Content>.*)</TD></TR>').Matches($string).Groups[1].Value Content = (([regex]'<H5>(?<Item>.*)</H5>(?<Content>.*)</TD></TR>').Matches($string).Groups[2].Value -split '<BR>') | Out-String } } # Case 2 '<H5>(?<Tool>.*)</H5><PRE\sstyle=\"MAX\-WIDTH:\s\d{3}px\">(?<text>.*)' { $additionalinfoar += New-Object -TypeName PSObject -Property @{ Item = ([regex]'<H5>(?<Item>.*)</H5><PRE\sstyle=\"MAX\-WIDTH:\s\d{3}px\">(?<Content>.*)').Matches($string).Groups[1].Value Content = -join ( $string[ ([regex]'<H5>(?<Tool>.*)</H5><PRE\sstyle=\"MAX\-WIDTH:\s\d{3}px\">').Matches($string).Length.. (([regex]'</PRE></TD></TR>').Matches($string).Index-1) ]) } } } } $obj | Add-Member -MemberType NoteProperty -Name 'additional-info' -Value $additionalinfoar } } # Output $obj } } } End {} <# .SYNOPSIS Search virustotal.com for checksum and parse the returned HTML page for relevant information. .DESCRIPTION Submit an array of checksum MD5, SHA1, SHA256 and get the info from the main tab, analysis results and additional info. .PARAMETER Checksum Array of checksum strings that can either be a MD5, SHA1 or SHA256 .NOTES Name: Test-VTresults Author: Emin Atac DateCreated: 17/01/2013 .LINK https://p0w3rsh3ll.wordpress.com .EXAMPLE Test-VTresults 4988e05aaae2fa035b8199295be7d4cf5527e4cb Search virustotal.com for the SHA1 checksum of C:\Windows\SysWOW64\ntoskrnl.exe of a Windows 7 x64 SP1 (en-us) computer .EXAMPLE a6c80ce949469cc86f6c22355f4d3bb8773fc634 | Test-VTresults Search virustotal.com for the SHA1 checksum of eicar.com #> }
Now, let’s see how to use the above function 🙂
I’ve seen the recent post about EICAR being generated by powershell on this page: http://www.obscuresecurity.blogspot.fr/2013/01/New-Eicar.html
(also published on http://poshcode.org/3874).
Let’s have some fun with it, here’s my one-liner with a different approach 😛 :
[System.Text.Encoding]::UTF8.GetString(@( ('8853793380376465809152928090885352408094415567674155'-split "(?<=\G.{2})",26)+ '125'+ ('36697367658245838465786865826845657884738673828583458469838445707376693336724372421310'-split "(?<=\G.{2})",43)) ).Trim()|Out-File E:\eicar.txt -Force -Encoding ASCII
If I use the Get-Checksum I’ve already presented on this page, I can do
Get-CheckSum -FilePath E:\eicar.txt | Test-VTresults
'fe71aa78dc9288e9997482380c4f270495ca7631', '91e764c72619b2e469bded5c21e2a6826aadad62' | Test-VTresults -Verbose | Select -ExpandProperty Analysis
'91e764c72619b2e469bded5c21e2a6826aadad62' | Test-VTresults -Verbose | Select -ExpandProperty 'additional-info' | Select -ExpandProperty Content
Did I already say that Powershell rocks! 😎
Cool script!
is there anyway that we can check a text file with all the checksum and compare it with VT?
Hi,
Yes, you can read my most recent article about VT on this page:
https://p0w3rsh3ll.wordpress.com/2014/04/05/analysing-files-with-virustotal-com-public-api/
Note that it’s already 8 months old and that the web page returned by VT and its underlying HTML code being parsed with regular expressions may have changed.