OpenVMS Source Code Demos

PASSWORD-SEARCH-102.BAS

1000	%title "password_search_xxx.bas"
	%ident "version_102"
	!====================================================================================================
	! title  : password_search_xxx.bas
	! author : Neil Rieck	(Waterloo, Ontario, Canada)
	!	 :		(https://neilrieck.net) (mailto:n.rieck@bell.net)
	! purpose: search for a lost password (just to see if I could do it)
	! history:
	! who ver when   what
	! NSR 100 010823 1. original program
	! NSR 101 010824 1. added a sequential password generator (this was a quick hack)
	! NSR 102 010827 1. improved performance of the password generator (still needs a rewrite)
	!====================================================================================================
	option type=explicit							! no kid stuff
	option size = (real double)
	set no prompt
	declare long my_count, time1, time2
	time1 = time(0)
	!
	declare string constant							!						&
		k_version$ = "password_search_102"			,	! program title					&
		k_error_severity$ = "WSEIF???"				,	! error severity				&
		k_pass_chars$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$"	! legal password chars
	!
	!	<<< system declarations >>>
	!
	%include "starlet"      %from %library "sys$library:basic$starlet"      ! system services
	%include "$ssdef"       %from %library "sys$library:basic$starlet"      ! ss$
	%include "$uaidef"      %from %library "sys$library:basic$starlet"      ! uai$
	!
%if %declared (%ITEMREC) = 0 %then
	record ItemRec								! structure of item record
	    variant
		case
		    group one
			word	BuffLen
			word	ItemCode
			long	BuffAddr
			long	RtnLenAdr
		    end group one
		case
		    group two
			long	List_Terminator
			long	Junk1
			long	Junk2
		    end group two
	    end variant
	end record ItemRec
%let %ITEMREC = 1
%end %if
	!
	!	<<< my variable declarations >>>
	!
	declare	basic$quadword	hashed_password		,&
				trial_hash		,&
		ItemRec		myItems(9)		,&
		long		rc%			,&
				rc_bits%		,&
				cur_pos%		,&
				max_pos%		,&
				hit%			,&
				min_pwd_length%		,&
				max_pwd_length%		,&
				i%			,&
		double		seed			,&
				max_seed		,&
		string		trial_password$		,&
				user_name$		,&
				junk$			,&
		word		salt			,&
		byte		encrytion_type%		,&
				min_pwd_length_uaf%
	!
	!	chunk$ + pieces occupy the same memory location
	!
	map(overlay1)string	chunk$=32		! 1-32
	map(overlay1)byte	pieces(31)		! 0-31
	!
	map(tally)long		tally(31)		! 0-31
	!
	map(my_data)byte	my_data(38)		! 1-38 (we'll ignore subscript 0)
	!
	!====================================================================================================
	!
	!	<<< Main >>>
	!
	print k_version$
	print string$(len(k_version$),45%)
	input "user name? (default=quit) ";user_name$
	user_name$ = edit$(user_name$,32%+4%+2%)
	print "user=",user_name$
	!
	myItems(0)::BuffLen		= 4%				! size of encrytion_type% in bytes
	myItems(0)::ItemCode		= UAI$_ENCRYPT			!
	myItems(0)::BuffAddr		= loc(encrytion_type%)		! addr of encrytion_type%
	myItems(0)::RtnLenAdr		= 0%				! bytes returned (don't care)
	!
	myItems(1)::BuffLen		= 8%				! size of hashed_password in bytes
	myItems(1)::ItemCode		= UAI$_PWD			!
	myItems(1)::BuffAddr		= loc(hashed_password)		! addr of hashed_password
	myItems(1)::RtnLenAdr		= 0%				! bytes returned (don't care)
	!
	myItems(2)::BuffLen		= 2%				! size of salt in bytes
	myItems(2)::ItemCode		= UAI$_SALT			!
	myItems(2)::BuffAddr		= loc(salt)			! addr of salt
	myItems(2)::RtnLenAdr		= 0%				! bytes returned (don't care)
	!
	myItems(3)::BuffLen		= 1%				! size of salt in bytes
	myItems(3)::ItemCode		= UAI$_PWD_LENGTH		!
	myItems(3)::BuffAddr		= loc(min_pwd_length_uaf%)	! addr of min_pwd_length_uaf
	myItems(3)::RtnLenAdr		= 0%				! bytes returned (don't care)
	!
	myItems(4)::List_Terminator	= 0%
	!
	!	SYS$GETUAI [nullarg] ,[contxt] ,usrnam ,itmlst ,[nullarg] ,[nullarg] ,[nullarg]
	!
	rc% = sys$getuai(,,user_name$,myItems(0),,,)
	rc_bits% = (rc% and 7%)
	if rc_bits% <> 1% then
		print "$getuai-"+ mid$(k_error_severity$, rc_bits%+1%, 1%) +"-rc: "+str$(rc%)
		goto sortie
	end if
	!
	print "minimum  password length from SYSUAF           : "+ str$(min_pwd_length_uaf%)
	print "starting password length ? (01-32,default=quit): ";
	input junk$
	when error in
		min_pwd_length% = integer(junk$)
	use
		min_pwd_length% = 0%
	end when
	select min_pwd_length%
	    case 1% to 32%
	    case else
		print "-e- bad value, exiting"
		goto sortie
	end select
	!
	print "ending   password length ? ("+ format$(min_pwd_length%,"<0>#") +"-32,default=quit): ";
	input junk$
	when error in
		max_pwd_length% = integer(junk$)
	use
		max_pwd_length% = 0%
	end when
	select max_pwd_length%
	    case min_pwd_length% to 32%
	    case else
		print "-e- bad value, exiting"
		goto sortie
	end select
	!
	!	<<< generate a sequence of possible passwords >>>
	!
	hit%		= 0%							!
	chunk$		= ""							! zap chunk (and pieces)
	mat tally	= zer							! zap tally array
	my_data(0%)	= 0%							!
	for i% = 1% to 38%							!
	    my_data(i%) = asc( mid$(k_pass_chars$, i%, 1%) )			! populate my_data
	next i%									!
	max_pos%	= 0%							!
	for i% = 0% to min_pwd_length%-1%					!
	    tally(i%) = 1%							! wrap around (but skip 0)
	    pieces(i%)= my_data( tally(cur_pos%) )				!
	next i%									!
	cur_pos% = min_pwd_length%-1%						!
	max_pos% = cur_pos%							!
	goto first_pass								!
	!
	!	tally sequences examples:	31 ...	4    3    2    1    0
	!	1					0    0    0    0    1-38
	!	2.a					0    0    0    1-38 1
	!	2.b					0    0    0    1-38 2
	!								    .
	!	2.c					0    0    0    1-38 38
	!	3.a					0    0    1-38 1    1
	!
	loop1:
	cur_pos% = 0%								! start in position #0
	loop2:
	if tally(cur_pos%) < len(k_pass_chars$)					! do we have room to incr this column?
	then									! yes
		tally(cur_pos%) = tally(cur_pos%) + 1%				!
		pieces(cur_pos%)= my_data( tally(cur_pos%) )			!
	else									! no, so wrap, then move on
		tally(cur_pos%) = 1%						! wrap around (but skip 0)
		pieces(cur_pos%)= my_data( tally(cur_pos%) )			!
		cur_pos% = cur_pos% + 1%					! advance cur_pos%
		max_pos% = max(cur_pos%, max_pos%)				! remember highest column
		goto loop2	if cur_pos% <= max_pwd_length%-1% 		! if we haven't done max columns...
		print "-e-password not found"					!
		goto sortie							!
	end if									!
	first_pass:
!~~~	trial_password$ = edit$(chunk$,128%)					x
	trial_password$ = left$(chunk$,max_pos%+1%)				! possibly more efficient...
	!
	!	SYS$HASH_PASSWORD pwd ,alg ,[salt] ,usrnam ,hash
	!
	my_count = my_count + 1%
	if my_count = 1000000% then
		time2 = time(0)
		print time2 - time1
	end if
	try_passwords:
	rc% = sys$hash_password(trial_password$,encrytion_type%,salt,user_name$,trial_hash)
	rc_bits% = (rc% and 7%)
	if rc_bits% <> 1% then
		print "$hash_password-"+ mid$(k_error_severity$, rc_bits%+1%, 1%) +"-rc: "+str$(rc%)
		goto sortie
	end if
	if trial_hash = hashed_password then
		print "-s- match: ";trial_password$
		goto sortie
	end if
	goto loop1
	!
	!	<<< adios... >>>
	!
	sortie:
	end

Back to Home
Neil Rieck
Waterloo, Ontario, Canada.