[batch-file] bat 파일의 입력 텍스트를 마스킹 할 수 있습니까?

다른 프로그램을 실행하기 위해 배치 파일을 작성 중입니다. 이 경우 암호를 입력해야합니다. 입력 텍스트를 마스킹 할 방법이 있습니까? 입력 문자 대신 ******* 문자를 인쇄 할 필요가 없습니다. Linux의 암호 프롬프트 동작 (입력하는 동안 아무것도 인쇄하지 않음)이면 충분합니다.

@echo off
SET /P variable=Password :
echo %variable%
Pause

이것은 입력을 읽을 것이지만이 방법을 사용하여 텍스트를 마스크 할 수 없습니다.



답변

XP 및 Server 2003까지 포함 된 다른 도구 (VBScript)를 사용할 수 있습니다. 다음 두 스크립트가 원하는 작업을 수행합니다.

첫째, getpwd.cmd:

@echo off
<nul: set /p passwd=Password:
for /f "delims=" %%i in ('cscript /nologo getpwd.vbs') do set passwd=%%i
echo.

그런 다음 getpwd.vbs:

Set oScriptPW = CreateObject("ScriptPW.Password")
strPassword = oScriptPW.GetPassword()
Wscript.StdOut.WriteLine strPassword

getpwd.vbs단순히 암호 개체를 사용하여 사용자로부터 암호를 입력 한 다음이를 표준 출력으로 인쇄합니다 (다음 단락에서는 터미널에 표시되지 않는 이유를 설명합니다).

getpwd.cmd명령 스크립트는 조금 까다 롭습니다하지만 기본적으로 다음과 작동합니다.

"<nul: set /p passwd=Password: "명령 의 효과는 후행 개행 문자없이 프롬프트를 출력하는 것 입니다. "echo -n"이는 bash쉘 에서 명령 을 에뮬레이트하는 교활한 방법 입니다. passwd관련없는 부작용으로 빈 문자열로 설정 되며 nul:장치 에서 입력을 받기 때문에 입력을 기다리지 않습니다 .

"for /f "delims=" %%i in ('cscript /nologo getpwd.vbs') do set passwd=%%i"문은 까다로운 비트입니다. Microsoft “광고”없이 VBScript를 실행하므로 유일한 줄 출력은 암호 (VBscript "Wscript.StdOut.WriteLine strPassword".

공백이있는 전체 입력 행을 캡처하려면 구분 기호를 아무것도 설정하지 않아도됩니다. 그렇지 않으면 첫 번째 단어 만 표시됩니다. "for ... do set ..."비트 세트 passwdVBScript를 실제의 패스워드 출력한다.

그런 다음 빈 줄을 에코하고 (줄을 종료하기 위해 "Password: ") passwd코드가 실행 된 후 암호가 환경 변수에 있습니다.


이제 언급했듯이 scriptpw.dllXP / 2003까지만 사용할 수 있습니다. 이를 수정하기 위해 XP / 2003 시스템의 폴더에서 사용자 시스템 의 또는 폴더로 scriptpw.dll파일을 복사하면 됩니다 . DLL이 복사되면 다음을 실행하여 등록해야합니다.Windows\System32Winnt\System32Windows\System32

regsvr32 scriptpw.dll

Vista 이상에서 DLL을 성공적으로 등록하려면 관리자 권한이 필요합니다. 나는 그런 이동의 합법성을 조사하지 않았기 때문에 동굴 강사.


편의 또는 법적 이유로 오래된 DLL 파일을 추적하고 등록하는 데 지나치게 관심 이 없다면 다른 방법이 있습니다. 최신 버전의 Windows ( 필수 DLL 이없는 버전 )에는 Powershell을 사용할 수 있어야합니다.

그리고 실제로 스크립트를 완전히 사용하기 위해 스크립트를 업그레이드하는 것을 고려해야합니다 cmd.exe.. 그러나 코드의 대부분을 cmd.exe스크립트 로 유지하려는 경우 (예 : 변환하고 싶지 않은 코드가 많은 경우 ) 동일한 트릭을 사용할 수 있습니다.

먼저 cmdCScript가 아닌 Powershell을 호출하도록 스크립트를 수정합니다 .

@echo off
for /f "delims=" %%i in ('powershell -file getpwd.ps1') do set passwd=%%i

Powershell 스크립트도 똑같이 간단합니다.

$password = Read-Host "Enter password" -AsSecureString
$password = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$password = [Runtime.InteropServices.Marshal]::PtrToStringAuto($password)
echo $password

실제 암호 텍스트를 얻기 위해 약간의 마샬링이 있지만.

컴퓨터에서 서명되지 않은 로컬 Powershell 스크립트를 실행하려면 다음과 같이 (매우 안전하지만 매우 안전한) 기본값에서 실행 정책을 수정해야 할 수 있습니다.

set-executionpolicy remotesigned

Powershell 자체 내에서.


답변

예-4 년 늦었습니다.

하지만 외부 스크립트를 만들지 않고도 한 줄로이 작업을 수행 할 수있는 방법을 찾았습니다. 배치 파일에서 powershell 명령을 호출하여.

TessellatingHeckler 덕분에-텍스트 파일로 출력하지 않고 (for 루프 내에서 한 줄로 매우 지저분하기 때문에 powershell 명령을 변수에 설정했습니다).

@echo off
set "psCommand=powershell -Command "$pword = read-host 'Enter Password' -AsSecureString ; ^
    $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); ^
        [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)""
