web-dev-qa-db-ja.com

WindowsバッチでファイルにHEX値を書き込む

Linuxでできること

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

hEX値をファイルに書き込む。

これをWindowsバッチで簡単に行うにはどうすればよいですか?

5
arminb

\ x00から\ xFFの範囲のすべての可能なバイナリバイトを書き込む機能が必要だと想定しています。残念ながら、純粋なバッチはこれを行う簡単なメカニズムを提供していません。

しかし、それほど難しくないオプションがいくつかあります。

文書化されていない_!=ExitCodeASCII!_動的変数

_!=ExitCodeASCII!_動的変数は、最後に実行された外部コマンドの戻りコードのASCII値を報告します。ただし、ASCII\x20〜\ x7E。

ポイズンキャラクターを気にする必要がないように、遅延展開を使用しています。

特定のエラーコードを返す最も簡単なメカニズムは、_cmd /c exit N_を使用することです。ここで、Nは10進値でなければなりません。 16進値を渡す場合は、値を最初に10進数に変換する必要があります。

Windowsバッチは0xNN表記を使用して16進値を指定します。他の人が指摘したように、_set /a val=0x66_を使用して変換を行うことができます。もう1つのオプションは、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!
_

利点:

  • 純粋なバッチ

欠点:

  • 一度に1文字ずつ文字列を作成する必要があります
  • 範囲は0x20-0x7Eに制限されています

プロフィール

FORFILESコマンドは0xNN構文をサポートしているため、ほとんどの文字を生成できます。ただし、文字列はCMD/Cを通過する必要があるため、\ 0x00、\ 0x0A、または\ 0x0Dの生成には使用できません。 (私はテストしていませんが、毒文字が適切に引用またはエスケープされていれば、他のすべての値が機能すると思います)

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

利点:

  • 純粋なバッチ
  • 文字列全体を1回のパスで処理できます

欠点:

  • ネイティブXPサポートなし
  • 0x00、0x0A、または0x0Dはサポートされていません
  • 毒文字のエスケープ/引用は注意が必要です

サーティティル

CERTUTILは、16進値を読み取り、ファイルに直接書き込むことができる-decodeHex verbをサポートします

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

利点:

  • 純粋なバッチ
  • サポートされるすべての可能なバイトコード
  • 改行と改行の絶対的な制御
  • 文字列全体(またはファイル!)を1回のパスで処理できます
  • 速い

欠点:

  • 一時ファイルが必要です

ハイブリッドJScript /バッチ-シンプルなソリューション

JScriptをバッチスクリプト内に埋め込み、実行するのは非常に簡単です。また、JScriptには、\ xNNを含む多くのエスケープシーケンスを解釈するネイティブ機能があります。ただし、\ xNNエスケープシーケンスは実際にはUnicodeコードポイントにマップされるため、一部の上位バイトコードは正しい文字値にマップされません。また、上位バイトの結果は、マシンのデフォルトの文字セットによって異なる場合があります。

以下に、エスケープシーケンスが埋め込まれた行を記述できる:jWriteサブルーチンを定義します。改行文字なしで文字列を記述したい場合は、JScriptコードでWriteLineWriteに変更するだけです。

_@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コード
  • 1回のパスで文字列全体を処理できます
  • _\\_、_\t_、_\r_、_\n_など、利用可能な他の多くのエスケープシーケンス.
  • 通常のテキストとエスケープシーケンスを簡単に組み合わせることができますが、二重引用符は_\x22_である必要があります

欠点:

  • すべての上位バイトが正しい結果を与えるわけではありません
  • 結果は、マシンのデフォルトの文字セットによって異なります。 Windows 1252の場合に最適

ハイブリッドJScript /バッチ-より堅牢ですが複雑なソリューション

マシンのデフォルトがWindows-1252である限り、すべての\ xNNコードを適切に解釈して正しいバイトを提供するJScriptコードを書くことはそれほど難しくありません。また、コマンドセッションのアクティブなコードページが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マシンでネイティブに実行される純粋なスクリプト
  • 1回のパスで文字列全体を処理できます
  • \ x00から\ xFFまでのすべてのバイトコードがサポートされています
  • _\\_、_\t_、_\r_、_\n_など、利用可能な他の多くのエスケープシーケンス.
  • 通常のテキストとエスケープシーケンスを簡単に組み合わせることができますが、二重引用符は_\x22_である必要があります

欠点:

  • マシンのデフォルトがWindows-1252の場合にのみ、すべてのバイトに対して正しい結果が得られます
  • やや複雑なJScriptコード

JREPL.BAT-ハイブリッドJScript /バッチ正規表現テキスト処理ユーティリティ

私の JREPL.BATユーティリティ は、当初、テキストファイルに対して正規表現の検索と置換操作を実行するために設計されました。ただし、エスケープシーケンスが埋め込まれた文字列を簡単に書き込むことができるオプションがあり、マシンが使用するデフォルトの文字セットに関係なく、すべてのバイトコードに対して正しい結果を得ることができます。

マシンのデフォルトが1バイト文字セットの場合、\ x00から\ xFFまでのすべての可能なエスケープシーケンスで以下を安全に使用でき、通常のテキストとエスケープシーケンスを自由に組み合わせることができます。

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

_/s "="_オプションは、未定義の環境変数を空の文字列として解釈される入力ソースとして指定します。最初の_$_引数は、空の文字列の末尾と一致します。 2番目の_"\x66\x6f\x6f"_引数は、置換値を指定します。 _/x_オプションは置換文字列内のエスケープシーケンスを有効にし、_/o test.txt_オプションは出力ファイルを指定します。

Test.txtに追加する場合は、_/APP_オプションを追加します。

\ nの代わりに\ n行末(WindowsではなくUNIXスタイル)が必要な場合は、_/U_オプションを追加します

改行文字が不要な場合は、_/M_オプションを追加します。

最後に、マシンがデフォルトでシングルバイト文字セットに設定されていない場合でも、出力形式としてWindows-1252のようなシングルバイト文字セットを指定することにより、すべてのエスケープシーケンスに対して正しい結果を強制できます。ただし、指定した文字セットがコマンドセッションのアクティブなコードページと一致しない場合は、エスケープシーケンスのみが機能することが保証されます。通常のテキスト文字の一部は、誤った結果をもたらす可能性があります。

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

利点:

  • XP以降のWindowsマシンで実行される純粋なスクリプト
  • 1回のパスで文字列全体を処理できます
  • \ x00から\ xFFまでのすべてのバイトコードがサポートされています
  • _\\_、_\t_、_\r_、_\n_など、利用可能な他の多くのエスケープシーケンス.
  • 通常のテキストとエスケープシーケンスを簡単に組み合わせることができますが、二重引用符は_\x22_または_\q_にする必要があります
  • デフォルトの文字セットに依存しない-常に正しい結果が得られます
  • ツールの武器にJREPLが含まれるようになると、JREPLの多くの用途が見つかります。強力なツールです。

欠点:

  • サードパーティスクリプトのダウンロードが必要
12
dbenham

「HEX値をファイルに書き込む」には:

set a=.
for /l %a in (0,1,255) do (
set /a dec=%a >nul
call cmd /c exit /b !dec!
set hex=!=exitcode!
rem set char=!=exitCodeASCII!
set a=!a! !hex:~-2!
)
echo %a:~1% > file.txt

すべての値を含むバッチからバイナリファイルを作成するには、ここを参照してください。
https://www.dostips.com/forum/viewtopic.php?f=3&t=5326

certutilは両方を実行できます。バイナリから16進ファイルを作成し、16進コードファイルからバイナリファイルを作成します。

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