huntr 1.0.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 +7 -0
- data/bin/huntr +4 -0
- data/lib/huntr.rb +216 -0
- data/lib/huntr/version.rb +3 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: eefda26d1cdf4a3ac01b9e405fd5264ff79d4074
|
4
|
+
data.tar.gz: edb3ab836db0ad0dbf47c9aebd90e9d94aaabe58
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 26f7591370d316b7d91ce2df46b55c288abdcc5f9030ed3a170b93fdcca97989e09af2f8f43bb77aaaa2611e42d807559dfc74b9a357c245f54b191d472d44c0
|
7
|
+
data.tar.gz: cacf78e7031c98b296d0aab071a771297ad133fbc9bb6267c77bd6bf47e964c3880a0682df356c826fd46a7f2009d27c445d295df9bdf0f60a47a39b61175a33
|
data/bin/huntr
ADDED
data/lib/huntr.rb
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
require "command_lion"
|
2
|
+
require "nmapr"
|
3
|
+
require "shodan"
|
4
|
+
require "yaml"
|
5
|
+
require "colorize"
|
6
|
+
require "socket"
|
7
|
+
require "unirest"
|
8
|
+
require "resolv"
|
9
|
+
require "ipaddress"
|
10
|
+
require "whois-parser"
|
11
|
+
require "huntr/version"
|
12
|
+
|
13
|
+
# The purpose of this libary is provide the tooling required
|
14
|
+
# to effectively perform reconnaissance on a given target.
|
15
|
+
#
|
16
|
+
# A *target* is simply an organization's IP address or domain name.
|
17
|
+
#
|
18
|
+
module Huntr
|
19
|
+
|
20
|
+
# Re-usable code to provision different stages of the reconnaissance.
|
21
|
+
module Utils
|
22
|
+
def self.target_file
|
23
|
+
data = {}
|
24
|
+
data["domains"] = []
|
25
|
+
data["ips"] = []
|
26
|
+
data.to_yaml
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
trap("SIGINT") { puts "Stopping huntr!"; exit 0 }
|
31
|
+
|
32
|
+
CommandLion::App.run do
|
33
|
+
if ENV["SHODAN_API_KEY"].nil?
|
34
|
+
puts "No shodan API key detected. Will not be able to use shodan!"
|
35
|
+
end
|
36
|
+
name "Huntr"
|
37
|
+
version Huntr::VERSION
|
38
|
+
description "A simple reconnaissance command-line application."
|
39
|
+
|
40
|
+
command :create do
|
41
|
+
description "Create a new reconnaissance directory to store relevant information."
|
42
|
+
type :string
|
43
|
+
before do
|
44
|
+
if argument.nil?
|
45
|
+
puts "Must provide an argument!"
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
if File.directory?(argument)
|
49
|
+
puts "Directory already exists!"
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
action do
|
54
|
+
Dir.mkdir(argument)
|
55
|
+
Dir.chdir(argument)
|
56
|
+
File.open("target.yaml", "w+") { |f| f.write Utils.target_file }
|
57
|
+
end
|
58
|
+
after do
|
59
|
+
puts "Directory #{argument.colorize(:yellow)} has been created."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
command :targets do
|
64
|
+
description "Add target domains and IP addresses to the target file."
|
65
|
+
type :strings
|
66
|
+
before do
|
67
|
+
if arguments.empty?
|
68
|
+
file = YAML.load(File.read("target.yaml"))
|
69
|
+
puts "HUNTR TARGETS:"
|
70
|
+
file["domains"].each do |domain|
|
71
|
+
puts "Domain: #{domain}"
|
72
|
+
end
|
73
|
+
file["ips"].each do |ip|
|
74
|
+
puts "IP: #{ip}"
|
75
|
+
end
|
76
|
+
exit
|
77
|
+
end
|
78
|
+
unless File.file?("target.yaml")
|
79
|
+
puts "No target file found! Are you in a reconnaissance directory?"
|
80
|
+
exit 1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
action do
|
84
|
+
file = YAML.load(File.read("target.yaml"))
|
85
|
+
arguments.each do |argument|
|
86
|
+
if IPAddress.valid?(argument)
|
87
|
+
file["ips"] << argument unless file["ips"].include?(argument)
|
88
|
+
if names = Resolv.getnames(argument)
|
89
|
+
names.each do |name|
|
90
|
+
file["domains"] << name unless file["domains"].include?(name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
elsif ip = IPSocket::getaddress(argument)
|
94
|
+
file["domains"] << argument unless file["domains"].include?(argument)
|
95
|
+
file["ips"] << ip unless file["ips"].include?(ip)
|
96
|
+
end
|
97
|
+
File.open("target.yaml", "w") { |f| f.write file.to_yaml }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
command :delete do
|
103
|
+
description "Delete a given reconnaissance directory."
|
104
|
+
type :string
|
105
|
+
before do
|
106
|
+
if argument.nil?
|
107
|
+
puts "Must provide an argument!"
|
108
|
+
exit 1
|
109
|
+
end
|
110
|
+
unless File.directory?(argument)
|
111
|
+
puts "That directroy doesn't exist, try again!"
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
action do
|
116
|
+
FileUtils.rm_rf(argument)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
command :shodan do
|
121
|
+
description "Perform shodan query on a given domain or IP address."
|
122
|
+
type :string
|
123
|
+
before do
|
124
|
+
if argument.nil?
|
125
|
+
puts "Must provide an argument!"
|
126
|
+
exit 1
|
127
|
+
end
|
128
|
+
unless File.file?("target.yaml")
|
129
|
+
puts "No target file found! Are you in a reconnaissance directory?"
|
130
|
+
exit 1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
action do
|
134
|
+
api = Shodan::Shodan.new(ENV["SHODAN_API_KEY"])
|
135
|
+
response = api.host(argument)
|
136
|
+
file = YAML.load(File.read("target.yaml"))
|
137
|
+
file["shodan"] = {} unless file["shodan"]
|
138
|
+
file["shodan"][argument] = response
|
139
|
+
File.open("target.yaml", "w") { |f| f.write file.to_yaml }
|
140
|
+
puts response.to_yaml
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
command :nmap do
|
145
|
+
description "Perform nmap scan on a given domain or IP address."
|
146
|
+
type :string
|
147
|
+
before do
|
148
|
+
if argument.nil?
|
149
|
+
puts "Must provide an argument!"
|
150
|
+
exit 1
|
151
|
+
end
|
152
|
+
unless File.file?("target.yaml")
|
153
|
+
puts "No target file found! Are you in a reconnaissance directory?"
|
154
|
+
exit 1
|
155
|
+
end
|
156
|
+
end
|
157
|
+
action do
|
158
|
+
nmap = `nmap #{argument} -vvvv --reason -oN -`
|
159
|
+
file = YAML.load(File.read("target.yaml"))
|
160
|
+
file["nmap"] = {} unless file["nmap"]
|
161
|
+
file["nmap"][argument] = nmap
|
162
|
+
File.open("target.yaml", "w") { |f| f.write file.to_yaml }
|
163
|
+
puts nmap
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
command :ipinfo do
|
168
|
+
description "Get ipinfo.io information on a given domain or IP address."
|
169
|
+
type :string
|
170
|
+
before do
|
171
|
+
if argument.nil?
|
172
|
+
puts "Must provide an argument!"
|
173
|
+
exit 1
|
174
|
+
end
|
175
|
+
unless File.file?("target.yaml")
|
176
|
+
puts "No target file found! Are you in a reconnaissance directory?"
|
177
|
+
exit 1
|
178
|
+
end
|
179
|
+
end
|
180
|
+
action do
|
181
|
+
data = Unirest.get('https://ipinfo.io/' + argument).body
|
182
|
+
file = YAML.load(File.read("target.yaml"))
|
183
|
+
file["ipinfo"] = {} unless file["ipinfo"]
|
184
|
+
file["ipinfo"][argument] = data
|
185
|
+
File.open("target.yaml", "w") { |f| f.write file.to_yaml }
|
186
|
+
puts data.to_yaml
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
command :whois do
|
191
|
+
description "Perform nmap scan on a given domain or IP address."
|
192
|
+
type :string
|
193
|
+
before do
|
194
|
+
if argument.nil?
|
195
|
+
puts "Must provide an argument!"
|
196
|
+
exit 1
|
197
|
+
end
|
198
|
+
unless File.file?("target.yaml")
|
199
|
+
puts "No target file found! Are you in a reconnaissance directory?"
|
200
|
+
exit 1
|
201
|
+
end
|
202
|
+
end
|
203
|
+
action do
|
204
|
+
data = Whois.whois(argument).to_s
|
205
|
+
file = YAML.load(File.read("target.yaml"))
|
206
|
+
file["whois"] = {} unless file["whois"]
|
207
|
+
file["whois"][argument] = data
|
208
|
+
File.open("target.yaml", "w") { |f| f.write file.to_yaml }
|
209
|
+
puts data
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
end
|
216
|
+
end
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: huntr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kent Gruber
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: shodan
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: command_lion
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nmapr
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: colorize
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: ipaddress
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: whois-parser
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: unirest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: bundler
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.15'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.15'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rake
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '10.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '10.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rspec
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '3.0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '3.0'
|
153
|
+
description:
|
154
|
+
email:
|
155
|
+
- kgruber1@emich.edu
|
156
|
+
executables:
|
157
|
+
- huntr
|
158
|
+
extensions: []
|
159
|
+
extra_rdoc_files: []
|
160
|
+
files:
|
161
|
+
- bin/huntr
|
162
|
+
- lib/huntr.rb
|
163
|
+
- lib/huntr/version.rb
|
164
|
+
homepage: https://github.com/picatz/huntr
|
165
|
+
licenses:
|
166
|
+
- MIT
|
167
|
+
metadata: {}
|
168
|
+
post_install_message:
|
169
|
+
rdoc_options: []
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 2.6.12
|
185
|
+
signing_key:
|
186
|
+
specification_version: 4
|
187
|
+
summary: A simple reconnaissance command-line application.
|
188
|
+
test_files: []
|