0

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 1

1

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 SHA512 hashes, salted with the usernames. This way your project will at least be less dangerous (assuming the usernames are not known to the attacker).

<# : 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 "%user%"

if defined user if defined hash (
    >> "%loginfile%" echo(%hash%
    goto main
)
goto registration

:login
echo Welcome to %~nx0!  Please log in.  Enter "new" to register a new account.
set /P "user=Username? "
if /I "%user%"=="new" goto registration
call :passwordPrompt hash plain "%user%"
find "%hash%" "%loginfile%" >NUL || (
    echo Invalid credentials.
    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> <username>
setlocal disabledelayedexpansion
set "user=%~3"
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 #>
$env:user = $env:user.toLower()
[console]::Error.Write("Password for $($env:user)? ")
$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:user)`n$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

rem # setlocal limits the scope of variables to this script.
rem # disabledelayedexpansion prevents exclamation marks from being mangled
setlocal disabledelayedexpansion

rem # set "loginfile=drive:\path\to\BatFileBaseName.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 "%user%"

if defined user if defined hash (
    >> "%loginfile%" echo(%hash%
    goto main
)
goto registration

:login
echo Welcome to %~nx0!  Please log in.  Enter "new" to register a new account.
set /P "user=Username? "
if /I "%user%"=="new" goto registration

rem # calls the :passwordPrompt function, which will set %hash% and %plain%
call :passwordPrompt hash plain "%user%"

rem # If hash doesn't exist in login file, then fail auth.
find "%hash%" "%loginfile%" >NUL || (
    echo Invalid credentials.
    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 # :passwordPrompt function
rem # The first two args are the names of empty vars to be populated with return values.
rem # The third arg is the username.  It's not modified.
:passwordPrompt <return_hash> <return_plain> <username>
setlocal disabledelayedexpansion
set "user=%~3"

rem # Use "for /f" to capture the output of the powershell command.  This powershell
rem # command executes the hybrid portion at the bottom of this script.
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0}|out-string)"') do set "%%I"

rem # To learn more about returning values from Batch functions, see this tutorial:
rem # http://www.dostips.com/DtTutoFunctions.php
endlocal && set "%~1=%h%" && set "%~2=%p%" && exit /b

rem # End multi-line PowerShell comment block.  Begin PowerShell scripting.
: end Batch / begin PowerShell hybrid code #>

# Make username case-insensitive
$env:user = $env:user.toLower()

# Output to stderr to avoid being captured or silenced by for /f
[console]::Error.Write("Password for $($env:user)? ")

# 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 + line feed + $plain to a byte array
$bytes = [Text.Encoding]::UTF8.GetBytes("$($env:user)`n$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"
Sign up to request clarification or add additional context in comments.

8 Comments

Very nice code ! i have just tested it and i like the trick of using the powershell function. I'm learning new stuff from you, just if you have some time for me to add some comments on your code ! Thank you again ;)
@Hackoo It was hard to write, so it should also be hard to read. (I'm kidding.) Are there any parts in particular you'd like annotated? If it's the Batch + PowerShell polyglot format in general that you're curious about, this forum thread has different examples.
Your code works and is good and thank you for your effort, but is there any way you can make the code more simple? My friend told me I can load the txt or dll files by a command "echo << C:\Program" for example or something like that... I don't even begin to understand your code. :'D
@miragetv7 I think your friend was mentioning set /P "variable=" < "txtfile.txt", but that convention is only appropriate when you have already determined the number of lines in the text file, or you know exactly which line number contains the data you need. For this script, for /F is more appropriate for reading the contents of the password file. Open a cmd console and enter help for for full details. I posted a heavily commented version of the script for you. Hopefully the comments will help you understand.
Can you code it? I mean if it is possible. I don't understand nor I ever tried to learn Powershell. I mean, without powershell, if it is possible to load the .txt file to Batch file and make it works. Thank you for helping btw!
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.