bettercap 1.4.6 → 1.5.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/bin/bettercap +1 -1
- data/lib/bettercap.rb +1 -0
- data/lib/bettercap/context.rb +63 -70
- data/lib/bettercap/discovery/agents/base.rb +2 -2
- data/lib/bettercap/discovery/thread.rb +5 -4
- data/lib/bettercap/firewalls/base.rb +2 -4
- data/lib/bettercap/firewalls/{osx.rb → bsd.rb} +3 -3
- data/lib/bettercap/firewalls/linux.rb +2 -2
- data/lib/bettercap/firewalls/redirection.rb +5 -2
- data/lib/bettercap/logger.rb +6 -11
- data/lib/bettercap/memory.rb +56 -0
- data/lib/bettercap/monkey/em-proxy/proxy.rb +23 -0
- data/lib/bettercap/monkey/packetfu/pcap.rb +51 -0
- data/lib/bettercap/network/arp_reader.rb +2 -2
- data/lib/bettercap/network/network.rb +2 -2
- data/lib/bettercap/network/packet_queue.rb +2 -2
- data/lib/bettercap/network/protos/base.rb +8 -5
- data/lib/bettercap/network/protos/dhcp.rb +5 -124
- data/lib/bettercap/network/target.rb +7 -2
- data/lib/bettercap/options/core_options.rb +189 -0
- data/lib/bettercap/options/options.rb +167 -0
- data/lib/bettercap/options/proxy_options.rb +258 -0
- data/lib/bettercap/options/server_options.rb +71 -0
- data/lib/bettercap/options/sniff_options.rb +90 -0
- data/lib/bettercap/options/spoof_options.rb +71 -0
- data/lib/bettercap/proxy/{module.rb → http/module.rb} +8 -4
- data/lib/bettercap/proxy/{modules → http/modules}/injectcss.rb +2 -2
- data/lib/bettercap/proxy/{modules → http/modules}/injecthtml.rb +2 -2
- data/lib/bettercap/proxy/{modules → http/modules}/injectjs.rb +2 -2
- data/lib/bettercap/proxy/{proxy.rb → http/proxy.rb} +5 -2
- data/lib/bettercap/proxy/{request.rb → http/request.rb} +4 -0
- data/lib/bettercap/proxy/{response.rb → http/response.rb} +3 -0
- data/lib/bettercap/proxy/{ssl → http/ssl}/authority.rb +3 -1
- data/lib/bettercap/proxy/{ssl → http/ssl}/bettercap-ca.pem +0 -0
- data/lib/bettercap/proxy/{ssl → http/ssl}/server.rb +3 -1
- data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/cookiemonitor.rb +2 -0
- data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/lock.ico +0 -0
- data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/strip.rb +4 -2
- data/lib/bettercap/proxy/{streamer.rb → http/streamer.rb} +7 -4
- data/lib/bettercap/proxy/stream_logger.rb +25 -9
- data/lib/bettercap/proxy/tcp/module.rb +75 -0
- data/lib/bettercap/proxy/tcp/proxy.rb +123 -0
- data/lib/bettercap/proxy/thread_pool.rb +1 -1
- data/lib/bettercap/sniffer/parsers/post.rb +1 -1
- data/lib/bettercap/sniffer/parsers/url.rb +1 -1
- data/lib/bettercap/sniffer/sniffer.rb +23 -17
- data/lib/bettercap/spoofers/arp.rb +21 -9
- data/lib/bettercap/spoofers/base.rb +12 -16
- data/lib/bettercap/spoofers/icmp.rb +4 -5
- data/lib/bettercap/spoofers/none.rb +0 -1
- data/lib/bettercap/version.rb +1 -1
- metadata +48 -19
- data/lib/bettercap/firewalls/openbsd.rb +0 -77
- data/lib/bettercap/options.rb +0 -600
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
|
4
|
+
BETTERCAP
|
5
|
+
|
6
|
+
Author : Simone 'evilsocket' Margaritelli
|
7
|
+
Email : evilsocket@gmail.com
|
8
|
+
Blog : http://www.evilsocket.net/
|
9
|
+
|
10
|
+
This project is released under the GPL 3 license.
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
module BetterCap
|
15
|
+
|
16
|
+
class SniffOptions
|
17
|
+
# If true the BetterCap::Sniffer will be enabled.
|
18
|
+
attr_accessor :enabled
|
19
|
+
# PCAP file name to save captured packets to.
|
20
|
+
attr_accessor :output
|
21
|
+
# BPF filter to apply to sniffed packets.
|
22
|
+
attr_accessor :filter
|
23
|
+
# Input PCAP file, if specified the BetterCap::Sniffer will read packets
|
24
|
+
# from it instead of the network.
|
25
|
+
attr_accessor :src
|
26
|
+
# Comma separated list of BetterCap::Parsers to enable.
|
27
|
+
attr_accessor :parsers
|
28
|
+
# Regular expression to use with the BetterCap::Parsers::Custom parser.
|
29
|
+
attr_accessor :custom_parser
|
30
|
+
# If true, bettercap will sniff packets from the local interface as well.
|
31
|
+
attr_accessor :local
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@enabled = false
|
35
|
+
@output = nil
|
36
|
+
@filter = nil
|
37
|
+
@src = nil
|
38
|
+
@parsers = ['*']
|
39
|
+
@custom_parser = nil
|
40
|
+
@local = false
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse!( ctx, opts )
|
44
|
+
opts.separator ""
|
45
|
+
opts.separator "SNIFFING:".bold
|
46
|
+
opts.separator ""
|
47
|
+
|
48
|
+
opts.on( '-X', '--sniffer', 'Enable sniffer.' ) do
|
49
|
+
@enabled = true
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on( '-L', '--local', "Parse packets coming from/to the address of this computer ( NOTE: Will set -X to true ), default to #{'false'.yellow}." ) do
|
53
|
+
@enabled = true
|
54
|
+
@local = true
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on( '--sniffer-source FILE', 'Load packets from the specified PCAP file instead of the interface ( will enable sniffer ).' ) do |v|
|
58
|
+
@enabled = true
|
59
|
+
@src = File.expand_path v
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on( '--sniffer-output FILE', 'Save all packets to the specified PCAP file ( will enable sniffer ).' ) do |v|
|
63
|
+
@enabled = true
|
64
|
+
@output = File.expand_path v
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on( '--sniffer-filter EXPRESSION', 'Configure the sniffer to use this BPF filter ( will enable sniffer ).' ) do |v|
|
68
|
+
@enabled = true
|
69
|
+
@filter = v
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on( '-P', '--parsers PARSERS', "Comma separated list of packet parsers to enable, '*' for all ( NOTE: Will set -X to true ), available: #{Parsers::Base.available.map { |x| x.yellow }.join(', ')} - default: #{'*'.yellow}" ) do |v|
|
73
|
+
@enabled = true
|
74
|
+
@parsers = Parsers::Base.from_cmdline(v)
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on( '--custom-parser EXPRESSION', 'Use a custom regular expression in order to capture and show sniffed data ( NOTE: Will set -X to true ).' ) do |v|
|
78
|
+
@enabled = true
|
79
|
+
@parsers = ['CUSTOM']
|
80
|
+
@custom_parser = Regexp.new(v)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Return true if the specified +parser+ is enabled, otherwise false.
|
85
|
+
def enabled?( parser = nil )
|
86
|
+
@enabled and ( parser.nil? or ( @parsers.include?('*') or @parsers.include?(parser.upcase) ) )
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
|
4
|
+
BETTERCAP
|
5
|
+
|
6
|
+
Author : Simone 'evilsocket' Margaritelli
|
7
|
+
Email : evilsocket@gmail.com
|
8
|
+
Blog : http://www.evilsocket.net/
|
9
|
+
|
10
|
+
This project is released under the GPL 3 license.
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
module BetterCap
|
15
|
+
|
16
|
+
class SpoofOptions
|
17
|
+
# Name of the spoofer to use.
|
18
|
+
attr_accessor :spoofer
|
19
|
+
# If true half duplex mode is enabled.
|
20
|
+
attr_accessor :half_duplex
|
21
|
+
# If true, bettercap won't forward packets for any target, causing
|
22
|
+
# connections to be killed.
|
23
|
+
attr_accessor :kill
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@spoofer = 'ARP'
|
27
|
+
@half_duplex = false
|
28
|
+
@kill = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse!( ctx, opts )
|
32
|
+
opts.separator ""
|
33
|
+
opts.separator "SPOOFING:".bold
|
34
|
+
opts.separator ""
|
35
|
+
|
36
|
+
opts.on( '-S', '--spoofer NAME', "Spoofer module to use, available: #{Spoofers::Base.available.map{|x| x.yellow }.join(', ')} - default: #{@spoofer.yellow}." ) do |v|
|
37
|
+
@spoofer = v
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on( '--no-spoofing', "Disable spoofing, alias for #{'--spoofer NONE'.yellow}." ) do
|
41
|
+
@spoofer = 'NONE'
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on( '--half-duplex', 'Enable half-duplex MITM, this will make bettercap work in those cases when the router is not vulnerable.' ) do
|
45
|
+
@half_duplex = true
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on( '--kill', 'Instead of forwarding packets, this switch will make targets connections to be killed.' ) do
|
49
|
+
@kill = true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return true if a spoofer module was specified, otherwise false.
|
54
|
+
def enabled?
|
55
|
+
@spoofer.upcase != 'NONE'
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Parse spoofers and return a list of BetterCap::Spoofers objects. Raise a
|
60
|
+
# BetterCap::Error if an invalid spoofer name was specified.
|
61
|
+
def parse_spoofers
|
62
|
+
valid = []
|
63
|
+
@spoofer.split(",").each do |module_name|
|
64
|
+
valid << Spoofers::Base.get_by_name( module_name )
|
65
|
+
end
|
66
|
+
valid
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -13,6 +13,8 @@ This project is released under the GPL 3 license.
|
|
13
13
|
|
14
14
|
module BetterCap
|
15
15
|
module Proxy
|
16
|
+
module HTTP
|
17
|
+
|
16
18
|
# Base class for transparent proxy modules.
|
17
19
|
class Module
|
18
20
|
@@path = File.dirname(__FILE__) + '/modules/'
|
@@ -40,13 +42,13 @@ class Module
|
|
40
42
|
# Load the module with +name+.
|
41
43
|
def self.load(ctx, opts, name)
|
42
44
|
if self.is_builtin?(name)
|
43
|
-
ctx.options.proxy_module = "#{@@path}/#{name}.rb"
|
45
|
+
ctx.options.proxies.proxy_module = "#{@@path}/#{name}.rb"
|
44
46
|
else
|
45
|
-
ctx.options.proxy_module = File.expand_path(name)
|
47
|
+
ctx.options.proxies.proxy_module = File.expand_path(name)
|
46
48
|
end
|
47
49
|
|
48
50
|
begin
|
49
|
-
require ctx.options.proxy_module
|
51
|
+
require ctx.options.proxies.proxy_module
|
50
52
|
|
51
53
|
self.register_options(opts)
|
52
54
|
rescue LoadError
|
@@ -83,7 +85,7 @@ class Module
|
|
83
85
|
|
84
86
|
private
|
85
87
|
|
86
|
-
# Loop each available BetterCap::Proxy::Proxy module and yield each
|
88
|
+
# Loop each available BetterCap::Proxy::HTTP::Proxy module and yield each
|
87
89
|
# one of them for the given code block.
|
88
90
|
def self.each_module
|
89
91
|
old_verbose, $VERBOSE = $VERBOSE, nil
|
@@ -97,5 +99,7 @@ class Module
|
|
97
99
|
$VERBOSE = old_verbose
|
98
100
|
end
|
99
101
|
end
|
102
|
+
|
103
|
+
end
|
100
104
|
end
|
101
105
|
end
|
@@ -12,7 +12,7 @@ This project is released under the GPL 3 license.
|
|
12
12
|
=end
|
13
13
|
|
14
14
|
# This proxy module will take care of CSS code injection.
|
15
|
-
class InjectCSS < BetterCap::Proxy::Module
|
15
|
+
class InjectCSS < BetterCap::Proxy::HTTP::Module
|
16
16
|
# CSS data to be injected.
|
17
17
|
@@cssdata = nil
|
18
18
|
# CSS file URL to be injected.
|
@@ -51,7 +51,7 @@ class InjectCSS < BetterCap::Proxy::Module
|
|
51
51
|
raise BetterCap::Error, "No --css-file, --css-url or --css-data options specified for the proxy module." if @@cssdata.nil? and @@cssurl.nil?
|
52
52
|
end
|
53
53
|
|
54
|
-
# Called by the BetterCap::Proxy::Proxy processor on each HTTP +request+ and
|
54
|
+
# Called by the BetterCap::Proxy::HTTP::Proxy processor on each HTTP +request+ and
|
55
55
|
# +response+.
|
56
56
|
def on_request( request, response )
|
57
57
|
# is it a html page?
|
@@ -12,7 +12,7 @@ This project is released under the GPL 3 license.
|
|
12
12
|
=end
|
13
13
|
|
14
14
|
# This proxy module will take care of HTML code injection.
|
15
|
-
class InjectHTML < BetterCap::Proxy::Module
|
15
|
+
class InjectHTML < BetterCap::Proxy::HTTP::Module
|
16
16
|
# URL of the iframe if --html-iframe-url was specified.
|
17
17
|
@@iframe = nil
|
18
18
|
# HTML data to be injected.
|
@@ -39,7 +39,7 @@ class InjectHTML < BetterCap::Proxy::Module
|
|
39
39
|
raise BetterCap::Error, "No --html-data or --html-iframe-url options specified for the proxy module." if @@data.nil? and @@iframe.nil?
|
40
40
|
end
|
41
41
|
|
42
|
-
# Called by the BetterCap::Proxy::Proxy processor on each HTTP +request+ and
|
42
|
+
# Called by the BetterCap::Proxy::HTTP::Proxy processor on each HTTP +request+ and
|
43
43
|
# +response+.
|
44
44
|
def on_request( request, response )
|
45
45
|
# is it a html page?
|
@@ -12,7 +12,7 @@ This project is released under the GPL 3 license.
|
|
12
12
|
=end
|
13
13
|
|
14
14
|
# This proxy module will take care of Javascript code injection.
|
15
|
-
class InjectJS < BetterCap::Proxy::Module
|
15
|
+
class InjectJS < BetterCap::Proxy::HTTP::Module
|
16
16
|
# JS data to be injected.
|
17
17
|
@@jsdata = nil
|
18
18
|
# JS file URL to be injected.
|
@@ -51,7 +51,7 @@ class InjectJS < BetterCap::Proxy::Module
|
|
51
51
|
raise BetterCap::Error, "No --js-file, --js-url or --js-data options specified for the proxy module." if @@jsdata.nil? and @@jsurl.nil?
|
52
52
|
end
|
53
53
|
|
54
|
-
# Called by the BetterCap::Proxy::Proxy processor on each HTTP +request+ and
|
54
|
+
# Called by the BetterCap::Proxy::HTTP::Proxy processor on each HTTP +request+ and
|
55
55
|
# +response+.
|
56
56
|
def on_request( request, response )
|
57
57
|
# is it a html page?
|
@@ -13,7 +13,9 @@ This project is released under the GPL 3 license.
|
|
13
13
|
|
14
14
|
module BetterCap
|
15
15
|
module Proxy
|
16
|
-
|
16
|
+
module HTTP
|
17
|
+
|
18
|
+
# Transparent HTTP proxy class.
|
17
19
|
class Proxy
|
18
20
|
# Initialize the transparent proxy, making it listen on +address+:+port+.
|
19
21
|
# If +is_https+ is true a HTTPS proxy will be created, otherwise a HTTP one.
|
@@ -171,9 +173,10 @@ class Proxy
|
|
171
173
|
|
172
174
|
# Return true if sslstrip is needed for this proxy instance.
|
173
175
|
def need_sslstrip?
|
174
|
-
( Context.get.options.sslstrip and !@is_https )
|
176
|
+
( Context.get.options.proxies.sslstrip and !@is_https )
|
175
177
|
end
|
176
178
|
end
|
177
179
|
|
178
180
|
end
|
179
181
|
end
|
182
|
+
end
|
@@ -13,6 +13,8 @@ This project is released under the GPL 3 license.
|
|
13
13
|
|
14
14
|
module BetterCap
|
15
15
|
module Proxy
|
16
|
+
module HTTP
|
17
|
+
|
16
18
|
# HTTP request parser.
|
17
19
|
class Request
|
18
20
|
# HTTP method.
|
@@ -184,5 +186,7 @@ class Request
|
|
184
186
|
@host = value if name == 'Host'
|
185
187
|
end
|
186
188
|
end
|
189
|
+
|
190
|
+
end
|
187
191
|
end
|
188
192
|
end
|
@@ -13,6 +13,7 @@ This project is released under the GPL 3 license.
|
|
13
13
|
|
14
14
|
module BetterCap
|
15
15
|
module Proxy
|
16
|
+
module HTTP
|
16
17
|
module SSL
|
17
18
|
|
18
19
|
# Simple wrapper class used to fetch a server HTTPS certificate.
|
@@ -67,7 +68,7 @@ class Store
|
|
67
68
|
s_cert = Fetcher.fetch( hostname, port )
|
68
69
|
save_to_file( s_cert, filename )
|
69
70
|
else
|
70
|
-
Logger.
|
71
|
+
Logger.debug "[#{'SSL'.green}] Loaded HTTPS certificate for '#{hostname}' from store."
|
71
72
|
end
|
72
73
|
|
73
74
|
@store[key] = s_cert
|
@@ -174,3 +175,4 @@ end
|
|
174
175
|
end
|
175
176
|
end
|
176
177
|
end
|
178
|
+
end
|
File without changes
|
@@ -13,6 +13,7 @@ This project is released under the GPL 3 license.
|
|
13
13
|
|
14
14
|
module BetterCap
|
15
15
|
module Proxy
|
16
|
+
module HTTP
|
16
17
|
module SSL
|
17
18
|
|
18
19
|
# Little utility class to handle SSLServer creation.
|
@@ -26,7 +27,7 @@ class Server
|
|
26
27
|
|
27
28
|
# Create an instance from the TCPSocket +socket+.
|
28
29
|
def initialize( socket )
|
29
|
-
@authority = Authority.new( Context.get.options.proxy_pem_file )
|
30
|
+
@authority = Authority.new( Context.get.options.proxies.proxy_pem_file )
|
30
31
|
@context = OpenSSL::SSL::SSLContext.new
|
31
32
|
@context.cert = @authority.certificate
|
32
33
|
@context.key = @authority.key
|
@@ -59,3 +60,4 @@ end
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
end
|
63
|
+
end
|
File without changes
|
@@ -13,6 +13,7 @@ This project is released under the GPL 3 license.
|
|
13
13
|
|
14
14
|
module BetterCap
|
15
15
|
module Proxy
|
16
|
+
module HTTP
|
16
17
|
module SSLStrip
|
17
18
|
|
18
19
|
# Represent a stripped url associated to the client that requested it.
|
@@ -105,7 +106,7 @@ class Strip
|
|
105
106
|
@stripped = []
|
106
107
|
@cookies = CookieMonitor.new
|
107
108
|
@favicon = Response.from_file( File.dirname(__FILE__) + '/lock.ico', 'image/x-icon' )
|
108
|
-
@resolver = BetterCap::Network::Servers::DNSD.new( nil, ctx.ifconfig[:ip_saddr], ctx.options.dnsd_port )
|
109
|
+
@resolver = BetterCap::Network::Servers::DNSD.new( nil, ctx.ifconfig[:ip_saddr], ctx.options.servers.dnsd_port )
|
109
110
|
|
110
111
|
@resolver.start
|
111
112
|
end
|
@@ -184,7 +185,7 @@ class Strip
|
|
184
185
|
|
185
186
|
# Clean some headers from +r+.
|
186
187
|
def process_headers!(r)
|
187
|
-
what = r.is_a?(BetterCap::Proxy::Request) ? :req : :res
|
188
|
+
what = r.is_a?(BetterCap::Proxy::HTTP::Request) ? :req : :res
|
188
189
|
HEADERS_TO_PATCH[what].each do |key,value|
|
189
190
|
r[key] = value;
|
190
191
|
end
|
@@ -321,3 +322,4 @@ end
|
|
321
322
|
end
|
322
323
|
end
|
323
324
|
end
|
325
|
+
end
|
@@ -13,7 +13,9 @@ This project is released under the GPL 3 license.
|
|
13
13
|
|
14
14
|
module BetterCap
|
15
15
|
module Proxy
|
16
|
-
|
16
|
+
module HTTP
|
17
|
+
|
18
|
+
# Handle data streaming between clients and servers for the BetterCap::Proxy::HTTP::Proxy.
|
17
19
|
class Streamer
|
18
20
|
# Initialize the class.
|
19
21
|
def initialize( sslstrip )
|
@@ -97,7 +99,7 @@ class Streamer
|
|
97
99
|
# Run proxy modules.
|
98
100
|
def process( request, response = nil )
|
99
101
|
# loop each loaded module and execute if enabled
|
100
|
-
BetterCap::Proxy::Module.modules.each do |mod|
|
102
|
+
BetterCap::Proxy::HTTP::Module.modules.each do |mod|
|
101
103
|
if mod.enabled?
|
102
104
|
# we need to save the original response in case something
|
103
105
|
# in the module will go wrong
|
@@ -153,8 +155,8 @@ class Streamer
|
|
153
155
|
[ client_ip, client_port ]
|
154
156
|
end
|
155
157
|
|
156
|
-
# Use a Net::HTTP object in order to perform the +req+ BetterCap::Proxy::Request
|
157
|
-
# object, will return a BetterCap::Proxy::Response object instance.
|
158
|
+
# Use a Net::HTTP object in order to perform the +req+ BetterCap::Proxy::HTTP::Request
|
159
|
+
# object, will return a BetterCap::Proxy::HTTP::Response object instance.
|
158
160
|
def perform_proxy_request(req, res)
|
159
161
|
path = req.path
|
160
162
|
response = nil
|
@@ -204,3 +206,4 @@ class Streamer
|
|
204
206
|
end
|
205
207
|
end
|
206
208
|
end
|
209
|
+
end
|
@@ -91,10 +91,23 @@ class StreamLogger
|
|
91
91
|
msg
|
92
92
|
end
|
93
93
|
|
94
|
-
def self.
|
95
|
-
|
96
|
-
|
97
|
-
|
94
|
+
def self.hexdump( data, opts = {} )
|
95
|
+
bytes = data
|
96
|
+
msg = ''
|
97
|
+
line_size = opts[:line_size] || 16
|
98
|
+
padding = opts[:padding] || ''
|
99
|
+
|
100
|
+
while bytes
|
101
|
+
line = bytes[0,line_size]
|
102
|
+
bytes = bytes[line_size,bytes.length]
|
103
|
+
d = ''
|
104
|
+
|
105
|
+
line.each_byte {|i| d += "%02X " % i}
|
106
|
+
d += ' ' * (line_size-line.length)
|
107
|
+
d += ' '
|
108
|
+
line.each_byte{|i| d += ( i.chr =~ /[[:print:]]/ ? i.chr : '.' ) }
|
109
|
+
|
110
|
+
msg += "#{padding}#{d}\n"
|
98
111
|
end
|
99
112
|
msg
|
100
113
|
end
|
@@ -102,7 +115,7 @@ class StreamLogger
|
|
102
115
|
def self.dump_gzip( request )
|
103
116
|
msg = ''
|
104
117
|
uncompressed = Zlib::GzipReader.new(StringIO.new(request.body)).read
|
105
|
-
self.
|
118
|
+
self.hexdump( uncompressed )
|
106
119
|
end
|
107
120
|
|
108
121
|
def self.dump_json( request )
|
@@ -127,14 +140,17 @@ class StreamLogger
|
|
127
140
|
when /application\/x-www-form-urlencoded.*/i
|
128
141
|
msg << self.dump_form( request )
|
129
142
|
|
130
|
-
when
|
143
|
+
when /text\/plain.*/i
|
144
|
+
msg << request.body + "\n"
|
145
|
+
|
146
|
+
when /gzip.*/i
|
131
147
|
msg << self.dump_gzip( request )
|
132
148
|
|
133
|
-
when
|
149
|
+
when /application\/json.*/i
|
134
150
|
msg << self.dump_json( request )
|
135
151
|
|
136
152
|
else
|
137
|
-
msg << self.
|
153
|
+
msg << self.hexdump( request.body )
|
138
154
|
end
|
139
155
|
|
140
156
|
Logger.raw "#{msg}\n"
|
@@ -157,7 +173,7 @@ class StreamLogger
|
|
157
173
|
|
158
174
|
Logger.raw "[#{self.addr2s(request.client)}] #{request.method.light_blue} #{request_s}#{response_s}"
|
159
175
|
# Log post body if the POST sniffer is enabled.
|
160
|
-
if Context.get.
|
176
|
+
if Context.get.options.sniff.enabled?('POST')
|
161
177
|
self.log_post( request )
|
162
178
|
end
|
163
179
|
end
|