~ubuntu-branches/ubuntu/trusty/ophcrack/trusty

« back to all changes in this revision

Viewing changes to src/samdump2/samdump2.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Cécile (Le_Vert)
  • Date: 2008-08-11 15:58:58 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080811155858-calnhe07mxkkqb1s
Tags: 3.0.1-1
* Upload to experimental because of lenny freeze.
* New upstream release.
* Update debian/watch.
* Switch from libgtk2.0-dev to libqt4-dev b-dep.
* Drop dpatch, not needed anymore.
* Add new package ophcrack-cli that provides command-line binary.
* Rewrite whole debian/rules to build qt4 and cli flavours.
* Update README.Debian with new tables names/urls.
* Do not depend anymore on bkhive/samdump2, both are embedded.
* Update debian/copyright.
* Add imagemagick b-dep to create icons.
* Write a new manpage for the new command line switches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  Samdump2
 
2
    Dump nt/lanman password hashes from a sam hive with Syskey enabled
 
3
    
 
4
    Thank to Dmitry Andrianov for the program name ^_^
 
5
    
 
6
    This program is free software; you can redistribute it and/or
 
7
    modify it under the terms of the GNU General Public License
 
8
    as published by the Free Software Foundation; either version 2
 
9
    of the License, or (at your option) any later version.
 
10
    
 
11
    This program is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
    
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
   
 
20
    This program is released under the GPL with the additional exemption 
 
21
    that compiling, linking, and/or using OpenSSL is allowed.
 
22
 
 
23
    Copyright (C) 2004-2006 Nicola Cuomo <ncuomo@studenti.unina.it>
 
24
    Improvments and some bugs fixes by Objectif Securité
 
25
    <http://www.objectif-securite.ch>
 
26
*/
 
27
 
 
28
#include <stdio.h>
 
29
#include <stdlib.h>
 
30
#include <openssl/rc4.h>
 
31
#include <openssl/md5.h>
 
32
#include <openssl/des.h>
 
33
#if defined(__linux__)
 
34
#include <endian.h>
 
35
#elif defined(__FreeBSD__)
 
36
#include <machine/endian.h>
 
37
#endif
 
38
#include "hive.h"
 
39
#include "list.h"
 
40
 
 
41
#ifdef BYTE_ORDER
 
42
#if BYTE_ORDER == LITTLE_ENDIAN
 
43
#elif BYTE_ORDER == BIG_ENDIAN
 
44
#include "bswap.h"
 
45
#else
 
46
#warning "Doesn't define a standard ENDIAN type"
 
47
#endif
 
48
#else
 
49
#warning "Doesn't define BYTE_ORDER"
 
50
#endif
 
51
 
 
52
 
 
53
/* Cut&Paste from pwdump source code */
 
54
 
 
55
/*
 
56
* Convert a 7 byte array into an 8 byte des key with odd parity.
 
57
*/
 
58
 
 
59
void str_to_key(unsigned char *str,unsigned char *key)
 
60
{
 
61
        // void des_set_odd_parity(des_cblock *);
 
62
        int i;
 
63
 
 
64
        key[0] = str[0]>>1;
 
65
        key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
 
66
        key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
 
67
        key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
 
68
        key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
 
69
        key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
 
70
        key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
 
71
        key[7] = str[6]&0x7F;
 
72
        for (i=0;i<8;i++) {
 
73
                key[i] = (key[i]<<1);
 
74
        }
 
75
        des_set_odd_parity((des_cblock *)key);
 
76
}
 
77
 
 
78
/*
 
79
* Function to convert the RID to the first decrypt key.
 
80
*/
 
81
 
 
82
void sid_to_key1(unsigned long sid,unsigned char deskey[8])
 
