Skip to content

Commit f9a804d

Browse files
committed
persistence libraries
1 parent 60a6658 commit f9a804d

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# -*- coding: binary -*-
2+
3+
module Msf
4+
module Exploit::Local::Persistence
5+
def initialize(info = {})
6+
@persistence_service = Rex::Sync::Event.new(auto_reset=false)
7+
@clean_up_rc = ''
8+
super(
9+
update_info(
10+
info,
11+
'DefaultOptions' => {},
12+
# https://github.com/rapid7/metasploit-framework/pull/19676#discussion_r1907594308
13+
'Stance' => Msf::Exploit::Stance::Passive,
14+
'Passive' => true
15+
)
16+
)
17+
18+
register_advanced_options(
19+
[
20+
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp/']),
21+
OptBool.new('CleanUpRc', [true, 'Create a cleanup resource file.', true])
22+
]
23+
)
24+
end
25+
26+
def exploit
27+
run_as_background = !datastore['DisablePayloadHandler']
28+
print_warning('Payload handler is disabled, the persistence will be installed only.') unless run_as_background
29+
30+
# Call the install_persistence function
31+
# must be declared inside the persistence module
32+
install_persistence
33+
34+
save_cleanup_rc if datastore['CleanUpRc'] && !@clean_up_rc.empty?
35+
36+
@persistence_service.wait if run_as_background
37+
end
38+
39+
def install_persistence
40+
# to be overloaded by the module
41+
end
42+
43+
def save_cleanup_rc
44+
host = session.sys.config.sysinfo['Computer']
45+
# Create Filename info to be appended to downloaded files
46+
filenameinfo = '_' + ::Time.now.strftime('%Y%m%d.%M%S')
47+
logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo))
48+
# Create the log directory
49+
::FileUtils.mkdir_p(logs)
50+
51+
# logfile name
52+
clean_rc = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + '.rc'
53+
file_local_write(clean_rc, @clean_up_rc)
54+
55+
print_status("Meterpreter-compatible Cleaup RC file: #{clean_rc}")
56+
57+
report_note(host: host,
58+
type: 'host.persistance.cleanup',
59+
data: {
60+
local_id: session.sid,
61+
stype: session.type,
62+
desc: session.info,
63+
platform: session.platform,
64+
via_payload: session.via_payload,
65+
via_exploit: session.via_exploit,
66+
created_at: Time.now.utc,
67+
commands: @clean_up_rc
68+
})
69+
end
70+
71+
def cleanup
72+
end
73+
end
74+
end
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# -*- coding: binary -*-
2+
3+
module Msf
4+
module Exploit::Local::Timespec
5+
TIMESPEC_REGEX = %r{
6+
\b(
7+
(?:[01]?\d|2[0-3]):[0-5]\d(?:\s?(?:AM|PM))? | # Matches HH:MM (12h/24h)
8+
midnight | noon | teatime | now | # Matches special keywords
9+
now\s?\+\s?\d+\s?(?:minutes?|hours?|days?|weeks?) | # Matches relative times
10+
(?:mon|tue|wed|thu|fri|sat|sun)(?:day)? | # Matches named days
11+
(?:next|last)\s(?:mon|tue|wed|thu|fri|sat|sun)(?:day)? | # Matches next/last weekday
12+
\d{1,2}/\d{1,2}/\d{2,4} | # Matches MM/DD/YY(YY)
13+
\d{1,2}\.\d{1,2}\.\d{2,4} | # Matches DD.MM.YY(YY)
14+
\d{6} | \d{8} # Matches MMDDYY or MMDDYYYY
15+
)\b
16+
}xi # 'x' allows extended mode, 'i' makes it case-insensitive
17+
18+
#
19+
# Attempts to validate a timespec.
20+
#
21+
# @param timespec [String] The timespec to test
22+
# @return [Boolean] If the timespec is valid or not
23+
#
24+
def self.valid_timespec?(timespec)
25+
!!(timespec =~ TIMESPEC_REGEX) # Ensures true/false return
26+
end
27+
end
28+
end

lib/msf/core/post/linux/user.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# -*- coding: binary -*-
2+
3+
module Msf
4+
class Post
5+
module Linux
6+
module User
7+
#
8+
# Returns a string of the user's home directory
9+
#
10+
def get_home_dir(user)
11+
cmd_exec("/bin/cat /etc/passwd | grep '^#{user}:' | cut -d ':' -f 6").chomp
12+
# could also be: "getent passwd #{user} | cut -d: -f6"
13+
end
14+
# User
15+
end
16+
# Linux
17+
end
18+
# Post
19+
end
20+
# Msf
21+
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require 'spec_helper'
2+
3+
RSpec.describe Msf::Exploit::Local::Timespec do
4+
describe '.valid_timespec?' do
5+
it 'returns true for military time' do
6+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('14:30')).to eq(true)
7+
end
8+
9+
it 'returns true for 12hr time' do
10+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('2:15 PM')).to eq(true)
11+
end
12+
13+
it 'returns true for midnight' do
14+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('midnight')).to eq(true)
15+
end
16+
17+
it 'returns true for now' do
18+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('now')).to eq(true)
19+
end
20+
21+
it 'returns true for now plus time' do
22+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('now + 10 minutes')).to eq(true)
23+
end
24+
25+
it 'returns true for relative days' do
26+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('next Monday')).to eq(true)
27+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('last Friday')).to eq(true) # unlikely to ever be used for our context
28+
end
29+
30+
it 'returns true for mm/dd/yy based date' do
31+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('07/04/23')).to eq(true)
32+
end
33+
34+
it 'returns true for mmddyy based date' do
35+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('010124')).to eq(true)
36+
end
37+
38+
it 'returns true for dd.mm.yyyy based date' do
39+
expect(Msf::Exploit::Local::Timespec.valid_timespec?('31.12.2023')).to eq(true)
40+
end
41+
end
42+
end

0 commit comments

Comments
 (0)