bettercap 1.5.7 → 1.5.8
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/bettercap/context.rb +1 -1
- data/lib/bettercap/network/protos/teamviewer.rb +7 -2
- data/lib/bettercap/options/proxy_options.rb +7 -0
- data/lib/bettercap/options/spoof_options.rb +3 -3
- data/lib/bettercap/proxy/http/modules/injectcss.rb +4 -4
- data/lib/bettercap/proxy/http/modules/injecthtml.rb +11 -5
- data/lib/bettercap/proxy/http/modules/injectjs.rb +4 -4
- data/lib/bettercap/proxy/http/ssl/authority.rb +1 -1
- data/lib/bettercap/proxy/stream_logger.rb +36 -3
- data/lib/bettercap/shell.rb +11 -0
- data/lib/bettercap/version.rb +1 -1
- metadata +34 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fae72c45d628b9638bb5b384c351065d75ad48b4
|
4
|
+
data.tar.gz: 5c8d16d02481507e50bbe97fe3a84122f8bb8ffb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9f33856ef7ef0194c584a9de47968642608464f6ec32bfa5dc502e4a0b97fc8352550b2d9edcd9953ba4a2dda54a6e8ae70bae6504d6ab837248d15bc9bf7b8
|
7
|
+
data.tar.gz: d901dc26801e51b558455b665454c59d3a9ce8ba977c0c77b39d4f66a1b5208af0a8956e22528bd6c519c08f8c5b88ff2e28fd27b8175b9baa68836e6fa9d070
|
data/lib/bettercap/context.rb
CHANGED
@@ -95,7 +95,7 @@ class Context
|
|
95
95
|
|
96
96
|
Logger.info "Changing interface MAC address to #{@options.core.use_mac}"
|
97
97
|
|
98
|
-
Shell.
|
98
|
+
Shell.change_mac( @options.core.iface, @options.core.use_mac )
|
99
99
|
end
|
100
100
|
|
101
101
|
cfg = PacketFu::Utils.ifconfig @options.core.iface
|
@@ -104,8 +104,13 @@ class Packet < Network::Protos::Base
|
|
104
104
|
uint8 :command_code
|
105
105
|
|
106
106
|
def version
|
107
|
-
|
108
|
-
|
107
|
+
if self.magic == 0x1724
|
108
|
+
return '1'
|
109
|
+
elsif self.magic == 0x1130
|
110
|
+
return '2'
|
111
|
+
else
|
112
|
+
return '?'
|
113
|
+
end
|
109
114
|
end
|
110
115
|
|
111
116
|
def command
|
@@ -36,6 +36,8 @@ class ProxyOptions
|
|
36
36
|
attr_accessor :sslstrip
|
37
37
|
# If true, direct connections to the IP of this machine will be allowed.
|
38
38
|
attr_accessor :allow_local_connections
|
39
|
+
# If true, log HTTP responses too.
|
40
|
+
attr_accessor :log_response
|
39
41
|
# If true, TCP proxy will be enabled.
|
40
42
|
attr_accessor :tcp_proxy
|
41
43
|
# TCP proxy local port.
|
@@ -69,6 +71,7 @@ class ProxyOptions
|
|
69
71
|
@proxy_module = nil
|
70
72
|
@sslstrip = true
|
71
73
|
@allow_local_connections = false
|
74
|
+
@log_response = false
|
72
75
|
|
73
76
|
@tcp_proxy = false
|
74
77
|
@tcp_proxy_port = 2222
|
@@ -160,6 +163,10 @@ class ProxyOptions
|
|
160
163
|
@sslstrip = false
|
161
164
|
end
|
162
165
|
|
166
|
+
opts.on( '--log-http-response', 'Log HTTP responses.' ) do
|
167
|
+
@log_response = true
|
168
|
+
end
|
169
|
+
|
163
170
|
opts.on( '--proxy-module MODULE', "Ruby proxy module to load, either a custom file or one of the following: #{Proxy::HTTP::Module.available.map{|x| x.yellow}.join(', ')}." ) do |v|
|
164
171
|
Proxy::HTTP::Module.load(ctx, opts, v)
|
165
172
|
@proxy = true
|
@@ -24,7 +24,7 @@ class SpoofOptions
|
|
24
24
|
|
25
25
|
def initialize
|
26
26
|
@spoofer = 'ARP'
|
27
|
-
@half_duplex =
|
27
|
+
@half_duplex = true
|
28
28
|
@kill = false
|
29
29
|
end
|
30
30
|
|
@@ -41,8 +41,8 @@ class SpoofOptions
|
|
41
41
|
@spoofer = 'NONE'
|
42
42
|
end
|
43
43
|
|
44
|
-
opts.on( '--
|
45
|
-
@half_duplex =
|
44
|
+
opts.on( '--full-duplex', 'Enable full-duplex MITM, this will make bettercap attack both the target(s) and the router.' ) do
|
45
|
+
@half_duplex = false
|
46
46
|
end
|
47
47
|
|
48
48
|
opts.on( '--kill', 'Instead of forwarding packets, this switch will make targets connections to be killed.' ) do
|
@@ -67,13 +67,13 @@ class InjectCSS < BetterCap::Proxy::HTTP::Module
|
|
67
67
|
BetterCap::Logger.info "[#{'INJECTCSS'.green}] Injecting CSS #{@@cssdata.nil?? "URL" : "file"} into #{request.to_url}"
|
68
68
|
# inject URL
|
69
69
|
if @@cssdata.nil?
|
70
|
-
|
71
|
-
response.body.sub!( '</head>' ) {replacement}
|
70
|
+
replacement = " <link rel=\"stylesheet\" href=\"#{@cssurl}\"></script></head> "
|
72
71
|
# inject data
|
73
72
|
else
|
74
|
-
|
75
|
-
response.body.sub!( '</head>' ) {replacement}
|
73
|
+
replacement = "#{@@cssdata}</head> "
|
76
74
|
end
|
75
|
+
|
76
|
+
response.body.sub!( /<\/head>/i ) { replacement }
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -36,6 +36,12 @@ class InjectHTML < BetterCap::Proxy::HTTP::Module
|
|
36
36
|
@@data = v
|
37
37
|
end
|
38
38
|
|
39
|
+
opts.on( '--html-file PATH', 'Path of the html file to be injected.' ) do |v|
|
40
|
+
filename = File.expand_path v
|
41
|
+
raise BetterCap::Error, "#{filename} invalid file." unless File.exists?(filename)
|
42
|
+
@@data = File.read( filename )
|
43
|
+
end
|
44
|
+
|
39
45
|
opts.on( '--html-iframe-url URL', 'URL of the iframe that will be injected, if this option is specified an "iframe" tag will be injected.' ) do |v|
|
40
46
|
@@iframe = v
|
41
47
|
end
|
@@ -44,7 +50,7 @@ class InjectHTML < BetterCap::Proxy::HTTP::Module
|
|
44
50
|
# Create an instance of this module and raise a BetterCap::Error if command
|
45
51
|
# line arguments weren't correctly specified.
|
46
52
|
def initialize
|
47
|
-
raise BetterCap::Error, "No --html-data or --html-iframe-url options specified for the proxy module." if @@data.nil? and @@iframe.nil?
|
53
|
+
raise BetterCap::Error, "No --html-file, --html-data or --html-iframe-url options specified for the proxy module." if @@data.nil? and @@iframe.nil?
|
48
54
|
end
|
49
55
|
|
50
56
|
# Called by the BetterCap::Proxy::HTTP::Proxy processor on each HTTP +request+ and
|
@@ -55,12 +61,12 @@ class InjectHTML < BetterCap::Proxy::HTTP::Module
|
|
55
61
|
BetterCap::Logger.info "[#{'INJECTHTML'.green}] Injecting HTML code into #{request.to_url}"
|
56
62
|
|
57
63
|
if @@data.nil?
|
58
|
-
|
59
|
-
response.body.sub!( '</body>' ) {replacement}
|
64
|
+
replacement = "<iframe src=\"#{@@iframe}\" frameborder=\"0\" height=\"0\" width=\"0\"></iframe></body>"
|
60
65
|
else
|
61
|
-
|
62
|
-
response.body.sub!( '</body>' ) {replacement}
|
66
|
+
replacement = "#{@@data}</body>"
|
63
67
|
end
|
68
|
+
|
69
|
+
response.body.sub!( /<\/body>/i ) { replacement }
|
64
70
|
end
|
65
71
|
end
|
66
72
|
end
|
@@ -67,13 +67,13 @@ class InjectJS < BetterCap::Proxy::HTTP::Module
|
|
67
67
|
BetterCap::Logger.info "[#{'INJECTJS'.green}] Injecting javascript #{@@jsdata.nil?? "URL" : "file"} into #{request.to_url}"
|
68
68
|
# inject URL
|
69
69
|
if @@jsdata.nil?
|
70
|
-
|
71
|
-
response.body.sub!( '</head>' ) {replacement}
|
70
|
+
replacement = "<script src=\"#{@@jsurl}\" type=\"text/javascript\"></script></head>"
|
72
71
|
# inject data
|
73
72
|
else
|
74
|
-
|
75
|
-
response.body.sub!( '</head>') {replacement}
|
73
|
+
replacement = "#{@@jsdata}</head>"
|
76
74
|
end
|
75
|
+
|
76
|
+
response.body.sub!( /<\/head>/i ) { replacement }
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -59,7 +59,7 @@ class Store
|
|
59
59
|
# Find the +hostname+:+port+ certificate and return it.
|
60
60
|
def find( hostname, port )
|
61
61
|
# make sure *.domain.tld hostnames are correctly sanitized
|
62
|
-
hostname.gsub!( "
|
62
|
+
hostname.gsub!( "*.", "www." )
|
63
63
|
|
64
64
|
key = Digest::SHA256.hexdigest( "#{hostname}_#{port}" )
|
65
65
|
|
@@ -130,11 +130,11 @@ class StreamLogger
|
|
130
130
|
def self.log_post( request )
|
131
131
|
# the packet could be incomplete
|
132
132
|
if request.post? and !request.body.nil? and !request.body.empty?
|
133
|
-
msg = "\n[#{'HEADERS'.green}]\n\n"
|
133
|
+
msg = "\n[#{'REQUEST HEADERS'.green}]\n\n"
|
134
134
|
request.headers.each do |name,value|
|
135
135
|
msg << " #{name.blue} : #{value.yellow}\n"
|
136
136
|
end
|
137
|
-
msg << "\n[#{'BODY'.green}]\n\n"
|
137
|
+
msg << "\n[#{'REQUEST BODY'.green}]\n\n"
|
138
138
|
|
139
139
|
case request['Content-Type']
|
140
140
|
when /application\/x-www-form-urlencoded.*/i
|
@@ -157,12 +157,40 @@ class StreamLogger
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
+
# This method will log every header and the body of +response+.
|
161
|
+
def self.log_response( response )
|
162
|
+
msg = "\n[#{'RESPONSE HEADERS'.light_red}]\n\n"
|
163
|
+
response.headers.each do |name,value|
|
164
|
+
msg << " #{name.blue} : #{value.to_s.yellow}\n"
|
165
|
+
end
|
166
|
+
msg << "\n[#{'RESPONSE BODY'.light_red}]\n\n"
|
167
|
+
|
168
|
+
case response['Content-Type']
|
169
|
+
when /application\/x-www-form-urlencoded.*/i
|
170
|
+
msg << self.dump_form( response )
|
171
|
+
|
172
|
+
when /text\/plain.*/i
|
173
|
+
msg << response.body + "\n"
|
174
|
+
|
175
|
+
when /gzip.*/i
|
176
|
+
msg << self.dump_gzip( response )
|
177
|
+
|
178
|
+
when /application\/json.*/i
|
179
|
+
msg << self.dump_json( response )
|
180
|
+
|
181
|
+
else
|
182
|
+
msg << self.hexdump( response.body )
|
183
|
+
end
|
184
|
+
|
185
|
+
Logger.raw "#{msg}\n"
|
186
|
+
end
|
187
|
+
|
160
188
|
# Log a HTTP ( HTTPS if +is_https+ is true ) stream performed by the +client+
|
161
189
|
# with the +request+ and +response+ most important informations.
|
162
190
|
def self.log_http( request, response )
|
163
191
|
response_s = ""
|
164
192
|
response_s += " ( #{response.content_type} )" unless response.content_type.nil?
|
165
|
-
request_s = request.to_url(
|
193
|
+
request_s = request.to_url( nil )
|
166
194
|
code = response.code.to_s[0]
|
167
195
|
|
168
196
|
if @@CODE_COLORS.has_key? code
|
@@ -172,10 +200,15 @@ class StreamLogger
|
|
172
200
|
end
|
173
201
|
|
174
202
|
Logger.raw "[#{self.addr2s(request.client)}] #{request.method.light_blue} #{request_s}#{response_s}"
|
203
|
+
|
175
204
|
# Log post body if the POST sniffer is enabled.
|
176
205
|
if Context.get.options.sniff.enabled?('POST')
|
177
206
|
self.log_post( request )
|
178
207
|
end
|
208
|
+
|
209
|
+
if Context.get.options.proxies.log_response
|
210
|
+
self.log_response( response )
|
211
|
+
end
|
179
212
|
end
|
180
213
|
end
|
181
214
|
end
|
data/lib/bettercap/shell.rb
CHANGED
@@ -56,6 +56,17 @@ module Shell
|
|
56
56
|
self.execute( "LANG=en && ifconfig #{iface}" )
|
57
57
|
end
|
58
58
|
|
59
|
+
# Change the +iface+ mac address to +mac+ using ifconfig.
|
60
|
+
def change_mac(iface, mac)
|
61
|
+
if RUBY_PLATFORM =~ /.+bsd/ or RUBY_PLATFORM =~ /darwin/
|
62
|
+
self.ifconfig( "#{iface} ether #{mac}")
|
63
|
+
elsif RUBY_PLATFORM =~ /linux/
|
64
|
+
self.ifconfig( "#{iface} hw ether #{mac}")
|
65
|
+
else
|
66
|
+
raise BetterCap::Error, 'Unsupported operating system'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
59
70
|
# Get the +iface+ network interface configuration ( using iproute2 ).
|
60
71
|
def ip(iface = '')
|
61
72
|
self.execute( "LANG=en && ip addr show #{iface}" )
|
data/lib/bettercap/version.rb
CHANGED
@@ -12,7 +12,7 @@ This project is released under the GPL 3 license.
|
|
12
12
|
=end
|
13
13
|
module BetterCap
|
14
14
|
# Current version of bettercap.
|
15
|
-
VERSION = '1.5.
|
15
|
+
VERSION = '1.5.8'
|
16
16
|
# Program banner.
|
17
17
|
BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
|
18
18
|
end
|
metadata
CHANGED
@@ -1,147 +1,147 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bettercap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simone Margaritelli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.8.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.8.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: packetfu
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.1'
|
34
|
-
- -
|
34
|
+
- - '>='
|
35
35
|
- !ruby/object:Gem::Version
|
36
36
|
version: 1.1.10
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
|
-
- -
|
41
|
+
- - ~>
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: '1.1'
|
44
|
-
- -
|
44
|
+
- - '>='
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 1.1.10
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: pcaprub
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- -
|
51
|
+
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '0.12'
|
54
|
-
- -
|
54
|
+
- - '>='
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: 0.12.0
|
57
57
|
type: :runtime
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
|
-
- -
|
61
|
+
- - ~>
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: '0.12'
|
64
|
-
- -
|
64
|
+
- - '>='
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: 0.12.0
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: network_interface
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
70
70
|
requirements:
|
71
|
-
- -
|
71
|
+
- - ~>
|
72
72
|
- !ruby/object:Gem::Version
|
73
73
|
version: '0.0'
|
74
|
-
- -
|
74
|
+
- - '>='
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: 0.0.1
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ~>
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0.0'
|
84
|
-
- -
|
84
|
+
- - '>='
|
85
85
|
- !ruby/object:Gem::Version
|
86
86
|
version: 0.0.1
|
87
87
|
- !ruby/object:Gem::Dependency
|
88
88
|
name: net-dns
|
89
89
|
requirement: !ruby/object:Gem::Requirement
|
90
90
|
requirements:
|
91
|
-
- -
|
91
|
+
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0.8'
|
94
|
-
- -
|
94
|
+
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 0.8.0
|
97
97
|
type: :runtime
|
98
98
|
prerelease: false
|
99
99
|
version_requirements: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0.8'
|
104
|
-
- -
|
104
|
+
- - '>='
|
105
105
|
- !ruby/object:Gem::Version
|
106
106
|
version: 0.8.0
|
107
107
|
- !ruby/object:Gem::Dependency
|
108
108
|
name: rubydns
|
109
109
|
requirement: !ruby/object:Gem::Requirement
|
110
110
|
requirements:
|
111
|
-
- -
|
111
|
+
- - ~>
|
112
112
|
- !ruby/object:Gem::Version
|
113
113
|
version: '1.0'
|
114
|
-
- -
|
114
|
+
- - '>='
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: 1.0.3
|
117
117
|
type: :runtime
|
118
118
|
prerelease: false
|
119
119
|
version_requirements: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
|
-
- -
|
121
|
+
- - ~>
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: '1.0'
|
124
|
-
- -
|
124
|
+
- - '>='
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: 1.0.3
|
127
127
|
- !ruby/object:Gem::Dependency
|
128
128
|
name: em-proxy
|
129
129
|
requirement: !ruby/object:Gem::Requirement
|
130
130
|
requirements:
|
131
|
-
- -
|
131
|
+
- - ~>
|
132
132
|
- !ruby/object:Gem::Version
|
133
133
|
version: '0.1'
|
134
|
-
- -
|
134
|
+
- - '>='
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: 0.1.8
|
137
137
|
type: :runtime
|
138
138
|
prerelease: false
|
139
139
|
version_requirements: !ruby/object:Gem::Requirement
|
140
140
|
requirements:
|
141
|
-
- -
|
141
|
+
- - ~>
|
142
142
|
- !ruby/object:Gem::Version
|
143
143
|
version: '0.1'
|
144
|
-
- -
|
144
|
+
- - '>='
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: 0.1.8
|
147
147
|
description: BetterCap is the state of the art, modular, portable and easily extensible
|
@@ -155,8 +155,6 @@ extra_rdoc_files: []
|
|
155
155
|
files:
|
156
156
|
- LICENSE.md
|
157
157
|
- README.md
|
158
|
-
- bin/bettercap
|
159
|
-
- lib/bettercap.rb
|
160
158
|
- lib/bettercap/banner
|
161
159
|
- lib/bettercap/context.rb
|
162
160
|
- lib/bettercap/discovery/agents/arp.rb
|
@@ -251,30 +249,31 @@ files:
|
|
251
249
|
- lib/bettercap/spoofers/none.rb
|
252
250
|
- lib/bettercap/update_checker.rb
|
253
251
|
- lib/bettercap/version.rb
|
252
|
+
- lib/bettercap.rb
|
253
|
+
- bin/bettercap
|
254
254
|
homepage: http://github.com/evilsocket/bettercap
|
255
255
|
licenses:
|
256
256
|
- GPL-3.0
|
257
257
|
metadata: {}
|
258
258
|
post_install_message:
|
259
259
|
rdoc_options:
|
260
|
-
-
|
260
|
+
- --charset=UTF-8
|
261
261
|
require_paths:
|
262
262
|
- lib
|
263
263
|
required_ruby_version: !ruby/object:Gem::Requirement
|
264
264
|
requirements:
|
265
|
-
- -
|
265
|
+
- - '>='
|
266
266
|
- !ruby/object:Gem::Version
|
267
267
|
version: '1.9'
|
268
268
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
269
269
|
requirements:
|
270
|
-
- -
|
270
|
+
- - '>='
|
271
271
|
- !ruby/object:Gem::Version
|
272
272
|
version: '0'
|
273
273
|
requirements: []
|
274
274
|
rubyforge_project:
|
275
|
-
rubygems_version: 2.
|
275
|
+
rubygems_version: 2.0.14.1
|
276
276
|
signing_key:
|
277
277
|
specification_version: 4
|
278
278
|
summary: A complete, modular, portable and easily extensible MITM framework.
|
279
279
|
test_files: []
|
280
|
-
has_rdoc:
|