Class: BetterCap::StreamLogger
- Inherits:
-
Object
- Object
- BetterCap::StreamLogger
- Defined in:
- lib/bettercap/proxy/stream_logger.rb
Overview
Raw or http streams pretty logging.
Constant Summary collapse
- @@MAX_REQ_SIZE =
50
- @@CODE_COLORS =
{ '2' => :green, '3' => :light_black, '4' => :yellow, '5' => :red }
- @@services =
nil
- @@lock =
Mutex.new
Class Method Summary collapse
-
.addr2s(addr, alt = nil) ⇒ Object
Search for the
addr
IP address inside the list of collected targets and return its compact string representation ( @see BetterCap::Target#to_s_compact ). - .dump_form(request) ⇒ Object
- .dump_gzip(request) ⇒ Object
- .dump_json(request) ⇒ Object
- .hexdump(data, opts = {}) ⇒ Object
-
.log_http(request, response) ⇒ Object
Log a HTTP ( HTTPS if
is_https
is true ) stream performed by theclient
with therequest
andresponse
most important informations. -
.log_post(request) ⇒ Object
If
request
is a complete POST request, this method will log every header and post field with its value. -
.log_raw(pkt, label, payload) ⇒ Object
Log a raw packet (
pkt
) datapayload
using the specifiedlabel
. -
.service(proto, port) ⇒ Object
Given
proto
andport
return the network service name if possible.
Class Method Details
.addr2s(addr, alt = nil) ⇒ Object
Search for the addr
IP address inside the list of collected targets and return its compact string representation ( @see BetterCap::Target#to_s_compact ).
31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 31 def self.addr2s( addr, alt = nil ) ctx = Context.get # check for the local address return 'local' if addr == ctx.iface.ip # is it a known target? target = ctx.find_target addr, nil return target.to_s_compact unless target.nil? # fix 0.0.0.0 if alt argument was specified return alt if addr == '0.0.0.0' and !alt.nil? # fix broadcast -> * return '*' if addr == '255.255.255.255' # nothing found, return the address as it is addr end |
.dump_form(request) ⇒ Object
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 83 def self.dump_form( request ) msg = '' request.body.split('&').each do |v| name, value = v.split('=') name ||= '' value ||= '' msg << " #{name.blue} : #{URI.unescape(value).yellow}\n" end msg end |
.dump_gzip(request) ⇒ Object
115 116 117 118 119 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 115 def self.dump_gzip( request ) msg = '' uncompressed = Zlib::GzipReader.new(StringIO.new(request.body)).read self.hexdump( uncompressed ) end |
.dump_json(request) ⇒ Object
121 122 123 124 125 126 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 121 def self.dump_json( request ) obj = JSON.parse( request.body ) json = JSON.pretty_unparse(obj) json.scan( /("[^"]+"):/ ).map { |x| json.gsub!( x[0], x[0].blue )} json end |
.hexdump(data, opts = {}) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 94 def self.hexdump( data, opts = {} ) bytes = data msg = '' line_size = opts[:line_size] || 16 padding = opts[:padding] || '' while bytes line = bytes[0,line_size] bytes = bytes[line_size,bytes.length] d = '' line.each_byte {|i| d += "%02X " % i} d += ' ' * (line_size-line.length) d += ' ' line.each_byte{|i| d += ( i.chr =~ /[[:print:]]/ ? i.chr : '.' ) } msg += "#{padding}#{d}\n" end msg end |
.log_http(request, response) ⇒ Object
Log a HTTP ( HTTPS if is_https
is true ) stream performed by the client
with the request
and response
most important informations.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 162 def self.log_http( request, response ) response_s = "" response_s += " ( #{response.content_type} )" unless response.content_type.nil? request_s = request.to_url( request.post?? nil : @@MAX_REQ_SIZE ) code = response.code.to_s[0] if @@CODE_COLORS.has_key? code response_s += " [#{response.code}]".send( @@CODE_COLORS[ code ] ) else response_s += " [#{response.code}]" end Logger.raw "[#{self.addr2s(request.client)}] #{request.method.light_blue} #{request_s}#{response_s}" # Log post body if the POST sniffer is enabled. if Context.get..sniff.enabled?('POST') self.log_post( request ) end end |
.log_post(request) ⇒ Object
If request
is a complete POST request, this method will log every header and post field with its value.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 130 def self.log_post( request ) # the packet could be incomplete if request.post? and !request.body.nil? and !request.body.empty? msg = "\n[#{'HEADERS'.green}]\n\n" request.headers.each do |name,value| msg << " #{name.blue} : #{value.yellow}\n" end msg << "\n[#{'BODY'.green}]\n\n" case request['Content-Type'] when /application\/x-www-form-urlencoded.*/i msg << self.dump_form( request ) when /text\/plain.*/i msg << request.body + "\n" when /gzip.*/i msg << self.dump_gzip( request ) when /application\/json.*/i msg << self.dump_json( request ) else msg << self.hexdump( request.body ) end Logger.raw "#{msg}\n" end end |
.log_raw(pkt, label, payload) ⇒ Object
Log a raw packet ( pkt
) data payload
using the specified label
.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 68 def self.log_raw( pkt, label, payload ) nl = label.include?("\n") ? "\n" : " " label = label.strip from = self.addr2s( pkt.ip_saddr, pkt.eth2s(:src) ) to = self.addr2s( pkt.ip_daddr, pkt.eth2s(:dst) ) if pkt.respond_to?('tcp_dst') to += ':' + self.service( :tcp, pkt.tcp_dst ).to_s.light_blue elsif pkt.respond_to?('udp_dst') to += ':' + self.service( :udp, pkt.udp_dst ).to_s.light_blue end Logger.raw( "[#{from} > #{to}] [#{label.green}]#{nl}#{payload.strip}" ) end |
.service(proto, port) ⇒ Object
Given proto
and port
return the network service name if possible.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 47 def self.service( proto, port ) @@lock.synchronize { if @@services.nil? @@services = { :tcp => {}, :udp => {} } filename = File.dirname(__FILE__) + '/../network/services' File.open( filename ).each do |line| if line =~ /([^\s]+)\s+(\d+)\/([a-z]+).*/i @@services[$3.to_sym][$2.to_i] = $1 end end end } if @@services.has_key?(proto) and @@services[proto].has_key?(port) @@services[proto][port] else port end end |