@@ -139,14 +139,28 @@ 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
+ case revision
145
+ when 1
146
+ hash = Digest ::MD5 . new
147
+ hash . update ( vf [ 0x70 , 16 ] + @sam_qwerty + bootkey + @sam_numeric )
148
+
149
+ rc4 = OpenSSL ::Cipher . new ( "rc4" )
150
+ rc4 . key = hash . digest
151
+ hbootkey = rc4 . update ( vf [ 0x80 , 32 ] )
152
+ hbootkey << rc4 . final
153
+ hbootkey
154
+ when 2
155
+ aes = OpenSSL ::Cipher . new ( 'aes-128-cbc' )
156
+ aes . key = bootkey
157
+ aes . padding = 0
158
+ aes . decrypt
159
+ aes . iv = vf [ 0x78 , 16 ]
160
+ aes . update ( vf [ 0x88 , 16 ] ) # we need only 16 bytes
161
+ else
162
+ raise NotImplementedError , "Unknown hboot_key revision: #{ revision } "
163
+ end
150
164
end
151
165
152
166
def capture_user_keys
@@ -200,21 +214,16 @@ def decrypt_user_keys(hbootkey, users)
200
214
users . each_key do |rid |
201
215
user = users [ rid ]
202
216
203
- hashlm_enc = ""
204
- hashnt_enc = ""
205
-
206
- hoff = user [ :V ] [ 0x9c , 4 ] . unpack ( "V" ) [ 0 ] + 0xcc
207
-
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
217
+ hashlm_off = user [ :V ] [ 0x9c , 4 ] . unpack ( "V" ) [ 0 ] + 0xcc
218
+ hashlm_len = user [ :V ] [ 0xa0 , 4 ] . unpack ( "V" ) [ 0 ]
219
+ hashlm_enc = user [ :V ] [ hashlm_off , hashlm_len ]
211
220
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
221
+ hashnt_off = user [ :V ] [ 0xa8 , 4 ] . unpack ( "V" ) [ 0 ] + 0xcc
222
+ hashnt_len = user [ :V ] [ 0xac , 4 ] . unpack ( "V" ) [ 0 ]
223
+ hashnt_enc = user [ :V ] [ hashnt_off , hashnt_len ]
215
224
216
- user [ :hashlm ] = decrypt_user_hash ( rid , hbootkey , hashlm_enc , @sam_lmpass )
217
- user [ :hashnt ] = decrypt_user_hash ( rid , hbootkey , hashnt_enc , @sam_ntpass )
225
+ user [ :hashlm ] = decrypt_user_hash ( rid , hbootkey , hashlm_enc , @sam_lmpass , @sam_empty_lm )
226
+ user [ :hashnt ] = decrypt_user_hash ( rid , hbootkey , hashnt_enc , @sam_ntpass , @sam_empty_nt )
218
227
end
219
228
220
229
users
@@ -241,16 +250,35 @@ def rid_to_key(rid)
241
250
[ convert_des_56_to_64 ( s1 ) , convert_des_56_to_64 ( s2 ) ]
242
251
end
243
252
244
- def decrypt_user_hash ( rid , hbootkey , enchash , pass )
253
+ def decrypt_user_hash ( rid , hbootkey , enchash , pass , default )
254
+ revision = enchash [ 2 , 2 ] . unpack ( 'v' ) [ 0 ]
245
255
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
252
- end
253
- return ""
256
+ case revision
257
+ when 1
258
+ if enchash . length < 20
259
+ return default
260
+ end
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
+ when 2
269
+ if enchash . length < 40
270
+ return default
271
+ end
272
+
273
+ aes = OpenSSL ::Cipher . new ( 'aes-128-cbc' )
274
+ aes . key = hbootkey [ 0 , 16 ]
275
+ aes . padding = 0
276
+ aes . decrypt
277
+ aes . iv = enchash [ 8 , 16 ]
278
+ okey = aes . update ( enchash [ 24 , 16 ] ) # we need only 16 bytes
279
+ else
280
+ print_error ( "Unknown user hash revision: #{ revision } " )
281
+ return default
254
282
end
255
283
256
284
des_k1 , des_k2 = rid_to_key ( rid )
@@ -263,13 +291,6 @@ def decrypt_user_hash(rid, hbootkey, enchash, pass)
263
291
d2 . padding = 0
264
292
d2 . key = des_k2
265
293
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
294
d1o = d1 . decrypt . update ( okey [ 0 , 8 ] )
274
295
d1o << d1 . final
275
296
0 commit comments