@@ -139,14 +139,29 @@ def capture_hboot_key(bootkey)
139
139
vf = vf . data
140
140
ok . close
141
141
142
- hash = Digest ::MD5 . new
143
- hash . update ( vf [ 0x70 , 16 ] + @sam_qwerty + bootkey + @sam_numeric )
144
-
145
- rc4 = OpenSSL ::Cipher . new ( "rc4" )
146
- rc4 . key = hash . digest
147
- hbootkey = rc4 . update ( vf [ 0x80 , 32 ] )
148
- hbootkey << rc4 . final
149
- return hbootkey
142
+ revision = vf [ 0x68 , 4 ] . unpack ( 'V' ) [ 0 ]
143
+
144
+ if revision == 1
145
+ hash = Digest ::MD5 . new
146
+ hash . update ( vf [ 0x70 , 16 ] + @sam_qwerty + bootkey + @sam_numeric )
147
+
148
+ rc4 = OpenSSL ::Cipher . new ( "rc4" )
149
+ rc4 . key = hash . digest
150
+ hbootkey = rc4 . update ( vf [ 0x80 , 32 ] )
151
+ hbootkey << rc4 . final
152
+ return hbootkey
153
+ end
154
+
155
+ if revision == 2
156
+ aes = OpenSSL ::Cipher . new ( 'aes-128-cbc' )
157
+ aes . key = bootkey
158
+ aes . padding = 0
159
+ aes . decrypt
160
+ aes . iv = vf [ 0x78 , 16 ]
161
+ return aes . update ( vf [ 0x88 , 16 ] ) # we need only 16 bytes
162
+ end
163
+
164
+ raise NotImplementedError , "Unknown hboot_key revision: #{ revision } "
150
165
end
151
166
152
167
def capture_user_keys
@@ -200,21 +215,16 @@ def decrypt_user_keys(hbootkey, users)
200
215
users . each_key do |rid |
201
216
user = users [ rid ]
202
217
203
- hashlm_enc = ""
204
- hashnt_enc = ""
205
-
206
- hoff = user [ :V ] [ 0x9c , 4 ] . unpack ( "V" ) [ 0 ] + 0xcc
218
+ hashlm_off = user [ :V ] [ 0x9c , 4 ] . unpack ( "V" ) [ 0 ] + 0xcc
219
+ hashlm_len = user [ :V ] [ 0xa0 , 4 ] . unpack ( "V" ) [ 0 ]
220
+ hashlm_enc = user [ :V ] [ hashlm_off , hashlm_len ]
207
221
208
- #Check if hashes exist (if 20, then we've got a hash)
209
- lm_exists = user [ :V ] [ 0x9c + 4 , 4 ] . unpack ( "V" ) [ 0 ] == 20 ? true : false
210
- nt_exists = user [ :V ] [ 0x9c + 16 , 4 ] . unpack ( "V" ) [ 0 ] == 20 ? true : false
222
+ hashnt_off = user [ :V ] [ 0xa8 , 4 ] . unpack ( "V" ) [ 0 ] + 0xcc
223
+ hashnt_len = user [ :V ] [ 0xac , 4 ] . unpack ( "V" ) [ 0 ]
224
+ hashnt_enc = user [ :V ] [ hashnt_off , hashnt_len ]
211
225
212
- #If we have a hashes, then parse them (Note: NT is dependant on LM)
213
- hashlm_enc = user [ :V ] [ hoff + 4 , 16 ] if lm_exists
214
- hashnt_enc = user [ :V ] [ ( hoff + ( lm_exists ? 24 : 8 ) ) , 16 ] if nt_exists
215
-
216
- user [ :hashlm ] = decrypt_user_hash ( rid , hbootkey , hashlm_enc , @sam_lmpass )
217
- user [ :hashnt ] = decrypt_user_hash ( rid , hbootkey , hashnt_enc , @sam_ntpass )
226
+ user [ :hashlm ] = decrypt_user_hash ( rid , hbootkey , hashlm_enc , @sam_lmpass , @sam_empty_lm )
227
+ user [ :hashnt ] = decrypt_user_hash ( rid , hbootkey , hashnt_enc , @sam_ntpass , @sam_empty_nt )
218
228
end
219
229
220
230
users
@@ -241,16 +251,37 @@ def rid_to_key(rid)
241
251
[ convert_des_56_to_64 ( s1 ) , convert_des_56_to_64 ( s2 ) ]
242
252
end
243
253
244
- def decrypt_user_hash ( rid , hbootkey , enchash , pass )
254
+ def decrypt_user_hash ( rid , hbootkey , enchash , pass , default )
255
+ revision = enchash [ 2 , 2 ] . unpack ( 'v' ) [ 0 ]
245
256
246
- if ( enchash . empty? )
247
- case pass
248
- when @sam_lmpass
249
- return @sam_empty_lm
250
- when @sam_ntpass
251
- return @sam_empty_nt
257
+ if revision == 1
258
+ if enchash . length < 20
259
+ return default
252
260
end
253
- return ""
261
+
262
+ md5 = Digest ::MD5 . new
263
+ md5 . update ( hbootkey [ 0 , 16 ] + [ rid ] . pack ( "V" ) + pass )
264
+
265
+ rc4 = OpenSSL ::Cipher . new ( 'rc4' )
266
+ rc4 . key = md5 . digest
267
+ okey = rc4 . update ( enchash [ 4 , 16 ] )
268
+
269
+ elsif revision == 2
270
+ if enchash . length < 40
271
+ return default
272
+ end
273
+
274
+ aes = OpenSSL ::Cipher . new ( 'aes-128-cbc' )
275
+ aes . key = hbootkey [ 0 , 16 ]
276
+ aes . padding = 0
277
+ aes . decrypt
278
+ aes . iv = enchash [ 8 , 16 ]
279
+ okey = aes . update ( enchash [ 24 , 16 ] ) # we need only 16 bytes
280
+
281
+ else
282
+ print_error ( "Unknown user hash revision: #{ revision } " )
283
+ return default
284
+
254
285
end
255
286
256
287
des_k1 , des_k2 = rid_to_key ( rid )
@@ -263,13 +294,6 @@ def decrypt_user_hash(rid, hbootkey, enchash, pass)
263
294
d2 . padding = 0
264
295
d2 . key = des_k2
265
296
266
- md5 = Digest ::MD5 . new
267
- md5 . update ( hbootkey [ 0 , 16 ] + [ rid ] . pack ( "V" ) + pass )
268
-
269
- rc4 = OpenSSL ::Cipher . new ( 'rc4' )
270
- rc4 . key = md5 . digest
271
- okey = rc4 . update ( enchash )
272
-
273
297
d1o = d1 . decrypt . update ( okey [ 0 , 8 ] )
274
298
d1o << d1 . final
275
299
0 commit comments