Skip to content
This repository has been archived by the owner on Feb 28, 2018. It is now read-only.

Commit

Permalink
Implemented NetBIOS NBNS address to hostname resolution.
Browse files Browse the repository at this point in the history
  • Loading branch information
evilsocket committed Dec 14, 2015
1 parent 320c500 commit f5258bf
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 23 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ This is a list of TODOs I use to keep track of tasks and upcoming features.

- [x] Implement `--ignore ADDR,ADDR,ADDR` option to filter out specific addresses from the targets list.
- [x] HTTP 1.1 chunked response support.
- [x] Ip address to hostname resolution.
- [ ] Implement event-driven core plugin infrastructure ( for webui, etc ).
- [ ] Implement web-ui core plugin.
- [ ] Ip address to hostname resolution.
- [ ] Rewrite proxy class using [em-proxy](https://github.com/igrigorik/em-proxy) library.
- [ ] HTTP/2 Support.
- [ ] IPV6 Support.
Expand Down
9 changes: 9 additions & 0 deletions lib/bettercap/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ def update_network
Logger.debug "IFCONFIG: #{@ifconfig.inspect}"
end

def find_target ip, mac
@targets.each do |target|
if target.ip == ip && ( mac.nil? || target.mac == mac )
return target
end
end
nil
end

def start_discovery_thread
@discovery_running = true
@discovery_thread = Thread.new {
Expand Down
8 changes: 7 additions & 1 deletion lib/bettercap/discovery/arp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ def self.parse( ctx )
if ctx.options.ignore_ip?(ip)
Logger.debug "Ignoring #{ip} ..."
else
targets << Target.new( ip, mac )
# reuse Target object if it's already a known address
known = ctx.find_target ip, mac
if known.nil?
targets << Target.new( ip, mac )
else
targets << known
end
end
end
end
Expand Down
17 changes: 11 additions & 6 deletions lib/bettercap/proxy/stream_logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,33 @@
module Proxy
class StreamLogger
@@MAX_REQ_SIZE = 50

@@CODE_COLORS = {
'2' => :green,
'3' => :light_black,
'4' => :yellow,
'5' => :red
}


def self.addr2s( addr )
target = Context.get.find_target addr, nil
return target.to_s_compact unless target.nil?
addr
end

def self.log( is_https, client, request, response )
request_s = "#{is_https ? 'https' : 'http'}://#{request.host}#{request.url}"
response_s = "( #{response.content_type} )"
request_s = request_s.slice(0..@@MAX_REQ_SIZE) + '...' unless request_s.length <= @@MAX_REQ_SIZE
code = response.code[0]

if @@CODE_COLORS.has_key? code
response_s += " [#{response.code}]".send( @@CODE_COLORS[ code ] )
response_s += " [#{response.code}]".send( @@CODE_COLORS[ code ] )
else
response_s += " [#{response.code}]"
response_s += " [#{response.code}]"
end

Logger.write "[#{client}] #{request.verb.light_blue} #{request_s} #{response_s}"
Logger.write "[#{self.addr2s(client)}] #{request.verb.light_blue} #{request_s} #{response_s}"
end
end
end

8 changes: 7 additions & 1 deletion lib/bettercap/sniffer/parsers/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ def initialize
@name = 'BASE'
end

def addr2s( addr )
target = Context.get.find_target addr, nil
return target.to_s_compact unless target.nil?
addr
end

def on_packet( pkt )
s = pkt.to_s
@filters.each do |filter|
if s =~ filter
Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
Logger.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
"[#{@name}] ".green +
pkt.payload.strip.yellow
end
Expand Down
9 changes: 4 additions & 5 deletions lib/bettercap/sniffer/parsers/httpauth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def on_packet( pkt )
lines.each do |line|
if line =~ /[A-Z]+\s+(\/[^\s]+)\s+HTTP\/\d\.\d/
path = $1

elsif line =~ /Host:\s*([^\s]+)/i
hostname = $1

Expand All @@ -31,15 +31,14 @@ def on_packet( pkt )
decoded = Base64.decode64(encoded)
user, pass = decoded.split(':')

Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
Logger.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
'[HTTP BASIC AUTH]'.green + " http://#{hostname}#{path} - username=#{user} password=#{pass}".yellow

elsif line =~ /Authorization:\s*Digest\s+(.+)/i
Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
Logger.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
'[HTTP DIGEST AUTH]'.green + " http://#{hostname}#{path}\n#{$1}".yellow

end
end
end
end

2 changes: 1 addition & 1 deletion lib/bettercap/sniffer/parsers/https.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def on_packet( pkt )
end

if @@prev.nil? or @@prev != hostname
Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
Logger.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
'[HTTPS] '.green +
"https://#{hostname}/".yellow

Expand Down
2 changes: 1 addition & 1 deletion lib/bettercap/sniffer/parsers/ntlmss.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def on_packet( pkt )
s = pkt.to_s
if s =~ /NTLMSSP\x00\x03\x00\x00\x00.+/
# TODO: Parse NTLMSSP packet.
Logger.write "[#{pkt.ip_saddr} > #{pkt.ip_daddr} #{pkt.proto.last}] " +
Logger.write "[#{addr2s(pkt.ip_saddr)} > #{addr2s(pkt.ip_daddr)} #{pkt.proto.last}] " +
'[NTLMSS] '.green +
bin2hex( pkt.payload ).yellow
end
Expand Down
2 changes: 1 addition & 1 deletion lib/bettercap/sniffer/parsers/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class PostParser < BaseParser
def on_packet( pkt )
s = pkt.to_s
if s =~ /POST\s+[^\s]+\s+HTTP.+/
Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
Logger.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
"[POST]\n".green +
pkt.payload.strip.yellow
end
Expand Down
2 changes: 1 addition & 1 deletion lib/bettercap/sniffer/parsers/url.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def on_packet( pkt )
host = $2
url = $1
if not url =~ /.+\.(png|jpg|jpeg|bmp|gif|img|ttf|woff|css|js).*/i
Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
Logger.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
'[GET] '.green +
"http://#{host}#{url}".yellow
end
Expand Down
52 changes: 47 additions & 5 deletions lib/bettercap/target.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,24 @@
=end
require 'bettercap/logger'
require 'socket'

class Target
attr_accessor :ip, :mac, :vendor, :hostname

NBNS_TIMEOUT = 30
NBNS_PORT = 137
NBNS_BUFSIZE = 65536
NBNS_REQUEST = "\x82\x28\x0\x0\x0\x1\x0\x0\x0\x0\x0\x0\x20\x43\x4B\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x0\x0\x21\x0\x1"

@@prefixes = nil

def initialize( ip, mac=nil )
@ip = ip
@mac = mac
@vendor = Target.lookup_vendor(mac) if not mac.nil?
@hostname = nil # for future use
@ip = ip
@mac = mac
@vendor = Target.lookup_vendor(mac) if not mac.nil?
@hostname = nil
@resolver = Thread.new { resolve! }
end

def mac=(value)
Expand All @@ -29,11 +36,46 @@ def mac=(value)
end

def to_s
"#{@ip} : #{@mac}" + ( @vendor ? " ( #{@vendor} )" : "" )
s = @ip
s += " ( #{@hostname} )" unless @hostname.nil?
s += " : #{@mac}"
s += " ( #{@vendor} )" unless @vendor.nil?
s
end

def to_s_compact
if @hostname
"#{@hostname}/#{@ip}"
else
@ip
end
end

private

def resolve!
resp, sock = nil, nil
begin
sock = UDPSocket.open
sock.send( NBNS_REQUEST, 0, @ip, NBNS_PORT )
resp = if select([sock], nil, nil, NBNS_TIMEOUT)
sock.recvfrom(NBNS_BUFSIZE)
end
if resp
@hostname = parse_nbns_response resp
Logger.info "Found NetBIOS name '#{@hostname}' for address #{@ip}"
end
rescue Exception => e
Logger.debug e
ensure
sock.close if sock
end
end

def parse_nbns_response resp
resp[0][57,15].to_s.strip
end

def self.lookup_vendor( mac )
if @@prefixes == nil
Logger.debug 'Preloading hardware vendor prefixes ...'
Expand Down

0 comments on commit f5258bf

Please sign in to comment.