for /f "usebackq delims=" %%p in (`%psCommand%`) do set password=%%p
echo %password%

원래는 텍스트 파일로 출력하기 위해 작성한 다음 해당 텍스트 파일에서 읽었습니다. 그러나 위의 방법이 더 좋습니다. 매우 길고 거의 이해할 수없는 한 줄 :

@echo off
powershell -Command $pword = read-host "Enter password" -AsSecureString ; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword) ; [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) > .tmp.txt & set /p password=<.tmp.txt & del .tmp.txt
echo %password%

저는 이것을 분해 할 ^것입니다. caret를 사용하여 몇 줄로 나눌 수 있습니다. 훨씬 더 좋습니다 .

@echo off
powershell -Command $pword = read-host "Enter password" -AsSecureString ; ^
    $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword) ; ^
        [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) > .tmp.txt
set /p password=<.tmp.txt & del .tmp.txt
echo %password%

이 문서에서는 powershell 명령이 수행하는 작업을 설명합니다. 기본적으로 Read-Host -AsSecureString다음 두 줄은 보안 문자열을 다시 일반 텍스트로 변환하고 출력 (일반 텍스트 암호)은를 사용하여 텍스트 파일로 전송됩니다 >.tmp.txt. 그런 다음 해당 파일을 변수로 읽어서 삭제합니다.


답변

1. (ab) XCOPY명령과 /P /L스위치를 사용하는 순수 배치 솔루션여기 에서 찾을 수 있습니다 (이에 대한 일부 개선 사항은 여기에서 찾을있음 ).

:: Hidden.cmd
::Tom Lavedas, 02/05/2013, 02/20/2013
::Carlos, 02/22/2013
::https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/f7mb_f99lYI


@Echo Off
:HInput
SetLocal EnableExtensions EnableDelayedExpansion
Set "FILE=%Temp%.\T"
Set "FILE=.\T"
Keys List >"%File%"
Set /P "=Hidden text ending with Ctrl-C?: " <Nul
Echo.
Set "HInput="
:HInput_
For /F "tokens=1* delims=?" %%A In (
 '"Xcopy /P /L "%FILE%" "%FILE%" 2>Nul"'
) Do (
  Set "Text=%%B"
  If Defined Text (
    Set "Char=!Text:~1,1!"
    Set "Intro=1"
    For /F delims^=^ eol^= %%Z in ("!Char!") Do Set "Intro=0"
    Rem If press Intro
    If 1 Equ !Intro! Goto :HInput#
    Set "HInput=!HInput!!Char!"
  )
)
Goto :HInput_
:HInput#
Echo(!HInput!
Goto :Eof

1.2 대체 명령에 기반한 또 다른 방법

@Echo Off
SetLocal EnableExtensions EnableDelayedExpansion

Set /P "=Enter a Password:" < Nul
Call :PasswordInput
Echo(Your input was:!Line!

Goto :Eof

:PasswordInput
::Author: Carlos Montiers Aguilera
::Last updated: 20150401. Created: 20150401.
::Set in variable Line a input password
For /F skip^=1^ delims^=^ eol^= %%# in (
'"Echo(|Replace.exe "%~f0" . /U /W"') Do Set "CR=%%#"
For /F %%# In (
'"Prompt $H &For %%_ In (_) Do Rem"') Do Set "BS=%%#"
Set "Line="
:_PasswordInput_Kbd
Set "CHR=" & For /F skip^=1^ delims^=^ eol^= %%# in (
'Replace.exe "%~f0" . /U /W') Do Set "CHR=%%#"
If !CHR!==!CR! Echo(&Goto :Eof
If !CHR!==!BS! (If Defined Line (Set /P "=!BS! !BS!" <Nul
Set "Line=!Line:~0,-1!"
)
) Else (Set /P "=*" <Nul
If !CHR!==! (Set "Line=!Line!^!"
) Else Set "Line=!Line!!CHR!"
)
Goto :_PasswordInput_Kbd

2. HTA 팝업을 사용하는 비밀번호 제출자
. 이것은 hybrit .bat / jscript / mshta 파일이며 .bat 로 저장해야합니다 .

<!-- :
:: PasswordSubmitter.bat
@echo off
for /f "tokens=* delims=" %%p in ('mshta.exe "%~f0"') do (
    set "pass=%%p"
)

echo your password is %pass%
exit /b
-->

<html>
<head><title>Password submitter</title></head>
<body>

    <script language='javascript' >
        window.resizeTo(300,150);
        function entperPressed(e){
                if (e.keyCode == 13) {
                    pipePass();
                }
        }
        function pipePass() {
            var pass=document.getElementById('pass').value;
            var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
            close(fso.Write(pass));

        }
    </script>

    <input type='password' name='pass' size='15' onkeypress="return entperPressed(event)" ></input>
    <hr>
    <button onclick='pipePass()'>Submit</button>

</body>
</html>

3. 자체 컴파일 된 .net 하이브리드.bat . 다시. 로 저장해야합니다 . 다른 솔루션과 달리 호출 될 작은 .exe 파일을 생성 / 컴파일합니다 (원하는 경우 삭제할 수 있음). 또한 설치된 .net 프레임 워크가 필요하지만 이는 문제가되지 않습니다.

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal enableDelayedExpansion

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)

