none
"call" in batch script removes characters from a variable... RRS feed

  • Question

  • Hello,

    I don't understand why the following batch :

    rem echo off
    setlocal
    set "u64=aDI0NDcxOQ=="
    call :atob usr %u64%
    pause
    goto :EOF
    :atob <var_to_set> <str>
    echo %~1 %~2
    goto :EOF

    removes the last 2 '=' characters as you can see with the following result :

    D:\TempProg>rem echo off
    D:\TempProg>setlocal
    D:\TempProg>set "u64=aDI0NDcxOQ=="
    D:\TempProg>call :atob usr aDI0NDcxOQ==
    D:\TempProg>echo usr aDI0NDcxOQ
    usr aDI0NDcxOQ
    D:\TempProg>goto :EOF
    What is the issue with "call" ?

    Tuesday, January 3, 2017 12:57 PM

Answers

  • As I said here, this Powershell script doesn't work. For the sake of completeness for this thread, here is a version of the batch that works :
    REM echo off
    setlocal
    set u64=aDI0NDcxOQ==
    call :atob usr "%u64%"
    schtasks /Run /S aaa.bbb.ccc.ddd /U %usr% /P toto /TN "My Scheduler Task Name"
    goto :EOF
    :atob <var_to_set> <str>
    for %%V in ("%~2") do for /f "delims=" %%I in ('
            powershell "[Text.Encoding]::UTF8.GetString([convert]::FromBase64String(\"%%~V\"))"
        ') do set "%~1=%%I"
    goto :EOF

    • Marked as answer by jmclej Thursday, January 5, 2017 4:12 PM
    Thursday, January 5, 2017 4:12 PM

All replies

  • rem echo off
    setlocal
    set u64=aDI0NDcxOQ==
    call :atob usr "%u64%"
    pause
    goto :EOF
    :atob <var_to_set> <str>
    echo %~1 %~2
    goto :EOF


    \_(ツ)_/

    • Marked as answer by jmclej Tuesday, January 3, 2017 2:31 PM
    • Unmarked as answer by jmclej Tuesday, January 3, 2017 5:57 PM
    Tuesday, January 3, 2017 2:11 PM
  • Great, thank you !

    But how come the '=' signs get removed when passed as a parameter...? Especially as I had already surrounded my set command with ""

    Tuesday, January 3, 2017 2:35 PM
  • Don't surround set commands with quotes.  == sign has special meaning and must be enclosed when passed.

    set name=value

    or

    set name="value"


    \_(ツ)_/

    Tuesday, January 3, 2017 2:41 PM
  • Actually I thought I had solved my issue but this is because I entered a lighter version of the batch, sorry... When I apply your correction to my whole batch, it still doesn't work. Here is the batch with your suggested correction :

    REM echo off
    setlocal
    set u64=aDI0NDcxOQ==
    call :atob usr "%u64%"
    schtasks /Run /S aaa.bbb.ccc.ddd /U %usr% /P toto /TN "My Scheduler Task Name"
    goto :EOF
    :atob <var_to_set> <str>
    for /f "delims=" %%I in (
    	'powershell "[Text.Encoding]::UTF8.GetString([convert]::FromBase64String(\"%~2\"))"'
    ) do set "%~1=%%I"
    goto :EOF

    Note as well that if I write set u64="aDI0NDcxOQ==", it doesn't work, so it seems to be different from set u64=aDI0NDcxOQ==

    The script gives the following output :

    C:\Users\lambda>REM echo off
    C:\Users\lambda>setlocal
    C:\Users\lambda>set u64=aDI0NDcxOQ==
    C:\Users\lambda>call :atob usr "aDI0NDcxOQ=="
    C:\Users\lambda>for /F "delims=" %I in ('powershell "[Text.Encoding]::UTF8.GetString([convert]::FromBase64String(\"aDI0NDcxOQ \"))"') do set "usr=%I"
    C:\Users\lambda>set "usr=Exception calling "FromBase64String" with "1" argument(s): "Longueur non "
    C:\Users\lambda>set "usr=valide pour un tableau de caractères Base 64 ou une chaîne.""
    C:\Users\lambda>set "usr=At line:1 char:1"
    C:\Users\lambda>set "usr=+ [Text.Encoding]::UTF8.GetString([convert]::FromBase64String("aDI0NDcxOQ "))"
    C:\Users\lambda>set "usr=+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
    C:\Users\lambda>set "usr=    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException"
    C:\Users\lambda>set "usr=    + FullyQualifiedErrorId : FormatException"
    C:\Users\lambda>set "usr= "
    C:\Users\lambda>goto :EOF
    C:\Users\lambda>schtasks /Run /S aaa.bbb.ccc.ddd /U   /P toto /TN "My Scheduler Task Name"
    Erreur : Syntaxe incorrecte. Valeur attendue pour '/U'.
    Entrez "SCHTASKS /RUN /?" pour afficher la syntaxe.
    C:\Users\lambda>goto :EOF

    I have tried /U "%usr%" instead of /U %usr% but it still doesn't work.

    Do you have any hints ?

    
    Tuesday, January 3, 2017 6:12 PM
  • I would recommend rewriting your script in PowerShell rather than fighting with cmd.exe batch.

    -- Bill Stewart [Bill_Stewart]

    Tuesday, January 3, 2017 6:29 PM
    Moderator
  • do set %~1=%%I

    \_(ツ)_/

    Tuesday, January 3, 2017 11:30 PM
  • Hello jrv,

    Thank you, I have tried to change to do set %~1=%%I but I still get the same error. Did the batch worked on your side ?

    The problem seems to occur before the call to the "do set" part as you can see that the argument of FromBase64String is already wrong.

    Wednesday, January 4, 2017 9:47 AM
  • Why do you think you need to do this?

    I cannot see where a base64 string is useful here.

    As noted above you should be using PowerShell.  Batch is nearly obsolete and will not be supported in future versions of Windows.  It is also much harder to do almost anything with  batch.


    \_(ツ)_/


    • Edited by jrv Wednesday, January 4, 2017 9:59 AM
    Wednesday, January 4, 2017 9:57 AM
  • Here is your batch in PowerShell.

    $u64='aDI0NDcxOQ=='
    $user = [Text.Encoding]::UTF8.GetString([convert]::FromBase64String($u64))
    schtasks /Run /S aaa.bbb.ccc.ddd /U $user /P toto /TN "My Scheduler Task Name"


    \_(ツ)_/


    • Edited by jrv Wednesday, January 4, 2017 10:04 AM
    Wednesday, January 4, 2017 10:03 AM
  • As I said here, this Powershell script doesn't work. For the sake of completeness for this thread, here is a version of the batch that works :
    REM echo off
    setlocal
    set u64=aDI0NDcxOQ==
    call :atob usr "%u64%"
    schtasks /Run /S aaa.bbb.ccc.ddd /U %usr% /P toto /TN "My Scheduler Task Name"
    goto :EOF
    :atob <var_to_set> <str>
    for %%V in ("%~2") do for /f "delims=" %%I in ('
            powershell "[Text.Encoding]::UTF8.GetString([convert]::FromBase64String(\"%%~V\"))"
        ') do set "%~1=%%I"
    goto :EOF

    • Marked as answer by jmclej Thursday, January 5, 2017 4:12 PM
    Thursday, January 5, 2017 4:12 PM
  • What is the purpose of encoding the username to pass to the schtasks command?

    Also, if you use PowerShell, it would be preferred to use the Task Scheduler cmdlets.


    -- Bill Stewart [Bill_Stewart]

    Thursday, January 5, 2017 5:13 PM
    Moderator
  • It is just a small security to prevent from somebody who would see the content of my file over the shoulder to know my username and password. Or that I could give it to a non IT guy without displaying directly my username/password.

    I all the time saw that in param files for instance, Base64 was used just to not display passwords too easily if you have to edit it often.

    Thursday, January 5, 2017 5:27 PM
  • Obfuscation is a dubious security measure, seeing as anyone can simply write


    [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("your string"))

    at a PowerShell prompt to see the resulting username. (And aside from that, they can see the username anyway by opening the Task Scheduler console, so I'm not sure what you gain by obfuscating it.)

    In any case, I would say that since you're using PowerShell to decode the string anyway, I would recommend that you simply write the whole script in PowerShell and dispense with the batch file altogether.


    -- Bill Stewart [Bill_Stewart]

    Thursday, January 5, 2017 5:51 PM
    Moderator
  • In my batch, I actually obfuscated my password, so while I was at it I obfuscated my username, that's why. I am aware of the easy way to revert to a readable string. But it won't be easy for the non-IT guys that I only have around me and they won't know of FromBase64String method plus they won't remember the base64 string just by having a glimpse potentially at my screen.

    To be honest the reason why I was using batch instead of Powershell is that I had never done any Powershell script before and that I have found parts of what I needed with batch, so I stuck to that. But I am also curious to know how to do it in Powershell, but don't really have the time as the batch in Powershell that was showned to me earlier in this thread is actually not working.

    
    Thursday, January 5, 2017 6:32 PM
  • It is an egregiously bad idea to store any kind of password in a batch file, even if obfuscated. You should definitely not do this under any circumstances.

    -- Bill Stewart [Bill_Stewart]

    Thursday, January 5, 2017 6:36 PM
    Moderator
  • It works perfectly:

    D:\scripts> $u64='aDI0NDcxOQ=='
    D:\scripts> $user = [Text.Encoding]::UTF8.GetString([convert]::FromBase64String($u64))
    D:\scripts> $user
    h244719
    D:\scripts>


    \_(ツ)_/

    Thursday, January 5, 2017 9:14 PM
  • Of course; that's what I was saying - it is trivial to un-obfuscate, and the OP says he is doing this to obfuscate a password in a batch file. This is an egregiously bad idea.

    -- Bill Stewart [Bill_Stewart]

    Thursday, January 5, 2017 9:18 PM
    Moderator