Javascriptコードでもある画像



画像は通常バイナリファイルとして保存され、Javascriptファイルは基本的にプレーンテキストです。どちらのタイプのファイルも、独自のルールに従う必要があります。画像には、特定の方法でデータをエンコードする特定のファイル形式があります。Javascriptファイルを実行可能にするには、特定の構文に従う必要があります。疑問に思いました:実行できるように、両方とも有効なJavascript構文であるイメージファイルを作成することは可能ですか?



読み続ける前に、私の実験結果を使用してこのコードサンドボックスを探索することを強くお勧めし



ます。https//codesandbox.io/s/executable-gif-8yq0j?file = / index.html



画像を表示して自分で探索したい場合は、ここからダウンロードできます:



https://executable-gif.glitch.me/image.gif



適切な画像タイプの選択



残念ながら、画像には多くのバイナリデータが含まれており、Javascriptとして解釈すると、エラーがスローされます。だから私の最初の考えはこれでした:もし私がすべての画像データを大きなコメントに入れたらどうなるでしょう、このようなもの:



/*ALL OF THE BINARY IMAGE DATA*/


これは有効なJavascriptファイルになります。ただし、画像ファイルは、特定のバイトシーケンス、つまり画像形式に固有のファイルヘッダーで始まる必要があります。たとえば、PNGファイルは常にバイトシーケンス89 50 4E 47 0D 0A 1A0Aで始まる必要があります。画像がで始まる場合、/*ファイルは画像ファイルではなくなります。



このファイルヘッダーから、次のアイデアが浮かびました。この一連のバイトを変数名として使用し、それに長い文字列の値を割り当てるとどうなるでしょうか。



PNG=`ALL OF THE BINARY IMAGE DATA`;


通常の文字列の代わりにテンプレート文字列を使用します。"または'、バイナリデータに改行を含めることができるため、テンプレート文字列の方が適しています。



残念ながら、画像ファイルヘッダーのほとんどのバイトシーケンスには、変数名で使用できない印刷不可能な文字が含まれています。ただし、使用できる形式はGIFです。GIFヘッダーブロックは4749 46 38 39 61のようになります。これは、ASCII文字列GIF89aに便利に変換されます-絶対に有効な変数名です!



適切な画像サイズの選択



有効な変数名で始まる画像フォーマットが見つかったので、等号記号とバックティックを追加する必要があります。したがって、ファイルの次の4バイトは次のようになります。3D0960 04





画像の最初のバイト



GIF形式では、ヘッダーの後の4バイトが画像の寸法を定義します。3D(等号)と60(バックティック、ラインを開く)をそれらに合わせる必要があります。 GIFはリトルエンディアンの順序を使用するため、2番目と4番目の文字は画像サイズに大きな影響を与えます。画像の幅と高さが数万ピクセルにならないように、できるだけ小さくする必要があります。したがって、大きな3Dバイト60の最下位バイトを格納する必要があります。



画像幅の2番目のバイトは、等しい符号と行の先頭の間のスペースになるため、有効な空白である必要があります。GIF89a= `.....。また、16進数の文字コードはできるだけ小さくする必要があります。そうしないと、画像が大きくなります。



最小の空白文字は09(水平タブ文字)です。これにより、3D 09画像の幅がわかります。これはリトルエンディアンで2365です。私が望むより少し広いですが、それでも完全に受け入れられます。



高さの2番目のバイトには、適切なアスペクト比が得られる値を選択できます。04を選択しました。これにより、高さは60 04、つまり1120ピクセルになります。



スクリプトをファイルに入れる



これまでのところ、実行可能なGIFはほとんど何もしません。単にGIF89a長い文字列をグローバル変数に割り当てます。何か面白いことが起こりたいです! GIF内のデータのほとんどは画像のエンコードに使用されるため、そこにJavascriptを挿入しようとすると、画像が大きく歪む可能性があります。しかし、何らかの理由で、GIF形式にはコメント拡張と呼ばれるものが含まれています。これは、GIFデコーダーによって解釈されないメタデータを格納する場所です。Javascriptロジックに最適な場所です。



このコメント拡張機能は、GIFカラーチャートの直後にあります。そこに任意のコンテンツを配置できるので、GIF89a行を簡単に閉じることができます、すべてのJavascriptを追加してから、複数行のコメントブロックを開始して、画像の残りの部分がJavascriptパーサーに影響を与えないようにします。



最終的に、ファイルは次のようになります。



GIF89a= ` BINARY COLOR TABLE DATA ... COMMENT BLOCK:

`;alert("Javascript!");/*

REST OF THE IMAGE */


