Skip to content
Browse files

Merge branch 'release/2012011000000' into stable

  • Loading branch information...
2 parents f524459 + 753ddb2 commit 9a377923286b791c4d2a0a7a55dc20cd8a3cd60d @jcran jcran committed Jan 10, 2012
Showing with 3,248 additions and 323 deletions.
  1. +4 −0 README
  2. BIN data/armitage/armitage.jar
  3. +33 −0 data/armitage/whatsnew.txt
  4. +3 −0 data/wordlists/http_default_pass.txt
  5. +3 −0 data/wordlists/http_default_userpass.txt
  6. +3 −0 data/wordlists/http_default_users.txt
  7. +1 −0 data/wordlists/root_userpass.txt
  8. +121 −20 lib/lab/driver/remote_esx_driver.rb
  9. +6 −13 lib/lab/driver/vm_driver.rb
  10. +65 −75 lib/lab/modifier/meterpreter_modifier.rb
  11. +10 −9 lib/lab/vm.rb
  12. +8 −13 lib/lab/vm_controller.rb
  13. +4 −3 lib/msf/core/exploit/exe.rb
  14. +5 −1 lib/msf/core/exploit/http/client.rb
  15. +40 −11 lib/msf/core/model/cred.rb
  16. +60 −0 lib/msf/core/post/windows/railgun.rb
  17. +3 −1 lib/msf/core/post/windows/shadowcopy.rb
  18. +30 −18 lib/msf/ui/console/command_dispatcher/core.rb
  19. +3 −3 lib/net/ssh.rb
  20. +11 −4 lib/net/ssh/authentication/key_manager.rb
  21. +17 −0 lib/net/ssh/authentication/methods/publickey.rb
  22. +10 −2 lib/net/ssh/authentication/session.rb
  23. +2 −0 lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb
  24. +22 −0 lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb
  25. +28 −0 lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb.ut.rb
  26. +9 −21 lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb
  27. +8 −0 lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb.ut.rb
  28. +105 −0 lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb
  29. +127 −0 lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb.ut.rb
  30. +21 −25 lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb
  31. +20 −0 lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb
  32. +7 −1 lib/rex/proto/http/client.rb
  33. +4 −0 lib/sshkey.rb
  34. +20 −0 lib/sshkey/LICENSE
  35. +71 −0 lib/sshkey/README.md
  36. +186 −0 lib/sshkey/lib/sshkey.rb
  37. +3 −0 lib/sshkey/lib/sshkey/version.rb
  38. +142 −0 modules/auxiliary/analyze/jtr_aix.rb
  39. +1 −1 modules/auxiliary/fuzzers/ftp/client_ftp.rb
  40. +1 −1 modules/auxiliary/fuzzers/ftp/ftp_pre_post.rb
  41. +5 −1 modules/auxiliary/scanner/ftp/ftp_login.rb
  42. +1 −1 modules/auxiliary/scanner/http/cisco_nac_manager_traversal.rb
  43. +116 −0 modules/auxiliary/scanner/http/drupal_views_user_enum.rb
  44. +17 −2 modules/auxiliary/scanner/http/http_login.rb
  45. +112 −0 modules/auxiliary/scanner/http/sybase_easerver_traversal.rb
  46. +1 −1 modules/auxiliary/scanner/http/webdav_scanner.rb
  47. +5 −9 modules/auxiliary/scanner/smtp/smtp_version.rb
  48. +333 −0 modules/auxiliary/scanner/ssh/ssh_identify_pubkeys.rb
  49. +6 −5 modules/auxiliary/scanner/ssh/ssh_login.rb
  50. +5 −2 modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb
  51. +4 −6 modules/auxiliary/scanner/telnet/telnet_login.rb
  52. +19 −19 modules/exploits/freebsd/telnet/telnet_encrypt_keyid.rb
  53. +134 −0 modules/exploits/freebsd/telnet/telnet_encrypt_keyid_bruteforce.rb
  54. +3 −3 modules/exploits/linux/telnet/telnet_encrypt_keyid.rb
  55. +108 −0 modules/exploits/multi/http/op5_license.rb
  56. +108 −0 modules/exploits/multi/http/op5_welcome.rb
  57. +652 −0 modules/exploits/windows/fileformat/adobe_reader_u3d.rb
  58. +1 −1 modules/exploits/windows/fileformat/apple_quicktime_pnsize.rb
  59. +1 −1 modules/exploits/windows/fileformat/foxit_title_bof.rb
  60. +1 −1 modules/exploits/windows/fileformat/magix_musikmaker_16_mmm.rb
  61. +1 −1 modules/exploits/windows/fileformat/mjm_coreplayer2011_s3m.rb
  62. +1 −1 modules/exploits/windows/fileformat/mjm_quickplayer_s3m.rb
  63. +1 −1 modules/exploits/windows/fileformat/nuance_pdf_launch_overflow.rb
  64. +1 −1 modules/exploits/windows/fileformat/videospirit_visprj.rb
  65. +1 −1 modules/exploits/windows/fileformat/wireshark_packet_dect.rb
  66. +2 −2 modules/exploits/windows/fileformat/xion_m3u_sehbof.rb
  67. +2 −2 modules/exploits/windows/ftp/32bitftp_list_reply.rb
  68. +1 −1 modules/exploits/windows/ftp/aasync_list_reply.rb
  69. +2 −2 modules/exploits/windows/ftp/filewrangler_list_reply.rb
  70. +1 −1 modules/exploits/windows/ftp/ftpgetter_pwd_reply.rb
  71. +1 −1 modules/exploits/windows/ftp/ftpshell51_pwd_reply.rb
  72. +1 −1 modules/exploits/windows/ftp/ftpsynch_list_reply.rb
  73. +1 −1 modules/exploits/windows/ftp/gekkomgr_list_reply.rb
  74. +1 −1 modules/exploits/windows/ftp/leapftp_list_reply.rb
  75. +1 −1 modules/exploits/windows/ftp/odin_list_reply.rb
  76. +1 −1 modules/exploits/windows/ftp/seagull_list_reply.rb
  77. +1 −1 modules/exploits/windows/http/integard_password_bof.rb
  78. +91 −0 modules/exploits/windows/http/xampp_webdav_upload_php.rb
  79. +1 −1 modules/exploits/windows/misc/hp_omniinet_4.rb
  80. +1 −1 modules/exploits/windows/misc/wireshark_packet_dect.rb
  81. +42 −17 modules/exploits/windows/scada/codesys_web_server.rb
  82. +1 −1 modules/exploits/windows/scada/iconics_genbroker.rb
  83. +1 −1 modules/exploits/windows/scada/igss9_igssdataserver_listall.rb
  84. +1 −1 modules/payloads/singles/windows/messagebox.rb
  85. +68 −0 modules/post/aix/hashdump.rb
  86. +8 −1 modules/post/windows/manage/vss_create.rb
  87. +8 −1 modules/post/windows/manage/vss_list.rb
  88. +8 −1 modules/post/windows/manage/vss_mount.rb
  89. +8 −1 modules/post/windows/manage/vss_set_storage.rb
  90. +8 −1 modules/post/windows/manage/vss_storage.rb
  91. +2 −2 plugins/lab.rb
  92. +66 −0 scripts/resource/oracle_login.rc
  93. +34 −0 scripts/resource/oracle_sids.rc
  94. +28 −0 scripts/resource/oracle_tns.rc
  95. +3 −0 scripts/resource/run_all_post.rc
