Storing a password to login to a batch script

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Cornbeetle
Posts: 31
Joined: 23 Nov 2015 09:34

Storing a password to login to a batch script

#1 Post by Cornbeetle » 10 Dec 2015 08:58

I'm working on a login system for my batch script and I'm trying to come up with the most secure way of storing a password locally on the machine running the script.

My idea is to output thousands of random (%random%) numbers to a hidden text file, with the real password (consisting of numbers only) contained somewhere inside. Also, to make sure that my password did not coincidentally appear in the text file from random numbers, I surround my password with a set of pre-determined numbers that will be searched for along with my password.

Could you give me your input or advice on this idea?

Here's the relevant code:

Code: Select all

::Set temp file as a hidden system file
attrib +h +s %temp%\binary-dump.log

::Begin counter
:pass_1
set /a n=%n%+1

::Output series of random numbers
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%>>%temp%\binary-dump.log
if %n% equ 400 goto:pass_3
goto:pass_1

::Output password surrounded by pre-determined set of numbers
:pass_3
echo %random%%random%%random%%random%%random%4829376%password%687328%random%%random%%random%>>%temp%\binary-dump.log

:pass_4
set n=1
set /a n=%n%+1
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%>>%temp%\binary-dump.log
if %n% equ 200 goto:finish
goto:pass_4

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Storing a password to login to a batch script

#2 Post by foxidrive » 10 Dec 2015 15:21

It's a fair way of hiding the password - but the script using the password will have the code to decrypt the file and people with the code can determine what it is.

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Storing a password to login to a batch script

#3 Post by Aacini » 10 Dec 2015 21:30

Cornbeetle wrote:I'm working on a login system for my batch script and I'm trying to come up with the most secure way of storing a password locally on the machine running the script.

. . .

Could you give me your input or advice on this idea?


That method just don't works. No matter how you try to hide the password, you must remember that Batch programs are provided in source code as foxidrive indicated, so any user may read the method you use and comprehend it, and extract the password from the code and/or data. The only thing you can do in this respect is use a complex and obfuscated code based on unusual features that may discourage most non-experienced users. However, no one method can avoid that a determined user would eventually break the password.

Below is my own version of an obfuscated method that supposedly should avoid that most users break it. Try to determine the right password for this code; if you give up, you may review the password at end of this post.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set /P "pass=Enter password: "
call :encryptPass
if "%encrypted%" neq "DDDDEDB3A0BA5B" echo Invalid password & goto :EOF
echo Access granted
goto :EOF


:encryptPass
setlocal EnableDelayedExpansion

set "val =code=1"
set "head=code:%val:~-2,1%"
set "tail=code:%val:~-1%"
set "charSet=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

:loop
   set /A "i=1, j=169"
   for /L %%i in (0 1 %j:~1,1%%j:~,1%) do (if "!pass:~0,1!" equ "!charSet:~%%i,1!" set /A i^^=1) & set /A j+=i
   cmd /C exit %j%
   set "head%%exit%%tail=!%val :~-2,1%exit%head%!!head%%exit%%tail!!%val :~-2,1%exit%tail%!"
   set "pass=%pass:~1%"
if defined pass goto loop

for %%a in (!head%%exit%%tail!) do endlocal & set "encrypted=%%a"
exit /B

However, all this stuff is just an academic exercise because you only need to remove the line that check the password in order to bypass the "password protection system", and even the most novice Batch file programmer should realize of this point.

Antonio

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Storing a password to login to a batch script

#4 Post by ShadowThief » 10 Dec 2015 23:16

There's a coding challenge on HackThisSite.org that took a fairly creative approach to the problem:

Code: Select all

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET PRIME=2  3  5  7  11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101
SET CHARS=a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
SET PASSWORDVALUE=1
SET INPUT=
SET /P INPUT=Insert password:
IF "%INPUT%"=="" "%~0"
ECHO Authenticating...
:OVERLOOP
SET CURRENTPOSITION=0
:SUBLOOP
IF /I "!INPUT:~%CHARACTERPOSITION%,1!"=="!CHARS:~%CURRENTPOSITION%,1!" SET /A PASSWORDVALUE*=!PRIME:~%CURRENTPOSITION%,3!
SET /A CURRENTPOSITION+=3
IF NOT %CURRENTPOSITION%==78 GOTO :SUBLOOP
SET /A CHARACTERPOSITION+=1
IF NOT "!INPUT:~%CHARACTERPOSITION%,1!"=="" GOTO :OVERLOOP
:END
ENDLOCAL&IF NOT %PASSWORDVALUE%==1065435274 GOTO :ACCESSDENIED
ECHO You have been authenticated. Welcome aboard!
GOTO :SILENTPAUSE
:ACCESSDENIED
ECHO Access denied!
:SILENTPAUSE
PAUSE > NUL


