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
addrIP 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_httpsis true ) stream performed by theclientwith therequestandresponsemost important informations. -
.log_post(request) ⇒ Object
If
requestis 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) datapayloadusing the specifiedlabel. -
.log_response(response) ⇒ Object
This method will log every header and the body of
response. -
.service(proto, port) ⇒ Object
Given
protoandportreturn 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
116 117 118 119 120 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 116 def self.dump_gzip( request ) msg = '' uncompressed = Zlib::GzipReader.new(StringIO.new(request.body)).read self.hexdump( uncompressed ) end |
.dump_json(request) ⇒ Object
122 123 124 125 126 127 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 122 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 114 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 94 def self.hexdump( data, opts = {} ) bytes = data msg = '' width = IO.console.winsize[1] line_size = opts[:line_size] || ( width / 4 ).round 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.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 191 def self.log_http( request, response ) response_s = "" response_s += " ( #{response.content_type} )" unless response.content_type.nil? request_s = request.to_url( nil ) 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 if Context.get..proxies.log_response self.log_response( response ) 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.
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 159 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 131 def self.log_post( request ) # the packet could be incomplete if request.post? and !request.body.nil? and !request.body.empty? msg = "\n[#{'REQUEST HEADERS'.green}]\n\n" request.headers.each do |name,value| msg << " #{name.blue} : #{value.yellow}\n" end msg << "\n[#{'REQUEST 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 |
.log_response(response) ⇒ Object
This method will log every header and the body of response.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/bettercap/proxy/stream_logger.rb', line 162 def self.log_response( response ) msg = "\n[#{'RESPONSE HEADERS'.light_red}]\n\n" response.headers.each do |name,value| msg << " #{name.blue} : #{value.to_s.yellow}\n" end msg << "\n[#{'RESPONSE BODY'.light_red}]\n\n" case response['Content-Type'] when /application\/x-www-form-urlencoded.*/i msg << self.dump_form( response ) when /text\/plain.*/i msg << response.body + "\n" when /gzip.*/i msg << self.dump_gzip( response ) when /application\/json.*/i msg << self.dump_json( response ) else msg << self.hexdump( response.body ) end Logger.raw "#{msg}\n" 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 |