View
4 README
@@ -48,12 +48,16 @@ This license does not apply to the following components:
- The Ruby-Lorcon library located under external/ruby-lorcon
- The SNMP library located under lib/snmp
- The Zip library located under lib/zip
+ - The SSHKey library located under lib/sshkey
The latest version of this software is available from http://metasploit.com/
Bug tracking and development information can be found at:
https://dev.metasploit.com/redmine/projects/framework/
+The public GitHub source repository can be found at:
+ https://github.com/rapid7/metasploit-framework
+
Questions and suggestions can be sent to:
msfdev[at]metasploit.com
View
BIN data/armitage/armitage.jar
Binary file not shown.
View
33 data/armitage/whatsnew.txt
@@ -1,6 +1,39 @@
Armitage Changelog
==================
+5 Jan 12
+--------
+- Armitage d-server now transmits hosts, service, and session state only
+ when something has changed. This makes teaming much snappier.
+- Uploading an imported hosts file now shows a progress dialog.
+- File browser upload function no longer blocks the user interface in team
+ mode. A progress dialog is shown for uploading larger files.
+- Removed Ctrl+R refresh hosts shortcut from graph view (it's no longer
+ necessary)
+- Armitage now exits if it was unable to connect to the collaboration server.
+- Hosts -> NMap Scans and Hosts -> MSF Scans dialogs are now populated with
+ the selected values from the target area by default.
+- You may now interact with a Windows command shell through Java meterpreter.
+- Armitage no longer shows Webcam Shot option through Java meterpreter.
+- Armitage now detects when it does not have read permissions for the database
+ YAML file and prompts with something helpful. Before it would just freeze
+ with a blank dialog. Not helpful. :)
+- Armitage now only shows services that are open.
+- View -> Reporting -> Export Data now has the capability of dumping the whole
+ database (not just the current workspace).
+- Added a dialog to View -> Reporting Export Data. Now you have the ability to
+ dump all hosts or choose to dump one of the dynamic workspaces. This gives
+ you a lot of flexibility with which hosts are included.
+- Cleaned up exported output of vulnerabilities in the Metasploit database:
+ -- duplicate entries are collapsed to one (this was the fault of my query)
+ -- refs column contains references separated by a comma and a space
+ -- added info and module columns. The module column indicates the appropriate
+ Metasploit module
+ -- Metasploit modules now populate name, info, and module in an appropriate
+ way.
+- Values exported to TSV are cleaned up such that newlines are replaced with a
+ literal \n and tabs are converted to three spaces.
+
30 Dec 11 - last release of the year?
---------
- Hosts -> Clear Database now clears the sessions and clients tables
View
3 data/wordlists/http_default_pass.txt
@@ -12,3 +12,6 @@ user
system
sys
none
+xampp
+wampp
+ppmax2011
View
3 data/wordlists/http_default_userpass.txt
@@ -4,3 +4,6 @@ admin 1234
cisco cisco
cisco sanfran
private private
+wampp xampp
+newuser wampp
+xampp-dav-unsecure ppmax2011
View
3 data/wordlists/http_default_users.txt
@@ -8,3 +8,6 @@ security
user
system
sys
+wampp
+newuser
+xampp-dav-unsecure
View
1 data/wordlists/root_userpass.txt
@@ -47,3 +47,4 @@ root letmein
root powerapp
root dbps
root ibm
+root monitor
View
141 lib/lab/driver/remote_esx_driver.rb
@@ -97,45 +97,146 @@ def delete_snapshot(snapshot, remove_children=false)
def delete_all_snapshots
remote_system_command("vim-cmd vmsvc/snapshot.removeall #{@vmid}")
end
-
- def run_command(command)
+
+ def check_file_exists(file)
+ raise "Not Implemented"
+ end
+
+ def create_directory(directory)
raise "Not Implemented"
end
+
+ def run_command(command, timeout=60)
+
+ setup_session
+ #puts "Using session #{@session}"
+
+ # TODO: pass the timeout down
- def copy_from_guest(from, to)
- if @os == "linux"
- scp_from(from, to)
+ if @session
+ if @session.type == "shell"
+ #puts "Running command via shell: #{command}"
+ @session.shell_command_token(command, timeout)
+ elsif @session.type == "meterpreter"
+ #puts "Running command via meterpreter: #{command}"
+ @session.shell_command(command)
+ end
else
- raise "Unimplemented"
+ raise "No session"
end
end
- def copy_to_guest(from, to)
- if @os == "linux"
- scp_to(from, to)
+ def copy_to_guest(local,remote)
+ setup_session
+ if @session.type == "meterpreter"
+ @session.run_cmd("upload #{local} #{remote}")
else
- raise "Unimplemented"
+ @driver.copy_to(local,remote)
end
end
-
- def check_file_exists(file)
- raise "Not Implemented"
- end
-
- def create_directory(directory)
- raise "Not Implemented"
+
+ def copy_from_guest(local, remote)
+ setup_session
+ if @session.type == "meterpreter"
+ @session.run_cmd("download #{local} #{remote}")
+ else
+ @driver.copy_from(local,remote)
+ end
end
def cleanup
-
end
def running?
power_status_string = `ssh #{@user}@#{@host} \"vim-cmd vmsvc/power.getstate #{@vmid}\"`
return true if power_status_string =~ /Powered on/
- false
end
+private
+
+ def create_framework
+ return if @framework
+ @framework = Msf::Simple::Framework.create
+ end
+
+ # perform the setup only once
+ def setup_session
+ return if @session
+
+ # require the framework (assumes this sits in lib/lab/modifiers)
+ require 'msf/base'
+
+ create_framework # TODO - this should use a single framework for all hosts, not one-per-host
+
+ @session = nil
+ @session_input = Rex::Ui::Text::Input::Buffer.new
+ @session_output = Rex::Ui::Text::Output::Buffer.new
+
+ if @os == "windows"
+ exploit_name = 'windows/smb/psexec'
+
+ # TODO - check for x86, choose the appropriate payload
+
+ payload_name = 'windows/meterpreter/bind_tcp'
+ options = {
+ "RHOST" => @hostname,
+ "SMBUser" => @vm_user,
+ "SMBPass" => @vm_pass}
+
+ #puts "DEBUG: using options #{options}"
+
+ # Initialize the exploit instance
+ exploit = @framework.exploits.create(exploit_name)
+
+ begin
+ # Fire it off.
+ @session = exploit.exploit_simple(
+ 'Payload' => payload_name,
+ 'Options' => options,
+ 'LocalInput' => @session_input,
+ 'LocalOutput' => @session_output)
+ @session.load_stdapi
+
+ #puts "DEBUG: Generated session: #{@session}"
+
+ rescue Exception => e
+ #puts "DEBUG: Unable to exploit"
+ #puts e.to_s
+ end
+ else
+ module_name = 'scanner/ssh/ssh_login'
+
+ # TODO - check for x86, choose the appropriate payload
+
+ payload_name = 'linux/x86/shell_bind_tcp'
+ options = { "RHOSTS" => @hostname,
+ "USERNAME" => @vm_user,
+ "PASSWORD" => @vm_pass,
+ "BLANK_PASSWORDS" => false,
+ "USER_AS_PASS" => false,
+ "VERBOSE" => false}
+
+ # Initialize the module instance
+ aux = @framework.auxiliary.create(module_name)
+
+ #puts "DEBUG: created module: #{aux}"
+
+ begin
+ # Fire it off.
+ aux.run_simple(
+ 'Payload' => payload_name,
+ 'Options' => options,
+ 'LocalInput' => @session_input,
+ 'LocalOutput' => @session_output)
+
+ @session = @framework.sessions.first.last
+ rescue Exception => e
+ #puts "DEBUG: Unable to exploit"
+ #puts e.to_s
+ end
+ end
+ end
+
def get_snapshots
# Command take the format:
# vmware-vim-cmd vmsvc/snapshot.revert [vmid: int] [snapshotlevel: int] [snapshotindex: int]
@@ -147,7 +248,7 @@ def get_snapshots
# ...
snapshots = []
- # Use these to keep track of the parsing...
+ # Use these to keep track of the parsing...
current_tree = -1
current_num = 0
count = 0
View
19 lib/lab/driver/vm_driver.rb
@@ -86,11 +86,11 @@ def delete_snapshot(snapshot)
def run_command(command)
raise "Command not Implemented"
end
-
+
def copy_from_guest(from, to)
raise "Command not Implemented"
end
-
+
def copy_to_guest(from, to)
raise "Command not Implemented"
end
@@ -117,7 +117,6 @@ def scp_to(local,remote)
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
# scp.upload!(from,to)
#end
-
system_command("scp #{local} #{@vm_user}@#{@hostname}:#{remote}")
end
@@ -127,17 +126,13 @@ def scp_from(local,remote)
#::Net::SCP.start(@hostname, @vm_user, :password => @vm_pass) do |scp|
# scp.download!(from,to)
#end
-
system_command("scp #{@vm_user}@#{@hostname}:#{remote} #{local}")
-
end
-
+
def ssh_exec(command)
-
::Net::SSH.start(@hostname, @vm_user, :password => @vm_pass) do |ssh|
result = ssh.exec!(command)
end
-
`scp #{@vm_user}@#{@hostname} from to`
end
@@ -148,7 +143,6 @@ def filter_input(string)
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
raise "WARNING! Invalid character in: #{string}"
end
-
string
end
@@ -159,18 +153,17 @@ def filter_command(string)
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\)]*$/.match string
raise "WARNING! Invalid character in: #{string}"
end
-
string
end
-
+
# The only reason we don't filter here is because we need
# the ability to still run clean (controlled entirely by us)
# command lines.
def system_command(command)
`#{command}`
end
-
-
+
+
def remote_system_command(command)
system_command("ssh #{@user}@#{@host} \"#{command}\"")
end
View
140 lib/lab/modifier/meterpreter_modifier.rb
@@ -1,51 +1,98 @@
$:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
-
-
-
-
# This allows us to override the default way of running commands
-# Currently useful for the esx controller
+# Currently useful for the remote esx driver
module Lab
module Modifier
module Meterpreter
-
+
attr_accessor :framework
attr_accessor :session
attr_accessor :session_input
attr_accessor :session_output
+ def meterpreter_run_command(command, timeout=60)
+
+ setup_session
+ puts "Using session #{@session}"
+
+ # TODO: pass the timeout down
+
+ if @session
+ if @session.type == "shell"
+ puts "Running command via shell: #{command}"
+ @session.shell_command_token(command, timeout)
+ elsif @session.type == "meterpreter"
+ puts "Running command via meterpreter: #{command}"
+ @session.shell_command(command) #, timeout)
+ end
+ else
+ raise "No session"
+ end
+ end
+
+ def meterpreter_copy_to_guest(local,remote)
+ puts "DEBUG: Meterpreter"
+ setup_session
+ if @session.type == "meterpreter"
+ @session.run_cmd("upload #{local} #{remote}")
+ else
+ @driver.copy_to(local,remote)
+ end
+ end
+
+ def meterpreter_copy_from_guest(local, remote)
+ puts "DEBUG: Meterpreter"
+ setup_session
+ if @session.type == "meterpreter"
+ @session.run_cmd("download #{local} #{remote}")
+ else
+ @driver.copy_from(local,remote)
+ end
+ end
+
+ # This isn't part of the normal API, but too good to pass up.
+ def meterpreter_run_script(script, options)
+ if @session.type == "meterpreter"
+ @session.execute_script(script, options)
+ else
+ raise "Unsupported on #{@session.type}"
+ end
+ end
+
+private
+
def create_framework
return if @framework
- @framework = Msf::Simple::Framework.create
+ @framework = Msf::Simple::Framework.create
end
-
+
# perform the setup only once
def setup_session
return if @session
# require the framework (assumes this sits in lib/lab/modifiers)
require 'msf/base'
- create_framework ## TODO - this should use a single framework
- ## for all hosts, not one-per-host
+ create_framework # TODO - this should use a single framework for all hosts, not one-per-host
- @session = nil
- @session_input = Rex::Ui::Text::Input::Buffer.new
- @session_output = Rex::Ui::Text::Output::Buffer.new
+ @session = nil
+ @session_input = Rex::Ui::Text::Input::Buffer.new
+ @session_output = Rex::Ui::Text::Output::Buffer.new
if @os == "windows"
exploit_name = 'windows/smb/psexec'
# TODO - check for x86, choose the appropriate payload
payload_name = 'windows/meterpreter/bind_tcp'
- options = { "RHOST" => @hostname,
- "SMBUser" => @vm_user,
- "SMBPass" => @vm_pass}
+ options = {
+ "RHOST" => @hostname,
+ "SMBUser" => @vm_user,
+ "SMBPass" => @vm_pass}
- puts "DEBUG: using options #{options}"
+ puts "DEBUG: using options #{options}"
# Initialize the exploit instance
exploit = @framework.exploits.create(exploit_name)
@@ -79,7 +126,7 @@ def setup_session
"USER_AS_PASS" => false,
"VERBOSE" => false}
- puts "DEBUG: using options #{options}"
+ puts "DEBUG: using options #{options}"
# Initialize the module instance
aux = @framework.auxiliary.create(module_name)
@@ -101,64 +148,7 @@ def setup_session
puts e.to_s
end
end
-
-
-
- end
-
- def run_command(command, timeout=60)
-
- setup_session
- puts "Using session #{@session}"
-
- # TODO: pass the timeout down
-
- if @session
- if @session.type == "shell"
- puts "Running command via shell: #{command}"
- @session.shell_command_token(command, timeout)
- elsif @session.type == "meterpreter"
- puts "Running command via meterpreter: #{command}"
- @session.shell_command(command) #, timeout)
- end
- else
- raise "No session"
- end
- end
-
-
- # This isn't part of the normal API, but too good to pass up.
- def run_script(script, options)
- if @session.type == "meterpreter"
- @session.execute_script(script, options)
- else
- raise "Unsupported on #{@session.type}"
- end
end
-
- # For meterpreter API compatibility
- #def execute_file(script,options)
- # run_script(script,options)
- #end
-
- def copy_to(local,remote)
- setup_session
- if @session.type == "meterpreter"
- @session.run_cmd("upload #{local} #{remote}")
- else
- @driver.copy_to(local,remote)
- end
- end
-
- def copy_from(local, remote)
- setup_session
- if @session.type == "meterpreter"
- @session.run_cmd("download #{local} #{remote}")
- else
- @driver.copy_from(local,remote)
- end
- end
-
end
end
end
View
19 lib/lab/vm.rb
@@ -103,12 +103,15 @@ def initialize(config = {})
# modifiers are properly used with the correct VM image.
@modifiers = config['modifiers']
- if @modifiers
- begin
- @modifiers.each { |modifier| self.class.send(:include, eval("Lab::Modifier::#{modifier}"))}
- rescue Exception => e
- # modifier likely didn't exist
- end
+ if @modifiers
+ @modifiers.each do |modifier|
+ begin
+ self.class.send(:include, eval("Lab::Modifier::#{modifier}"))
+ rescue Exception => e
+ #puts "WARNING: Unable to load: #{modifier}"
+ #puts "Exception: #{e}"
+ end
+ end
end
# Consume all tags
@@ -206,11 +209,9 @@ def to_s
end
def to_yaml
-
- # TODO - push this down to the drivers.
-
# Standard configuration options
out = " - vmid: #{@vmid}\n"
+ out = " hostname: #{@hostname}\n"
out += " driver: #{@driver_type}\n"
out += " location: #{@location}\n"
out += " type: #{@type}\n"
View
21 lib/lab/vm_controller.rb
@@ -158,21 +158,19 @@ def build_from_running(driver_type=nil, user=nil, host=nil, clear=false)
case driver_type.intern
when :workstation
vm_list = ::Lab::Controllers::WorkstationController::running_list
-
+
vm_list.each do |item|
-
+
## Name the VM
index = @vms.count + 1
-
+
## Add it to the vm list
@vms << Vm.new( { 'vmid' => "vm_#{index}",
'driver' => driver_type,
'location' => item,
'user' => user,
'host' => host } )
end
-
-
when :virtualbox
vm_list = ::Lab::Controllers::VirtualBoxController::running_list
vm_list.each do |item|
@@ -189,10 +187,10 @@ def build_from_running(driver_type=nil, user=nil, host=nil, clear=false)
vm_list = ::Lab::Controllers::RemoteWorkstationController::running_list(user, host)
vm_list.each do |item|
-
+
## Name the VM
index = @vms.count + 1
-
+
## Add it to the vm list
@vms << Vm.new( { 'vmid' => "vm_#{index}",
'driver' => driver_type,
@@ -202,20 +200,18 @@ def build_from_running(driver_type=nil, user=nil, host=nil, clear=false)
end
when :remote_esx
vm_list = ::Lab::Controllers::RemoteEsxController::running_list(user,host)
-
vm_list.each do |item|
@vms << Vm.new( { 'vmid' => "#{item[:id]}",
'name' => "#{item[:name]}",
'driver' => driver_type,
'user' => user,
'host' => host } )
end
-
else
raise TypeError, "Unsupported VM Type"
end
- end
+ end
def build_from_config(driver_type=nil, user=nil, host=nil, clear=false)
if clear
@@ -234,18 +230,17 @@ def build_from_config(driver_type=nil, user=nil, host=nil, clear=false)
'user' => user,
'host' => host } )
end
-
else
raise TypeError, "Unsupported VM Type"
end
- end
+ end
def running?(vmid)
if includes_vmid?(vmid)
return self.find_by_hostname(vmid).running?
end
- return false
+ return false
end
end
end
View
7 lib/msf/core/exploit/exe.rb
@@ -16,16 +16,17 @@ def initialize(info = {})
register_advanced_options(
[
- OptString.new( 'EXE::Custom', [ false, 'Use custom exe instead of automatically generating a payload exe']),
- OptString.new( 'EXE::Path', [ false, 'The directory in which to look for the executable template' ]),
- OptString.new( 'EXE::Template', [ false, 'The executable template file name.' ]),
+ OptPath.new( 'EXE::Custom', [ false, 'Use custom exe instead of automatically generating a payload exe']),
+ OptPath.new( 'EXE::Path', [ false, 'The directory in which to look for the executable template' ]),
+ OptPath.new( 'EXE::Template', [ false, 'The executable template file name.' ]),
OptBool.new( 'EXE::Inject', [ false, 'Set to preserve the original EXE function' ]),
OptBool.new( 'EXE::OldMethod', [ false, 'Set to use the substitution EXE generation method.' ]),
OptBool.new( 'EXE::FallBack', [ false, 'Use the default template in case the specified one is missing' ])
], self.class)
end
def get_custom_exe
+ print_status("Using custom executable #{datastore["EXE::Custom"]}, RHOST and RPORT settings will be ignored!")
datastore['DisablePayloadHandler'] = true
file = ::File.open(datastore['EXE::Custom'],'rb')
exe = file.read(file.stat.size)
View
6 lib/msf/core/exploit/http/client.rb
@@ -492,11 +492,15 @@ def send_digest_request_cgi(opts={}, timeout=20)
end
].compact
+ headers ={ 'Authorization' => auth.join(', ') }
+ headers.merge!(opts['headers']) if opts['headers']
+
+
# Send main request with authentication
r = c.request_cgi(opts.merge({
'uri' => path,
'method' => method,
- 'headers' => { 'Authorization' => auth.join(', ') }}))
+ 'headers' => headers }))
resp = c.send_recv(r, to)
unless resp.kind_of? Rex::Proto::Http::Response
return [nil,nil]
View
51 lib/msf/core/model/cred.rb
@@ -5,18 +5,47 @@ class Cred < ActiveRecord::Base
include DBSave
belongs_to :service
- def ssh_key_matches?(other)
- return false unless other.kind_of? self.class
+ KEY_ID_REGEX = /([0-9a-fA-F:]{47})/ # Could be more strict
+
+ # Returns its workspace
+ def workspace
+ self.service.host.workspace
+ end
+
+ # Returns its key id. If this is not an ssh-type key, returns nil.
+ def ssh_key_id
+ return nil unless self.ptype =~ /^ssh_/
+ return nil unless self.proof =~ KEY_ID_REGEX
+ $1.downcase # Can't run into NilClass problems.
+ end
+
+ # Returns all private keys with matching key ids, including itself
+ # If this is not an ssh-type key, always returns an empty array.
+ def ssh_private_keys
+ return [] unless self.ssh_key_id
+ matches = self.class.all(:conditions => ["creds.ptype = ? AND creds.proof ILIKE ?", "ssh_key", "%#{self.ssh_key_id}%"])
+ matches.select {|c| c.workspace == self.workspace}
+ end
+
+ # Returns all public keys with matching key ids, including itself
+ # If this is not an ssh-type key, always returns an empty array.
+ def ssh_public_keys
+ return [] unless self.ssh_key_id
+ matches = self.class.all(:conditions => ["creds.ptype = ? AND creds.proof ILIKE ?", "ssh_pubkey", "%#{self.ssh_key_id}%"])
+ matches.select {|c| c.workspace == self.workspace}
+ end
+
+ # Returns all keys with matching key ids, including itself
+ # If this is not an ssh-type key, always returns an empty array.
+ def ssh_keys
+ (self.ssh_private_keys | self.ssh_public_keys)
+ end
+
+ def ssh_key_matches?(other_cred)
return false unless self.ptype == "ssh_key"
- return false unless self.ptype == other.ptype
- return false unless other.proof
- return false if other.proof.empty?
- return false unless self.proof
- return false if self.proof.empty?
- key_id_regex = /[0-9a-fA-F:]+/
- my_key_id = self.proof[key_id_regex].to_s.downcase
- other_key_id = other.proof[key_id_regex].to_s.downcase
- my_key_id == other_key_id
+ return false unless other_cred.ptype == self.ptype
+ matches = self.ssh_private_keys
+ matches.include?(self) and matches.include?(other_cred)
end
end
View
60 lib/msf/core/post/windows/railgun.rb
@@ -0,0 +1,60 @@
+require 'rex/post/meterpreter/extensions/stdapi/railgun/railgun'
+
+module Msf
+class Post
+module Windows
+module Railgun
+
+ # Go through each dll and add a corresponding convenience method of the same name
+ Rex::Post::Meterpreter::Extensions::Stdapi::Railgun::Railgun::BUILTIN_DLLS.each do |api|
+ # We will be interpolating within an eval. We exercise due paranoia.
+ unless api.to_s =~ /^\w+$/
+ print_error 'Something is seriously wrong with Railgun.BUILTIN_DLLS list'
+ next
+ end
+
+ # don't override existing methods
+ if method_defined? api.to_sym
+ # We don't warn as the override may have been intentional
+ next
+ end
+
+ # evaling a String is faster than calling define_method
+ eval "def #{api.to_s}; railgun.#{api.to_s}; end"
+ end
+
+ #
+ # Return an array of windows constants names matching +winconst+
+ #
+ def select_const_names(winconst, filter_regex=nil)
+ railgun.constant_manager.select_const_names(winconst, filter_regex)
+ end
+
+ #
+ # Returns an array of windows error code names for a given windows error code matching +err_code+
+ #
+ def lookup_error (err_code, filter_regex=nil)
+ select_const_names(err_code, /^ERROR_/).select do |name|
+ name =~ filter_regex
+ end
+ end
+
+ def memread(address, length)
+ railgun.memread(address, length)
+ end
+
+ def memwrite(address, length)
+ railgun.memwrite(address, length)
+ end
+
+ def railgun
+ client.railgun
+ end
+
+ def pointer_size
+ railgun.util.pointer_size
+ end
+end
+end
+end
+end
View
4 lib/msf/core/post/windows/shadowcopy.rb
@@ -5,9 +5,11 @@ module Msf
class Post
module Windows
+# Based on the research from Tim Tomes and Mark Baggett, at
+# http://pauldotcom.com/2011/11/safely-dumping-hashes-from-liv.html
module ShadowCopy
- include Msf::Post::Windows::WindowsServices
+ include Msf::Post::Windows::WindowsServices
def get_vss_device(id)
result = get_sc_param(id,'DeviceObject')
View
48 lib/msf/ui/console/command_dispatcher/core.rb
@@ -190,7 +190,7 @@ def cmd_resource(*args)
cmd_resource_help
return false
end
-
+
args.each do |res|
good_res = nil
if (File.file? res and File.readable? res)
@@ -201,7 +201,7 @@ def cmd_resource(*args)
::Msf::Config.script_directory + File::SEPARATOR + "resource",
::Msf::Config.user_script_directory + File::SEPARATOR + "resource"
].each do |dir|
- res_path = dir + File::SEPARATOR + res
+ res_path = dir + File::SEPARATOR + res
if (File.file?(res_path) and File.readable?(res_path))
good_res = res_path
break
@@ -216,7 +216,7 @@ def cmd_resource(*args)
end
end
end
-
+
#
# Tab completion for the resource command
#
@@ -227,7 +227,7 @@ def cmd_resource_tabs(str, words)
# then you are probably specifying a full path so let's just use normal file completion
return tab_complete_filenames(str,words)
elsif (not words[1] or not words[1].match(/^\//))
- # then let's start tab completion in the scripts/resource directories
+ # then let's start tab completion in the scripts/resource directories
begin
[
::Msf::Config.script_directory + File::SEPARATOR + "resource",
@@ -2179,7 +2179,7 @@ def cmd_previous_help
print_line "Set the previously loaded module as the current module"
print_line
end
-
+
#
# Command to enqueque a module on the module stack
#
@@ -2190,7 +2190,7 @@ def cmd_pushm(*args)
@module_name_stack.push(arg)
# Note new modules are appended to the array and are only module (full)names
end
- else #then just push the active module
+ else #then just push the active module
if active_module
#print_status "Pushing the active module"
@module_name_stack.push(active_module.fullname)
@@ -2200,7 +2200,11 @@ def cmd_pushm(*args)
end
end
end
-
+
+ def cmd_pushm_tabs(str, words)
+ tab_complete_module(str, words)
+ end
+
#
# Help for the 'pushm' command
#
@@ -2210,7 +2214,7 @@ def cmd_pushm_help
print_line "push current active module or specified modules onto the module stack"
print_line
end
-
+
#
# Command to dequeque a module from the module stack
#
@@ -2251,17 +2255,9 @@ def cmd_popm_help
# Tab completion for the use command
#
def cmd_use_tabs(str, words)
- res = []
- return res if words.length > 1
-
- framework.modules.module_types.each do |mtyp|
- mset = framework.modules.module_names(mtyp)
- mset.each do |mref|
- res << mtyp + '/' + mref
- end
- end
+ return [] if words.length > 1
- return res.sort
+ tab_complete_module(str, words)
end
#
@@ -2277,6 +2273,22 @@ def cmd_version(*args)
end
#
+ # Tab complete module names
+ #
+ def tab_complete_module(str, words)
+ res = []
+ framework.modules.module_types.each do |mtyp|
+ mset = framework.modules.module_names(mtyp)
+ mset.each do |mref|
+ res << mtyp + '/' + mref
+ end
+ end
+
+ return res.sort
+ end
+
+
+ #
# Provide tab completion for option values
#
def tab_complete_option(str, words)
View
6 lib/net/ssh.rb
@@ -71,7 +71,7 @@ module SSH
:rekey_limit, :rekey_packet_limit, :timeout, :verbose,
:global_known_hosts_file, :user_known_hosts_file, :host_key_alias,
:host_name, :user, :properties, :passphrase, :msframework, :msfmodule,
- :record_auth_info
+ :record_auth_info, :skip_private_keys, :accepted_key_callback, :disable_agent
]
# The standard means of starting a new SSH connection. When used with a
@@ -196,7 +196,7 @@ def self.start(host, user, options={}, &block)
# Tell MSF not to auto-close this socket anymore...
# This allows the transport socket to surive with the session.
if options[:msfmodule]
- options[:msfmodule].remove_socket(transport.socket)
+ options[:msfmodule].remove_socket(transport.socket)
end
if block_given?
@@ -206,7 +206,7 @@ def self.start(host, user, options={}, &block)
return connection
end
else
- transport.close
+ transport.close
raise AuthenticationFailed, user
end
end
View
15 lib/net/ssh/authentication/key_manager.rb
@@ -121,10 +121,16 @@ def each_identity
end
key_data.each do |data|
- private_key = KeyFactory.load_data_private_key(data)
- key = private_key.send(:public_key)
- known_identities[key] = { :from => :key_data, :data => data, :key => private_key }
- yield key
+ if @options[:skip_private_keys]
+ key = KeyFactory.load_data_public_key(data)
+ known_identities[key] = { :from => :key_data, :data => data }
+ yield key
+ else
+ private_key = KeyFactory.load_data_private_key(data)
+ key = private_key.send(:public_key)
+ known_identities[key] = { :from => :key_data, :data => data, :key => private_key }
+ yield key
+ end
end
self
@@ -165,6 +171,7 @@ def sign(identity, data)
# Identifies whether the ssh-agent will be used or not.
def use_agent?
+ return false if @options[:disable_agent]
@use_agent
end
View
17 lib/net/ssh/authentication/methods/publickey.rb
@@ -54,6 +54,23 @@ def authenticate_with(identity, next_service, username)
case message.type
when USERAUTH_PK_OK
+ debug { "publickey will be accepted (#{identity.fingerprint})" }
+
+ # The key is accepted by the server, trigger a callback if set
+ if session.accepted_key_callback
+ session.accepted_key_callback.call({ :user => username, :fingerprint => identity.fingerprint, :key => identity.dup })
+ end
+
+ if session.skip_private_keys
+ if session.options[:record_auth_info]
+ session.auth_info[:method] = "publickey"
+ session.auth_info[:user] = username
+ session.auth_info[:pubkey_data] = identity.inspect
+ session.auth_info[:pubkey_id] = identity.fingerprint
+ end
+ return true
+ end
+
buffer = build_request(identity, username, next_service, true)
sig_data = Net::SSH::Buffer.new
sig_data.write_string(session_id)
View
12 lib/net/ssh/authentication/session.rb
@@ -33,6 +33,12 @@ class Session
# when a successful auth is made, note the auth info if session.options[:record_auth_info]
attr_accessor :auth_info
+
+ # when a public key is accepted (even if not used), trigger a callback
+ attr_accessor :accepted_key_callback
+
+ # when we only want to test a key and not login
+ attr_accessor :skip_private_keys
# Instantiates a new Authentication::Session object over the given
# transport layer abstraction.
@@ -43,8 +49,10 @@ def initialize(transport, options={})
@auth_methods = options[:auth_methods] || %w(publickey hostbased password keyboard-interactive)
@options = options
- @allowed_auth_methods = @auth_methods
- @auth_info = {}
+ @allowed_auth_methods = @auth_methods
+ @skip_private_keys = options[:skip_private_keys] || false
+ @accepted_key_callback = options[:accepted_key_callback]
+ @auth_info = {}
end
# Attempts to authenticate the given user, in preparation for the next
View
2 lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb
@@ -5,6 +5,8 @@
require 'rex'
require 'railgun/api_constants.rb.ut'
+require 'railgun/type/pointer_util.rb.ut'
+require 'railgun/platform_util.rb.ut'
require 'railgun/buffer_item.rb.ut'
require 'railgun/dll_function.rb.ut'
require 'railgun/dll_helper.rb.ut'
View
22 lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb
@@ -0,0 +1,22 @@
+module Rex
+module Post
+module Meterpreter
+module Extensions
+module Stdapi
+module Railgun
+module PlatformUtil
+
+ X86_64 = :x86_64
+ X86_32 = :x86_32
+
+ def self.parse_client_platform(meterp_client_platform)
+ meterp_client_platform =~ /win64/ ? X86_64 : X86_32
+ end
+
+end # PlatformUtil
+end # Railgun
+end # Stdapi
+end # Extensions
+end # Meterpreter
+end # Post
+end # Rex
View
28 lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb.ut.rb
@@ -0,0 +1,28 @@
+#!/usr/bin/env ruby
+
+$:.unshift(File.join(File.dirname(__FILE__), '..','..','..','..','..', '..', '..', 'lib'))
+
+require 'rex/post/meterpreter/extensions/stdapi/railgun/platform_util'
+require 'rex/post/meterpreter/extensions/stdapi/railgun/mock_magic'
+require 'test/unit'
+
+module Rex
+module Post
+module Meterpreter
+module Extensions
+module Stdapi
+module Railgun
+class PlatformUtil::UnitTest < Test::Unit::TestCase
+ def test_parse_client_platform
+ assert_equal(PlatformUtil.parse_client_platform('x86/win32'), PlatformUtil::X86_32,
+ 'parse_client_platform should translate Win32 client platforms')
+ assert_equal(PlatformUtil.parse_client_platform('x86/win64'), PlatformUtil::X86_64,
+ 'parse_client_platform should translate Win64 client platforms')
+ end
+end
+end
+end
+end
+end
+end
+end
View
30 lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb
@@ -61,9 +61,9 @@ class Railgun
# definition class 'rex/post/meterpreter/extensions/stdapi/railgun/def/'.
# Naming is important and should follow convention. For example, if your
# dll's name was "my_dll"
- # file name:: def_my_dll.rb
- # class name:: Def_my_dll
- # entry below:: 'my_dll'
+ # file name: def_my_dll.rb
+ # class name: Def_my_dll
+ # entry below: 'my_dll'
#
BUILTIN_DLLS = [
'kernel32',
@@ -104,6 +104,10 @@ def initialize(client)
self.dlls = {}
end
+ def self.builtin_dlls
+ BUILTIN_DLLS
+ end
+
#
# Return this Railgun's Util instance.
#
@@ -184,8 +188,8 @@ def add_function(dll_name, function_name, return_type, params, windows_name=nil)
# For backwards compatibility, we ensure the dll is thawed
if dll.frozen?
- # dup will copy values, but not the frozen status
- dll = dll.dup
+ # Duplicate not only the dll, but its functions as well. Frozen status will be lost
+ dll = Marshal.load(Marshal.dump(dll))
# Update local dlls with the modifiable duplicate
dlls[dll_name] = dll
@@ -277,22 +281,6 @@ def method_missing(dll_symbol, *args)
def const(str)
return constant_manager.parse(str)
end
-
- #
- # Return an array of windows constants names matching +winconst+
- #
-
- def const_reverse_lookup(winconst,filter_regex=nil)
- return constant_manager.rev_lookup(winconst,filter_regex)
- end
-
- #
- # Returns an array of windows error code names for a given windows error code matching +err_code+
- #
-
- def error_lookup (err_code,filter_regex=/^ERROR_/)
- return constant_manager.rev_lookup(err_code,filter_regex)
- end
#
# The multi-call shorthand (["kernel32", "ExitProcess", [0]])
View
8 lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb.ut.rb
@@ -120,6 +120,14 @@ def test_get_dll
assert(!unfrozen_dll.frozen?,
"add_function should create a local unfrozen instance that get_dll can then access")
+
+ railgun2 = Railgun.new(make_mock_client())
+
+ assert(!railgun2.get_dll(dll_name).functions.has_key?('__lolz'),
+ "functions added to one instance of railgun should not be accessible to others")
+
+ assert_not_same(!railgun2.get_dll(dll_name).functions, unfrozen_dll.functions,
+ "function hash should have been duplicated during unfreeze")
end
end
View
105 lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb
@@ -0,0 +1,105 @@
+require 'rex/post/meterpreter/extensions/stdapi/railgun/platform_util'
+
+module Rex
+module Post
+module Meterpreter
+module Extensions
+module Stdapi
+module Railgun
+module Type
+module PointerUtil
+
+ ARCH_POINTER_SIZE = {
+ PlatformUtil::X86_64 => 8,
+ PlatformUtil::X86_32 => 4
+ }.freeze
+
+ # Returns the pointer size for this architecture. Should accept client or platform or arch
+ def self.pointer_size(platform)
+ ARCH_POINTER_SIZE[platform]
+ end
+
+ def self.pack_pointer(pointer, platform)
+ if pointer.nil?
+ return pack_pointer(0, platform)
+ end
+
+ case platform
+ when PlatformUtil::X86_64
+ # XXX: Only works if attacker and victim are like-endianed
+ [pointer].pack('Q')
+ when PlatformUtil::X86_32
+ [pointer].pack('V')
+ else
+ raise "platform symbol #{platform.to_s} not supported"
+ end
+ end
+
+ # Given a packed pointer, unpack it according to architecture
+ def self.unpack_pointer(packed_pointer, platform)
+ case platform
+ when PlatformUtil::X86_64
+ # XXX: Only works if attacker and victim are like-endianed
+ packed_pointer.unpack('Q').first
+ when PlatformUtil::X86_32
+ packed_pointer.unpack('V').first
+ else
+ raise "platform symbol #{platform.to_s} not supported"
+ end
+ end
+
+ def self.null_pointer(pointer, platform)
+ pack_pointer(0, platform)
+ end
+
+ ###
+ # Summary: Returns true if pointer will be considered a 'null' pointer
+ #
+ # If given nil, returns true
+ # If given 0, returns true
+ # If given a string, if 0 after unpacking, returns true
+ # false otherwise
+ ##
+ def self.is_null_pointer?(pointer, platform)
+ if pointer.kind_of?(String)
+ pointer = unpack_pointer(pointer, platform)
+ end
+
+ return pointer.nil? || pointer == 0
+ end
+#
+# def self.is_unpacked_pointer?(pointer, platform)
+# # TODO also check that the integer size is appropriate for the platform
+# unless pointer.kind_of?(Fixnum) and pointer > 0 # and pointer <
+# return false
+# end
+#
+# packed_pointer = pack_pointer(pointer, platform)
+# if !packed_pointer.nil? and packed_pointer.length == pointer_size(platform)
+# return true
+# end
+#
+# return false
+# end
+#
+ # Returns true if the data type is a pointer, false otherwise
+ def self.is_pointer_type?(type)
+ if type == :pointer
+ return true
+ end
+
+ if type.kind_of?(String) && type =~ /^L?P/
+ return true
+ end
+
+ return false
+ end
+
+end # PointerUtil
+end # Type
+end # Railgun
+end # Stdapi
+end # Extensions
+end # Meterpreter
+end # Post
+end # Rex
View
127 lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb.ut.rb
@@ -0,0 +1,127 @@
+#!/usr/bin/env ruby
+
+$:.unshift(File.join(File.dirname(__FILE__), '..', '..','..','..','..','..', '..', '..', 'lib'))
+
+require 'rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util'
+require 'rex/post/meterpreter/extensions/stdapi/railgun/platform_util'
+require 'rex/post/meterpreter/extensions/stdapi/railgun/mock_magic'
+require 'test/unit'
+
+module Rex
+module Post
+module Meterpreter
+module Extensions
+module Stdapi
+module Railgun
+module Type
+class PlatformUtil::UnitTest < Test::Unit::TestCase
+
+ include Rex::Post::Meterpreter::Extensions::Stdapi::Railgun::MockMagic
+
+ # memread value of win x86 pointer mapped to target unpack value
+ X86_32_POINTERS = {
+ "8D\x15\x00" => 1393720,
+ "\x1C\x84\x15\x00" => 1410076,
+ "\x0E\x84\x15\x00" => 1410062,
+ "\x02\x84\x15\x00" => 1410050,
+ "\xE6\x83\x15\x00" => 1410022,
+ "\xC4\x83\x15\x00" => 1409988,
+ "\x00\x00\x00\x00" => 0,
+ }
+ X86_64_POINTERS = {
+ "\x10^ \x00\x00\x00\x00\x00" => 2121232,
+ "\xCA\x9D \x00\x00\x00\x00\x00" => 2137546,
+ "\xC8\x9D \x00\x00\x00\x00\x00" => 2137544,
+ "Z\x9D \x00\x00\x00\x00\x00" => 2137434,
+ "X\x9D \x00\x00\x00\x00\x00" => 2137432,
+ "\x00\x00\x00\x00\x00\x00\x00\x00" => 0,
+ }
+
+ X86_64_NULL_POINTER = "\x00\x00\x00\x00\x00\x00\x00\x00"
+ X86_32_NULL_POINTER = "\x00\x00\x00\x00"
+
+ X86_64 = PlatformUtil::X86_64
+ X86_32 = PlatformUtil::X86_32
+
+ def test_pack_pointer
+ X86_64_POINTERS.invert.each_pair do |unpacked, packed|
+ assert_equal(packed, PointerUtil.pack_pointer(unpacked.to_i, X86_64),
+ "pack_pointer should pack 64-bit numberic pointers")
+ end
+
+ X86_32_POINTERS.invert.each_pair do |unpacked, packed|
+ assert_equal(packed, PointerUtil.pack_pointer(unpacked.to_i, X86_32),
+ "pack_pointer should pack 32-bit numberic pointers")
+ end
+
+ assert_equal(X86_64_NULL_POINTER, PointerUtil.pack_pointer(nil, X86_64),
+ 'pack_pointer should pack "nil" as a null pointer for x86_64')
+
+ assert_equal(X86_32_NULL_POINTER, PointerUtil.pack_pointer(nil, X86_32),
+ 'pack_pointer should pack "nil" as a null pointer for x86_32')
+
+ assert_equal(X86_64_NULL_POINTER, PointerUtil.pack_pointer(0, X86_64),
+ 'pack_pointer should pack numeric 0 as a null pointer for x86_64')
+
+ assert_equal(X86_32_NULL_POINTER, PointerUtil.pack_pointer(0, X86_32),
+ 'pack_pointer should pack numeric 9 as a null pointer for x86_32')
+ end
+
+ def test_unpack_pointer
+ X86_64_POINTERS.each_pair do |packed, unpacked|
+ assert_equal(unpacked, PointerUtil.unpack_pointer(packed, X86_64),
+ "unpack_pointer should unpack 64-bit pointers")
+ end
+
+ X86_32_POINTERS.each_pair do |packed, unpacked|
+ assert_equal(unpacked, PointerUtil.unpack_pointer(packed, X86_32),
+ "unpack_pointer should unpack 32-bit pointers")
+ end
+
+
+ end
+
+ def test_is_null_pointer
+ [X86_32, X86_64].each do |platform|
+ assert(PointerUtil.is_null_pointer?(nil, platform), 'nil should be a null pointer')
+ assert(PointerUtil.is_null_pointer?(0, platform), 'numeric 0 should be a null pointer')
+ end
+
+ assert_equal(true, PointerUtil.is_null_pointer?(X86_32_NULL_POINTER, X86_32),
+ 'is_null_pointer? should return true for packed 32-bit null pointers')
+
+ assert_equal(true, PointerUtil.is_null_pointer?(X86_64_NULL_POINTER, X86_64),
+ 'is_null_pointer? should return true for packed 64-bit null pointers')
+
+ end
+
+ def test_pointer_size
+ assert_equal(8, PointerUtil.pointer_size(X86_64),
+ 'pointer_size should report X86_64 arch as 8 (bytes)')
+
+ assert_equal(4, PointerUtil.pointer_size(X86_32),
+ 'pointer_size should report X86_32 arch as 4 (bytes)')
+ end
+
+ def test_is_pointer_type
+ assert_equal(true, PointerUtil.is_pointer_type?(:pointer),
+ 'pointer_type should return true for the symbol :pointer')
+
+ assert_equal(true, PointerUtil.is_pointer_type?('LPVOID'),
+ 'pointer_type should return true if string begins with LP')
+
+ assert_equal(true, PointerUtil.is_pointer_type?('PDWORD'),
+ 'pointer_type should return true if string begins with P')
+
+ assert_equal(false, PointerUtil.is_pointer_type?('LOLZ'),
+ 'pointer_type should return false if not a pointer type')
+
+ end
+end
+end
+end
+end
+end
+end
+end
+end
View
46 lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb
@@ -33,19 +33,18 @@ module Railgun
# Manages our library of windows constants
#
class WinConstManager
+ attr_reader :consts
def initialize(initial_consts = {})
@consts = {}
initial_consts.each_pair do |name, value|
add_const(name, value)
end
-
- # Load utility
end
def add_const(name, value)
- @consts[name] = value
+ consts[name] = value
end
# parses a string constaining constants and returns an integer
@@ -59,41 +58,38 @@ def parse(s)
return_value = 0
for one_const in s.split('|')
one_const = one_const.strip()
- if not @consts.has_key? one_const
+ if not consts.has_key? one_const
return nil # at least one "Constant" is unknown to us
end
- return_value |= @consts[one_const]
+ return_value |= consts[one_const]
end
return return_value
end
def is_parseable(s)
- return parse(s) != nil
+ return !parse(s).nil?
end
-
- # looks up a windows constant (integer or hex) and returns an array of matching winconstant names
+
#
- # this function will NOT throw an exception but return "nil" if it can't find an error code
- def rev_lookup(winconst, filter_regex=nil)
- c = winconst.to_i # this is what we're gonna reverse lookup
- arr = [] # results array
- @consts.each_pair do |k,v|
- arr << k if v == c
+ # Returns an array of constant names that have a value matching "winconst"
+ # and (optionally) a name that matches "filter_regex"
+ #
+ def select_const_names(winconst, filter_regex=nil)
+ matches = []
+
+ consts.each_pair do |name, value|
+ matches << name if value == winconst
end
- if filter_regex # this is how we're going to filter the results
- # in case we get passed a string instead of a Regexp
- filter_regex = Regexp.new(filter_regex) unless filter_regex.class == Regexp
- # do the actual filtering
- arr.select! do |item|
- item if item =~ filter_regex
+
+ # Filter matches by name if a filter has been provided
+ unless filter_regex.nil?
+ matches.reject! do |name|
+ name !~ filter_regex
end
end
- return arr
- end
- def is_parseable(s)
- return parse(s) != nil
- end
+ return matches
+ end
end
end; end; end; end; end; end
View
20 lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb
@@ -12,6 +12,26 @@ module Extensions
module Stdapi
module Railgun
class WinConstManager::UnitTest < Test::Unit::TestCase
+
+ def test_select_const_names
+ const_manager = WinConstManager.new
+
+ names = %w(W WW WWW)
+
+ names.each do |name|
+ const_manager.add_const(name, 23)
+ end
+
+ assert(const_manager.select_const_names(23).sort == names,
+ 'select_const_names should return all names for given value')
+
+ const_manager.add_const('Skidoo!', 23)
+
+ assert(const_manager.select_const_names(23, /^\w{1,3}$/).sort == names,
+ 'select_const_names should filter names with provided regex')
+
+ end
+
def test_is_parseable
const_manager = WinConstManager.new
View
8 lib/rex/proto/http/client.rb
@@ -99,16 +99,22 @@ def initialize(host, port = 80, context = {}, ssl = nil, ssl_version = nil, prox
#
def set_config(opts = {})
opts.each_pair do |var,val|
+ # Default type is string
typ = self.config_types[var] || 'string'
+ # These are enum types
if(typ.class.to_s == 'Array')
if not typ.include?(val)
raise RuntimeError, "The specified value for #{var} is not one of the valid choices"
end
end
+ # The caller should have converted these to proper ruby types, but
+ # take care of the case where they didn't before setting the
+ # config.
+
if(typ == 'bool')
- val = (val =~ /^(t|y|1)$/i ? true : false)
+ val = (val =~ /^(t|y|1)$/i ? true : false || val === true)
end
if(typ == 'integer')
View
4 lib/sshkey.rb
@@ -0,0 +1,4 @@
+class SSHKey
+end
+
+require 'sshkey/lib/sshkey'
View
20 lib/sshkey/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2011 James Miller
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
71 lib/sshkey/README.md
@@ -0,0 +1,71 @@
+sshkey
+======
+
+Generate private and public SSH keys (RSA and DSA supported) using pure Ruby.
+
+ gem install sshkey
+
+Tested on the following Rubies: MRI 1.8.7, 1.9.2, 1.9.3, REE. Ruby must be compiled with OpenSSL support.
+
+[![Build Status](https://secure.travis-ci.org/bensie/sshkey.png)](http://travis-ci.org/bensie/sshkey)
+
+Usage
+-----
+
+When generating a new keypair the default key type is 2048-bit RSA, but you can supply the `type` (RSA or DSA) and `bits` in the options.
+You can also (optionally) supply a `comment`:
+
+``` ruby
+k = SSHKey.generate
+
+k = SSHKey.generate(:type => "DSA", :bits => 1024, :comment => "foo@bar.com")
+```
+
+Return an SSHKey object from an existing RSA or DSA private key (provided as a string)
+
+``` ruby
+k = SSHKey.new(File.read("~/.ssh/id_rsa"), :comment => "foo@bar.com")
+```
+
+Both of these will return an SSHKey object with the following methods:
+
+``` ruby
+# Returns an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA key object
+# http://www.ruby-doc.org/stdlib/libdoc/openssl/rdoc/classes/OpenSSL/PKey/RSA.html
+# http://www.ruby-doc.org/stdlib/libdoc/openssl/rdoc/classes/OpenSSL/PKey/DSA.html
+k.key_object
+# => -----BEGIN RSA PRIVATE KEY-----\nMIIEowI...
+
+# Returns the Private Key as a string
+k.private_key
+# => "-----BEGIN RSA PRIVATE KEY-----\nMIIEowI..."
+
+# Returns the Public Key as a string
+k.public_key
+# => "-----BEGIN RSA PUBLIC KEY-----\nMIIBCg..."
+
+# Returns the SSH Public Key as a string
+k.ssh_public_key
+# => "ssh-rsa AAAAB3NzaC1yc2EA...."
+
+# Returns the comment as a string
+k.comment
+# => "foo@bar.com"
+
+# Returns the MD5 fingerprint as a string
+k.md5_fingerprint
+# => "2a:89:84:c9:29:05:d1:f8:49:79:1c:ba:73:99:eb:af"
+
+# Returns the SHA1 fingerprint as a string
+k.sha1_fingerprint
+# => "e4:f9:79:f2:fe:d6:be:2d:ef:2e:c2:fa:aa:f8:b0:17:34:fe:0d:c0"
+
+# Validates SSH Public Key
+SSHKey.valid_ssh_public_key? "ssh-rsa AAAAB3NzaC1yc2EA...."
+# => true
+```
+
+Copyright
+---------
+
+Copyright (c) 2011 James Miller
View
186 lib/sshkey/lib/sshkey.rb
@@ -0,0 +1,186 @@
+require 'openssl'
+require 'base64'
+require 'digest/md5'
+require 'digest/sha1'
+
+class SSHKey
+ SSH_TYPES = {"rsa" => "ssh-rsa", "dsa" => "ssh-dss"}
+ SSH_CONVERSION = {"rsa" => ["e", "n"], "dsa" => ["p", "q", "g", "pub_key"]}
+
+ attr_reader :key_object, :comment, :type
+ attr_accessor :passphrase
+
+ # Generate a new keypair and return an SSHKey object
+ #
+ # The default behavior when providing no options will generate a 2048-bit RSA
+ # keypair.
+ #
+ # ==== Parameters
+ # * options<~Hash>:
+ # * :type<~String> - "rsa" or "dsa", "rsa" by default
+ # * :bits<~Integer> - Bit length
+ # * :comment<~String> - Comment to use for the public key, defaults to ""
+ # * :passphrase<~String> - Encrypt the key with this passphrase
+ #
+ def self.generate(options = {})
+ type = options[:type] || "rsa"
+ bits = options[:bits] || 2048
+ cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC") if options[:passphrase]
+
+ case type.downcase
+ when "rsa" then SSHKey.new(OpenSSL::PKey::RSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
+ when "dsa" then SSHKey.new(OpenSSL::PKey::DSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
+ else
+ raise "Unknown key type: #{type}"
+ end
+ end
+
+ # Validate an existing SSH public key
+ #
+ # Returns true or false depending on the validity of the public key provided
+ #
+ # ==== Parameters
+ # * ssh_public_key<~String> - "ssh-rsa AAAAB3NzaC1yc2EA...."
+ #
+ def self.valid_ssh_public_key?(ssh_public_key)
+ ssh_type, encoded_key = ssh_public_key.split(" ")
+ type = SSH_TYPES.invert[ssh_type]
+ prefix = [0,0,0,7].pack("C*")
+ decoded = Base64.decode64(encoded_key)
+
+ # Base64 decoding is too permissive, so we should validate if encoding is correct
+ return false unless Base64.encode64(decoded).gsub("\n", "") == encoded_key
+ return false unless decoded.sub!(/^#{prefix}#{ssh_type}/, "")
+
+ unpacked = decoded.unpack("C*")
+ data = []
+ index = 0
+ until unpacked[index].nil?
+ datum_size = from_byte_array unpacked[index..index+4-1], 4
+ index = index + 4
+ datum = from_byte_array unpacked[index..index+datum_size-1], datum_size
+ data << datum
+ index = index + datum_size
+ end
+
+ SSH_CONVERSION[type].size == data.size
+ rescue
+ false
+ end
+
+ def self.from_byte_array(byte_array, expected_size = nil)
+ num = 0
+ raise "Byte array too short" if !expected_size.nil? && expected_size != byte_array.size
+ byte_array.reverse.each_with_index do |item, index|
+ num += item * 256**(index)
+ end
+ num
+ end
+
+ # Create a new SSHKey object
+ #
+ # ==== Parameters
+ # * private_key - Existing RSA or DSA private key
+ # * options<~Hash>
+ # * :comment<~String> - Comment to use for the public key, defaults to ""
+ # * :passphrase<~String> - If the key is encrypted, supply the passphrase
+ #
+ def initialize(private_key, options = {})
+ @passphrase = options[:passphrase]
+ @comment = options[:comment] || ""
+ begin
+ @key_object = OpenSSL::PKey::RSA.new(private_key, passphrase)
+ @type = "rsa"
+ rescue
+ @key_object = OpenSSL::PKey::DSA.new(private_key, passphrase)
+ @type = "dsa"
+ end
+ end
+
+ # Fetch the RSA/DSA private key
+ #
+ # rsa_private_key and dsa_private_key are aliased for backward compatibility
+ def private_key
+ key_object.to_pem
+ end
+ alias_method :rsa_private_key, :private_key
+ alias_method :dsa_private_key, :private_key
+
+ # Fetch the encrypted RSA/DSA private key using the passphrase provided
+ #
+ # If no passphrase is set, returns the unencrypted private key
+ def encrypted_private_key
+ return private_key unless passphrase
+ key_object.to_pem(OpenSSL::Cipher::Cipher.new("AES-128-CBC"), passphrase)
+ end
+
+ # Fetch the RSA/DSA public key
+ #
+ # rsa_public_key and dsa_public_key are aliased for backward compatibility
+ def public_key
+ key_object.public_key.to_pem
+ end
+ alias_method :rsa_public_key, :public_key
+ alias_method :dsa_public_key, :public_key
+
+ # SSH public key
+ def ssh_public_key
+ [SSH_TYPES[type], Base64.encode64(ssh_public_key_conversion).gsub("\n", ""), comment].join(" ").strip
+ end
+
+ # Fingerprints
+ #
+ # MD5 fingerprint for the given SSH public key
+ def md5_fingerprint
+ Digest::MD5.hexdigest(ssh_public_key_conversion).gsub(/(.{2})(?=.)/, '\1:\2')
+ end
+ alias_method :fingerprint, :md5_fingerprint
+
+ # SHA1 fingerprint for the given SSH public key
+ def sha1_fingerprint
+ Digest::SHA1.hexdigest(ssh_public_key_conversion).gsub(/(.{2})(?=.)/, '\1:\2')
+ end
+
+ private
+
+ # SSH Public Key Conversion
+ #
+ # All data type encoding is defined in the section #5 of RFC #4251.
+ # String and mpint (multiple precision integer) types are encoded this way:
+ # 4-bytes word: data length (unsigned big-endian 32 bits integer)
+ # n bytes: binary representation of the data
+
+ # For instance, the "ssh-rsa" string is encoded as the following byte array
+ # [0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a']
+ def ssh_public_key_conversion
+ out = [0,0,0,7].pack("C*")
+ out += SSH_TYPES[type]
+
+ SSH_CONVERSION[type].each do |method|
+ byte_array = to_byte_array(key_object.public_key.send(method).to_i)
+ out += encode_unsigned_int_32(byte_array.length).pack("c*")
+ out += byte_array.pack("C*")
+ end
+
+ return out
+ end
+
+ def encode_unsigned_int_32(value)
+ out = []
+ out[0] = value >> 24 & 0xff
+ out[1] = value >> 16 & 0xff
+ out[2] = value >> 8 & 0xff
+ out[3] = value & 0xff
+ return out
+ end
+
+ def to_byte_array(num)
+ result = []
+ begin
+ result << (num & 0xff)
+ num >>= 8
+ end until (num == 0 || num == -1) && (result.last[7] == num[7])
+ result.reverse
+ end
+
+end
View
3 lib/sshkey/lib/sshkey/version.rb
@@ -0,0 +1,3 @@
+class SSHKey
+ VERSION = "1.3.0"
+end
View
142 modules/auxiliary/analyze/jtr_aix.rb
@@ -0,0 +1,142 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+#
+##
+
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Auxiliary::JohnTheRipper
+
+ def initialize
+ super(
+ 'Name' => 'John the Ripper Linux Password Cracker',
+ 'Version' => '$Revision$',
+ 'Description' => %Q{
+ This module uses John the Ripper to identify weak passwords that have been
+ acquired from passwd files on AIX systems.
+ },
+ 'Author' =>
+ [
+ 'TheLightCosine <thelightcosine[at]gmail.com>',
+ 'hdm'
+ ] ,
+ 'License' => MSF_LICENSE # JtR itself is GPLv2, but this wrapper is MSF (BSD)
+ )
+
+ end
+
+ def