mihari 3.7.2 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/mihari/analyzers/rule.rb +1 -0
- data/lib/mihari/analyzers/virustotal_intelligence.rb +63 -0
- data/lib/mihari/cli/analyzer.rb +2 -0
- data/lib/mihari/commands/passivetotal.rb +1 -0
- data/lib/mihari/commands/virustotal.rb +1 -0
- data/lib/mihari/commands/virustotal_intelligence.rb +22 -0
- data/lib/mihari/structs/virustotal_intelligence.rb +75 -0
- data/lib/mihari/types.rb +13 -3
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari.rb +2 -1
- data/mihari.gemspec +1 -1
- data/sig/lib/mihari/analyzers/virustotal_intelligence.rbs +32 -0
- data/sig/lib/mihari/structs/virustotal_intelligence.rbs +33 -0
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aac91d43689cb53dc0570bfed3cec57a07cbe88de0716530f2ea8bfac8f8d39d
|
4
|
+
data.tar.gz: 0f59bdc53cfa75e56884dd3497fa0492d3a41a3b7540cbdab1345ec5b301c69c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30aef30fb14c7c1a50e75162141d1266b1ec5b847f6329935a221a90f59d37a2bed97c6a8aa4371962ab85b18c5ff23cf0417f08f9dc3320c737721ac1a07602
|
7
|
+
data.tar.gz: 1029878ec85cbdbe0a2c800b6b68cce99d45510818dde6b1d84a826022379cbe21fc57f490e3a77521136dbc22e8112b804d891892ea0a351e0d1db935b28b4b
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ Mihari supports the following services by default.
|
|
46
46
|
- [Shodan](https://shodan.io)
|
47
47
|
- [Spyse](https://spyse.com)
|
48
48
|
- [urlscan.io](https://urlscan.io)
|
49
|
-
- [VirusTotal](http://virustotal.com)
|
49
|
+
- [VirusTotal](http://virustotal.com) & [VirusTotal Intelligence](https://www.virustotal.com/gui/intelligence-overview)
|
50
50
|
- [ZoomEye](https://zoomeye.org)
|
51
51
|
|
52
52
|
## Docs
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "virustotal"
|
4
|
+
|
5
|
+
module Mihari
|
6
|
+
module Analyzers
|
7
|
+
class VirusTotalIntelligence < Base
|
8
|
+
param :query
|
9
|
+
option :title, default: proc { "VirusTotal Intelligence search" }
|
10
|
+
option :description, default: proc { "query = #{query}" }
|
11
|
+
option :tags, default: proc { [] }
|
12
|
+
|
13
|
+
def initialize(*args, **kwargs)
|
14
|
+
super
|
15
|
+
|
16
|
+
@query = query
|
17
|
+
end
|
18
|
+
|
19
|
+
def artifacts
|
20
|
+
responses = search_witgh_cursor
|
21
|
+
responses.map do |response|
|
22
|
+
response.data.map(&:value)
|
23
|
+
end.flatten.compact.uniq
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def configuration_keys
|
29
|
+
%w[virustotal_api_key]
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# VT API
|
34
|
+
#
|
35
|
+
# @return [::VirusTotal::API]
|
36
|
+
#
|
37
|
+
def api
|
38
|
+
@api = ::VirusTotal::API.new(key: Mihari.config.virustotal_api_key)
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Search with cursor
|
43
|
+
#
|
44
|
+
# @return [Array<Structs::VirusTotalIntelligence::Response>]
|
45
|
+
#
|
46
|
+
def search_witgh_cursor
|
47
|
+
cursor = nil
|
48
|
+
responses = []
|
49
|
+
|
50
|
+
loop do
|
51
|
+
response = Structs::VirusTotalIntelligence::Response.from_dynamic!(api.intelligence.search(query, cursor: cursor))
|
52
|
+
responses << response
|
53
|
+
|
54
|
+
break if response.meta.cursor.nil?
|
55
|
+
|
56
|
+
cursor = response.meta.cursor
|
57
|
+
end
|
58
|
+
|
59
|
+
responses
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/mihari/cli/analyzer.rb
CHANGED
@@ -14,6 +14,7 @@ require "mihari/commands/securitytrails"
|
|
14
14
|
require "mihari/commands/shodan"
|
15
15
|
require "mihari/commands/spyse"
|
16
16
|
require "mihari/commands/urlscan"
|
17
|
+
require "mihari/commands/virustotal_intelligence"
|
17
18
|
require "mihari/commands/virustotal"
|
18
19
|
require "mihari/commands/zoomeye"
|
19
20
|
|
@@ -42,6 +43,7 @@ module Mihari
|
|
42
43
|
include Mihari::Commands::Spyse
|
43
44
|
include Mihari::Commands::Urlscan
|
44
45
|
include Mihari::Commands::VirusTotal
|
46
|
+
include Mihari::Commands::VirusTotalIntelligence
|
45
47
|
include Mihari::Commands::ZoomEye
|
46
48
|
end
|
47
49
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mihari
|
4
|
+
module Commands
|
5
|
+
module VirusTotalIntelligence
|
6
|
+
def self.included(thor)
|
7
|
+
thor.class_eval do
|
8
|
+
desc "virustotal_intelligence [QUERY]", "VirusTotal Intelligence search"
|
9
|
+
method_option :title, type: :string, desc: "title"
|
10
|
+
method_option :description, type: :string, desc: "description"
|
11
|
+
method_option :tags, type: :array, desc: "tags"
|
12
|
+
def virustotal_intelligence(query)
|
13
|
+
with_error_handling do
|
14
|
+
run_analyzer Analyzers::VirusTotalIntelligence, query: query, options: options
|
15
|
+
end
|
16
|
+
end
|
17
|
+
map "vt_intel" => :virustotal_intelligence
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "json"
|
2
|
+
require "dry/struct"
|
3
|
+
|
4
|
+
module Mihari
|
5
|
+
module Structs
|
6
|
+
module VirusTotalIntelligence
|
7
|
+
class ContextAttributes < Dry::Struct
|
8
|
+
attribute :url, Types.Array(Types::String).optional
|
9
|
+
|
10
|
+
def self.from_dynamic!(d)
|
11
|
+
d = Types::Hash[d]
|
12
|
+
new(
|
13
|
+
url: d["url"]
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Datum < Dry::Struct
|
19
|
+
attribute :type, Types::String
|
20
|
+
attribute :id, Types::String
|
21
|
+
attribute :context_attributes, ContextAttributes.optional
|
22
|
+
|
23
|
+
def value
|
24
|
+
case type
|
25
|
+
when "file"
|
26
|
+
id
|
27
|
+
when "url"
|
28
|
+
(context_attributes.url || []).first
|
29
|
+
when "domain"
|
30
|
+
id
|
31
|
+
when "ip_address"
|
32
|
+
id
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.from_dynamic!(d)
|
37
|
+
d = Types::Hash[d]
|
38
|
+
|
39
|
+
context_attributes = nil
|
40
|
+
context_attributes = ContextAttributes.from_dynamic!(d.fetch("context_attributes")) if d.key?("context_attributes")
|
41
|
+
|
42
|
+
new(
|
43
|
+
type: d.fetch("type"),
|
44
|
+
id: d.fetch("id"),
|
45
|
+
context_attributes: context_attributes
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Meta < Dry::Struct
|
51
|
+
attribute :cursor, Types::String.optional
|
52
|
+
|
53
|
+
def self.from_dynamic!(d)
|
54
|
+
d = Types::Hash[d]
|
55
|
+
new(
|
56
|
+
cursor: d["cursor"]
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Response < Dry::Struct
|
62
|
+
attribute :meta, Meta
|
63
|
+
attribute :data, Types.Array(Datum)
|
64
|
+
|
65
|
+
def self.from_dynamic!(d)
|
66
|
+
d = Types::Hash[d]
|
67
|
+
new(
|
68
|
+
meta: Meta.from_dynamic!(d.fetch("meta")),
|
69
|
+
data: d.fetch("data").map { |x| Datum.from_dynamic!(x) }
|
70
|
+
)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/mihari/types.rb
CHANGED
@@ -13,9 +13,19 @@ module Mihari
|
|
13
13
|
DataTypes = Types::String.enum(*ALLOWED_DATA_TYPES)
|
14
14
|
|
15
15
|
AnalyzerTypes = Types::String.enum(
|
16
|
-
"binaryedge",
|
17
|
-
"
|
18
|
-
"
|
16
|
+
"binaryedge",
|
17
|
+
"censys",
|
18
|
+
"circl",
|
19
|
+
"dnpedia",
|
20
|
+
"dnstwister",
|
21
|
+
"onyphe",
|
22
|
+
"otx",
|
23
|
+
"passivetotal",
|
24
|
+
"pulsedive",
|
25
|
+
"securitytrails",
|
26
|
+
"shodan",
|
27
|
+
"virustotal_intelligence",
|
28
|
+
"virustotal"
|
19
29
|
)
|
20
30
|
end
|
21
31
|
end
|
data/lib/mihari/version.rb
CHANGED
data/lib/mihari.rb
CHANGED
@@ -112,6 +112,7 @@ require "mihari/structs/censys"
|
|
112
112
|
require "mihari/structs/ipinfo"
|
113
113
|
require "mihari/structs/onyphe"
|
114
114
|
require "mihari/structs/shodan"
|
115
|
+
require "mihari/structs/virustotal_intelligence"
|
115
116
|
|
116
117
|
# Schemas
|
117
118
|
require "mihari/schemas/analyzer"
|
@@ -163,9 +164,9 @@ require "mihari/analyzers/securitytrails"
|
|
163
164
|
require "mihari/analyzers/shodan"
|
164
165
|
require "mihari/analyzers/spyse"
|
165
166
|
require "mihari/analyzers/urlscan"
|
167
|
+
require "mihari/analyzers/virustotal_intelligence"
|
166
168
|
require "mihari/analyzers/virustotal"
|
167
169
|
require "mihari/analyzers/zoomeye"
|
168
|
-
|
169
170
|
require "mihari/analyzers/rule"
|
170
171
|
|
171
172
|
# Notifiers
|
data/mihari.gemspec
CHANGED
@@ -92,7 +92,7 @@ Gem::Specification.new do |spec|
|
|
92
92
|
spec.add_dependency "thread_safe", "~> 0.3"
|
93
93
|
spec.add_dependency "urlscan", "~> 0.7"
|
94
94
|
spec.add_dependency "uuidtools", "~> 2.2"
|
95
|
-
spec.add_dependency "virustotalx", "~> 1.
|
95
|
+
spec.add_dependency "virustotalx", "~> 1.2"
|
96
96
|
spec.add_dependency "whois", "~> 5.0"
|
97
97
|
spec.add_dependency "whois-parser", "~> 1.2"
|
98
98
|
spec.add_dependency "zoomeye-rb", "~> 0.2"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Mihari
|
2
|
+
module Analyzers
|
3
|
+
class VirusTotalIntelligence < Base
|
4
|
+
attr_reader query: String
|
5
|
+
attr_reader title: String
|
6
|
+
attr_reader description: String
|
7
|
+
attr_reader tags: Array[String]
|
8
|
+
|
9
|
+
def initialize: (*untyped args, **untyped kwargs) -> void
|
10
|
+
|
11
|
+
def artifacts: () -> (Array[String] | Array[Mihari::Artifact])
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def configuration_keys: () -> ::Array["virustotal_api_key"]
|
16
|
+
|
17
|
+
#
|
18
|
+
# VT API
|
19
|
+
#
|
20
|
+
# @return [::VirusTotal::API]
|
21
|
+
#
|
22
|
+
def api: () -> untyped
|
23
|
+
|
24
|
+
#
|
25
|
+
# Search with cursor
|
26
|
+
#
|
27
|
+
# @return [Array<Mihari::Structs::VirusTotalIntelligence::Response>]
|
28
|
+
#
|
29
|
+
def search_witgh_cursor: () -> Array[Mihari::Structs::VirusTotalIntelligence::Response]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Mihari
|
2
|
+
module Structs
|
3
|
+
module VirusTotalIntelligence
|
4
|
+
class ContextAttributes
|
5
|
+
attr_reader url: Array[String]?
|
6
|
+
|
7
|
+
def self.from_dynamic!: (Hash[(String | Symbol), untyped] d) -> Mihari::Structs::VirusTotalIntelligence::ContextAttributes
|
8
|
+
end
|
9
|
+
|
10
|
+
class Datum
|
11
|
+
attr_reader type: String
|
12
|
+
attr_reader context_attributes: Mihari::Structs::VirusTotalIntelligence::ContextAttributes?
|
13
|
+
|
14
|
+
def value: () -> String?
|
15
|
+
|
16
|
+
def self.from_dynamic!: (Hash[(String | Symbol), untyped] d) -> Mihari::Structs::VirusTotalIntelligence::Datum
|
17
|
+
end
|
18
|
+
|
19
|
+
class Meta
|
20
|
+
attr_reader cursor: String?
|
21
|
+
|
22
|
+
def self.from_dynamic!: (Hash[(String | Symbol), untyped] d) -> Mihari::Structs::VirusTotalIntelligence::Meta
|
23
|
+
end
|
24
|
+
|
25
|
+
class Response
|
26
|
+
attr_reader meta: Mihari::Structs::VirusTotalIntelligence::Meta
|
27
|
+
attr_reader data: Array[Mihari::Structs::VirusTotalIntelligence::Datum]
|
28
|
+
|
29
|
+
def self.from_dynamic!: (Hash[(String | Symbol), untyped] d) -> Mihari::Structs::VirusTotalIntelligence::Response
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mihari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manabu Niseki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -940,14 +940,14 @@ dependencies:
|
|
940
940
|
requirements:
|
941
941
|
- - "~>"
|
942
942
|
- !ruby/object:Gem::Version
|
943
|
-
version: '1.
|
943
|
+
version: '1.2'
|
944
944
|
type: :runtime
|
945
945
|
prerelease: false
|
946
946
|
version_requirements: !ruby/object:Gem::Requirement
|
947
947
|
requirements:
|
948
948
|
- - "~>"
|
949
949
|
- !ruby/object:Gem::Version
|
950
|
-
version: '1.
|
950
|
+
version: '1.2'
|
951
951
|
- !ruby/object:Gem::Dependency
|
952
952
|
name: whois
|
953
953
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1046,6 +1046,7 @@ files:
|
|
1046
1046
|
- lib/mihari/analyzers/spyse.rb
|
1047
1047
|
- lib/mihari/analyzers/urlscan.rb
|
1048
1048
|
- lib/mihari/analyzers/virustotal.rb
|
1049
|
+
- lib/mihari/analyzers/virustotal_intelligence.rb
|
1049
1050
|
- lib/mihari/analyzers/zoomeye.rb
|
1050
1051
|
- lib/mihari/cli/analyzer.rb
|
1051
1052
|
- lib/mihari/cli/base.rb
|
@@ -1072,6 +1073,7 @@ files:
|
|
1072
1073
|
- lib/mihari/commands/urlscan.rb
|
1073
1074
|
- lib/mihari/commands/validator.rb
|
1074
1075
|
- lib/mihari/commands/virustotal.rb
|
1076
|
+
- lib/mihari/commands/virustotal_intelligence.rb
|
1075
1077
|
- lib/mihari/commands/web.rb
|
1076
1078
|
- lib/mihari/commands/zoomeye.rb
|
1077
1079
|
- lib/mihari/constants.rb
|
@@ -1123,6 +1125,7 @@ files:
|
|
1123
1125
|
- lib/mihari/structs/ipinfo.rb
|
1124
1126
|
- lib/mihari/structs/onyphe.rb
|
1125
1127
|
- lib/mihari/structs/shodan.rb
|
1128
|
+
- lib/mihari/structs/virustotal_intelligence.rb
|
1126
1129
|
- lib/mihari/templates/rule.yml.erb
|
1127
1130
|
- lib/mihari/type_checker.rb
|
1128
1131
|
- lib/mihari/types.rb
|
@@ -1204,6 +1207,7 @@ files:
|
|
1204
1207
|
- sig/lib/mihari/analyzers/spyse.rbs
|
1205
1208
|
- sig/lib/mihari/analyzers/urlscan.rbs
|
1206
1209
|
- sig/lib/mihari/analyzers/virustotal.rbs
|
1210
|
+
- sig/lib/mihari/analyzers/virustotal_intelligence.rbs
|
1207
1211
|
- sig/lib/mihari/analyzers/zoomeye.rbs
|
1208
1212
|
- sig/lib/mihari/cli/analyzer.rbs
|
1209
1213
|
- sig/lib/mihari/cli/base.rbs
|
@@ -1269,6 +1273,7 @@ files:
|
|
1269
1273
|
- sig/lib/mihari/structs/ipinfo.rbs
|
1270
1274
|
- sig/lib/mihari/structs/onyphe.rbs
|
1271
1275
|
- sig/lib/mihari/structs/shodan.rbs
|
1276
|
+
- sig/lib/mihari/structs/virustotal_intelligence.rbs
|
1272
1277
|
- sig/lib/mihari/type_checker.rbs
|
1273
1278
|
- sig/lib/mihari/types.rbs
|
1274
1279
|
- sig/lib/mihari/version.rbs
|