83
{
 
84
        unsigned char s[7];
 
85
 
 
86
        s[0] = (unsigned char)(sid & 0xFF);
 
87
        s[1] = (unsigned char)((sid>>8) & 0xFF);
 
88
        s[2] = (unsigned char)((sid>>16) & 0xFF);
 
89
        s[3] = (unsigned char)((sid>>24) & 0xFF);
 
90
        s[4] = s[0];
 
91
        s[5] = s[1];
 
92
        s[6] = s[2];
 
93
 
 
94
        str_to_key(s,deskey);
 
95
}
 
96
 
 
97
/*
 
98
* Function to convert the RID to the second decrypt key.
 
99
*/
 
100
 
 
101
void sid_to_key2(unsigned long sid,unsigned char deskey[8])
 
102
{
 
103
        unsigned char s[7];
 
104
 
 
105
        s[0] = (unsigned char)((sid>>24) & 0xFF);
 
106
        s[1] = (unsigned char)(sid & 0xFF);
 
107
        s[2] = (unsigned char)((sid>>8) & 0xFF);
 
108
        s[3] = (unsigned char)((sid>>16) & 0xFF);
 
109
        s[4] = s[0];
 
110
        s[5] = s[1];
 
111
        s[6] = s[2];
 
112
 
 
113
        str_to_key(s,deskey);
 
114
}
 
115
 
 
116
//---
 