Granted, it doesn't check for the correct order of the letters, just that all of the letters are there. If the password was BAA, it would also accept AAB and ABA.

Cornbeetle
Posts: 31
Joined: 23 Nov 2015 09:34

Re: Storing a password to login to a batch script

#5 Post by Cornbeetle » 11 Dec 2015 08:20

@Aacini

I like your approach as it uses a very complex way to analyze the user input. I think I've given up, but I'm not sure what these two commands do at the end of the FOR line:

Code: Select all

...set /A i^^=1) & set /A j+=i

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Storing a password to login to a batch script

#6 Post by penpen » 11 Dec 2015 09:03

You could use AES encryption or MD5 hash.

MD5-Login-System Sample:

Code: Select all

@echo off
setlocal enableExtensions enableDelayedExpansion
call :addUser "2C1743A391305FBF367DF8E4F069F9F9" "E31606C221DBEA17DBDEDB9DCE486E6E"
call :addUser "4F7AD45C100C79B3D23EA63832475D31" "CE28845B29A373002C28C8E1552FC626"

set /P "login=Login   : "
set /P "passw=Password: "

for /F "tokens=* delims=" %%a in ('md5.bat "!login!"') do (
   set "login_md5=%%~a"
)

for /F "tokens=* delims=" %%a in ('md5.bat "!passw!"') do (
   set "passw_md5=%%~a"
)

