Search code examples
windowscmdbinarywritefile

How to write binary file from hex string in Windows command prompt


I want to make binary executable file from hex string in windows cmd. I used "echo" cmd command but it is written in normal string, not binary format. So output exe file could not be executed.

input: "\x4d\x5a\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\..." (this is first part of PE)
output: binary executable file

Is it possible in windows cmd? If possible, please help me. Thanks in advance.


Solution

  • Yes, there is a way: there is the tool named CertUtil.exe (available since Windows XP, though some verbs may have been altered), which features a verb called -decodehex (for the optional parameter type take a look at the argument dwFlags of the function CryptBinaryToStringA):

    Usage:
      CertUtil [Options] -decodehex InFile OutFile [type]
      Decode hexadecimal-encoded file
        type -- numeric CRYPT_STRING_* encoding type
    [...]
    

    However, this does not understand the hex codes of your input data, the \x need to be removed.


    The following script reads your input hex string from a file, replaces every \x by a SPACE in a temporary file and converts this to a binary file using certutil -decodehex:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    
    rem // Define constants here:
    set "_INPF=%~1" & rem // (input file; `%~1` is first command line argument)
    set "_OUTF=%~2" & rem // (output file; `%~2` is second command line argument)
    set "_TMPF=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (temporary file)
    
    rem // Prepare input file by replacing `\x` with ` ` and writing result to temp. file:
    < nul set /P ="Preparing data... "
    < "%_INPF%" > "%_TMPF%" call :PREPARE
    echo done.
    rem // Convert temporary file with hex codes into binary output file:
    certutil -f -v -decodehex "%_TMPF%" "%_OUTF%" 4
    rem // Clean up temporary file:
    del "%_TMPF%"
    
    endlocal
    exit /B
    
    
    :PREPARE
        setlocal EnableDelayedExpansion
        rem // Initialise auxiliary variables:
        set "REST="
        rem /* Read input file in chunks of 1 KBytes using `set /P`; `for /F` is avoided
        rem    for reading the file, because it would limit line lengths to 8 KBytes: */
    :PREPARE_LOOP
        rem // Read a chunk or line of hex codes:
        set "LINE=" & set /P LINE=""
        rem // Read chunk is empty, hence end of data is reached, so terminate loop:
        if not defined LINE goto :PREPARE_NEXT
        rem // Prepend potential fragment from previous chunk:
        set "LINE=!REST!!LINE!" & set "REST="
        rem // Now replace every `\x` by ` `:
        set "LINE=!LINE:\x= !"
        rem // Store remaining fragment of search string to be processed with next chunk:
        if "!LINE:~-1!"=="\" (set "LINE=!LINE:~,-1!" & set "REST=\")
        rem /* Return converted chunk without trailing line-break in order to avoid hex
        rem    codes to become torn apart: */
        < nul set /P ="!LINE!"
        rem // Loop back at this point:
        goto :PREPARE_LOOP
    :PREPARE_NEXT
        endlocal
        exit /B
    

    Note that certutil limits file sizes to a few dozens of MBytes (as also mentioned here).