?? chntpw.c
字號:
/* * chntpw.c - Offline Password Edit Utility for NT 3.51 & 4.0 SAM database. * 1999-feb: Now able to browse registry hives. (write support to come) * 2000-jan: Attempt to detect and disable syskey * * Copyright (c) 1997-2000 Petter Nordahl-Hagen. * Freely distributable in source or binary for noncommercial purposes. * * Uses (links with) DES SSL Library by Eric Young (eay@mincom.oz.au) * and MD4 routines by RSA. * * Part of some routines, information and ideas taken from * pwdump by Jeremy Allison. * * Some stuff (like proto.h) from NTCrack by Jonathan Wilkins. * * Please see the COPYING file for more details on * copyrights & credits. * * THIS SOFTWARE IS PROVIDED BY PETTER NORDAHL-HAGEN `AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <ctype.h>#include <stdlib.h>#include <string.h>/* #include <unistd.h> *//* These are from the DESlib & MD packages, see Makefile & README */#include <des.h>#include <mddriver/global.h>#include <md4/md4.h>#include "proto.h"#include "ntreg.h"const char chntpw_version[] = "chntpw version 0.98.1 000607, (c) Petter N Hagen";extern char *val_types[REG_MAX+1];#define MAX_HIVES 10#define H_SAM 0#define H_SYS 1#define H_SEC 2/* Array of loaded hives */struct hive *hive[MAX_HIVES+1];int no_hives = 0;int syskeyreset = 0;int dirty = 0;/* * of user with RID 500, because silly MS decided * to localize the bloody admin-username!! AAAGHH! */char admuser[129]="StupidMS";/* ============================================================== *//* Crypto-stuff & support for what we'll do in the V-value *//* Zero out string for lanman passwd, then uppercase * the supplied password and put it in here */void make_lanmpw(char *p, char *lm, int len){ int i; for (i=0; i < 15; i++) lm[i] = 0; for (i=0; i < len; i++) lm[i] = toupper(p[i]);}/* * Convert a 7 byte array into an 8 byte des key with odd parity. */void str_to_key(unsigned char *str,unsigned char *key){ void des_set_odd_parity(des_cblock *); int i; key[0] = str[0]>>1; key[1] = ((str[0]&0x01)<<6) | (str[1]>>2); key[2] = ((str[1]&0x03)<<5) | (str[2]>>3); key[3] = ((str[2]&0x07)<<4) | (str[3]>>4); key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5); key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6); key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7); key[7] = str[6]&0x7F; for (i=0;i<8;i++) { key[i] = (key[i]<<1); } des_set_odd_parity((des_cblock *)key);}/* * Function to convert the RID to the first decrypt key. */void sid_to_key1(unsigned long sid,unsigned char deskey[8]){ unsigned char s[7]; s[0] = (unsigned char)(sid & 0xFF); s[1] = (unsigned char)((sid>>8) & 0xFF); s[2] = (unsigned char)((sid>>16) & 0xFF); s[3] = (unsigned char)((sid>>24) & 0xFF); s[4] = s[0]; s[5] = s[1]; s[6] = s[2]; str_to_key(s,deskey);}/* * Function to convert the RID to the second decrypt key. */void sid_to_key2(unsigned long sid,unsigned char deskey[8]){ unsigned char s[7]; s[0] = (unsigned char)((sid>>24) & 0xFF); s[1] = (unsigned char)(sid & 0xFF); s[2] = (unsigned char)((sid>>8) & 0xFF); s[3] = (unsigned char)((sid>>16) & 0xFF); s[4] = s[0]; s[5] = s[1]; s[6] = s[2]; str_to_key(s,deskey);}/* DES encrypt, for LANMAN */void E1(uchar *k, uchar *d, uchar *out){ des_key_schedule ks; des_cblock deskey; str_to_key(k,(uchar *)deskey);#ifdef __FreeBSD__ des_set_key(&deskey,ks);#else /* __FreeBsd__ */ des_set_key((des_cblock *)deskey,ks);#endif /* __FreeBsd__ */ des_ecb_encrypt((des_cblock *)d,(des_cblock *)out, ks, DES_ENCRYPT);}/* Decode the V-struct, and change the password * vofs - offset into SAM buffer, start of V struct * rid - the users RID, required for the DES decrypt stage * If rid==0 it will try to extract the rid out of the V struct * else the supplied one will be used * * Some of this is ripped & modified from pwdump by Jeremy Allison * */char *change_pw(char *buf, int rid, int vlen, int stat){ uchar x1[] = {0x4B,0x47,0x53,0x21,0x40,0x23,0x24,0x25}; char magic[] = {0x24, 0, 0x44 }; int pl,ridofs,vend; char *vp; static char username[128],fullname[128]; char comment[128],homedir[128],md4[32],lanman[32]; char newunipw[34], newp[20], despw[20], newlanpw[16], newlandes[20]; char yn[4]; int username_offset,username_len; int fullname_offset,fullname_len; int comment_offset,comment_len; int homedir_offset,homedir_len; int ntpw_len,lmpw_len,ntpw_offs,lmpw_offs,i; des_key_schedule ks1, ks2; des_cblock deskey1, deskey2; MD4_CTX context; unsigned char digest[16]; vp = buf; username_offset = get_int(vp + 0xC); username_len = get_int(vp + 0x10); fullname_offset = get_int(vp + 0x18); fullname_len = get_int(vp + 0x1c); comment_offset = get_int(vp + 0x24); comment_len = get_int(vp + 0x28); homedir_offset = get_int(vp + 0x48); homedir_len = get_int(vp + 0x4c); lmpw_offs = get_int(vp + 0x9c); lmpw_len = get_int(vp + 0xa0); ntpw_offs = get_int(vp + 0xa8); ntpw_len = get_int(vp + 0xac);#if 0 printf("lmpw_offs: 0x%x, lmpw_len: %d (0x%x)\n",lmpw_offs,lmpw_len,lmpw_len); printf("ntpw_offs: 0x%x, ntpw_len: %d (0x%x)\n",ntpw_offs,ntpw_len,ntpw_len);#endif *username = 0; *fullname = 0; *comment = 0; *homedir = 0; if(username_len <= 0 || username_len > vlen || username_offset <= 0 || username_offset >= vlen || comment_len < 0 || comment_len > vlen || fullname_len < 0 || fullname_len > vlen || homedir_offset < 0 || homedir_offset >= vlen || comment_offset < 0 || comment_offset >= vlen || lmpw_offs < 0 || lmpw_offs >= vlen) { if (stat != 1) printf("Not a legal struct? (negative lengths)\n"); return(NULL); } /* Offsets in top of struct is relative to end of pointers, adjust */ username_offset += 0xCC; fullname_offset += 0xCC; comment_offset += 0xCC; homedir_offset += 0xCC; ntpw_offs += 0xCC; lmpw_offs += 0xCC; cheap_uni2ascii(vp + username_offset,username,username_len); cheap_uni2ascii(vp + fullname_offset,fullname,fullname_len); cheap_uni2ascii(vp + comment_offset,comment,comment_len); cheap_uni2ascii(vp + homedir_offset,homedir,homedir_len); #if 0 if (!rid) { printf("No RID supplied, doing some magic to find it.\n"); ridofs = find_in_buf(buf, magic,3, 0); if (!ridofs || ridofs > vlen) { printf("No RID found in struct..\n"); rid = 0; } else { rid = get_int(buf+ridofs+0x1e); } }#endif#if 0 /* Reset hash-lengths to 16 if syskey has been reset */ if (syskeyreset && ntpw_len > 16 && !stat) { ntpw_len = 16; lmpw_len = 16; ntpw_offs -= 4; (unsigned int)*(vp+0xa8) = ntpw_offs - 0xcc; *(vp + 0xa0) = 16; *(vp + 0xac) = 16; }#endif if (stat) { printf("RID: %04x, Username: <%s>%s\n", rid, username, ( !rid ? ", account locked?" : (ntpw_len < 16) ? ", *BLANK password*" : "") ); return(username); } printf("RID : %04d [%04x]\n",rid,rid); printf("Username: %s\n",username); printf("fullname: %s\n",fullname); printf("comment : %s\n",comment); printf("homedir : %s\n\n",homedir); if (ntpw_len < 16) { printf("** This user _probably_ has a BLANK password! (Unable to change it, let NT do it instead :)\n\n"); return(0); } if (!rid) { printf("No RID given. Unable to change passwords..\n"); return(0); } hexprnt("Crypted NT pw: ",(vp+ntpw_offs),16); hexprnt("Crypted LM pw: ",(vp+lmpw_offs),16); /* Get the two decrpt keys. */ sid_to_key1(rid,(unsigned char *)deskey1); des_set_key((des_cblock *)deskey1,ks1); sid_to_key2(rid,(unsigned char *)deskey2); des_set_key((des_cblock *)deskey2,ks2); /* Decrypt the NT md4 password hash as two 8 byte blocks. */ des_ecb_encrypt((des_cblock *)(vp+ntpw_offs ), (des_cblock *)md4, ks1, DES_DECRYPT); des_ecb_encrypt((des_cblock *)(vp+ntpw_offs + 8), (des_cblock *)&md4[8], ks2, DES_DECRYPT); /* Decrypt the lanman password hash as two 8 byte blocks. */ des_ecb_encrypt((des_cblock *)(vp+lmpw_offs), (des_cblock *)lanman, ks1, DES_DECRYPT); des_ecb_encrypt((des_cblock *)(vp+lmpw_offs + 8), (des_cblock *)&lanman[8], ks2, DES_DECRYPT); hexprnt("MD4 hash : ",md4,16); hexprnt("LANMAN hash : ",lanman,16); pl = fmyinput("\nPlease enter new password\nor nothing to leave unchanged: ",newp,16); /* printf("password: [%s] have length %d\n",newp,pl); */ if (!pl) { printf("Nothing changed.\n"); return(0); } cheap_ascii2uni(newp,newunipw,pl); make_lanmpw(newp,newlanpw,pl); /* printf("Ucase Lanman: %s\n",newlanpw); */ MD4Init (&context); MD4Update (&context, newunipw, pl<<1); MD4Final (digest, &context); hexprnt("\nNEW MD4 hash : ",digest,16); E1(newlanpw, x1, lanman); E1(newlanpw+7, x1, lanman+8); hexprnt("NEW LANMAN hash : ",lanman,16); /* Encrypt the NT md4 password hash as two 8 byte blocks. */ des_ecb_encrypt((des_cblock *)digest, (des_cblock *)despw, ks1, DES_ENCRYPT); des_ecb_encrypt((des_cblock *)(digest+8), (des_cblock *)&despw[8], ks2, DES_ENCRYPT); des_ecb_encrypt((des_cblock *)lanman, (des_cblock *)newlandes, ks1, DES_ENCRYPT); des_ecb_encrypt((des_cblock *)(lanman+8), (des_cblock *)&newlandes[8], ks2, DES_ENCRYPT); hexprnt("NEW DES crypt : ",despw,16); hexprnt("NEW LANMAN crypt: ",newlandes,16); fmyinput("\nDo you really wish to change it? (y/n) [n] ",yn,2); /* Reset hash length to 16 if syskey enabled, this will cause * a conversion to syskey-hashes upon next boot */ if (syskeyreset && ntpw_len > 16) { ntpw_len = 16; lmpw_len = 16; ntpw_offs -= 4; (unsigned int)*(vp+0xa8) = ntpw_offs - 0xcc; *(vp + 0xa0) = 16; *(vp + 0xac) = 16; } if (*yn == 'y') { for (i = 0; i < 16; i++) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -