Page 1 of 1

Creating .EXE auxiliary programs in Batch files

Posted: 14 Apr 2012 21:40
by Aacini
NOTE: If you want to convert a filename.exe.hex file to filename.exe, just copy both HexToBin.bat and HexChar.vbs files below, and type: hextobin filename.exe.hex
__________________________________________________________________________________

I used to write small programs in assembly language as aid for Batch files. I prefer the .COM format because it is the most compact form of executable files and they can be directly inserted in a Batch file as a string of ASCII characters; I have posted several of them in this forum. However, .COM format files can not be used in 64-bits versions of Windows, so these programs have a somewhat limited use.

Although an assembly program may also generate an .EXE file, this format have some disadvantages for this purpose. .EXE files are longer than .COM ones and include control characters that can not be easily changed like in a .COM file. To distribute an .EXE program in a Batch file, a different method to create it is needed. I devised a method to convert the .EXE into an ASCII representation via Hexadecimal digits (that I borrowed from this post: w w w . dostips.com/forum/viewtopic.php?f=3&t=3089&p=14361#p14361), and then convert back the Hex digits into the .EXE. First conversion can be achieved via a Batch file, but the problem here is the opposite conversion that can NOT be directly done with original CMD Batch commands (as far as I know).

This problem may be solved via a VBS script like this one: w w w . dostips.com/forum/viewtopic.php?f=3&t=3143&p=14704#p14704, but it is a little cumbersome to use Batch for one part of the conversion and VBS for the other one because the complete solution can be written in VBS. On the other hand, VBS script facility is not installed in every machine, so this solution would have a limited use again. Another possible solution is achieve the Hex-to-Exe conversion via an auxiliary assembly program that would be faster and much convenient, but the problem here is the classical chicken-and-egg dilemma: How to create an .EXE auxiliary file if we have not an .EXE auxiliary file designed to create such files? The only solution I devised is this one (any additional suggestion is welcome): use a VBS script to create the first .EXE auxiliary Hex-to-Exe program, so any posterior auxiliary program will be created using that file. If you have not VBS scripting installed in your machine, you need to run the Batch file below in another machine with VBS support and then copy the HexChar.exe resulting file to your computer.

This is HexToBin.bat:

Code: Select all

@echo off

REM Convert a *.ext.hex file created by BINTOHEX.BAT to binary *.ext
REM Antonio Perez Ayala - Apr/14/2012

if "%~1" == "" echo HEXTOBIN File&echo/&echo Convert a *.ext.hex file created by BINTOHEX.BAT to *.ext binary&goto :EOF
set "inFile=%~1"
if not exist "%inFile%" echo File not found: %1& goto :EOF
set "outFile=%~N1"
if exist HexChar.exe (
   HexChar.exe < "%inFile%" > "%outFile%"
) else (
   Cscript /B /E:VBS HexChar.vbs < "%inFile%" > "%outFile%"
)
echo %outFile% file created

This is HexChar.vbs:

Code: Select all

Rem Hex digits to Ascii Characters conversion
Rem Antonio Perez Ayala - Apr/14/2012

Dim line,index,count
line = WScript.StdIn.ReadLine()
While line <> ""
   index = 1
   While index < len(line)
      If Mid(line,index,1) = "[" Then
         index = index+1
         count = 0
         While Mid(line,index+count,1) <> "]"
            count = count+1
         WEnd
         For i=1 To Int(Mid(line,index,count))
            WScript.StdOut.Write Chr(0)
         Next
         index = index+count+1
      Else
         WScript.StdOut.Write Chr(CByte("&H"&Mid(line,index,2)))
         index = index+2
      End If
   WEnd
   line = WScript.StdIn.ReadLine()
WEnd

This is HexChar.exe.hex:

Code: Select all

4D5A27000300010020[3]FFFF[3]01[4]19003E[3]0100FB306A72[28]010019[847]B810008ED8FC33F6E857003C5B752033C9BB0A00E8
4B003C5D740A250F0091F7E303C8EBEF32D2B402CD21E2FAEBD92C303C0976082C073C0F76022C20C0E0048AD0E81D002C30
3C0976082C073C0F76022C2002D0B40280FA097502B406CD21EBA6AC0AC07521535152BB[2]B9800033D2B43FCD2172190BC0
74155A595B8BF0C6040033F6EBDA3C3072D63C6677D2C332C0B44CCD21

This way, to create the HexChar.exe file execute this line:

Code: Select all

hextobin hexchar.exe.hex

Note that HexToBin.bat file test if HexChar.exe file not exist to use HexChar.vbs instead; you may eliminate the IF in this file after creating HexChar.exe to make it faster.

HexToBin.bat file is currently used to create these auxiliary programs:

- ColorMsg: Show a message in the screen in any color.

As soon as possible I will write .exe.hex versions to also create these auxiliary programs (more coming soon):

- w w w . dostips.com/forum/viewtopic.php?f=3&t=2800 - TypeOfHandle: Detect redirection and EOF in standard handles.
- w w w . dostips.com/forum/viewtopic.php?f=3&t=2823 - SetFilePointer: Read/write redirected input/output files in any order; this program allows to develop a basic Relational Data Base: w w w . dostips.com/forum/viewtopic.php?f=3&t=3126

Just to complete this topic, below is the BinToHex.bat file you must use in case you want to encode your own files; note that this method works with any type of file and is very efficient with large groups of zeros (like those in .EXE files). You need to have admin credentials to run this file (because the FSUTIL command):

Code: Select all

@echo off 

REM Convert any file to HEX representation in ASCII
REM Antonio Perez Ayala - Apr/14/2012

if "%~1" == "" echo BINTOHEX File&echo/&echo Convert any File to ASCII Hex code&goto :EOF
setlocal EnableDelayedExpansion
set "inFile=%~1"
if not exist "%infile%" echo File not found: %1& goto :EOF
set "outFile=%~1.hex"
set "tempFile=%temp%\#.tmp"
del "%tempFile%" 2>NUL
fsutil file createnew "%tempFile%" %~Z1 >NUL || echo Error in creating temporary file&& goto :EOF
set /A a=0, d=0
(
   for /F "skip=1 tokens=1,2 delims=: " %%b in ('fc /B "%inFile%" "%tempFile%"') do (
      set /A b=0x%%b
      if !a! neq !b! (
         set /A c=b-a, d+=1
         if !c! equ 1 (
            set /P "=00" <NUL
         ) else (
            set /P "=[!c!]" <NUL
         )
      )
      set /P "=%%c" <NUL
      set /A a=b+1, d+=1
      if !d! geq 50 set d=0& echo/
   )
   if !a! neq %~Z1 (
      set /A c=%~Z1-a
      set /P "=[!c!]" <NUL
   )
   echo/
) > "%outfile%"
echo %outfile% file created
del "%tempFile%"


Antonio

Re: Creating .EXE auxiliary programs in Batch files

Posted: 15 Apr 2012 02:25
by foxidrive
Aacini wrote:the complete solution can be written in VBS. On the other hand, VBS script facility is not installed in every machine, so this solution would have a limited use again.


WSH is a standard part of every machine from XP onwards I think, and it is an optional install from Win9x, so it's probably fair in this age to use a VBS solution.

Some businesses may lock down WSH but then those machines are crippled even further.

Re: Creating .EXE auxiliary programs in Batch files

Posted: 03 Nov 2012 19:15
by Ed Dyreen
'
Hey tooSimple :D

I had to reWrite both 'HexToBin.CMD' and 'HexChar.VBS' to get it working on XP :o

HexToBin.CMD: on XP the active directory is !userProfile! when using drag'n drop hence absolute paths are required.

Code: Select all

@echo off &title %~n0
:: ------------------------------------------------------------------------------------------------------------
:: hexToBin                                                                                                   -
:: ------------------------------------------------------------------------------------------------------------
:: (
::   Converts from .HEX to .COM
::
::   Drag'n drop file to convert.
::
::   supported platforms: x86 ( winXP and up )
::   dependencies       : hexChar.VBS
::   last updated       : 2012^11^02
::   programmer         : Antonio Perez Ayala - 2012^04^14
::                        tooComplex     - 2012^11^02
:: )
:: ------------------------------------------------------------------------------------------------------------

:: ------------------------------------------------------------------------------------------------------------
:§init ( paramRAW )
:: ------------------------------------------------------------------------------------------------------------
:: last updated       : 2012^11^02
::
setlocal enableExtensions disableDelayedExpansion %=         special chars are supported in disableDelayed   =%
:: (
   set /a $err = 0
   ::
   (set $=%*)
   ::
   if not defined $ (

      echo. &<nul set /p "= hexToBin.CMD"
      echo. &<nul set /p "= "
      echo. &<nul set /p "=  Converts from .HEX to .COM"
      echo. &<nul set /p "= "
      echo. &<nul set /p "=  Drag'n drop file to convert."

   ) else    call :§main "%$%" ^!
::
endlocal &ping /n 4 0.0.0.0 >nul 2>&1 &exit %$err%
:: ------------------------------------------------------------------------------------------------------------
:skip ()
::
goto :skip "()"
pause
exit
:: ------------------------------------------------------------------------------------------------------------
:§main ( #$iFile )
:: ------------------------------------------------------------------------------------------------------------
:: last updated       : 2012^11^02
:: language dependant : no
:: supported languages: N/A
::
setlocal enableDelayedExpansion
:: (
   set "$hexChar.fileName=%~dp0hexChar"
   set       "$iFile=%~f1"
   set       "$oFile=%~dpn1.COM"

   del /f /q "%$oFile%" 2>nul &if exist "!$hexChar.fileName!.EXE" (
      ::
      "!$hexChar.fileName!.EXE" < "%$iFile%" > "%$oFile%"

   ) else (

      echo.
      echo. ^< '!$iFile!'
      echo.  cScript.EXE //noLogo /e:VBS '!$hexChar.fileName!.VBS'
      ::
      < "!$iFile!" (

         cScript.EXE //noLogo /e:VBS "!$hexChar.fileName!.VBS" ||(
            ::
            set /a $err = !errorLevel!
         )

      ) > "!$oFile!"
      ::
      echo. ^> '!$oFile!' [error:!$err!]
      ::
      if !$err! neq  0 ( pause )
   )
:: )
endlocal &exit /b %$err%
:: ------------------------------------------------------------------------------------------------------------
:skip ()
::
goto :skip "()"
pause
exit
HexChar.VBS: I prefer to handle non-fatal errors 'end of stream' where you suppress them for simplicity's sake ( just a matter of taste ) :wink:

Code: Select all

' Converts from .HEX to .COM
' Antonio Perez Ayala - 2012^04^14
' tooComplex          - 2012^11^02

' init ()
'(
   Dim line, index, count
')

' main ()
'(
   On Error Resume Next
   '
   While 1
      '
      line = WScript.StdIn.ReadLine()
      '
      If Err.Number = 0 Then
         '
         index = 1
         '
         While index < len( line )
            '
            If Mid( line, index, 1 ) = "[" Then
               '
               index = index + 1
               count = 0
               While Mid( line, index + count, 1 ) <> "]"
                  '
                  count = count + 1
                  '
               WEnd
               For i=1 To Int( Mid( line, index, count ) )
                  '
                  WScript.StdOut.Write Chr(0)
                  '
               Next
               index = index + count + 1
               '
            Else
               '
               WScript.StdOut.Write Chr( CByte( "&H" &Mid( line, index, 2 ) ) )
               index = index + 2
               '
            End If
            '
         WEnd
         '
      Else
         '
         WScript.Quit
         '
      End If
   '
   WEnd
')
later :wink:

Re: Creating .EXE auxiliary programs in Batch files

Posted: 19 Dec 2012 18:42
by carlos
Aacini I read this post. And I found in bintohex.cmd a little bug. If the file to convert have only NUL characters the .hex output file is wrong. This is my fix:

BinToHex.bat

Code: Select all

@echo off

REM Convert any file to HEX representation in ASCII
REM Antonio Perez Ayala - Apr/14/2012
REM Carlos - Dec/19/2012 (Fixed for convert files with only NUL characters)

if "%~1" == "" echo BINTOHEX File&echo/&echo Convert any File to ASCII Hex code&goto :EOF
setlocal EnableDelayedExpansion
set "inFile=%~1"
if not exist "%infile%" echo File not found: %1& goto :EOF
set "outFile=%~1.hex"
set "tempFile1=%temp%\#.tmp"
set "tempFile2=%temp%\##.tmp"
del "%tempFile1%" "%tempFile2%" 2>NUL
fsutil file createnew "%tempFile1%" %~Z1 >NUL || echo Error in creating temporary file&& goto :EOF
fc /B "%inFile%" "%tempFile1%" > "%tempFile2%"
if errorlevel 1 (
(
   set /A a=0, d=0
   for /F "skip=1 tokens=1,2 delims=: " %%b in ('type "%tempFile2%"') do (
      set /A b=0x%%b
      if !a! neq !b! (
         set /A c=b-a, d+=1
         if !c! equ 1 (
            set /P "=00" <NUL
         ) else (
            set /P "=[!c!]" <NUL
         )
      )
      set /P "=%%c" <NUL
      set /A a=b+1, d+=1
      if !d! geq 50 set d=0& echo/
   )

   if !a! neq %~Z1 (
      set /A c=%~Z1-a
      set /P "=[!c!]" <NUL
   )
   echo/
) > "%outfile%"
) else (
set /P "=[%~Z1]" <NUL >"%outfile%"
)
echo %outfile% file created
del "%tempFile1%" "%tempFile2%"