Login and Register system in Batch File

So, I was so badly trying to make Login and Register system in Batch file. I succeded at Registering, simply echoed username and password to .dll files or .txt files, but I don't know how to make to login. I tried much codes, and I don't understand the Login/Register codes I found on the internet.

For example, what I tried:

@echo off
title Login and Register
cls

:register
cls
set /p name="Username: "
echo %name% >> username.txt
cls
set /p password="Password: "
echo %password% >> password.txt
goto :login

:login
cls
set /p uname="Username: "
if %uname% EQU %name% goto :program
if not %uname% EQU %name% goto :error
cls
set /p pass="Password: "
if %pass% EQU %password% goto :program
if not %pass% EQU %password% goto :error

:program
cls
echo Welcome!
echo.
pause

So, this is just example on how my login code would look like. I tried much things but it's still the same. I am begginer in programming so I am not experienced much, I hope you all understand. Thank you.

1 answer

  • answered 2017-06-17 18:33 rojo

    The problem with creating a batch script to handle authentication is that it's trivially easy for someone to edit the batch script and simply insert goto program near the top. You're creating a lot of work for yourself for very little benefit.

    What your script above is missing is, within the :login section, you are not reading the values stored in password.txt. So "%uname%" will never equal "%name%". There's lots of other stuff missing as well, not the least of which is that storing plain text passwords in a text file is dangerous.

    If you insist on continuing down this road, then try this. It stores passwords as Base64-encoded salted SHA512 hashes, so your project will at least be somewhat less dangerous. Of course with the salt hard coded in the bat script, the stored password hashes are still vulnerable to brute force decryption.

    <# : Batch portion
    @echo off
    setlocal disabledelayedexpansion
    
    set "loginfile=%~dpn0.data"
    if exist "%loginfile%" goto login
    
    :registration
    echo Welcome to %~nx0!  Please register.
    set /P "user=Username? "
    call :passwordPrompt hash plain
    
    if defined user if defined hash (
        >> "%loginfile%" echo(%user%=%hash%
        goto main
    )
    goto registration
    
    :login
    for /f "usebackq delims=" %%I in ("%loginfile%") do set "l_%%I"
    echo Welcome to %~nx0!  Please log in.  Enter "new" to register a new account.
    set /P "user=Username? "
    if /I "%user%"=="new" goto registration
    if not defined l_%user% (echo Username not found.&& goto login)
    call :passwordPrompt hash plain
    call set "stored=%%l_%user%%%"
    if not "%hash%"=="%stored%" (
        echo Invalid password.
        goto login
    )
    
    :main
    rem // In case you need it, the entered password is stored in %plain%
    echo Login successful.  Enjoy the fruits of your labor.
    wmic os get localdatetime /value
    
    rem // end main runtime
    goto :EOF
    
    :passwordPrompt <return_hash> <return_plain>
    setlocal disabledelayedexpansion
    set "salt=Top of the world momma!"
    for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0}|out-string)"') do set "%%I"
    endlocal && set "%~1=%h%" && set "%~2=%p%" && exit /b
    
    : end Batch / begin PowerShell hybrid code #>
    [console]::Error.Write("Password? ")
    $i = read-host -AsSecureString
    $m = [Runtime.InteropServices.Marshal]
    $p = $m::PtrToStringAuto($m::SecureStringToBSTR($i))
    "h={0}" -f [Convert]::ToBase64String([Security.Cryptography.HashAlgorithm]::Create(`
        'SHA512').ComputeHash([Text.Encoding]::UTF8.GetBytes("$($env:salt)$p")))
    "p=$p"
    

    Here's the same script annotated with comments. Let me know if you'd like further explanation of anything.

    <# : Batch portion
    @rem // The previous line does nothing in Batch, but begins a multiline comment block
    @rem // in PowerShell.  This allows a single script to be executed by both interpreters.
    @echo off
    setlocal disabledelayedexpansion
    
    rem // If this bat script is named login.bat, then %loginfile% will be set to login.data
    set "loginfile=%~dpn0.data"
    if exist "%loginfile%" goto login
    
    :registration
    echo Welcome to %~nx0!  Please register.
    set /P "user=Username? "
    
    rem // calls the :passwordPrompt function, which will set %hash% and %plain%
    call :passwordPrompt hash plain
    
    if defined user if defined hash (
        >> "%loginfile%" echo(%user%=%hash%
        goto main
    )
    goto registration
    
    :login
    rem // Use "for /f" to capture the contents of a text file with an unknown number of
    rem // lines, or the output of a command.  See "help for" in a cmd console for details.
    for /f "usebackq delims=" %%I in ("%loginfile%") do set "l_%%I"
    echo Welcome to %~nx0!  Please log in.  Enter "new" to register a new account.
    set /P "user=Username? "
    if /I "%user%"=="new" goto registration
    if not defined l_%user% (echo Username not found.&& goto login)
    
    rem // calls the :passwordPrompt function, which will set %hash% and %plain%
    call :passwordPrompt hash plain
    
    rem // "call" here expands %user%, then expands %l_username%
    call set "stored=%%l_%user%%%"
    if not "%hash%"=="%stored%" (
        echo Invalid password.
        goto login
    )
    
    :main
    rem // In case you need it, the entered password is stored in %plain%
    echo Login successful.  Enjoy the fruits of your labor.
    wmic os get localdatetime /value
    
    rem // end main runtime
    goto :EOF
    
    rem // The :passwordPrompt function called with two arguments.  Those args are the names
    rem // of variables that will be set by the function as return values.  You might find
    rem // this batch function tutorial helpful: http://www.dostips.com/DtTutoFunctions.php
    :passwordPrompt <return_hash> <return_plain>
    setlocal disabledelayedexpansion
    set "salt=Top of the world momma!"
    
    rem // "for /f" captures the output of the powershell command, which executes self
    for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0}|out-string)"') do set "%%I"
    endlocal && set "%~1=%h%" && set "%~2=%p%" && exit /b
    
    rem // End PowerShell multiline comment block.
    : end Batch / begin PowerShell hybrid code #>
    
    # Output to stderr to avoid being captured or silenced by for /f
    [console]::Error.Write("Password? ")
    
    # Get user input.  Hide keystrokes with stars.  Store as a secure object
    $secure = read-host -AsSecureString
    
    # Marshal direct access to RAM
    $marshal = [Runtime.InteropServices.Marshal]
    
    # Get pointer to RAM location containing entered string
    $PTR = $marshal::SecureStringToBSTR($secure)
    
    # Retrieve contents of RAM at that pointer
    $plain = $marshal::PtrToStringAuto($PTR)
    
    # Convert %salt% + $pass to a byte array
    $bytes = [Text.Encoding]::UTF8.GetBytes("$($env:salt)$plain")
    
    # Create SHA512 hash algorithm
    $SHA512 = [Security.Cryptography.HashAlgorithm]::Create('SHA512')
    
    # Compute hash
    $hash = $SHA512.ComputeHash($bytes)
    
    # Convert hash to Base64
    $b64 = [Convert]::ToBase64String($hash)
    
    # Output results
    "h=$b64"
    "p=$plain"