117
 
 
118
int samdump2(char *sam, list_t *list, unsigned char *bootkey, char *error, int debug ) {
 
119
 
 
120
  /* const */
 
121
  char *regaccountkey, *reguserskey;
 
122
  unsigned char aqwerty[] = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%";
 
123
  unsigned char anum[] = "0123456789012345678901234567890123456789";
 
124
  unsigned char antpassword[] = "NTPASSWORD";
 
125
  unsigned char almpassword[] = "LMPASSWORD";
 
126
 
 
127
  char *buff; int buff_len;
 
128
 
 
129
  char *root_key;
 
130
 
 
131
  /* hive */
 
132
  struct hive h;
 
133
  nk_hdr *n = NULL;
 
134
  
 
135
  /* hive buffer */
 
136
  unsigned char *b = NULL;
 
137
  int blen;   
 
138
  unsigned char regkeyname[50];
 
139
  int regkeynamelen;
 
140
  char  *keyname;
 
141
  
 
142
  /* md5 contex, hash, rc4 key, hashed bootkey */
 
143
  MD5_CTX md5c;
 
144
  unsigned char md5hash[0x10];
 
145
  RC4_KEY rc4k;
 
146
  unsigned char hbootkey[0x20];
 
147
  
 
148
  /* Des */
 
149
  des_key_schedule ks1, ks2;
 
150
  des_cblock deskey1, deskey2;
 
151
  
 
152
  int i, j, z;
 
153
  
 
154
  char *username;
 
155
  int rid;
 
156
  int usernameoffset, usernamelen;
 
157
  int lm_hashesoffset, nt_hashesoffset;
 
158
  int lm_size, nt_size;
 
159
  
 
160
  unsigned char obfkey[0x10];
 
161
  unsigned char fb[0x10];
 
162
    
 
163
  /* Initialize registry access function */
 
164
  _InitHive( &h );
 
165
  
 
166
  /* Open sam hive */
 
167
  if( _RegOpenHive(sam, &h ) ) {
 
168
    sprintf( error, "Error opening sam hive or not valid file(\"%s\")\n", sam );
 
169
    return -1;
 
170
  }
 
171
  
 
172
  /* Get Root key name 
 
173
     SAM for 2k/XP,
 
174
     CMI-CreateHive{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx} for Vista */
 
175
  if( _RegGetRootKey( &h, &root_key)) {
 
176
    sprintf( error, "Error reading hive root key\n");
 
177
    return -1;
 
178
  }
 
179
  if (debug)
 
180
    printf("Root Key : %s\n", root_key);
 
181
 
 
182
  regaccountkey = (char *) malloc(strlen(root_key)+30);
 
183
  reguserskey = (char *) malloc(strlen(root_key)+30);
 
184
 
 
185
  sprintf(regaccountkey, "%s\\SAM\\Domains\\Account", root_key);
 
186
  sprintf(reguserskey, "%s\\SAM\\Domains\\Account\\Users", root_key);
 
187
 
 
188
  n = (nk_hdr*) malloc(sizeof(nk_hdr));
 
189
 
 
190
  /* Open SAM\\SAM\\Domains\\Account key*/
 
191
  if( _RegOpenKey( &h, regaccountkey, &n ) ) {
 
192
    _RegCloseHive( &h );
 
193
    sprintf( error, "%s key!\n", regaccountkey );
 
194
    return -1;
 
195
  }
 
196
  
 
197
  if( _RegQueryValue( &h, "F", n, &b, &blen ) ) {       
 
198
    _RegCloseHive( &h );
 
199
    sprintf( error, "No F!\n" );
 
200
    return -1;
 
201
  }
 
202
  
 
203
  /* hash the bootkey */
 
204
  MD5_Init( &md5c );
 
205
  MD5_Update( &md5c, &b[0x70], 0x10 );
 
206
  MD5_Update( &md5c, aqwerty, 0x2f );
 
207
  MD5_Update( &md5c, bootkey, 0x10 );
 
208
  MD5_Update( &md5c, anum, 0x29 );
 
209
  MD5_Final( md5hash, &md5c );
 
210
  RC4_set_key( &rc4k, 0x10, md5hash );
 
211
  RC4( &rc4k, 0x20, &b[0x80], hbootkey );
 
212
  
 
213
  j = 0;
 
214
  
 
215
  /* Enumerate user */
 
216
  while( j != -1 ) {
 
217
    /* Open  SAM\\SAM\\Domains\\Account\\Users */
 
218
    if( _RegOpenKey( &h, reguserskey, &n ) ) {
 
219
      _RegCloseHive( &h );
 
220
      sprintf( error, "No Users key!\n" );
 
221
      return -1;
 
222
    }
 
223
    
 
224
    regkeynamelen = sizeof( regkeyname );
 
225
    
 
226
    j = _RegEnumKey( &h, n, j, (char*)regkeyname, &regkeynamelen );
 
227
 
 
228
    if (debug)
 
229
    printf("******************** %d ********************\n", j);
 
230
    
 
231
    /* Skip Names key */
 
232
    if( !memcmp( regkeyname, "Names", regkeynamelen ) )
 
233
      continue;
 
234
    
 
235
    keyname = (char*) malloc( strlen( reguserskey ) + regkeynamelen + 2 );
 
236
    
 
237
    /* Open SAM\\SAM\\Domains\\Account\\Users\\userrid */
 
238
    strcpy( keyname, reguserskey );
 
239
    strcat( keyname, "\\" ) ;
 
240
    strcat( keyname, (char*)regkeyname ) ;
 
241
    
 
242
    if( _RegOpenKey( &h, keyname, &n ) ) {
 
243
      _RegCloseHive( &h );
 
244
      
 
245
      sprintf( error, "Asd -_- _RegEnumKey fail!\n" );
 
246
      return -1;
 
247
    }
 
248
    
 
249
    if( _RegQueryValue( &h, "V", n, &b, &blen ) ) {
 
250
      _RegCloseHive( &h );
 
251
      
 
252
      sprintf( error, "No V value!\n" );
 
253
      return -1;
 
254
    }
 
255
    
 
256
    /* rid */
 
257
    rid = strtoul( (char*)regkeyname, NULL, 16 );
 
258
    
 
259
    /* get the username */
 
260
    /* 0x10 username size 0xc username offset */
 
261
#if BYTE_ORDER == LITTLE_ENDIAN
 
262
    usernamelen = *(int*)(b + 0x10) >> 1;
 
263
#elif BYTE_ORDER == BIG_ENDIAN
 
264
    usernamelen = __bswap_32(*(int*)(b + 0x10) >> 1);
 
265
#endif 
 
266
    usernameoffset = b[0xc] + 0xcc;
 
267
 
 
268
    if (debug)
 
269
      printf("\nusername len=%d, off=%x\n", usernamelen, usernameoffset);
 
270
    
 
271
    username = (char *) malloc(  usernamelen + 1 );
 
272
 
 
273
    // Quick hack for unicode -> ascii translation
 
274
    for( z = 0; z < usernamelen; z++)
 
275
      username[z] = b[usernameoffset + z*2];
 
276
    
 
277
    username[ usernamelen ] = 0;
 
278
#if BYTE_ORDER == LITTLE_ENDIAN
 
279
    lm_hashesoffset = *(int *)(b + 0x9c ) + 0xcc;
 
280
    lm_size = *(int *)(b + 0xa0 );
 
281
    nt_hashesoffset = *(int *)(b + 0xa8 ) + 0xcc;
 
282
    nt_size = *(int *)(b + 0xac );
 
283
#elif BYTE_ORDER == BIG_ENDIAN
 
284
    lm_hashesoffset = __bswap_32(*(int *)(b + 0x9c )) + 0xcc;
 
285
    lm_size = __bswap_32(*(int *)(b + 0xa0 ));
 
286
    nt_hashesoffset = __bswap_32(*(int *)(b + 0xa8 )) + 0xcc;
 
287
    nt_size = __bswap_32(*(int *)(b + 0xac ));
 
288
#endif
 
289
 
 
290
    if (debug) {
 
291
      printf("lm_hashoffset = %x, lm_size = %x\n", lm_hashesoffset, lm_size);
 
292
      printf("nt_hashoffset = %x, nt_size = %x\n", nt_hashesoffset, nt_size);
 
293
    }
 
294
 
 
295
    buff = (char*)malloc(512);
 
296
    /* Print the user hash */
 
297
    buff_len = sprintf(buff, "%s:%d:", username, rid );
 
298
          
 
299
    if( lm_size == 0x14 ) {
 
300
      if (debug) {
 
301
        printf("\n");
 
302
        for( i = 0; i < 0x10; i++ )
 
303
          printf( "%.2x", b[lm_hashesoffset+4+i] );
 
304
      }
 
305
 
 
306
      /* LANMAN */
 
307
      /* hash the hbootkey and decode lanman password hashes */
 
308
      MD5_Init( &md5c );
 
309
      MD5_Update( &md5c, hbootkey, 0x10 );
 
310
#if BYTE_ORDER == LITTLE_ENDIAN
 
311
      MD5_Update( &md5c, &rid, 0x4 );
 
312
#elif BYTE_ORDER == BIG_ENDIAN
 
313
      rid = __bswap_32(rid);
 
314
      MD5_Update( &md5c, &rid, 0x4 );
 
315
      rid = __bswap_32(rid);
 
316
#endif
 
317
      MD5_Update( &md5c, almpassword, 0xb );
 
318
      MD5_Final( md5hash, &md5c );        
 
319
      
 
320
      RC4_set_key( &rc4k, 0x10, md5hash );
 
321
      RC4( &rc4k, 0x10, &b[ lm_hashesoffset + 4 ], obfkey );
 
322
      if (debug) {
 
323
        printf("\nobfkey: ");
 
324
        for( i = 0; i < 0x10; i++ )
 
325
          printf( "%.2x", (unsigned char)obfkey[i] );
 
326
        printf("\n");
 
327
      }
 
328
 
 
329
      
 
330
      /* From Pwdump */
 
331
      
 
332
      /* Get the two decrpt keys. */
 
333
      sid_to_key1(rid,(unsigned char *)deskey1);
 
334
      des_set_key_checked((des_cblock *)deskey1,ks1);
 
335
      sid_to_key2(rid,(unsigned char *)deskey2);
 
336
      des_set_key_unchecked((des_cblock *)deskey2,ks2);
 
337
      
 
338
      /* Decrypt the lanman password hash as two 8 byte blocks. */
 
339
      des_ecb_encrypt((des_cblock *)obfkey,
 
340
                      (des_cblock *)fb, ks1, DES_DECRYPT);
 
341
      des_ecb_encrypt((des_cblock *)(obfkey + 8),
 
342
                      (des_cblock *)&fb[8], ks2, DES_DECRYPT);
 
343
      
 
344
      
 
345
      
 
346
      // sf25( obfkey, (int*)&rid, fb );
 
347
      
 
348
      for( i = 0; i < 0x10; i++ ) {
 
349
        sprintf(buff+buff_len, "%.2x", fb[i] );
 
350
        buff_len +=2;
 
351
      }
 
352
    } else {
 
353
      sprintf(buff+buff_len, "aad3b435b51404eeaad3b435b51404ee" );
 
354
      buff_len+=32;
 
355
    }
 
356
    sprintf(buff+buff_len, ":" );
 
357
    buff_len++;
 
358
    
 
359
    if( nt_size == 0x14 ) {
 
360
      if (debug) {
 
361
        printf("\n");
 
362
        for( i = 0; i < 0x10; i++ )
 
363
          printf( "%.2x", b[nt_hashesoffset+4+i] );
 
364
        printf("\n");
 
365
      }
 
366
      
 
367
      /* NT */
 
368
      /* hash the hbootkey and decode the nt password hashes */
 
369
      MD5_Init( &md5c );
 
370
      MD5_Update( &md5c, hbootkey, 0x10 );
 
371
#if BYTE_ORDER == LITTLE_ENDIAN
 
372
      MD5_Update( &md5c, &rid, 0x4 );
 
373
#elif BYTE_ORDER == BIG_ENDIAN
 
374
      rid = __bswap_32(rid);
 
375
      MD5_Update( &md5c, &rid, 0x4 );
 
376
      rid = __bswap_32(rid);
 
377
#endif
 
378
      MD5_Update( &md5c, antpassword, 0xb );
 
379
      MD5_Final( md5hash, &md5c );        
 
380
      
 
381
      RC4_set_key( &rc4k, 0x10, md5hash );
 
382
      RC4( &rc4k, 0x10, &b[ nt_hashesoffset + 4], obfkey );
 
383
 
 
384
      if (lm_size != 0x14) {
 
385
        /* Get the two decrpt keys. */
 
386
        sid_to_key1(rid,(unsigned char *)deskey1);
 
387
        des_set_key((des_cblock *)deskey1,ks1);
 
388
        sid_to_key2(rid,(unsigned char *)deskey2);
 
389
        des_set_key((des_cblock *)deskey2,ks2);
 
390
      }
 
391
 
 
392
      /* Decrypt the NT md4 password hash as two 8 byte blocks. */
 
393
      des_ecb_encrypt((des_cblock *)obfkey,
 
394
                      (des_cblock *)fb, ks1, DES_DECRYPT);
 
395
      des_ecb_encrypt((des_cblock *)(obfkey + 8),
 
396
                      (des_cblock *)&fb[8], ks2, DES_DECRYPT);
 
397
      
 
398
      /* sf27 wrap to sf25 */
 
399
      //sf27( obfkey, (int*)&rid, fb );
 
400
      
 
401
      for( i = 0; i < 0x10; i++ ) {
 
402
        sprintf(buff+buff_len, "%.2x", fb[i] );
 
403
        buff_len +=2;
 
404
      }
 
405
    } else {
 
406
      sprintf(buff+buff_len, "31d6cfe0d16ae931b73c59d7e0c089c0");
 
407
      buff_len+=32;
 
408
    }
 
409
    sprintf(buff+buff_len, ":::" );
 
410
    buff_len+=3;
 
411
 
 
412
    /* add the hash to the list */
 
413
    list_add_tail(list, buff);
 
414
    
 
415
    free( username );
 
416
    free( keyname );
 
417
  }
 
418
  
 
419
  _RegCloseHive( &h );
 
420
  free(n);
 
421
  free(b);
 
422
  
 
423
  return 0;
 
424
}