diff --git a/debian/changelog b/debian/changelog index 9abb72e..8bc0053 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +chntpw (1.0-2) unstable; urgency=low + + * debian/patches/12_samusrgrp.c_interactive_typo: + interactive typo in the source code + * debian/patches/13_sampasswd.c_improved_its_definition + Sampasswd definition was improved + * debian/patches/14_added_samunlock_binary + New samunlock binary (SAM database, unlock a user) + * debian/patches/15_sampasswd_write_hive_fix + sampasswd binary was fixed so that it actually writes its hive in non + interactive mode. + * debian/samunlock.8: Write manpage for the new samunlock program + + -- Adrian Gibanel Lopez Wed, 06 Dec 2017 09:49:52 +0000 + chntpw (1.0-1) unstable; urgency=low * Update to latest upstream release, published in 2014-02-01 diff --git a/debian/patches/12_samusrgrp.c_interactive_typo b/debian/patches/12_samusrgrp.c_interactive_typo new file mode 100644 index 0000000..bd187b7 --- /dev/null +++ b/debian/patches/12_samusrgrp.c_interactive_typo @@ -0,0 +1,12 @@ +samusrgrp.c: Interactive TYPO +--- a/samusrgrp.c ++++ b/samusrgrp.c +@@ -1,7 +1,7 @@ + /* + * samusrgrp.c - SAM database, add or remove user in a group + * +- * Command line utility, non-inreractive to add or remove a user to/from ++ * Command line utility, non-interactive to add or remove a user to/from + * a local group in the SAM database, list groups with memberships etc + * + * When run as: diff --git a/debian/patches/13_sampasswd.c_improved_its_definition b/debian/patches/13_sampasswd.c_improved_its_definition new file mode 100644 index 0000000..a1ccfc3 --- /dev/null +++ b/debian/patches/13_sampasswd.c_improved_its_definition @@ -0,0 +1,10 @@ +sampasswd.c: Improved its definition +--- a/sampasswd.c ++++ b/sampasswd.c +@@ -1,5 +1,5 @@ + /* +- * sampasswd.c - SAM database, add or remove user in a group ++ * sampasswd.c - SAM database, reset user password or account bits + * + * Command line utility, non-interactive to reset user password and/or + * account bits for a user in the SAM database diff --git a/debian/patches/14_added_samunlock_binary b/debian/patches/14_added_samunlock_binary new file mode 100644 index 0000000..ff1836c --- /dev/null +++ b/debian/patches/14_added_samunlock_binary @@ -0,0 +1,283 @@ +Added samunlock binary that let's you unlock or list users. + This command is suited for scripts and it is also interactive +--- a/Makefile ++++ b/Makefile +@@ -12,7 +12,7 @@ + LIBS=$(shell libgcrypt-config --libs) + + +-all: chntpw cpnt reged samusrgrp sampasswd ++all: chntpw cpnt reged samusrgrp sampasswd samunlock + + chntpw: chntpw.o ntreg.o edlib.o libsam.o + $(CC) $(CFLAGS) -o chntpw chntpw.o ntreg.o edlib.o libsam.o $(LIBS) +@@ -41,6 +41,11 @@ + sampasswd.static: sampasswd.o ntreg.o libsam.o + $(CC) -static $(CFLAGS) -o sampasswd.static sampasswd.o ntreg.o libsam.o + ++samunlock: samunlock.o ntreg.o libsam.o ++ $(CC) $(CFLAGS) -o samunlock samunlock.o ntreg.o libsam.o ++ ++samunlock.static: samunlock.o ntreg.o libsam.o ++ $(CC) -static $(CFLAGS) -o samunlock.static samunlock.o ntreg.o libsam.o + + + #ts: ts.o ntreg.o +@@ -52,5 +57,5 @@ + $(CC) -c $(CFLAGS) $< + + clean: +- -rm -f *.o chntpw chntpw.static cpnt reged reged.static samusrgrp samusrgrp.static sampasswd sampasswd.static *~ ++ -rm -f *.o chntpw chntpw.static cpnt reged reged.static samusrgrp samusrgrp.static sampasswd sampasswd.static samunlock samunlock.static *~ + +--- /dev/null ++++ b/samunlock.c +@@ -0,0 +1,248 @@ ++/* ++ * samunlock.c - SAM database, Unlock user ++ * ++ * Command line utility, non-interactive to unlock a user ++ * in the SAM database ++ * ++ * Changes: ++ * 2014 - oct: First version, some code from earlier sampasswd.c. ++ * ++ ***** ++ * ++ * Copyright (c) 2014 Adrian Gibanel ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * See file GPL.txt for the full license. ++ * ++ ***** ++ */ ++ ++ ++#include ++#include ++#include ++#include ++ ++#include "ntreg.h" ++#include "sam.h" ++ ++ ++const char samunlock_version[] = "samunlock version 0.1 141018, (c) Adrian Gibanel"; ++ ++ ++/* Global verbosity flag */ ++int gverbose = 0; ++ ++/* Array of loaded hives */ ++#define MAX_HIVES 10 ++struct hive *hive[MAX_HIVES+1]; ++int no_hives = 0; ++ ++int H_SAM = -1; ++ ++ ++ ++int do_unlock(char *user, int inrid, int verb) ++{ ++ int rid = 0; ++ int ret; ++ char *resolvedname = NULL; ++ char s[200]; ++ unsigned short acb; ++ ++ if ((H_SAM < 0) || (!user && !inrid) ) return(1); ++ ++ if (inrid) { ++ rid = inrid; ++ } else { ++ if (*user == '0' && *(user+1) == 'x') sscanf(user,"%i",&rid); ++ } ++ ++ if (!rid) { /* Look up username */ ++ /* Extract the unnamed value out of the username-key, value is RID */ ++ snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\Names\\%s\\@",user); ++ rid = get_dword(hive[H_SAM],0,s, TPF_VK_EXACT|TPF_VK_SHORT); ++ if (rid == -1) { ++ printf("ERROR: User <%s> not found\n",user); ++ return(1); ++ } ++ } ++ ++ /* At this point we have a RID, so get the real username it maps to just to show it */ ++ resolvedname = sam_get_username(hive[H_SAM], rid); ++ ++ if (!resolvedname) return(1); /* RID lookup failed, no such user */ ++ ++ if (gverbose) printf("do_unlock: Username: %s, RID = %d (0x%0x)\n",resolvedname,rid,rid); ++ ++ acb = sam_handle_accountbits(hive[H_SAM], rid,2); ++ ++ ret = acb & 0x8000; /* ret != 0 means locked ; ret == 0 means unlocked */ ++ ++ if (!ret && verb) printf("Unlock user %s, RID = %d [0x%0x]\n",resolvedname,rid,rid); ++ ++ FREE(resolvedname); ++ return(ret); ++ ++} ++ ++ ++ ++void usage(void) ++{ ++ printf(" [-U|-l] [-H] -u \n" ++ "Unlock user or list users in SAM database\n" ++ "Mode:\n" ++ " -U = Unlock user\n" ++ " -l = list users in sam\n" ++ "Parameters:\n" ++ " can be given as a username or a RID in hex with 0x in front\n" ++ " Example:\n" ++ " -U -u theboss -> Unlocks user named 'theboss' if found\n" ++ " -U -u 0x3ea -> Unlocks user with RID 0x3ea (hex)\n" ++ " -U -f -> Unlocks admin user with lowest RID\n" ++ " not counting built-in admin (0x1f4) unless it is the only admin\n" ++ " Usernames with international characters usually fails to be found,\n" ++ " please use RID number instead\n" ++ " If success, there will be no output, and exit code is 0\n" ++ "Options:\n" ++ " -H : For list: Human readable listing (default is parsable table)\n" ++ " -H : For unlock: Will output confirmation message if success\n" ++ " -N : No allocate mode, only allow edit of existing values with same size\n" ++ " -E : No expand mode, do not expand hive file (safe mode)\n" ++ " -t : Debug trace of allocated blocks\n" ++ " -v : Some more verbose messages/debug\n" ++ ); ++} ++ ++ ++int main(int argc, char **argv) ++{ ++ ++ extern int optind; ++ extern char* optarg; ++ ++ int what = 0; ++ int unlock = 0; ++ int list = 0; ++ int mode = 0; ++ int human = 0; ++ int adm = 0; ++ int first = 0; ++ int ret, wret, il; ++ char *hivename; ++ char c; ++ char *usr = NULL; ++ ++ char *options = "UlHu:vNEthaf"; ++ ++ while((c=getopt(argc,argv,options)) > 0) { ++ switch(c) { ++ case 'U': unlock = 1; break; ++ case 'l': list = 2; break; ++ case 'u': usr = optarg; break; ++ case 'f': first = 1; break; ++ case 'H': human = 1; break; ++ case 'v': mode |= HMODE_VERBOSE; gverbose = 1; break; ++ case 'N': mode |= HMODE_NOALLOC; break; ++ case 'E': mode |= HMODE_NOEXPAND; break; ++ case 't': mode |= HMODE_TRACE; break; ++ case 'h': printf("%s\n%s ",samunlock_version,argv[0]); usage(); exit(0); break; ++ default: printf("%s\n%s ",samunlock_version,argv[0]); usage(); exit(1); break; ++ } ++ } ++ ++ if (!unlock && !list && !what) { ++ fprintf(stderr,"%s: ERROR: Mode -U or -l must be specified. -h for help\n",argv[0]); ++ exit(1); ++ } ++ ++#if 0 /* Should both be allowed at same time?? */ ++ if (list && unlock) { ++ fprintf(stderr,"%s: ERROR: Mode -U and -l impossible at the same time. -h for help\n",argv[0]); ++ exit(1); ++ } ++#endif ++ ++ if (unlock && !first && (!usr || !*usr)) { ++ fprintf(stderr,"%s: ERROR: Need a user for unlock, -u must be specified.\n",argv[0]); ++ exit(1); ++ } ++ ++ ++ /* Load hives. Only first SAM hive will be used however */ ++ ++ hivename = argv[optind+no_hives]; ++ if (!hivename || !*hivename) { ++ fprintf(stderr,"%s: ERROR: You must specify a SAM registry hive filename.\n",argv[0]); ++ exit(1); ++ } ++ do { ++ if (!(hive[no_hives] = openHive(hivename, ++ HMODE_RW|mode))) { ++ fprintf(stderr,"%s: ERROR: Unable to open/read registry hive, cannot continue\n",argv[0]); ++ exit(1); ++ } ++ switch(hive[no_hives]->type) { ++ case HTYPE_SAM: H_SAM = no_hives; break; ++ // case HTYPE_SOFTWARE: H_SOF = no_hives; break; ++ // case HTYPE_SYSTEM: H_SYS = no_hives; break; ++ // case HTYPE_SECURITY: H_SEC = no_hives; break; ++ } ++ no_hives++; ++ hivename = argv[optind+no_hives]; ++ } while (hivename && *hivename && no_hives < MAX_HIVES); ++ ++ if (H_SAM == -1) { ++ fprintf(stderr,"%s: WARNING: Hive file does not look like SAM, but continuing anyway in case detection was wrong\n" ++ "%s: WARNING: If it really is not a SAM file you will get strange errors or bad results\n",argv[0],argv[0]); ++ H_SAM = 0; ++ } ++ ++ ++ /* Do logic */ ++ ++ if (list) { ++ adm = sam_list_users(hive[H_SAM], human); ++ if (gverbose) printf(" sam_list_users found admin to be 0x%x\n",adm); ++ } ++ ++ if (unlock) { ++ if (first) { ++ adm = sam_list_users(hive[H_SAM], 2); ++ if (!adm) { ++ fprintf(stderr,"%s: ERROR: Unable to unlock, no admin users found\n",argv[0]); ++ } else { ++ // printf("Resetting password of user with RID %x\n",adm); ++ ret = do_unlock(usr, adm, human); ++ } ++ } else { ++ ret = do_unlock(usr, 0, human); ++ if (ret) { ++ fprintf(stderr,"%s: ERROR: Failed to unlock %s\n",argv[0],usr); ++ } ++ } ++ } ++ ++ /* write registry hive (if needed) */ ++ ++ wret = 0; ++ for (il = 0; il < no_hives; il++) { ++ wret |= writeHive(hive[il]); ++ if (hive[il]->state & HMODE_DIDEXPAND) ++ fprintf(stderr," WARNING: Registry file %s was expanded! Experimental! Use at own risk!\n",hive[il]->filename); ++ while (no_hives > 0) ++ closeHive(hive[--no_hives]); ++ } ++ ++ return(ret | wret); ++} ++ diff --git a/debian/patches/15_sampasswd_write_hive_fix b/debian/patches/15_sampasswd_write_hive_fix new file mode 100644 index 0000000..58ad160 --- /dev/null +++ b/debian/patches/15_sampasswd_write_hive_fix @@ -0,0 +1,13 @@ +sampasswd: Now it does work because we actually write the + Hive as we were not doing before +--- a/sampasswd.c ++++ b/sampasswd.c +@@ -243,7 +243,7 @@ + + wret = 0; + for (il = 0; il < no_hives; il++) { +- // wret |= writeHive(hive[il]); ++ wret |= writeHive(hive[il]); + if (hive[il]->state & HMODE_DIDEXPAND) + fprintf(stderr," WARNING: Registry file %s was expanded! Experimental! Use at own risk!\n",hive[il]->filename); + while (no_hives > 0) diff --git a/debian/patches/series b/debian/patches/series index 757f8a8..1d531f4 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -9,3 +9,7 @@ 09_improve_robustness 10_remove_static 11_improve_documentation +12_samusrgrp.c_interactive_typo +13_sampasswd.c_improved_its_definition +14_added_samunlock_binary +15_sampasswd_write_hive_fix diff --git a/debian/rules b/debian/rules index 1bfad59..5cab2cd 100644 --- a/debian/rules +++ b/debian/rules @@ -51,6 +51,7 @@ install: build install -m 755 reged $(CURDIR)/debian/chntpw/usr/sbin/ install -m 755 sampasswd $(CURDIR)/debian/chntpw/usr/sbin/ install -m 755 samusrgrp $(CURDIR)/debian/chntpw/usr/sbin/ + install -m 755 samunlock $(CURDIR)/debian/chntpw/usr/sbin/ binary-indep: build-indep install @@ -64,7 +65,7 @@ binary-arch: build-arch install [ ! -f faq.html ] || dh_installdocs faq.html bootdisk.html *.gif dh_installdocs dh_installexamples - dh_installman debian/chntpw.8 debian/samusrgrp.8 debian/reged.8 debian/sampasswd.8 + dh_installman debian/chntpw.8 debian/samusrgrp.8 debian/reged.8 debian/sampasswd.8 debian/samunlock.8 dh_installchangelogs HISTORY.txt dh_link dh_strip diff --git a/debian/samunlock.8 b/debian/samunlock.8 new file mode 100644 index 0000000..1423a32 --- /dev/null +++ b/debian/samunlock.8 @@ -0,0 +1,109 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH SAMUNLOCK 8 "6th December 2017" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +samunlock \- unlock users in the SAM user database +.SH SYNOPSIS +.B samunlock +.RI [ options ] +.RI -u user +.RI < samfile > +.br +.SH DESCRIPTION +This manual page documents briefly the +.B samunlock +command. +This manual page was written for the Debian distribution +because the original program does not have a manual page. + +.PP +.B samunlock +is a non-interactive command line utility that can unlock a user +and/or the user's account bits from the SAM user database file of a +Microsoft Windows system (Windows NT, 2000, XP, Vista, 7, 8.1, etc.). +This file is usually located at +\\WINDOWS\\system32\\config\\SAM on the file system of a Microsoft Windows +Operating System + +On success, the program does not output any informatin and the exit code is 0. + +.SH OPTIONS +.TP +.B \-h +Show summary of options. +.TP +.B \-U +Unlock the user. +.TP +.B \-a +Unlock all the users. If this option is used there is no need to specify the next option. +.TP +.B \-u +User to unlock. The user value can be provided as a username, or a RID number in +hexadecimal (if the username is preceded with '0x'). Usernames including +international characters will probably not work. +.TP +.B \-l +Lists the users in the SAM database. +.TP +.B \-H +Output human readable output. The program by default will print a parsable table unless +this option is used. +.TP +.B \-N +Do not allocate more information, only allow the editing of existing values with same size. +.TP +.B \-E +Do not expand the hive file (safe mode). +.TP +.B \-t +Print debug information of allocated blocks. +.TP +.B \-v +Print verbose information and debug messages. + +.SH EXAMPLES +.TP +.B samunlock -U -u theboss +Unlock an user named 'theboss', if found. + +.TP +.B samunlock -U -u 0x3ea +Unlock an user with RID '0x3a'. + +.SH KNOWN BUGS + +If the username includes international (non-ASCII) characters the program +will not (usually) find it. Use the RID number instead. + +.SH SEE ALSO +.B chntpwd, reged, samusrgrp +.br +You will find more information available on how this program works, in the +text files +.IR /usr/share/doc/chntpw/README.txt +and +.IR /usr/share/doc/chntpw/MANUAL.txt + +More documentation is available at the non upstream's author site: +.BR https://github.com/rescatux/chntpw + +.SH AUTHOR +This program was written by Adrian Gibanel Lopez. + +This manual page was written by Adrian Gibanel Lopez , +for the Debian GNU/Linux system (but may be used by others).