Multiple Echo statements within a Code Block crashing cmd.exe

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Multiple Echo statements within a Code Block crashing cmd.exe

#1 Post by Squashman » 17 Oct 2018 12:14

I am running into case where cmd.exe is crashing and I think it is because I have too much code within a code block that is redirecting to a file.

Code: Select all

(
echo line1
echo line2
rem I am actually echoing over 13,700 lines that are 64 bytes each.
)>decode.tmp
I am using batch file to encode a file using certutil and it in turn creates another batch file to do the decoding. I think I got from Foxidrive or someone else here.
The executable I am encoding is only 644 bytes but when you run it through certutil it creates over 13,700 encoded lines.

Code: Select all

@echo off
set suffix=create.bat
if "%~1"=="" (
  echo( Syntax: "%~0" "filename.mp3"
  echo( to encode the filename.mp3 into a filename.%suffix% batch script
  echo( - any filetype can be encoded into a batch script, even another .bat file
  echo(
  pause & goto :EOF
  )
echo(creating "%~n1.%suffix%"
certutil /encode /f "%~1" "encode.tmp"
find /v /i "CERTIFICATE---" <"encode.tmp" >"encode.tm"
(
echo @echo off
echo if not exist "%~nx1" (
echo echo creating "%~nx1"
echo (
for /f "usebackq delims=" %%a in ("encode.tm") do echo echo %%a
echo ^)^>"decode.tmp"
echo certutil /decode /f "decode.tmp" "%~nx1" ^>nul
echo del "decode.tmp"
echo ^)
)>"%~n1.%suffix%"
del "encode.tm*"
I ended up changing it to use a FOR command to iterate all the lines. But it takes almost 10 seconds to recreate the executable.

Code: Select all

@echo off
set suffix=create.bat
if "%~1"=="" (
  echo( Syntax: "%~0" "filename.mp3"
  echo( to encode the filename.mp3 into a filename.%suffix% batch script
  echo( - any filetype can be encoded into a batch script, even another .bat file
  echo(
  pause & goto :EOF
  )
echo(creating "%~n1.%suffix%"
certutil /encode /f "%~1" "encode.tmp"
find /v /i "CERTIFICATE---" <"encode.tmp" >"encode.tm"
(
echo @echo off
echo if not exist "%~nx1" (
echo echo creating "%~nx1"
echo (
echo FOR %%%%G IN (
for /f "usebackq delims=" %%a in ("encode.tm") do echo "%%a"
echo ^) DO echo %%%%~G
echo ^)^>"decode.tmp"
echo certutil /decode /f "decode.tmp" "%~nx1" ^>nul
echo del "decode.tmp"
echo ^)
)>"%~n1.%suffix%"
del "encode.tm*"
The executable I am testing with is SFK

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#2 Post by dbenham » 17 Oct 2018 12:37

I suspect it has nothing to do with ECHO or redirection, but rather has to do with a maximum code block size, whether it be lines or bytes. I don't know that such a limit exists. But remember that the entire code block must be parsed all at once and the result stored in memory, so it makes sense that there would be a limit.

Currently the dynamically generated code has the form:

Code: Select all

(
echo line1
echo line2
...
echo linen
)>decode.tmp
I predict the following structure would eliminate the size limit:

Code: Select all

call :makeDecode >decode.tmp
...
exit /b

:makeDecode
echo line1
echo line2
...
echo linen
exit /b
Such a change shouldn't be too hard to implement.


Dave Benham

Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#3 Post by Squashman » 17 Oct 2018 12:44

Thanks Dave,
I will test that to see if it is faster then using the FOR command.

Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#4 Post by Squashman » 17 Oct 2018 13:04

Just testing some more with the original code. This time I first made a cab file of the executable and then ran certutil on the cab file. That brought it down to 5,951 lines. So that makes each line with the CRLF 71 bytes long. That is only 422,521 bytes. I find it hard to believe it can't handle that much data within a code block.

Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#5 Post by Squashman » 17 Oct 2018 13:40

The amount of data seems to be sporadic on what it can handle. I tested 5338 lines with echoing 64 bytes and it worked. I then added one line and it didn't work. I then put it back to 5338 lines and it didn't work. Making no sense to me. I then subtracted one byte from the last line and it worked.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#6 Post by dbenham » 17 Oct 2018 14:31

Have you tried the called :proc technique instead of the code block?

Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#7 Post by Squashman » 17 Oct 2018 14:40

dbenham wrote:
17 Oct 2018 14:31
Have you tried the called :proc technique instead of the code block?
Yes that works fine. I just wanted to see what the code block limit was. It seems rather small if it is dying at 378,927 bytes inside the code block.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#8 Post by dbenham » 17 Oct 2018 15:07

Perhaps the code block limit is not a constant. It could depend on available memory, .... ? I remember that the stack size limit for the total number of CALLs is also unpredictable.

How is the called :proc performance compared to the FOR performance?

Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#9 Post by Squashman » 17 Oct 2018 15:13

dbenham wrote:
17 Oct 2018 15:07
How is the called :proc performance compared to the FOR performance?
80% quicker!!!

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Multiple Echo statements within a Code Block crashing cmd.exe

#10 Post by dbenham » 19 Oct 2018 15:18

Here is a really simple script that uses CERTUTIL to encode any binary file as base64 and then embeds that into a batch file that will recreate the original file when run.

The resultant batch file is only ~1.4 times the original binary size, and both the encode and decode operations are very fast.

encodeBin.bat

Code: Select all

@echo off
certutil -f -encodehex %1 "%~1.dat" 1 >nul
findstr /bc:"  " "%~f0" >"%~1.create.bat"
type "%~1.dat" >>"%~1.create.bat"
del "%~1.dat"
echo Created "%~1.create.bat"
exit /b
=== decode script ====
  @echo off
  for %%F in ("%~dpn0") do (
    findstr /vbc:"  " "%~f0" >"%%~dpnF.dat"
    certutil -f -decode "%%~dpnF.dat" "%%~dpnF" >nul
    del "%%~dpnF.dat"
    echo Created "%%~dpnF"
  )
  exit /b
For example encodeBin myBinary.exe will create "myBinary.exe.create.bat"

If you then execute myBinary.exe.create it will recreate the original "myBinary.exe"

If you prefer, the encodeBin script could be modified to embed the original binary name in the resultant create batch, so then the name of the create batch is not important.


Dave Benham

Post Reply