snackhack2 0.6.5 → 0.6.7
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/lib/snackhack2/bannergrabber.rb +96 -15
- data/lib/snackhack2/phishing_tlds.rb +279 -136
- data/lib/snackhack2/ssh.rb +15 -0
- data/lib/snackhack2/version.rb +1 -1
- data/lib/snackhack2.rb +18 -5
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f24d3c225a7262763bb360b50b139af3d73222abfa7288d1149f5f47a7c837e4
|
|
4
|
+
data.tar.gz: 90f9e49687132acd4930f01ce2d03bd98b1911301d81f26130e253461f94d5a5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c535c224366a2ad8a2ebcb047d47c4157d1fad3a3aa30b782decd5b2291823cd1b0b91043bfd60ab21f3d9c40b66c47e4e85957fb784cd6a0209b3117c6cfa5
|
|
7
|
+
data.tar.gz: 97232dc976b82e3a677d87fda6ea3319fc6ddc09526657d731bf89701b8ccaf70f84b4215977b17cdb7fb2ac05e6143aebf7791ce0488b88e5a0ca5cd7f14e22
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
2
|
require 'socket'
|
|
4
3
|
module Snackhack2
|
|
5
4
|
class BannerGrabber
|
|
@@ -8,24 +7,19 @@ module Snackhack2
|
|
|
8
7
|
def initialize(port: 443, save_file: true)
|
|
9
8
|
@site = site
|
|
10
9
|
@port = port
|
|
11
|
-
@headers = Snackhack2.get(@site).headers
|
|
12
10
|
@save_file = save_file
|
|
13
11
|
end
|
|
14
12
|
|
|
15
|
-
def site
|
|
16
|
-
# @site.gsub('https://', '')
|
|
17
|
-
end
|
|
18
|
-
|
|
19
13
|
def run
|
|
20
14
|
nginx
|
|
21
15
|
apache2
|
|
22
16
|
wordpress
|
|
23
|
-
|
|
17
|
+
get_ssh_info
|
|
18
|
+
end
|
|
19
|
+
def headers
|
|
20
|
+
@headers = Snackhack2.get(@site).headers
|
|
24
21
|
end
|
|
25
|
-
|
|
26
22
|
def nginx
|
|
27
|
-
return unless @headers['server'].match(/nginx/)
|
|
28
|
-
|
|
29
23
|
puts "[+] Server is running NGINX... Now checking if #{File.join(@site, 'nginx_status')} is valid..."
|
|
30
24
|
nginx = Snackhack2.get(File.join(@site, 'nginx_status'))
|
|
31
25
|
if nginx.code == 200
|
|
@@ -37,20 +31,25 @@ module Snackhack2
|
|
|
37
31
|
|
|
38
32
|
def curl
|
|
39
33
|
servers = ''
|
|
34
|
+
# rus the curl command to get the headers of the given site.
|
|
40
35
|
cmd = `curl -s -I #{@site.gsub('https://', '')}`
|
|
36
|
+
# extracts the server header from the curl results
|
|
41
37
|
version = cmd.split('Server: ')[1].split("\n")[0].strip
|
|
42
38
|
if @save_file
|
|
43
39
|
servers += version.to_s
|
|
44
40
|
else
|
|
45
41
|
puts "Banner: #{cmd.split('Server: ')[1].split("\n")[0]}"
|
|
46
42
|
end
|
|
43
|
+
|
|
44
|
+
# saves the results if '@save_file' is set to true.
|
|
47
45
|
Snackhack2.file_save(@site, 'serverversion', servers) if @save_file
|
|
48
46
|
end
|
|
49
47
|
|
|
50
48
|
def apache2
|
|
51
|
-
if
|
|
49
|
+
if headers['server'].match(/Apache/)
|
|
52
50
|
puts "[+] Server is running Apache2... Now checking #{File.join(@site, 'server-status')}..."
|
|
53
51
|
apache = Snackhack2.get(File.join(@site, 'server-status'))
|
|
52
|
+
# status code 200 means the request was successful.
|
|
54
53
|
if apache.code == 200
|
|
55
54
|
puts "Check #{@site}/server-status"
|
|
56
55
|
else
|
|
@@ -67,16 +66,98 @@ module Snackhack2
|
|
|
67
66
|
|
|
68
67
|
puts "[+] Wordpress found [+]\n\n\n"
|
|
69
68
|
end
|
|
69
|
+
def types
|
|
70
|
+
{
|
|
71
|
+
"cloudflare": [ "cf-cache-status", "cf-ray", "cloudflare"],
|
|
72
|
+
"aws CloudFront": [ "X-Amz-Cf-Pop", "X-Amz-Cf-Id", "CloudFront", "x-amz-cf-pop", "x-amz-cf-id", "cloudfront.net"]
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
def find_headers
|
|
76
|
+
# make a request to the site and grab the headers.
|
|
77
|
+
Snackhack2.get(@site).headers
|
|
78
|
+
end
|
|
70
79
|
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
def get_tcp_info(ports: "")
|
|
81
|
+
ports = 22 if ports.empty?
|
|
82
|
+
begin
|
|
83
|
+
TCPSocket.new(@site, ports).recv(1024)
|
|
84
|
+
rescue => e
|
|
85
|
+
puts "ERROR OCCURRED"
|
|
86
|
+
end
|
|
74
87
|
end
|
|
88
|
+
def cloudflare(print_status: true)
|
|
89
|
+
# the purpose of this method is to
|
|
90
|
+
# check to see if a site has
|
|
91
|
+
# cloudflare in the headers
|
|
92
|
+
|
|
93
|
+
cf_status = false
|
|
94
|
+
cf_count = 0
|
|
75
95
|
|
|
96
|
+
# access the 'types' hash to get the cloudflare strings.
|
|
97
|
+
cf = types[:"cloudflare"]
|
|
98
|
+
|
|
99
|
+
# make a single get request to the site defined at '@site'
|
|
100
|
+
find_headers.each do |k,v|
|
|
101
|
+
# if the key is in the array cf
|
|
102
|
+
if cf.include?(k)
|
|
103
|
+
cf_status = true
|
|
104
|
+
cf_count += 1
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
if print_status
|
|
108
|
+
# cf_status[0] : the status if cloudflare was found
|
|
109
|
+
# cf_count[1] : the number of found elements in the 'cloudflare' hash.
|
|
110
|
+
return [cf_status, cf_count]
|
|
111
|
+
else
|
|
112
|
+
if cf_status
|
|
113
|
+
puts "Cloudflare was found. The count is: #{cf_count}"
|
|
114
|
+
else
|
|
115
|
+
puts "Cloudflare was NOT found. The count is #{cf_count}"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
def detect_header(return_status: true)
|
|
120
|
+
# stores the data found in
|
|
121
|
+
# the headers.
|
|
122
|
+
data = {}
|
|
123
|
+
# loops through the hash stored in the 'types' method.
|
|
124
|
+
# the t_k is the KEY of the hash
|
|
125
|
+
# the t_v is the VALUE of the hash.
|
|
126
|
+
types.each do |t_k, t_v|
|
|
127
|
+
# make a single get request to the site
|
|
128
|
+
# to get the headers.
|
|
129
|
+
find_headers.each do |fh_k, fh_v|
|
|
130
|
+
# Get the keys from the 'types' method
|
|
131
|
+
# which is basicly a hash
|
|
132
|
+
type_key = t_k
|
|
133
|
+
# uses the key of the 'types' hash
|
|
134
|
+
# to see if includes the string found in 'fh_k'
|
|
135
|
+
if types[type_key].include?(fh_k)
|
|
136
|
+
if data.has_key?(type_key)
|
|
137
|
+
data[type_key] << fh_k
|
|
138
|
+
else
|
|
139
|
+
data[type_key] = [fh_k]
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
if return_status
|
|
145
|
+
return data
|
|
146
|
+
else
|
|
147
|
+
data.each do |k,v|
|
|
148
|
+
puts "K:#{k}"
|
|
149
|
+
puts "V: #{v}"
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
76
153
|
def server
|
|
77
154
|
@headers['server']
|
|
78
155
|
end
|
|
79
156
|
|
|
80
157
|
attr_reader :site
|
|
81
|
-
|
|
158
|
+
private :find_headers
|
|
159
|
+
end
|
|
82
160
|
end
|
|
161
|
+
# to do: instead of doing mutiple methods for each type of
|
|
162
|
+
# header make one method that is dynamic...
|
|
163
|
+
# and can do different ones
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Snackhack2
|
|
4
|
-
|
|
4
|
+
class PhishingData
|
|
5
5
|
def domains
|
|
6
6
|
[
|
|
7
7
|
".com",
|
|
@@ -44,154 +44,297 @@ module Snackhack2
|
|
|
44
44
|
".work"
|
|
45
45
|
]
|
|
46
46
|
end
|
|
47
|
+
def domain_keywords
|
|
48
|
+
[
|
|
49
|
+
"connect",
|
|
50
|
+
"corp",
|
|
51
|
+
"duo",
|
|
52
|
+
"help",
|
|
53
|
+
"he1p",
|
|
54
|
+
"helpdesk",
|
|
55
|
+
"helpnow",
|
|
56
|
+
"info",
|
|
57
|
+
"internal",
|
|
58
|
+
"mfa",
|
|
59
|
+
"my",
|
|
60
|
+
"okta",
|
|
61
|
+
"onelogin",
|
|
62
|
+
"schedule",
|
|
63
|
+
"service",
|
|
64
|
+
"servicedesk",
|
|
65
|
+
"servicenow",
|
|
66
|
+
"rci",
|
|
67
|
+
"rsa",
|
|
68
|
+
"sso",
|
|
69
|
+
"ssp",
|
|
70
|
+
"support",
|
|
71
|
+
"usa",
|
|
72
|
+
"vpn",
|
|
73
|
+
"work",
|
|
74
|
+
"dev",
|
|
75
|
+
"workspace",
|
|
76
|
+
"it",
|
|
77
|
+
"ops",
|
|
78
|
+
"hr",
|
|
79
|
+
"login",
|
|
80
|
+
"secure"
|
|
81
|
+
]
|
|
82
|
+
end
|
|
47
83
|
private :domains
|
|
48
84
|
end
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
85
|
+
class PhishingTlds < PhishingData
|
|
86
|
+
attr_reader :site
|
|
87
|
+
def initialize
|
|
88
|
+
@site = site
|
|
89
|
+
end
|
|
90
|
+
def domain_split
|
|
91
|
+
# This method splits up the value block_given
|
|
92
|
+
# given in @site by the period. Which is used
|
|
93
|
+
# by 'remove_tlds' method to remove the TLDs
|
|
94
|
+
@site.split(".")
|
|
95
|
+
end
|
|
96
|
+
def site=(s)
|
|
97
|
+
@site = s
|
|
98
|
+
end
|
|
99
|
+
def remove_tlds
|
|
100
|
+
# this method function is to remove
|
|
101
|
+
# the TLDs from the @site. For Example
|
|
102
|
+
# it will remove .org, .com
|
|
103
|
+
|
|
104
|
+
ds = domain_split
|
|
105
|
+
|
|
106
|
+
# remove ".com" (last element in array)
|
|
107
|
+
ds.pop
|
|
108
|
+
|
|
109
|
+
# returns the domain w/o the tlds
|
|
110
|
+
ds
|
|
111
|
+
end
|
|
112
|
+
def check_domains(array: true)
|
|
113
|
+
# The function of this method is to
|
|
114
|
+
# check if the given domains are valid or not.
|
|
115
|
+
# By valid I mean resolvable and active.
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# if domains is set to true, this array will hold the domains
|
|
119
|
+
domains_out = []
|
|
120
|
+
|
|
121
|
+
# build the list of domains
|
|
122
|
+
generated_tlds = change_tld
|
|
123
|
+
|
|
124
|
+
valid_domains = []
|
|
125
|
+
not_valid_domains = []
|
|
126
|
+
|
|
127
|
+
generated_tlds.each do |domain|
|
|
128
|
+
# if array is true; add the domains to array
|
|
129
|
+
if array
|
|
130
|
+
domains_out << domain
|
|
131
|
+
else
|
|
132
|
+
# if array is false print out the domains
|
|
133
|
+
puts domain
|
|
53
134
|
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
135
|
+
domains_out if array
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
def remove_letters(array_out: true)
|
|
139
|
+
# This method will remove letters that
|
|
140
|
+
# occur more than once. For example:
|
|
141
|
+
# google.com would become goggle.com
|
|
142
|
+
|
|
143
|
+
# store the letter count in a hash.
|
|
144
|
+
letter_count = {}
|
|
145
|
+
|
|
146
|
+
ds = remove_tlds
|
|
147
|
+
|
|
148
|
+
# Creates an array with each character being
|
|
149
|
+
# stored in a element. It will loop through the array
|
|
150
|
+
# and figure out the number of occurrences for each character
|
|
151
|
+
ds.shift.split(//).each do |letter|
|
|
152
|
+
if letter_count.has_key?(letter)
|
|
153
|
+
letter_count[letter] += 1
|
|
154
|
+
else
|
|
155
|
+
letter_count[letter] = 1
|
|
59
156
|
end
|
|
60
|
-
|
|
61
|
-
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# After it creates the hash with the character and
|
|
160
|
+
# the number of time it cocures. This method
|
|
161
|
+
# will loop through the hash and check to see
|
|
162
|
+
# if the value is greater than 1. If it is then the key ( the letter)
|
|
163
|
+
# is added to the array named 'letters_with_more_than_one'
|
|
164
|
+
letters_with_more_than_one = []
|
|
165
|
+
letter_count.each do |key, value|
|
|
166
|
+
if value > 1
|
|
167
|
+
letters_with_more_than_one << key
|
|
62
168
|
end
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
ds = remove_tlds
|
|
173
|
+
new_ds = ds.shift
|
|
174
|
+
|
|
175
|
+
# the final array with the duplicates letters removed
|
|
176
|
+
remove_letters_out = []
|
|
177
|
+
|
|
178
|
+
# Loops through the 'letters_with_more_than_one'
|
|
179
|
+
# array and uses 'sub' to remove the occurence
|
|
180
|
+
# of one of the letters
|
|
181
|
+
letters_with_more_than_one.each do |l|
|
|
182
|
+
# removes only first character ( l )
|
|
183
|
+
remove_letters_out << new_ds.sub(l, "")
|
|
184
|
+
# removes ALL chracters ( l )
|
|
185
|
+
remove_letters_out << new_ds.gsub(l, "")
|
|
186
|
+
end
|
|
187
|
+
# add tldds to the created list
|
|
188
|
+
domains_with_tlds = add_tlds(remove_letters_out)
|
|
189
|
+
if array_out
|
|
190
|
+
domains_with_tlds
|
|
191
|
+
else
|
|
192
|
+
# will print the contents of the array
|
|
193
|
+
# instead of returning the array
|
|
194
|
+
domains_with_tlds.each { |a| puts a }
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
def add_tlds(list)
|
|
198
|
+
# takes the newly created domains (list)
|
|
199
|
+
# and adds the tlds (domains) to the newly created
|
|
200
|
+
# ones.
|
|
201
|
+
o = []
|
|
202
|
+
list.each do |rr|
|
|
203
|
+
domains.each do |dd|
|
|
204
|
+
o << "#{rr}#{dd}"
|
|
75
205
|
end
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
else
|
|
96
|
-
# if array is false print out the domains
|
|
97
|
-
puts domain
|
|
98
|
-
end
|
|
99
|
-
domains_out if array
|
|
206
|
+
end
|
|
207
|
+
o
|
|
208
|
+
end
|
|
209
|
+
def combosquatting
|
|
210
|
+
# where the generated domains will be located.
|
|
211
|
+
results = []
|
|
212
|
+
|
|
213
|
+
# get the domain_keywords array from the PhishingData class.
|
|
214
|
+
keywords = domain_keywords
|
|
215
|
+
|
|
216
|
+
prefixes = ["-", ".", "--"]
|
|
217
|
+
ds = remove_tlds
|
|
218
|
+
# this will generate the 'new_domain' with the keywords
|
|
219
|
+
# as a prefix
|
|
220
|
+
prefixes.each do |pre|
|
|
221
|
+
ds.each do |domain|
|
|
222
|
+
keywords.each do |key|
|
|
223
|
+
new_domain = "#{key}#{pre}#{domain}"
|
|
224
|
+
results << new_domain
|
|
100
225
|
end
|
|
101
226
|
end
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
# Creates an array with each character being
|
|
113
|
-
# stored in a element. It will loop through the array
|
|
114
|
-
# and figure out the number of occurrences for each character
|
|
115
|
-
ds.shift.split(//).each do |letter|
|
|
116
|
-
if letter_count.has_key?(letter)
|
|
117
|
-
letter_count[letter] += 1
|
|
118
|
-
else
|
|
119
|
-
letter_count[letter] = 1
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# After it creates the hash with the character and
|
|
124
|
-
# the number of time it cocures. This method
|
|
125
|
-
# will loop through the hash and check to see
|
|
126
|
-
# if the value is greater than 1. If it is then the key ( the letter)
|
|
127
|
-
# is added to the array named 'letters_with_more_than_one'
|
|
128
|
-
letters_with_more_than_one = []
|
|
129
|
-
letter_count.each do |key, value|
|
|
130
|
-
if value > 1
|
|
131
|
-
letters_with_more_than_one << key
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
ds = remove_tlds
|
|
137
|
-
new_ds = ds.shift
|
|
138
|
-
|
|
139
|
-
# the final array with the duplicates letters removed
|
|
140
|
-
remove_lettters_out = []
|
|
141
|
-
|
|
142
|
-
# Loops through the 'letters_with_more_than_one'
|
|
143
|
-
# array and uses 'sub' to remove the occurence
|
|
144
|
-
# of one of the letters
|
|
145
|
-
letters_with_more_than_one.each do |l|
|
|
146
|
-
remove_lettters_out << new_ds.sub(l, "")
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
if array_out
|
|
150
|
-
remove_lettters_out
|
|
151
|
-
else
|
|
152
|
-
# will print the contents of the array
|
|
153
|
-
# instead of returning the array
|
|
154
|
-
remove_lettters_out.each { |a| puts a }
|
|
227
|
+
end
|
|
228
|
+
suffixes = ["-", ".", "--"]
|
|
229
|
+
# this will generate the 'new_domain' with the keywords
|
|
230
|
+
# as a suffixes
|
|
231
|
+
suffixes.each do |suf|
|
|
232
|
+
ds.each do |domain|
|
|
233
|
+
keywords.each do |key|
|
|
234
|
+
new_domain = "#{domain}#{suf}#{key}"
|
|
235
|
+
results << new_domain
|
|
155
236
|
end
|
|
156
237
|
end
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
238
|
+
end
|
|
239
|
+
# adds the tlds to the newly created domains
|
|
240
|
+
|
|
241
|
+
add_tlds(results)
|
|
242
|
+
end
|
|
243
|
+
def change_tld(no_tld: true)
|
|
244
|
+
# This method will take the inputted site in @site and
|
|
245
|
+
# remove the TLDs and add a new TLDs to the domain.
|
|
246
|
+
# its uses the 'domain' method in the PhishingData class
|
|
247
|
+
# which has an array of a bunch of different tlds.
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# if the @site does not have a tlds
|
|
251
|
+
if no_tld
|
|
252
|
+
new_domains = []
|
|
253
|
+
# loop through the tlds
|
|
254
|
+
domains.each do |d|
|
|
255
|
+
# combine the inputed @site
|
|
256
|
+
# and the tlds
|
|
257
|
+
new_domains << "#{@site}#{d}"
|
|
258
|
+
end
|
|
259
|
+
new_domains
|
|
260
|
+
else
|
|
261
|
+
# If the @site does have a TLDs.
|
|
163
262
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
#
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
263
|
+
# this is where the final results
|
|
264
|
+
# are stored.
|
|
265
|
+
list_of_domains = []
|
|
266
|
+
|
|
267
|
+
# removes .com, .org, etc
|
|
268
|
+
ds = remove_tlds
|
|
269
|
+
|
|
270
|
+
# join the elements together with .
|
|
271
|
+
ds = ds.join(".")
|
|
272
|
+
|
|
273
|
+
# loops through the tlds
|
|
274
|
+
domains.each do |tlds|
|
|
275
|
+
# adds the new domains to the array
|
|
276
|
+
list_of_domains << "#{ds}#{tlds}"
|
|
277
|
+
#ds + tlds
|
|
278
|
+
end
|
|
279
|
+
list_of_domains
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
def idn_homograph
|
|
283
|
+
letters = {
|
|
284
|
+
"o" => ["0", "О", "ó", "о","ο","օ","ȯ","ọ","ỏ","ơ","ó","ö"],
|
|
285
|
+
"i" => ["1","ı", "ỉ", "і", "í", "ï"],
|
|
286
|
+
"a" => ["а","α", "ạ"],
|
|
287
|
+
"h" => ["н", "һ", "ĥ"],
|
|
288
|
+
"c" => ["с"],
|
|
289
|
+
"I" => "l",
|
|
290
|
+
"e" => ["е", "℮", "ё", "ė", "ẹ"],
|
|
291
|
+
"b" => [ "þ", "в", "B" ],
|
|
292
|
+
"g" => [ "ɢ"],
|
|
293
|
+
"l" => ["Ɩ", "Ι"],
|
|
294
|
+
"m" => ["m", "ʍ", "м"],
|
|
295
|
+
"t" => ["т", "ţ"],
|
|
296
|
+
"p" => ["р"],
|
|
297
|
+
"y" => ["у", "ý"],
|
|
298
|
+
"k" => ["ķ"],
|
|
299
|
+
"d" => ["ɗ"],
|
|
300
|
+
"z" => ["ź","ʐ", "ż"],
|
|
301
|
+
"s" => ["ś", "ṣ"],
|
|
302
|
+
"u" => ["ų", "υ", "ս","ü","ú","ù"],
|
|
303
|
+
"n" => ["ń", "ñ"],
|
|
304
|
+
"r" => ["ɾ", "R", "r", "ʀ", "Ի", "Ꮢ", "ᚱ", "R", "r"],
|
|
305
|
+
"ll" => ["ǁ"],
|
|
306
|
+
"q" => ["զ"],
|
|
307
|
+
"j" => ["ј", "ʝ"],
|
|
308
|
+
"v" => ["ν", "ѵ"],
|
|
309
|
+
"x" => ["х" "ҳ"]
|
|
310
|
+
}
|
|
311
|
+
tlds = @site.split(".")
|
|
312
|
+
# removes the tlds
|
|
313
|
+
tlds.pop
|
|
314
|
+
# joins back the rest of the site
|
|
315
|
+
tlds = tlds.join(".")
|
|
316
|
+
|
|
317
|
+
new_domains = []
|
|
318
|
+
letters.each do |k, v|
|
|
319
|
+
tlds.split(//).each do |letter|
|
|
320
|
+
# if the letter elements
|
|
321
|
+
# are qual to the key vlaue
|
|
322
|
+
# located in the letters hash
|
|
323
|
+
if letter.eql?(k)
|
|
324
|
+
# find the key and replace it
|
|
325
|
+
# the v ( idn )
|
|
326
|
+
if v.kind_of?(Array)
|
|
327
|
+
# detct if the v ( value )
|
|
328
|
+
# is an array. If it is
|
|
329
|
+
# then it will "randomly" pick an element
|
|
330
|
+
v = v.sample
|
|
191
331
|
end
|
|
192
|
-
|
|
332
|
+
new_domains << tlds.gsub(k, v)
|
|
193
333
|
end
|
|
194
334
|
end
|
|
195
|
-
private :remove_tlds, :domain_split
|
|
196
335
|
end
|
|
336
|
+
add_tlds(new_domains)
|
|
337
|
+
end
|
|
338
|
+
private :remove_tlds, :domain_split
|
|
339
|
+
end
|
|
197
340
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'socket'
|
|
2
|
+
|
|
3
|
+
# Grab the banner of a given +ip+ address and +port+
|
|
4
|
+
# to attempt to connect to.
|
|
5
|
+
#
|
|
6
|
+
# @param ip [String] Target IP address.
|
|
7
|
+
# @param port [Integer] Target port.
|
|
8
|
+
#
|
|
9
|
+
# @return [String]
|
|
10
|
+
def grab_banner(ip, port)
|
|
11
|
+
TCPSocket.new(ip, port).recv(1024)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Print the result of the method to STDOUT.
|
|
15
|
+
puts grab_banner('100.106.14.40', 22)
|
data/lib/snackhack2/version.rb
CHANGED
data/lib/snackhack2.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'uri'
|
|
4
4
|
require 'httparty'
|
|
5
|
-
|
|
5
|
+
=begin
|
|
6
6
|
require_relative 'snackhack2/version'
|
|
7
7
|
require_relative 'snackhack2/bannergrabber'
|
|
8
8
|
require_relative 'snackhack2/wordpress'
|
|
@@ -36,6 +36,12 @@ require_relative 'snackhack2/ssrf'
|
|
|
36
36
|
require_relative 'snackhack2/dns'
|
|
37
37
|
require_relative 'snackhack2/CVE-2017-9841'
|
|
38
38
|
require_relative 'snackhack2/phishing_tlds'
|
|
39
|
+
=end
|
|
40
|
+
Dir.glob(File.join(File.dirname(__FILE__), "snackhack2", "*")).each do |file|
|
|
41
|
+
unless File.directory?(file)
|
|
42
|
+
require_relative file
|
|
43
|
+
end
|
|
44
|
+
end
|
|
39
45
|
module Snackhack2
|
|
40
46
|
UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
|
|
41
47
|
def self.read_serverversion
|
|
@@ -57,10 +63,17 @@ module Snackhack2
|
|
|
57
63
|
end
|
|
58
64
|
end
|
|
59
65
|
|
|
60
|
-
def self.file_save(site, type, content, ip: false)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
def self.file_save(site, type, content, ip: false, host: true)
|
|
67
|
+
if host
|
|
68
|
+
hostname = URI.parse(site).host
|
|
69
|
+
File.open("#{hostname}_#{type}.txt", 'w+') { |file| file.write(content) }
|
|
70
|
+
puts "[+] Saving file to #{hostname}_#{type}.txt..."
|
|
71
|
+
else
|
|
72
|
+
File.open("#{site}_#{type}.txt", 'w+') { |file| file.write(content) }
|
|
73
|
+
puts "[+] Saving file to #{site}_#{type}.txt..."
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
64
77
|
end
|
|
65
78
|
|
|
66
79
|
def self.get(site)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: snackhack2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- mike
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-10-
|
|
11
|
+
date: 2025-10-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: httparty
|
|
@@ -99,6 +99,7 @@ files:
|
|
|
99
99
|
- lib/snackhack2/robots.rb
|
|
100
100
|
- lib/snackhack2/screenshots.rb
|
|
101
101
|
- lib/snackhack2/sitemap.rb
|
|
102
|
+
- lib/snackhack2/ssh.rb
|
|
102
103
|
- lib/snackhack2/sshbrute.rb
|
|
103
104
|
- lib/snackhack2/ssrf.rb
|
|
104
105
|
- lib/snackhack2/subdomains.rb
|