在Windows批处理中将HEX值写入文件

时间:2017-12-11 10:21:45

标签: batch-file binary hex

在Linux中我们可以做到

echo -n -e '\x66\x6f\x6f' > test.txt

将HEX值写入文件。

如何在Windows批处理中完成此操作?

2 个答案:

答案 0 :(得分:7)

我假设您希望能够在\ x00到\ xFF范围内编写所有可能的二进制字节。不幸的是,纯批次并没有提供一种简单的机制来实现这一点。

但是有很多选择并不太难。

未记录的!=ExitCodeASCII!动态变量

!=ExitCodeASCII!动态变量报告最近运行的外部命令的返回码的ASCII值。但它仅限于从\ x20到\ x7E的ASCII码。

我使用延迟扩展,这样我就不用担心毒药了。

返回特定错误代码的最简单机制是使用cmd /c exit N,其中N必须是十进制值。如果要传入十六进制值,则必须先将值转换为十进制。

Windows批处理使用0xNN表示法指定十六进制值。正如其他人所说,您可以使用set /a val=0x66进行转换。另一种选择是使用for /l %%N in (0x66 1 0x66) do ...,这样做的好处是您不需要定义一个中间环境变量来保存该值。

@echo off
setlocal enableDelayedExpansion
set "str="
for %%H in (0x66 0x6f 0x6f) do (
  for /l %%N in (%%H 1 %%H) do cmd /c exit %%N
  set "str=!str!!=ExitCodeASCII!"
)
>test.txt echo(!str!

优点:

  • 纯批次

缺点:

  • 必须一次构建一个字符串
  • 范围限制为0x20 - 0x7E

FORFILES

FORFILES命令支持0xNN语法,因此它可以生成大多数字符。但字符串必须通过CMD / C,因此它不能用于生成\ 0x00,\ 0x0A或\ 0x0D。 (我没有经过测试,但我相信所有其他价值观都有效,前提是毒药字符被适当引用或逃脱)

@echo off
forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x660x6f0x6f"

优点:

  • 纯批次
  • 可以一次处理整个字符串

缺点:

  • 没有本机XP支持
  • 不支持0x00,0x0A或0x0D
  • 逃避/引用毒药字符可能会非常棘手

CERTUTIL

CERTUTIL支持-decodeHex动词,它可以读取十六进制值并直接写入文件

@echo off
>temp.txt echo(66 6f 6f 0d 0a
certutil -f -decodehex temp.txt test.txt >nul
del temp.txt

优点:

  • 纯批次
  • 支持所有可能的字节代码
  • 绝对控制换行和回车
  • 可以一次处理整个字符串(或文件!)
  • 快速

缺点:

  • 需要临时文件

混合JScript /批处理 - 简单解决方案

在批处理脚本中嵌入和执行JScr​​ipt非常容易。 JScript具有解释许多转义序列的本机能力,包括\ xNN。但是,\ xNN转义序列实际上映射到Unicode代码点,因此某些高阶字节代码不会映射到正确的字符值。高阶字节的结果可能因机器的默认字符集而异。

下面我定义一个:jWrite子例程,它可以写入带有嵌入转义序列的行。如果要编写没有换行符的字符串,只需将J WriteLine更改为Write

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
:: -------- Batch code --------------
@echo off
call :jWrite "\x66\x6f\x6f" >test.txt
exit /b

:jWrite
cscript.exe //E:JScript //nologo "%~f0" %1
exit /b
:: --------- JScript code -----------*/
WScript.StdOut.WriteLine(eval('"'+WScript.Arguments.Unnamed(0)+'"'));

优点:

  • 从XP开始在所有Windows机器上本机运行的纯脚本
  • 非常简单的JScript代码
  • 可以一次处理整个字符串
  • 许多其他可用的转义序列,例如\\\t\r\n等。
  • 易于将普通文本与转义序列混合,但双引号必须为\x22

缺点:

  • 并非所有高阶字节都能提供正确的结果
  • 结果取决于您机器的默认字符集。最好的Windows 1252

混合JScript /批处理 - 更强大但更复杂的解决方案

只要您的机器默认为Windows-1252,编写一些JScript代码来正确解释所有\ xNN代码以提供正确的字节并不困难。如果您的命令会话的活动代码页也与Windows 1252匹配,那么您可以在普通文本中自由混合。

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment
:: -------- Batch code --------------
@echo off
call :jWrite "\x66\x6f\x6f"
call :jWrite "Hello\nworld\x80"
exit /b

:jWrite
cscript.exe //E:JScript //nologo "%~f0" %1
exit /b
:: --------- JScript code -----------*/
WScript.StdOut.WriteLine(WScript.Arguments.Unnamed(0).replace(
  /\\(\\|b|f|n|r|t|v|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/g,
  function($0,$1) {
    switch ($1.toLowerCase()) {
      case 'x80': return '\u20AC';
      case 'x82': return '\u201A';
      case 'x83': return '\u0192';
      case 'x84': return '\u201E';
      case 'x85': return '\u2026';
      case 'x86': return '\u2020';
      case 'x87': return '\u2021';
      case 'x88': return '\u02C6';
      case 'x89': return '\u2030';
      case 'x8a': return '\u0160';
      case 'x8b': return '\u2039';
      case 'x8c': return '\u0152';
      case 'x8e': return '\u017D';
      case 'x91': return '\u2018';
      case 'x92': return '\u2019';
      case 'x93': return '\u201C';
      case 'x94': return '\u201D';
      case 'x95': return '\u2022';
      case 'x96': return '\u2013';
      case 'x97': return '\u2014';
      case 'x98': return '\u02DC';
      case 'x99': return '\u2122';
      case 'x9a': return '\u0161';
      case 'x9b': return '\u203A';
      case 'x9c': return '\u0153';
      case 'x9d': return '\u009D';
      case 'x9e': return '\u017E';
      case 'x9f': return '\u0178';
      default:    return eval('"'+$0+'"');
    }
  }
));

优点:

  • 从XP开始在所有Windows机器上本机运行的纯脚本
  • 可以一次处理整个字符串
  • 支持从\ x00到\ xFF的所有字节代码
  • 许多其他可用的转义序列,例如\\\t\r\n等。
  • 易于将普通文本与转义序列混合,但双引号必须为\x22

缺点:

  • 如果您的计算机默认为Windows-1252
  • ,则仅为所有字节提供正确的结果
  • 中等复杂的JScript代码

JREPL.BAT - 混合JScript /批处理正则表达式文本处理实用程序

我的JREPL.BAT utility最初设计用于对文本文件执行正则表达式搜索和替换操作。但它有一些选项可以让它轻松编写带有嵌入式转义序列的字符串,并且无论机器使用什么默认字符集,它都可以为所有字节代码提供正确的结果。

如果您的机器默认使用任何单字节字符集,那么您可以安全地使用以下所有可能的转义序列,从\ x00到\ xFF,您可以在正常文本和转义序列中自由混合。

call jrepl $ "\x66\x6f\x6f" /s "=" /x /o test.txt

/s "="选项将未定义的环境变量指定为输入源,将其解释为空字符串。第一个$参数匹配空字符串的结尾。第二个"\x66\x6f\x6f"参数指定替换值。 /x选项在替换字符串中启用转义序列,/o test.txt选项指定输出文件。

如果要附加到test.txt,请添加/APP选项。

如果你想要\ n行结束而不是\ r \ n,(Unix风格而不是Windows),那么添加/U选项

如果您不想要任何新的行终止符,请添加/M选项。

最后,如果您的机器没有默认为单字节字符集,您仍然可以通过为输出格式指定单字节字符集(如Windows-1252)来强制所有转义序列的正确结果。但是,如果指定的字符集与命令会话的活动代码页不匹配,则只保证转义序列有效 - 某些正常的文本字符可能会产生错误的结果。

call jrepl $ "\x66\x6f\x6f" /s "=" /x /o "test.txt|Windows-1252"

优点:

  • 从XP开始在任何Windows机器上运行的纯脚本
  • 可以一次处理整个字符串
  • 支持从\ x00到\ xFF的所有字节代码
  • 许多其他可用的转义序列,例如\\\t\r\n等。
  • 简单地将普通文本与转义序列混合,但双引号必须为\x22\q
  • 默认字符集不可知 - 始终可以提供正确的结果
  • 一旦你的工具库中有JREPL,你会发现它有很多用途。它是一个强大的工具。

缺点:

  • 需要下载第三方脚本

答案 1 :(得分:0)

要写入“十六进制值到文件”:

toMap(t -> t.to, t -> t,
                (x, y) -> y, () -> new EnumMap<>(Phase.class))));

要使用所有值从批处理创建二进制文件,请参见此处:
https://www.dostips.com/forum/viewtopic.php?f=3&t=5326

set a=. for /l %a in (0,1,255) do ( set /a dec=%a >nul call cmd /c exit /b !dec! set hex=!=exitcode! set a=!a! !hex:~-2! ) echo %a:~2% > file.txt 可以同时执行以下操作:从二进制文件创建十六进制文件,并从十六进制编码文件创建二进制文件:

certutil

要从CMD写入具有给定(已解码)十六进制值字节的二进制文件:

certutil -f -decodeHex hex.txt out.bin >nul
certutil -f -encodeHex out.bin out.txt >nul

如果您刚写完可打印的字符(从0x20到0x7E),那么set data="66 6F 6F" echo Dim File : Set File = CreateObject("Scripting.FileSystemObject").CreateTextFile("test.txt") > tmp.vbs echo data = %data% >> tmp.vbs echo data = Split (data) >> tmp.vbs echo for each x in data >> tmp.vbs echo File.write chr("&H" ^& x) >> tmp.vbs echo next >> tmp.vbs echo File.Close >> tmp.vbs cscript //nologo tmp.vbs 是一个好/更快的(批处理)解决方案。