リスト1●偽装プログラム(merge.php)のソースコード
リスト1●偽装プログラム(merge.php)のソースコード
[画像のクリックで拡大表示]
図1●a.jpgとa.txtを合体して偽装ファイル(x.jpg)を作成
図1●a.jpgとa.txtを合体して偽装ファイル(x.jpg)を作成
[画像のクリックで拡大表示]
リスト2●復元プログラム(split.php)のソースコード
リスト2●復元プログラム(split.php)のソースコード
[画像のクリックで拡大表示]
レシピ
■ PHP 4.xまたは5.x
http://www.php.net/
別途モジュールは必要ありません

 今回は「インプラント・ファイル」という技に挑戦です。一見,画像ファイルなのに,実は画像ファイルの“裏”に別のデータ・ファイルが格納されているというウラ技です。PHPをデフォルトでインストール済みと仮定して解説していきます。

 テキスト・ファイル同士を連結するとき,二つのファイルを読み込んで,単純に連結して保存するだけですね。では画像とテキスト・ファイルを連結するとどうなると思いますか?実はWindowsのファイル・システムというのは極めて単純で,バイナリとテキストであっても何の障害もなく連結できます。これを利用してファイルの先頭部に画像を,その後ろにテキスト・ファイルをくっつけて,どうなるかを見てみようというのが今回のサンプルです。元々はWarezなどのアングラ系で育ってきた技術ですが,ちょっとしたファイルをこうやって偽装しておくと,強引な解析を試みられても比較的安全という使い方もできます。

 連結用にa.jpgとa.txtというファイルを用意してください。a.jpgのサイズは問いませんが,きちんとしたJPEG画像ファイルである必要があります。a.txtはテキスト・ファイルです。用意したファイルをリスト1[拡大表示]のサンプル(merge.php)と同じフォルダ(ここではC:\php)に置きます。まずは実行してみましょう。コマンドプロンプトで「C:\php\php merge.php」とすると,a.jpgとa.txtを連結した「x.jpg」というファイルが作成されます(図1[拡大表示])。ファイル・サイズを確認するとa.jpgとa.txtが合成されていることがわかります。

<?php
$filename = "a.jpg";
$handle = fopen($filename, "rb");
$c_jpg = fread($handle, filesize($filename));
fclose($handle);

$filename = "a.txt";
$handle = fopen($filename, "rb");
$c_txt = fread($handle, filesize($filename));
fclose($handle);

$split = "\n--&&split here&&--\n";

$c_obj = $c_jpg.$split.$c_txt;
$filename = "x.jpg";
$handle = fopen($filename, "w");
fwrite($handle, $c_obj);
fclose($handle);
?>

 このx.jpgをダブルクリックすると,なんとa.jpgと同じ画像が表示されます。テキスト・ファイル部分が画面上でゴミになることはありません。ファイル内に間違いなくa.txtの内容が合成されているのに,あたかもa.jpgそのものであるかのように見えます。偽装完了です。

 ただしこのままではa.txt部分を見ることができません。そこで復元用のプログラムが必要です。復元プログラムはリスト2[拡大表示](split.php)です。コマンドプロンプトで「c:\php\php split.php」と実行すると,xx.jpgとxx.txtという二つのファイルができます。xx.jpgは元のa.jpg,xx.txtは元のa.txtと同じものです。復元完了というわけですね。

<?php
$filename = "x.jpg"; // 偽装ファイル名
$split = "--&&split here&&--"; // セパレータ
$handle = fopen($filename, "rb"); // 偽装ファイルをオープン
$flg_split = 0; // セパレータ確認フラグ

while(!feof($handle)){
    $c_tmp = fgets($handle);
    if(!ereg($split,$c_tmp) && !$flg_split){
        $c_jpg .= $c_tmp;
    }else{
        $flg_split=1;
    }
    if($flg_split){
        $c_txt .= $c_tmp;
    }
}
fclose($handle);
$filename = "xx.jpg";
$handle = fopen($filename, "w");
fwrite($handle, $c_jpg); // 復元した画像ファイルを出力
fclose($handle);
$c_txt = ereg_replace($split."\n","",$c_txt); // セパレータを削除
$filename = "xx.txt";
$handle = fopen($filename, "w");
fwrite($handle, $c_txt); // 復元したテキスト・ファイルを出力
fclose($handle);
?>

バイナリ+テキストの
順番が偽装のポイント

 サンプルは画像ファイルの頭にテキストを連結しましたが,この順番を逆にするとテキスト・ファイルの後ろに画像ファイルのバイナリが文字化けのような状態で表示されてしまいます。ダブルクリックしたときに何かのアプリケーションが実行され,かつバイナリ・ファイルであるものを先頭に置くというのがポイントです。例えば動画ファイルを先頭部に埋め込むと,偽装ファイルは動画ファイルのように振る舞うようになります。化けたりゴミが入ったりしないのは不思議な感じですが,少なくても現時点のWindowsでは,OSはインプラントを感知できないようです。画像+画像や画像+ZIP書庫といった組み合わせもぜひ試してみてください。サンプルのロジックは単純なので,Ruby,Perl,VB,Delphi,Javaなどにも移植できると思います。

 ファイルのやり取りをする際に,お互いがインプラントの作成/復元プログラムを持っていれば(結合部のセパレータによって特定復元ツールでしか復元できません),暗号化されているのと同等の秘匿性を確保できるというわけです。他人には画像にしか見えないので,よもやそれが仕事関係の重要ファイルだなんてことはばれないでしょう。暗号化や偽装ということに関しては裏社会のほうが一歩先んじているものです。セキュリティにうるさいご時勢になって,裏社会技術が表社会で脚光を浴びるというのも面白い状況だといえます。今回の偽装ファイルは,複数のファイルを一つのファイルにまとめたという意味で,書庫ファイルの一種と言ってもいいかもしれません。

出典:日経ソフトウエア 2005年12月号 148ページより
記事は執筆時の情報に基づいており、現在では異なる場合があります。