-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmulti-query.ps1
More file actions
112 lines (95 loc) · 3.55 KB
/
multi-query.ps1
File metadata and controls
112 lines (95 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
param (
[string]$outfile
)
if (-not $outfile) {
Write-Host "Usage: .\script.ps1 -outfile <path_to_output_file>"
exit
}
function Get-ApiKeys {
# Replace these with your primary and secondary API keys
return @("API_KEY1", "API_KEY2")
}
function Query-VirusTotalApi {
param (
[string]$identifier,
[string]$type,
[int]$retryCount = 0
)
$apiKeys = Get-ApiKeys
$apiKey = $apiKeys[$retryCount % $apiKeys.Count]
if ($type -eq "hash") {
$apiUrl = "https://www.virustotal.com/api/v3/files/$identifier"
} elseif ($type -eq "ip") {
$apiUrl = "https://www.virustotal.com/api/v3/ip_addresses/$identifier"
}
$headers = @{
"x-apikey" = $apiKey
}
$quotaExceeded = $false
try {
$response = Invoke-RestMethod -Uri $apiUrl -Method Get -Headers $headers -ErrorAction Stop
} catch [System.Net.WebException] {
$webException = $_.Exception
if ($webException.Response -and ($webException.Response -is [System.Net.HttpWebResponse])) {
$statusCode = [int]$webException.Response.StatusCode
if ($statusCode -eq 429) {
$quotaExceeded = $true
}
}
}
if ($quotaExceeded -or ($response -and $response.error -and $response.error.code -eq "QuotaExceededError")) {
if ($retryCount -lt $apiKeys.Count - 1) {
Start-Sleep -Seconds 2 # Adding delay between requests
return Query-VirusTotalApi -identifier $identifier -type $type -retryCount ($retryCount + 1)
}
}
return $response
}
function Process-ApiResponse {
param (
[object]$response,
[string]$identifier,
[int]$processId,
[string]$outfile,
[string]$type
)
if ($response -eq $null) {
$output = "Error querying: $($identifier), PID: $($processId)"
} elseif ($response.data.attributes.last_analysis_stats.malicious -gt 0) {
$output = "Malicious $type detected: $($identifier), PID: $($processId)"
} else {
$output = "$type is clean: $($identifier), PID: $($processId)"
}
$output | Out-File -Filepath $outfile -Append
}
function Get-ActiveProcessesHashes {
$processes = Get-WmiObject Win32_Process | Where-Object { $_.ExecutablePath -ne $null } | Select-Object Name, ExecutablePath, ProcessId
foreach ($process in $processes) {
$hash = (Get-FileHash -Algorithm SHA256 -Path $process.ExecutablePath).Hash
[PSCustomObject]@{
Name = $process.Name
ExecutablePath = $process.ExecutablePath
ProcessId = $process.ProcessId
Hash = $hash
}
}
}
function Get-ActiveConnections {
Get-NetTCPConnection | Select-Object -Property RemoteAddress, OwningProcess -Unique
}
$processes = Get-ActiveProcessesHashes
foreach ($process in $processes) {
$hash = $process.Hash
$processId = $process.ProcessId
$response = Query-VirusTotalApi -identifier $hash -type "hash"
$null = Process-ApiResponse -response $response -identifier $hash -processId $processId -outfile $outfile -type "File hash"
Start-Sleep -Seconds 1 # Adjust or remove
}
$activeConnections = Get-ActiveConnections
foreach ($connection in $activeConnections) {
$ip = $connection.RemoteAddress
$processId = $connection.OwningProcess
$response = Query-VirusTotalApi -identifier $ip -type "ip"
$null = Process-ApiResponse -response $response -identifier $ip -processId $processId -outfile $outfile -type "IP address"
Start-Sleep -Seconds 1 # Adjust or remove
}