Skip to content

Commit e903044

Browse files
jvazquez-r7Brent Cook
authored andcommitted
Allow to provide writable dir
1 parent f17a7e8 commit e903044

File tree

2 files changed

+44
-29
lines changed

2 files changed

+44
-29
lines changed

lib/rex/post/meterpreter/client_core.rb

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ module Meterpreter
2525
###
2626
class ClientCore < Extension
2727

28+
UNIX_PATH_MAX = 108
29+
DEFAULT_SOCK_PATH = "/tmp/meterpreter.sock"
30+
2831
#
2932
# Initializes the 'core' portion of the meterpreter client commands.
3033
#
@@ -180,7 +183,7 @@ def use(mod, opts = { })
180183
# Migrates the meterpreter instance to the process specified
181184
# by pid. The connection to the server remains established.
182185
#
183-
def migrate(pid, socket_path="/tmp/meterpreter.sock")
186+
def migrate(pid, writable_dir="/tmp/")
184187
keepalive = client.send_keepalives
185188
client.send_keepalives = false
186189
process = nil
@@ -216,23 +219,44 @@ def migrate(pid, socket_path="/tmp/meterpreter.sock")
216219
end
217220

218221
if client.platform =~ /linux/
219-
if socket_path.blank?
220-
socket_path = "/tmp/meterpreter.sock"
222+
if writable_dir.blank?
223+
writable_dir = "/tmp/"
221224
end
222225

223-
socket_dir = ::File.dirname(socket_path)
224-
stat_dir = client.fs.filestat.new(socket_dir)
226+
stat_dir = client.fs.filestat.new(writable_dir)
225227

226228
unless stat_dir.directory?
227-
raise RuntimeError, "Directory #{socket_dir} not found", caller
229+
raise RuntimeError, "Directory #{writable_dir} not found", caller
228230
end
229231
# Rex::Post::FileStat#writable? isn't available
230232
end
231233

232-
blob = generate_payload_stub(client, process, socket_path)
234+
blob = generate_payload_stub(client, process)
233235

234236
# Build the migration request
235237
request = Packet.create_request( 'core_migrate' )
238+
239+
if client.platform =~ /linux/i
240+
socket_path = File.join(writable_dir, Rex::Text.rand_text_alpha_lower(5 + rand(5)))
241+
242+
if socket_path > UNIX_PATH_MAX - 1
243+
raise RuntimeError, "The writable dir is too long", caller
244+
end
245+
246+
pos = blob.index(DEFAULT_SOCK_PATH)
247+
248+
if pos.nil?
249+
raise RuntimeError, "The meterpreter binary is wrong", caller
250+
end
251+
252+
blob[pos, socket_path.length + 1] = socket_path + "\x00"
253+
254+
ep = elf_ep(blob)
255+
request.add_tlv(TLV_TYPE_MIGRATE_BASE_ADDR, 0x20040000)
256+
request.add_tlv(TLV_TYPE_MIGRATE_ENTRY_POINT, ep)
257+
request.add_tlv(TLV_TYPE_MIGRATE_SOCKET_PATH, socket_path, false, client.capabilities[:zlib])
258+
end
259+
236260
request.add_tlv( TLV_TYPE_MIGRATE_PID, pid )
237261
request.add_tlv( TLV_TYPE_MIGRATE_LEN, blob.length )
238262
request.add_tlv( TLV_TYPE_MIGRATE_PAYLOAD, blob, false, client.capabilities[:zlib])
@@ -242,13 +266,6 @@ def migrate(pid, socket_path="/tmp/meterpreter.sock")
242266
request.add_tlv( TLV_TYPE_MIGRATE_ARCH, 1 ) # PROCESS_ARCH_X86
243267
end
244268

245-
if client.platform =~ /linux/i
246-
ep = elf_ep(blob)
247-
request.add_tlv(TLV_TYPE_MIGRATE_BASE_ADDR, 0x20040000)
248-
request.add_tlv(TLV_TYPE_MIGRATE_ENTRY_POINT, ep)
249-
request.add_tlv(TLV_TYPE_MIGRATE_SOCKET_PATH, socket_path, false, client.capabilities[:zlib])
250-
end
251-
252269
# Send the migration request (bump up the timeout to 60 seconds)
253270
client.send_request( request, 60 )
254271

@@ -344,12 +361,12 @@ def shutdown
344361

345362
private
346363

347-
def generate_payload_stub(client, process, socket_path)
364+
def generate_payload_stub(client, process)
348365
case client.platform
349366
when /win/i
350367
blob = generate_windows_stub(client, process)
351368
when /linux/i
352-
blob = generate_linux_stub(socket_path)
369+
blob = generate_linux_stub
353370
else
354371
raise RuntimeError, "Unsupported platform '#{client.platform}'"
355372
end
@@ -405,21 +422,12 @@ def generate_windows_stub(client, process)
405422
blob
406423
end
407424

408-
def generate_linux_stub(socket_path)
409-
pos = nil
425+
def generate_linux_stub
410426
file = ::File.join(Msf::Config.data_directory, "meterpreter", "msflinker_linux_x86.bin")
411427
blob = ::File.open(file, "rb") {|f|
412428
f.read(f.stat.size)
413429
}
414430

415-
unless socket_path.blank?
416-
pos = blob.index("/tmp/meterpreter.sock")
417-
end
418-
419-
unless pos.nil?
420-
blob[pos, socket_path.length + 1] = socket_path + "\x00"
421-
end
422-
423431
blob
424432
end
425433

lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def cmd_irb(*args)
322322

323323
def cmd_migrate_help
324324
if client.platform =~ /linux/
325-
print_line "Usage: migrate <pid> [af_unix_socket_path]"
325+
print_line "Usage: migrate <pid> [writable_path]"
326326
else
327327
print_line "Usage: migrate <pid>"
328328
end
@@ -349,7 +349,10 @@ def cmd_migrate(*args)
349349
print_error("A process ID must be specified, not a process name")
350350
return
351351
end
352-
socket_path = (args.length >= 2) ? args[1] : "/tmp/meterpreter.sock"
352+
353+
if client.platform =~ /linux/
354+
writable_dir = (args.length >= 2) ? args[1] : "/tmp/"
355+
end
353356

354357
begin
355358
server = client.sys.process.open
@@ -391,7 +394,11 @@ def cmd_migrate(*args)
391394
server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}")
392395

393396
# Do this thang.
394-
client.core.migrate(pid, socket_path)
397+
if client.platform =~ /linux/
398+
client.core.migrate(pid)
399+
else
400+
client.core.migrate(pid, writable_dir)
401+
end
395402

396403
print_status("Migration completed successfully.")
397404

0 commit comments

Comments
 (0)