if not exist "%~n0.exe" (
    "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)

for /f "tokens=* delims=" %%p in ('"%~n0.exe"') do (
    set "pass=%%p"
)

echo your password is !pass!

endlocal & exit /b %errorlevel%

*/



import System;



var pwd = "";
var key;

Console.Error.Write("Enter password: ");

        do {
           key = Console.ReadKey(true);

           if ( (key.KeyChar.ToString().charCodeAt(0)) >= 20 && (key.KeyChar.ToString().charCodeAt(0) <= 126) ) {
              pwd=pwd+(key.KeyChar.ToString());
              Console.Error.Write("*");
           }

           if ( key.Key == ConsoleKey.Backspace && pwd.Length > 0 ) {
               pwd=pwd.Remove(pwd.Length-1);
               Console.Error.Write("\b \b");
           }


        } while (key.Key != ConsoleKey.Enter);
        Console.Error.WriteLine();
        Console.WriteLine(pwd);


답변

나는 아마도 다음과 같이 할 것입니다.

..
echo Before you enter your password, make sure no-one is looking!
set /P password=Password:
cls
echo Thanks, got that.
..

따라서 프롬프트가 표시되고 입력 후 화면이 지워집니다.

명령 프롬프트에서 배치 파일을 실행하면 입력 한 암호가 CMD 기록에 저장됩니다 ( @Mark K Cowan 에게 감사드립니다 ).

충분하지 않다면 파이썬으로 전환하거나 스크립트 대신 실행 파일을 작성했습니다.

나는 이것들 중 어느 것도 완벽한 soutions가 아니라는 것을 알고 있지만 아마도 하나는 당신에게 충분할 것입니다 🙂


답변

모든 종류의 형식화 된 입력에 ReadFormattedLine 서브 루틴을 사용할 수 있습니다. 예를 들어, 아래 명령은 8 자의 암호를 읽고 화면에 별표를 표시 한 다음 Enter 키를 누를 필요없이 자동으로 계속합니다.

call :ReadFormattedLine password="********" /M "Enter password (8 chars): "

이 서브 루틴은 순수 Batch로 작성되므로 추가 프로그램이 필요하지 않으며 숫자 만 읽기, 문자를 대문자로 변환 등과 같은 여러 형식화 된 입력 작업을 허용 합니다 . Read a line with specific format 에서 ReadFormattedLine 서브 루틴을 다운로드 할 수 있습니다 .


2018-08-18 수정 : “보이지 않는”비밀번호를 입력하는 새로운 방법

FINDSTR 명령에는이 명령을 사용하여 문자를 컬러로 표시하고 이러한 명령의 출력이 CON 장치로 리디렉션 될 때 발생하는 이상한 버그가 있습니다. FINDSTR 명령을 사용하여 텍스트를 색상으로 표시하는 방법에 대한 자세한 내용은 이 항목을 참조하십시오 .

이 형식의 FINDSTR 명령의 출력이 CON으로 리디렉션 될 때 텍스트가 원하는 색상으로 출력 된 후 이상한 일이 발생합니다. 더 정확한 설명은 텍스트가 다음과 같다는 것이지만 이후의 모든 텍스트는 “보이지 않는”문자로 출력됩니다. 검정 배경 위에 검정 텍스트로 출력합니다. COLOR 명령을 사용하여 전체 화면의 전경색과 배경색을 재설정하면 원본 텍스트가 나타납니다. 그러나 텍스트가 “보이지 않는”경우 SET / P 명령을 실행할 수 있으므로 입력 한 모든 문자가 화면에 나타나지 않습니다.

@echo off
setlocal

set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"


답변

또 다른 대안은 내 EditV32 (x86) 또는 EditV64 (x64) 명령 줄 도구입니다. 예를 들면 :

editv32 -m -p "Password: " PWD

-m은 “마스킹 된 입력”을 의미하고 -p는 프롬프트입니다. 사용자 입력은 PWD 환경 변수에 저장됩니다. 여기에서 얻을 수 있습니다.

https://westmesatech.com/?page_id=19


답변

소스 코드가 부족해서 귀찮다면 다른 대안이 있습니다.

@echo off
for /f "delims=" %%p in ('ReadLine -h -p "Enter password: "') do set PWD=%%p
echo You entered: %PWD%

https://westmesatech.com/?page_id=49 에서 얻을 수 있습니다 . 소스 코드가 포함되어 있습니다.