ただし、小さな制限があります。コメントブロック自体は任意のサイズにすることができますが、複数のサブブロックで構成され、各サブブロックの最大サイズは255です。次のサブブロックの長さを決定するサブブロック間に1バイトがあります。したがって、大きなスクリプトをそこに収めるには、次のような小さなフラグメントに分割する必要があります。



alert('Javascript');/*0x4A*/console.log('another subblock');/*0x1F*/...


コメント内の16進コードは、次のサブブロックのサイズを決定するバイトです。これらはJavascriptに固有のものではありませんが、GIFファイル形式に必要です。コードの残りの部分に干渉しないように、コメントに配置する必要があります。スクリプトフラグメントを処理してイメージファイルに追加する小さなスクリプトを作成しました:https



//gist.github.com/SebastianStamm/c2433819cb9e2e5af84df0904aa43cb8



バイナリデータのクリーンアップ



基本的な構造ができたので、バイナリイメージデータがコードの構文を台無しにしないことを確認する必要があります。前のセクションで説明したように、ファイルは3つのセクションに分かれています。1つ目はGIF89a変数への割り当て、2つ目はJavascriptコード、3つ目は複数行のコメントです。



変数への値の割り当てに関する最初の部分を見てみましょう。



GIF89a= ` BINARY DATA `;


バイナリデータに文字`または文字の組み合わせが含まれている場合、${パターン文字列が終了するか、無効な式が作成されるため、問題が発生します。修正は非常に簡単です:バイナリデータを変更するだけです!たとえば、文字`(hex 60)の代わりに文字a(hex 61)を使用できますファイルのこの部分には色のパレットが含まれているため、たとえば、の#286148代わりに色を使用するなど、一部の色に小さな変更が加えられ#286048ます。誰もが違いに気付く可能性は低いです。



歪みへの対処



Javascriptコードの最後に、バイナリイメージデータがJavascriptの解析に影響を与えないように、複数行のコメントを開きました。



alert("Script done");/*BINARY IMAGE DATA ...


画像データに一連の文字が含まれている場合、*/コメントは途中で終了し、Javascriptファイルが無効になります。ここでも、コメントが終了しないように、2つの文字のいずれかを手動で変更できます。ただし、エンコードされた画像のセクションにいるため、結果として画像が破損します。たとえば、次のようになります。





破損した画像



最悪の場合、画像がまったく表示されない場合があります。反転するビットを慎重に選択することで、歪みを最小限に抑えることができました。幸いなことに、組み合わせに損傷を与えるケースはごくわずかでした*/たとえば、「有効なJavascriptファイル」行の下部など、完成した画像にはまだわずかな歪みがありますが、全体的には非常に満足しています。



ファイルの仕上げ



最後の操作であるファイルの完了が残ります。ファイルは003Bバイトで終了する必要があるため、コメントを早期に終了する必要があります。これはファイルの終わりであり、潜在的な損傷は微妙であるため、ファイルの終わりが解析の問題を引き起こさないように、ブロックコメントを終了して1行のコメントを追加しました。



/* BINARY DATA*/// 00 3B


画像を実行するようにブラウザを説得する



これで、最終的にイメージと有効なJavascriptファイルの両方であるファイルができました。ただし、最後の障害を克服する必要があります。サーバーに画像をアップロードしてタグscript使用しようとすると、同様のエラーが発生する可能性があります。



MIMEタイプ( 'image / gif')が実行できないため、' http:// localhost:8080 /image.gif 'からのスクリプトの実行を拒否しました[ MIMEタイプが実行できないため、' http:// localhost:8080 /image.gif 'からのスクリプトの実行を中止します。]


つまり、ブラウザは「これは画像です。実行しません!」と正しく表示します。そしてほとんどの場合、これは非常に適切です。しかし、私たちはまだそれを実現したいと思っています。解決策は、これが画像であることをブラウザに通知しないことです。このために、ヘッダー情報なしで画像を提供する小さなサーバーを作成しました。



ヘッダーからのMIMEタイプ情報がないと、ブラウザーはそれがイメージであることを認識せず、コンテキストで最適なことを正確に<img>実行し<script>ます。タグ内のイメージとしてレンダリングするか、タグ内のJavascriptとして実行します。



しかし...なぜこれがすべてなのですか?



私はまだそれを自分で理解していません。そのような仕事は心のウォームアップとしては良いのですが、それが本当に役立つ状況を考えられるなら、私に知らせてください!






広告



開発者向けのサーバーは、当社の仮想サーバーに関するものです。

長い間、私たちはIntelの高速サーバードライブのみを使用しており、ハードウェアを節約していません。ブランド化された機器と、サービスを提供するための市場で最新のソリューションのみを使用しています。






All Articles