Class: BetterCap::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/bettercap/context.rb

Overview

This class holds global states and data, moreover it exposes high level methods to manipulate the program behaviour.

Constant Summary collapse

@@instance =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeContext

Initialize the global context object.


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/bettercap/context.rb', line 55

def initialize
  begin
    iface = Pcap.lookupdev
  rescue Exception => e
    iface = nil
    Logger.debug e.message
  end

  @running         = true
  @timeout         = 5
  @options         = Options.new iface
  @ifconfig        = nil
  @firewall        = nil
  @gateway         = nil
  @targets         = []
  @proxy_processor = nil
  @spoofer         = nil
  @httpd           = nil
  @certificate     = nil
  @proxies         = []
  @redirections    = []
  @discovery       = Discovery::Thread.new self
  @firewall        = Factories::Firewall.get
  @packets         = nil
end

Instance Attribute Details

#certificateObject

Instance of OpenSSL::X509::Certificate class used for the HTTPS transparent proxy.


37
38
39
# File 'lib/bettercap/context.rb', line 37

def certificate
  @certificate
end

#discoveryObject

Instance of BetterCap::Discovery::Thread class.


30
31
32
# File 'lib/bettercap/context.rb', line 30

def discovery
  @discovery
end

#firewallObject

Instance of the current BetterCap::Firewalls class.


24
25
26
# File 'lib/bettercap/context.rb', line 24

def firewall
  @firewall
end

#gatewayObject

Network gateway IP address.


26
27
28
# File 'lib/bettercap/context.rb', line 26

def gateway
  @gateway
end

#httpdObject

Instance of BetterCap::HTTPD::Server class.


34
35
36
# File 'lib/bettercap/context.rb', line 34

def httpd
  @httpd
end

#ifconfigObject

A dictionary containing information about the selected network interface.


22
23
24
# File 'lib/bettercap/context.rb', line 22

def ifconfig
  @ifconfig
end

#optionsObject

Instance of BetterCap::Options class.


20
21
22
# File 'lib/bettercap/context.rb', line 20

def options
  @options
end

#packetsObject (readonly)

Instance of BetterCap::PacketQueue.


44
45
46
# File 'lib/bettercap/context.rb', line 44

def packets
  @packets
end

#runningObject

Set to true if the program is running, to false if a shutdown was scheduled by the user which pressed CTRL+C


40
41
42
# File 'lib/bettercap/context.rb', line 40

def running
  @running
end

#spooferObject

A list of BetterCap::Spoofers class instances.


32
33
34
# File 'lib/bettercap/context.rb', line 32

def spoofer
  @spoofer
end

#targetsObject

A list of BetterCap::Target objects which is periodically updated.


28
29
30
# File 'lib/bettercap/context.rb', line 28

def targets
  @targets
end

#timeoutObject (readonly)

Timeout for discovery operations.


42
43
44
# File 'lib/bettercap/context.rb', line 42

def timeout
  @timeout
end

Class Method Details

.getObject

Return the global instance of the program Context, if the instance was not yet created it will be initialized and returned.


50
51
52
# File 'lib/bettercap/context.rb', line 50

def self.get
  @@instance ||= self.new
end

Instance Method Details

#create_proxiesObject

Initialize the needed transparent proxies and the processor routined which is needed in order to run proxy modules.


128
129
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/bettercap/context.rb', line 128

def create_proxies
  if @options.has_proxy_module?
    Proxy::Module.register_modules

    raise BetterCap::Error, "#{@options.proxy_module} is not a valid bettercap proxy module." if Proxy::Module.modules.empty?
  end

  @proxy_processor = Proc.new do |request,response|
    if Proxy::Module.modules.empty?
      Logger.warn 'WARNING: No proxy module loaded, skipping request.'
    else
      # loop each loaded module and execute if enabled
      Proxy::Module.modules.each do |mod|
        if mod.enabled?
          # we need to save the original response in case something
          # in the module will go wrong
          original = response

          begin
            mod.on_request request, response
          rescue Exception => e
            Logger.warn "Error with proxy module: #{e.message}"
            response = original
          end
        end
      end
    end
  end

  # create HTTP proxy
  @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_port, false, @proxy_processor )
  # create HTTPS proxy
  if @options.proxy_https
    # We're not acting as a normal HTTPS proxy, thus we're not
    # able to handle CONNECT requests, thus we don't know the
    # hostname the client is going to connect to.
    # We can only use a self signed certificate.
    if @options.proxy_pem_file.nil?
      @certificate = Proxy::CertStore.get_selfsigned
    else
      @certificate = Proxy::CertStore.from_file @options.proxy_pem_file
    end

    @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_https_port, true, @proxy_processor )
  end

  @proxies.each do |proxy|
    proxy.start
  end
end

#enable_port_redirection!Object

Apply needed BetterCap::Firewalls::Redirection objects.


118
119
120
121
122
123
124
# File 'lib/bettercap/context.rb', line 118

def enable_port_redirection!
  @redirections = @options.to_redirections @ifconfig
  @redirections.each do |r|
    Logger.warn "Redirecting #{r.protocol} traffic from port #{r.src_port} to #{r.dst_address}:#{r.dst_port}"
    @firewall.add_port_redirection( r )
  end
end

#finalizeObject

Stop every running daemon that was started and reset system state.


180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/bettercap/context.rb', line 180

def finalize
  @running = false

  # Logger is silent if @running == false
  puts "\nShutting down, hang on ...\n"

  @packets.stop

  Logger.debug 'Stopping target discovery manager ...'
  @discovery.stop

  Logger.debug 'Stopping spoofers ...'
  @spoofer.each do |spoofer|
    spoofer.stop
  end

  Logger.debug 'Stopping proxies ...'
  @proxies.each do |proxy|
    proxy.stop
  end

  Logger.debug 'Disabling port redirections ...'
  @redirections.each do |r|
    @firewall.del_port_redirection( r )
  end

  Logger.debug 'Restoring firewall state ...'
  @firewall.restore

  @httpd.stop unless @httpd.nil?
end

#find_target(ip, mac) ⇒ Object

Find a target given its ip and mac addresses inside the #targets list, if not found return nil.


108
109
110
111
112
113
114
115
# File 'lib/bettercap/context.rb', line 108

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

#update!Object

Update the Context state parsing network related informations.

Raises:


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/bettercap/context.rb', line 82

def update!
  @ifconfig = PacketFu::Utils.ifconfig @options.iface
  @gateway  = Network.get_gateway if @gateway.nil?

  raise BetterCap::Error, "Could not determine IPv4 address of '#{@options.iface}', make sure this interface "\
                          'is active and connected.' if @ifconfig[:ip4_obj].nil?

  raise BetterCap::Error, "Could not detect the gateway address for interface #{@options.iface}, "\
                          'make sure you\'ve specified the correct network interface to use and to have the '\
                          'correct network configuration, this could also happen if bettercap '\
                          'is launched from a virtual environment.' if @gateway.nil? or !Network.is_ip?(@gateway)

  Logger.debug '----- NETWORK INFORMATIONS -----'
  Logger.debug "  network  = #{@ifconfig[:ip4_obj]}"
  Logger.debug "  gateway  = #{@gateway}"
  Logger.debug "  local_ip = #{@ifconfig[:ip_saddr]}\n"
  @ifconfig.each do |key,value|
    Logger.debug "  ifconfig[:#{key}] = #{value}"
  end
  Logger.debug "--------------------------------\n"

  @packets = Network::PacketQueue.new( @ifconfig[:iface], @options.packet_throttle, 4 )
end