最終更新:2026-01-12
前回の記事では、NTFSファイルシステムの機能である「代替データストリーム(ADS)」を利用したデータ隠蔽について解説した。
しかし、データを隠す手法はファイルシステムに依存するものだけではない。ファイルそのもののフォーマット(構造)の仕様を突き、画像ファイルの中にアーカイブファイルなどを埋め込む手法が存在する。
これは一般に「EOF(End of File)インジェクション」や「オーバーレイ」と呼ばれ、古くからあるステガノグラフィ(データ隠蔽技術)の一種である。
本記事では、Windows標準のコマンドのみを使用してこの現象を再現し、その仕組みと特性について解説する。
EOFインジェクションの仕組み
JPEGやPNGといった一般的な画像ファイルフォーマットには、データの終わりを示す「終端マーカー」が定義されている。
- JPEGの場合: バイナリの末尾に
FF D9(EOI: End of Image) というマーカーがある。 - PNGの場合:
IENDというチャンク(データの塊)が末尾にある。
多くの画像ビューア(フォトアプリやブラウザなど)は、ファイルを先頭から読み込み、この終端マーカーを見つけた時点で画像の描画処理を終了する。
そのため、終端マーカーより後ろに余分なデータが結合されていても、画像ビューアはそれを「存在しないもの(またはゴミデータ)」として無視する。この性質を利用し、画像の見た目を保ったまま、後ろに別のファイルを隠すことができるのである。
コマンドプロンプトでの再現手順
特別なツールは必要ない。Windows標準のコマンドプロンプト(cmd.exe)にある copy コマンドのバイナリ結合オプションを利用するだけで再現可能である。
1. 準備
以下の2つのファイルを用意する。
image.jpg: 隠れ蓑にする普通の画像ファイル。secret.zip: 隠したいデータ(中身は何でも良い)。
2. ファイルの結合
以下のコマンドを実行し、2つのファイルをバイナリモード(/b)で結合して、新しいファイル output.jpg を作成する。
copy /b image.jpg + secret.zip output.jpg
解説:
/b : バイナリファイルとして扱うオプション。これがないとテキストとして扱われ、データが破損する可能性がある。
+ : 複数のファイルを連結する。
3. 結果の確認
生成された output.jpg をダブルクリックして開いてみてほしい。通常通り画像が表示され、エラーも出ないはずである。見た目上は元の image.jpg と全く変わらない。隠されたデータを取り出す方法では、結合されたZIPファイルの中身にはどうアクセスすればよいのだろうか。
方法1: 拡張子の変更
もっとも単純な方法は、拡張子を偽装することである。output.jpg の名前を output.zip に変更し、エクスプローラーで開くと、画像部分は無視され、後ろにくっついているZIPファイルとして認識される。これで中のファイルを取り出すことができる。
方法2: アーカイバソフトで直接開く7-ZipやWinRARなどの高機能なアーカイバソフトは、ファイル形式をヘッダー(先頭データ)だけでなく、内部構造から判断する機能を持っている場合がある。output.jpg をそのまま 7-Zip で開く(右クリックメニュー等から)と、画像部分は無視され、内部に含まれるアーカイブ構造が展開される。
代替データストリーム(ADS)との決定的な違い
以前の記事で紹介したADSも「隠しデータ」を作る手法だったが、今回のEOFインジェクションとは**永続性(Persistence)**において決定的な違いがある。
| 観点 | ADS (Zone.Identifier 等) | EOF インジェクション(結合) |
|---|---|---|
| 隠し場所 | ファイルシステムのメタデータ領域 | ファイルデータ本体の末尾 |
| ファイルサイズ | 見た目上のサイズは増えない | 結合した分だけサイズが増える |
| ファイルシステム依存 | NTFS のみ(FAT32 等は不可) | 依存なし |
| コピー時の挙動 | USB 等へコピーすると消える | コピーしてもデータは維持される |
| Web 転送 | アップロード/ダウンロードで消える | 維持される |
コピーしても消えない強みと弱み
EOFインジェクションで作成されたファイルは、単なる「バイト列の塊」であるため、USBメモリ(FAT32/exFAT)にコピーしたり、メールに添付して送信したりしても、隠されたデータは消滅しない。一方で、ファイルサイズ(バイト数)を確認すると 画像サイズ + ZIPサイズ の合計値になっているため、元の画像サイズを知っている場合や、小さな画像なのにファイルサイズが異常に大きい場合などには、比較的容易に露見する。
まとめ
copy /b コマンドを使用したファイルの結合は、OSのバグではなく、ファイルフォーマットの仕様とコマンドの機能を組み合わせた古典的なトリックである。画像ビューアは「終端マーカー」までしか見ない。アーカイバソフトや拡張子変更により、後ろのデータにアクセスできる。ADSとは異なり、ファイルシステムを移動してもデータが残留する。セキュリティの観点からは、一見無害な画像ファイルであっても、その内部にスクリプトや機密情報が含まれている可能性があることを示唆している。不審なファイルを受け取った際は、見た目だけでなくファイルサイズやヘッダー情報にも注意を払う必要があるだろう。
追記:Pythonによる検知(簡易フォレンジック)
コマンドプロンプトやプロパティでの確認は手軽だが、大量のファイルを検査する場合や、自動化したい場合には不向きである。 ここではPythonを使用し、JPEGファイルの構造的な末尾(EOIマーカー)以降に余分なデータが存在するかどうかを機械的に判定するコード例を紹介する。
検知コードの実装例
JPEGファイルは原則としてバイナリの FF D9 (EOI) で終了する。ファイルの末尾からこのマーカーを検索し、それより後ろにデータが存在する場合、何らかのデータが隠蔽されている(Injectionされている)可能性が高いと判断できる。
import os
def detect_eof_injection(file_path):
"""
Detects data appended after the JPEG End of Image (EOI) marker.
"""
# JPEG EOI marker: 0xFF 0xD9
EOI_MARKER = b'\xff\xd9'
try:
with open(file_path, 'rb') as f:
content = f.read()
# Search for the LAST occurrence of the EOI marker
eoi_index = content.rfind(EOI_MARKER)
if eoi_index == -1:
print(f"[-] {file_path}: EOI marker not found (Not a standard JPEG?).")
return
# Calculate sizes
# EOI marker is 2 bytes, so valid end is index + 2
valid_end_position = eoi_index + 2
total_size = len(content)
extra_bytes = total_size - valid_end_position
if extra_bytes > 0:
print(f"[!] {file_path}: Suspicious data detected!")
print(f" - Original Image Size: {valid_end_position} bytes")
print(f" - Injected Data Size : {extra_bytes} bytes")
print(f" - Total File Size : {total_size} bytes")
else:
print(f"[+] {file_path}: Clean (No data after EOI).")
except FileNotFoundError:
print(f"[x] File not found: {file_path}")
except Exception as e:
print(f"[x] Error processing file: {e}")
if __name__ == "__main__":
# Test with the file created earlier
target_file = "output.jpg"
detect_eof_injection(target_file)
実行結果
上記のコードを実行すると、結合されたファイルに対しては以下のような警告が出力される。
[!] output.jpg: Suspicious data detected!
- Original Image Size: 102400 bytes
- Injected Data Size : 5120 bytes
- Total File Size : 107520 bytes
統合的なフォレンジックツールへ
このスクリプトはEOFインジェクションのみを検知するが、前回の記事で触れた**代替データストリーム(ADS)**の検知と組み合わせることで、簡易的なWindows向けフォレンジックツールを作成することも可能である。
PythonでADSにアクセスする場合、Windows環境ではファイルパスに
このように「ファイルサイズ」と「実際のデータ構造」の乖離をプログラムでチェックすることは、セキュリティ実務において重要なアプローチの一つである。