0

I want to make this code to ask for a password that timeouts after 10 seconds and if you wrote the correct password it goes to :wow but if it's incorrect it just continues the code . (the code is just an example)

@ECHO OFF
TIMEOUT /t 10>nul
exit
:wow
echo now this is fun!
pause
exit
elyazzi
  • 1
  • 1

2 Answers2

1

MD5sum

Batch scripts, as they live in the world of plain text files, aren't very conducive to storing and matching passwords. After all, the person running the script could just as easily open it in Notepad and see the expected password. That's not very hacksy, now, is it?

These batch password questions pop up from time to time, and hard-coded passwords in scripts always irritate me. So how about, for a change, we obfuscate the password with an MD5 hash? There's no simple command built into Windows that makes this happen, but it can be accomplished with a (admittedly convoluted) PowerShell one-liner.

Save this helper script as md5sum.bat:

@echo off
setlocal

if "%~1"=="" goto :EOF

powershell "[Security.Cryptography.HashAlgorithm]::Create('MD5').ComputeHash([Text.Encoding]::UTF8.GetBytes('%~1')) | %%{write-host -n $_.tostring('x2')}"

Then use it to find the MD5 hash of the password you want like this:

md5sum.bat "password"

The result will output

5f4dcc3b5aa765d61d8327deb882cf99

Rather than hard coding the password itself into your script, you can now hard code 5f4dcc3b5aa765d61d8327deb882cf99.


User Entry

Now comes the interesting stuff. You can also borrow from Powershell to obfuscate the user entry like this:

@echo off
setlocal

<NUL set /P "=Password? "
set "psCommand=powershell -command "$p=read-host -AsSecureString;^
$m=[Runtime.InteropServices.Marshal];$m::PtrToStringAuto($m::SecureStringToBSTR($p))""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set "pass=%%p"

setlocal enabledelayedexpansion
echo You entered !pass!
endlocal

Combine the two methods and you can check to see whether the password entered by the user matches the hash hard coded into the script.

@echo off
setlocal

<NUL set /P "=Password? "
set "psCommand=powershell "$p=read-host -AsSecureString;^
$m=[Runtime.InteropServices.Marshal];$x=$m::PtrToStringAuto($m::SecureStringToBSTR($p));^
[Security.Cryptography.HashAlgorithm]::Create('MD5').ComputeHash([Text.Encoding]::UTF8.GetBytes($x)) ^| %%{write-host -n $_.tostring('x2')}""

for /f "usebackq delims=" %%I in (`%psCommand%`) do (
    if "%%~I"=="5f4dcc3b5aa765d61d8327deb882cf99" goto :match
)

echo Nope.
goto :EOF

:match
echo w00!

Voila! Now you can expect a user entry of password but the user can't easily see by opening in Notepad that password is the correct password. Cool, huh?


Self-Destruct

Back to your original question of how you can make this timeout after 10 seconds, you'll have to get a little creative. One solution would be to launch a helper script in the background that waits for 10 seconds, then kills all powershell.exe tasks. This can interfere with other powershell-ish stuff you might have running -- but let's be honest. Given the elementary nature of the question, I think it's safe to assume that won't be a problem in this situation.

I would do it this way:

@echo off
setlocal

if "%~1"=="helper" goto helper
start /b "" "%~f0" helper

<NUL set /P "=Password? "
set "psCommand=powershell "$p=read-host -AsSecureString;^
$m=[Runtime.InteropServices.Marshal];$x=$m::PtrToStringAuto($m::SecureStringToBSTR($p));^
[Security.Cryptography.HashAlgorithm]::Create('MD5').ComputeHash([Text.Encoding]::UTF8.GetBytes($x)) ^| %%{write-host -n $_.tostring('x2')}""

for /f "usebackq delims=" %%I in (`%psCommand%`) do (
    waitfor /s %computername% /si PasswordEntered >NUL 2>NUL
    if "%%~I"=="5f4dcc3b5aa765d61d8327deb882cf99" goto :match
)

echo Nope.
goto :EOF

:match
echo w00!
goto :EOF
:: // END MAIN RUNTIME

:helper
>NUL 2>NUL (
    title Enter password.
    waitfor PasswordEntered /t 10 || taskkill /im "powershell.exe" /f
)
exit

If you'd rather not taskkill Powershell, it is possible to make read-host time out, but I'll leave that as an exercise for the reader.

Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101
  • This still is not secure, just obfuscated. I mean, the user can just edit the program to, for example, authenticate when the password is wrong... or delete the check for it altogether. If you used a better hashing algorithm, it would at least make it harder for a malicious user to compute an alternative password, but md5 is not good for this. It is much too fast. Don't get me wrong, there are some useful aspects to your post, but I don't think it solves the issue of storing/matching passwords in a batch program. – Gray Mar 23 '15 at 19:07
  • It doesn't solve, no, but it is an improvement over `if "%entry%"=="password"`. I doubt the OP will care, in any case. – rojo Mar 23 '15 at 19:12
  • I know they could just open with notepad and that's why I always convert files like that to .exe and save the .bat somewhere else. I'd like to just get answer directly to my question, not stuff I have my own answers to, so if you have a simpler way I'd like to know – elyazzi Mar 24 '15 at 16:24
0

You could start a VBS file with a password prompt. http://www.robvanderwoude.com/vbstech_ui_password.php

The link above links to a page with a password prompt script. You could add a timeout wich would wait for 10 seconds and then close.

Script_Coded
  • 709
  • 8
  • 21