📄 chntpw.c
字号:
struct keyval *v; int nkofs,vkofs; int rid; int count = 0, countri = 0; struct ex_data ex; nkofs = trav_path(hive[H_SAM], 0,"\\SAM\\Domains\\Account\\Users\\Names\\",0); if (!nkofs) { printf("Cannot find usernames in registry! (is this a SAM-hive?)\n"); return(1); } while ((ex_next_n(hive[H_SAM], nkofs+4, &count, &countri, &ex) > 0)) { /* Extract the value out of the username-key, value is RID */ snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\Names\\%s\\@",ex.name); rid = get_dword(hive[H_SAM], 0, s); if (rid == 500) strncpy(admuser,ex.name,128); /* Copy out admin-name */ /* printf("name: %s, rid: %d (0x%0x)\n", ex.name, rid, rid); */ /* Now that we have the RID, build the path to, and get the V-value */ snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\%08X\\V",rid); v = get_val2buf(hive[H_SAM], NULL, 0, s, REG_BINARY); if (!v) { printf("Cannot find value <%s>\n",s); return(1); } if (v->len < 0xcc) { printf("Value <%s> is too short (only %d bytes) to be a SAM user V-struct!\n", s, v->len); } else { change_pw( (char *)&v->data , rid, v->len, 1); } FREE(v); FREE(ex.name); } return(0);}/* Find a username in the SAM registry, then get it's V-value, * and feed it to the password changer. */void find_n_change(char *username){ char s[200]; struct vk_key *vkkey; int vkofs; int rid; struct keyval *v; /* Extract the unnamed value out of the username-key, value is RID */ snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\Names\\%s\\@",username); rid = get_dword(hive[H_SAM],0,s); if (rid == -1) { printf("Cannot find value <%s>\n",s); return; } /* printf("Username: %s, RID = %d (0x%0x)\n",username,rid,rid); */ /* Now that we have the RID, build the path to, and get the V-value */ snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\%08X\\V",rid); v = get_val2buf(hive[H_SAM], NULL, 0, s, REG_BINARY); if (!v) { printf("Cannot find value <%s>\n",s); return; } if (v->len < 0xcc) { printf("Value <%s> is too short (only %d bytes) to be a SAM user V-struct!\n", s, vkkey->len_data); } else { change_pw( (char *)&v->data , rid, v->len, 0); if (dirty) { if (!(put_buf2val(hive[H_SAM], v, 0, s, REG_BINARY))) { printf("Failed to write updated <%s> to registry! Password change not completed!\n",s); } } } FREE(v);}/* Check for presence of syskey and possibly disable it if * user wants it. * This is tricky, and extremely undocumented! * See docs for more info on what's going on when syskey is installed */#undef LSADATAvoid handle_syskey(void){ /* This is \SAM\Domains\Account\F */ struct samkeyf { char unknown[0x50]; /* 0x0000 - Unknown. May be machine SID */ char unknown2[0x14]; char syskeymode; /* 0x0064 - Type/mode of syskey in use */ char syskeyflags1[0xb]; /* 0x0065 - More flags/settings */ char syskeyobf[0x30]; /* 0x0070 - This may very well be the obfuscated syskey */ }; /* There may be more, usually 8 null-bytes? */ /* Security\Policy\SecretEncryptionKey\@, only on NT5 */ /* Probably contains some keyinfo for syskey. Second DWORD seems to be syskeymode */ struct secpoldata { int unknown1; /* Some kind of flag? usually 1 */ int syskeymode; /* Is this what we're looking for? */ int unknown2; /* Usually 0? */ char keydata[0x40]; /* Some kind of scrambled keydata? */ };#ifdef LSADATA /* SYSTEM\CurrentControlSet\Control\Lsa\Data, only on NT5?? */ /* Probably contains some keyinfo for syskey. Byte 0x34 seems to be mode */ struct lsadata { char keydata[0x34]; /* Key information */ int syskeymode; /* Is this what we're looking for? */ };#endif void *fdata; struct samkeyf *ff = NULL; struct secpoldata *sf = NULL; struct lsadata *ld = NULL; int len,i,secboot, samfmode, secmode, ldmode; struct keyval *samf, *secpol, *lsad; char *syskeytypes[4] = { "off", "key-in-registry", "enter-passphrase", "key-on-floppy" }; char yn[5]; printf("** Checking for syskey!\n"); samf = get_val2buf(hive[H_SAM], NULL, 0, "\\SAM\\Domains\\Account\\F", REG_BINARY); if (samf && samf->len > 0x70 ) { ff = (struct samkeyf *)&samf->data; samfmode = ff->syskeymode; } else { samfmode = -1; } secboot = -1; if (no_hives >= 2) { secboot = get_dword(hive[H_SYS], 0, "\\ControlSet001\\Control\\Lsa\\SecureBoot"); } secmode = -1; if (no_hives >= 3) { secpol = get_val2buf(hive[H_SEC], NULL, 0, "\\Policy\\PolSecretEncryptionKey\\@", REG_NONE); if (secpol) { /* Will not be found in NT 4, take care of that */ sf = (struct secpoldata *)&secpol->data; secmode = sf->syskeymode; } }#ifdef LSADATA lsad = get_val2buf(hive[H_SYS], NULL, 0, "\\ControlSet001\\Control\\Lsa\\Data\\Pattern", REG_BINARY); if (lsad && lsad->len >= 0x38) { ld = (struct lsadata *)&lsad->data; ldmode = ld->syskeymode; } else { ldmode = -1; }#endif printf("SYSTEM SecureBoot : %d -> %s\n", secboot, (secboot < 0 || secboot > 3) ? "Not Set (not installed, good!)" : syskeytypes[secboot]); printf("SAM Account\\F : %d -> %s\n", samfmode, (samfmode < 0 || samfmode > 3) ? "Not Set" : syskeytypes[samfmode]); printf("SECURITY PolSecretEncryptionKey: %d -> %s\n", secmode, (secmode < 0 || secmode > 3) ? "Not Set (OK if this is NT4)" : syskeytypes[secmode]);#ifdef LSADATA printf("SYSTEM LsaData : %d -> %s\n\n", ldmode, (ldmode < 0 || ldmode > 3) ? "Not Set (strange?)" : syskeytypes[ldmode]);#endif if (secboot != samfmode && secboot != -1) { printf("WARNING: Mismatch in syskey settings in SAM and SYSTEM!\n"); printf("WARNING: It may be dangerous to continue (however, resetting syskey\n"); printf(" may very well fix the problem)\n"); } if (secboot > 0 || samfmode > 0) { printf("\n***************** SYSKEY ENABLED! **************\n"); printf("This installation very likely has the syskey passwordhash-obfuscator installed\n"); printf("It's currently in mode = %d, %s-mode\n",secboot, (secboot < 0 || secboot > 3) ? "Unknown" : syskeytypes[secboot]); if (no_hives < 2) { printf("\nSYSTEM (and possibly SECURITY) hives not loaded, unable to disable syskey!\n"); printf("Please start the program with at least SAM & SYSTEM-hive filenames as arguments!\n\n"); return; } printf("SYSKEY is on! However, you do not have to disable it just to\n"); printf("change a password, only if you have lost the key (floppy/passphrase)\n"); printf("you must turn it off. NOTE: On WINDOWS 2000 it will not be possible\n"); printf("to turn it on again! (and other problems may also show..)\n\n"); printf("NOTE: Disabling syskey will invalidate ALL\n"); printf("passwords, requiring them to be reset. You should at least reset the\n"); printf("administrator password using this program, then the rest ought to be\n"); printf("done from NT.\n"); fmyinput("\nDo you really wish to disable SYSKEY? (y/n) [n] ",yn,2); if (*yn == 'y') { /* Reset SAM syskey infostruct, fill with zeroes */ if (ff) { ff->syskeymode = 0; for (i = 0; i < 0x3b; i++) { ff->syskeyflags1[i] = 0; } put_buf2val(hive[H_SAM], samf, 0, "\\SAM\\Domains\\Account\\F", REG_BINARY); } /* Reset SECURITY infostruct (if any) */ if (sf) { memset(sf, 0, secpol->len); sf->syskeymode = 0; put_buf2val(hive[H_SEC], secpol, 0, "\\Policy\\PolSecretEncryptionKey\\@", REG_BINARY); }#if LSADATA if (ld) { ld->syskeymode = 0; put_buf2val(hive[H_SYS], lsad, 0, "\\ControlSet001\\Control\\Lsa\\Data\\Pattern", REG_BINARY); }#endif /* And SYSTEM SecureBoot parameter */ put_dword(hive[H_SYS], 0, "\\ControlSet001\\Control\\Lsa\\SecureBoot", 0); dirty = 1; syskeyreset = 1; printf("Updating passwordhash-lengths..\n"); list_users(1); printf("* SYSKEY RESET!\nNow please set new administrator password!\n"); } else { syskeyreset = 1; } } else { printf("Syskey not installed!\n"); return; }}void usage(void) { printf("chntpw: change password of a user in a NT SAM file, or invoke registry editor.\n" "chntpw [OPTIONS] <samfile> [systemfile] [securityfile] [otherreghive] [...]\n" " -h This message\n" " -u <user> Username to change, Administrator is default\n" " -l list all users in SAM file\n" " -i Interactive. List users (as -l) then ask for username to change\n" " -e Registry editor (currently only in-place writesupport)\n" " -d Enter buffer debugger instead (hex editor), \n" " -t Trace. Show hexdump of structs/segments. (deprecated debug function)\n" "See readme file on how to extract/read/write the NT's SAM file\n" "if it's on an NTFS partition!\n" "Source/binary freely distributable. See README/COPYING for details\n" "(Contains DESlib code (c) Eric Young)\n" "NOTE: This program is somewhat hackish! You are on your own!\n" );}int main(int argc, char **argv){ int vofs; int dodebug = 0, list = 1, inter = 0,edit = 0,il,d = 0, dd = 0; extern int opterr,optind; extern char* optarg; char *filename,c; char *who = "Administrator"; char iwho[20]; char *options = "idehltu:"; printf("%s\n",chntpw_version); while((c=getopt(argc,argv,options)) > 0) { switch(c) { case 'd': dodebug = 1; break; case 'e': edit = 1; break; case 'l': list = 1; who = 0; break; case 't': list = 2; who = 0; break; case 'i': list = 1; who = 0; inter = 1; break; case 'u': who = optarg; list = 1; break; case 'h': usage(); exit(0); break; default: usage(); exit(1); break; } } filename=argv[optind]; if (!filename || !*filename) { usage(); exit(1); } do { if (!(hive[no_hives] = openHive(filename, HMODE_RW|(list == 2 ? HMODE_VERBOSE : 0)))) { printf("Unable to open/read a hive, exiting..\n"); exit(1); } no_hives++; filename = argv[optind+no_hives]; } while (filename && *filename && no_hives < MAX_HIVES); if (dodebug) debugit(hive[0]->buffer,hive[0]->size); else { if (list && !edit) { if ( list_users(1) ) edit = 1; } if (edit) mainloop(); else if (who) { handle_syskey(); find_n_change(who); } if (inter) handle_syskey(); while (inter) { printf("\nUsername to change (! to quit, . to list users): [%s] ",admuser); il = fmyinput("",iwho,15); if (il == 1 && *iwho == '.') { list_users(1); continue; } if (il == 1 && *iwho == '!') { inter = 0; break; } if (il == 0) strcpy(iwho,admuser); find_n_change(iwho); } } printf("Hives that have changed:\n # Name\n"); for (il = 0; il < no_hives; il++) { if (hive[il]->state & HMODE_DIRTY) { printf("%2d <%s>\n",il,hive[il]->filename); d = 1; } } if (d) { fmyinput("Write hive files? (y/n) [n] : ",iwho,3); if (*iwho == 'y') { for (il = 0; il < no_hives; il++) { if (hive[il]->state & HMODE_DIRTY) { printf("%2d <%s> - ",il,hive[il]->filename); if (!writeHive(hive[il])) { printf("OK\n"); dd = 2; } } } } else { printf("Not written!\n"); } } else { printf("None!\n"); } return(dd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -