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. -
.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
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 |