for /L %%a in (1, 1, !user.length!) do (
   if /I "!login_md5!!passw_md5!" == "!user[%%~a].login_md5!!user[%%~a].passw_md5!" goto :access
)
echo(Incorrect login or bad password.
endlocal
exit /b 1


:access
echo(Welcome user "!login!".
echo(Bye.
endlocal
exit /b 0


:addUser
if not defined user[1].login_md5 ( set "user.length=1"
) else set /A "user.length+=1"

set "user[%user.length%].login_md5=%~1"
set "user[%user.length%].passw_md5=%~2"

There are two users predefined (without doublequotes):

Code: Select all

                login      password
user_1        "alpha"    "xylophon"
user_2  "Donald Duck"       "Daisy"
Note: Actually both should be pretty save, but AES is stronger (but slower).


penpen

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Storing a password to login to a batch script

#7 Post by Squashman » 11 Dec 2015 09:32

Cornbeetle wrote:@Aacini

I like your approach as it uses a very complex way to analyze the user input. I think I've given up, but I'm not sure what these two commands do at the end of the FOR line:

Code: Select all

...set /A i^^=1) & set /A j+=i

Read the HELP for the SET command.

Code: Select all

The /A switch specifies that the string to the right of the equal sign
is a numerical expression that is evaluated.  The expression evaluator
is pretty simple and supports the following operations, in decreasing
order of precedence:

    ()                  - grouping
    ! ~ -               - unary operators
    * / %               - arithmetic operators
    + -                 - arithmetic operators
    << >>               - logical shift
    &                   - bitwise and
    ^                   - bitwise exclusive or
    |                   - bitwise or
    = *= /= %= += -=    - assignment
      &= ^= |= <<= >>=
    ,                   - expression separator

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Storing a password to login to a batch script

#8 Post by Ed Dyreen » 11 Dec 2015 10:39

AES is pretty slow, when I need to encrypt or decrypt strings I use a combination of several weak methods, but if they are combined they are very difficult to crack. for example this is how I do an encrypt:

1 determine the stringLength.
2 apply a mask ( the mask is provided to the encrypt algo as a parameter, the longer the mask the better because if the string is longer than the mask the mask will be repeated over and over )
char = char[i] + mask[i]
3 apply positional ROTK ( the rotation direction switches for even and uneven positions, the initial offset is stringLength and increases by 1 for every next char )
4 apply random ROTK ( the random character is inserted at a fixed position and will later be used for decryption, the effect is that no string is the same, you could for example encode the string "hello" which will produce for example "Xjuksy" the first time but the next time you encode it it will give a different string for example "ytglMp" yet both decode to the same string "hello", there are as many encoded variations for the word "hello" as there are valid random chars, If I remember well I use around 60 printable chars that means somewhere around 60 possible variations for every word ).

something like this:

Code: Select all

   :: get $array[]
   :: (
      %forQ_% (

         !$inputArray!

      ) do    set /A $array[0] = !%%~?[0]! &%forI_% (

         1, 1, !$array[0]!

      ) do    set "$array[%%i]=!%%~?[%%i]!"
   :: )

   :: put mask on $array[]
   :: (
      %forI_% (

         1, 1, !$array[0]!

      ) do (
         rem get stingLength
         rem (
            ( %stringLen_% $len, $array[%%i] )
         rem )

         rem apply mask
         rem (
            ( %mask_% $array[%%i], $mask, "+", "4" )
         rem )

         rem apply positional rotK
         rem (
            set /A $arrayLen = $len - 1
            set "$oldString=!$array[%%i]!" &set "$newString=!$oldString:~,1!" &%forI_% (

               1, 1, !$arrayLen!

            ) do (
               set "$char=!$oldString:~%%i,1!"
               set /A $pos = %%i + $arrayLen
               ( %isEven_% "%%i" ) &&(

                  ( %rotK_% $char, $char, "+!$pos!", "4" )
               ) ||    ( %rotK_% $char, $char, "-!$pos!", "4" )

               set "$newString=!$newString!!$char!"
            )
            set "$array[%%i]=!$newString!"
         rem )

         rem apply random rotK
         rem (
            call :§parser_ randomFileNameableDec $randomDec ^!

            set /A $n = $len + $randomDec

            ( %rotK_% $array[%%i], $array[%%i], "+!$n!", "4" )
         rem )

         rem insert random char
         rem (
            ( %decToChar_% $randomChar, $randomDec )

            set "$array[%%i]=!$randomChar!!$array[%%i]!"
         rem )
      )
   :: )
When a user wants to decrypt the string he will have to know which mask was used. If many strings are encrypted the chances of the algo being cracked increases due to the way pattern search algos compare strings, but it will be difficult because a random char is inserted in the string but is not part of the string itself, it only tells the decrypter how to undo the random ROTK.

Let's do the decryption:

Code: Select all

   :: get $array[]
   :: (
      %forQ_% (

         !$inputArray!

      ) do    set /A $array[0] = !%%~?[0]! &%forI_% (

         1, 1, !$array[0]!

      ) do    set "$array[%%i]=!%%~?[%%i]!"
   :: )

   :: put mask on $array[]
   :: (
      %forI_% (

         1, 1, !$array[0]!

      ) do (
         rem remove random char
         rem (
            set "$firstChar=!$array[%%i]:~0,1!"

            set "$array[%%i]=!$array[%%i]:~1!"
         rem )

         rem get stingLength
         rem (
            ( %stringLen_% $len, $array[%%i] )
         rem )

         rem remove random rotK
         rem (
            ( %CharToDec_% $firstDec, $firstChar )

            set /A $n = $len + $firstDec

            ( %rotK_% $array[%%i], $array[%%i], "-!$n!", "4" )
         rem )

         rem remove positional rotK
         rem (
            set /A $arrayLen = $len - 1
            set "$oldString=!$array[%%i]!" &set "$newString=!$oldString:~,1!" &%forI_% (

               1, 1, !$arrayLen!

            ) do (
               set "$char=!$oldString:~%%i,1!"
               set /A $pos = %%i + $arrayLen
               ( %isEven_% "%%i" ) &&(

                  ( %rotK_% $char, $char, "-!$pos!", "4" )
               ) ||    ( %rotK_% $char, $char, "+!$pos!", "4" )

               set "$newString=!$newString!!$char!"
            )
            set "$array[%%i]=!$newString!"
         rem )

         rem remove mask
         rem (
            ( %mask_% $array[%%i], $mask, "-", "4" )
         rem )
      )
   :: )
I did this to find something relatively fast, then I thought about porting the code to vbScript so I would be able to speed up things. Later I discovered AutoIT has a built in function for encryption.

Just don't encrypt hundreds of strings with the same mask, every time you apply the same mask the pattern compare algorithm has another hint to work on and the random ROTK only has a finite number of valid chars ( one could always increase this by using more random chars if one uses two random chars the number of encoded variation goes up to 60 * 60 = 3600 and so on, a good rule of thumb is to make sure the number of encoded variations is equal or higher than the number of repetitive words ).

Post Reply