ランタイムコードの変更(実行時にプログラム自体のコードを変更するプログラム)の正当な(スマートな)使用について考えられますか?
最新のオペレーティングシステムでは、検出を回避するためにウイルスがこの手法を使用しているため、これを実行するプログラムを嫌うようです。
私が考えることができるすべては、コンパイル時に知ることができない実行時に何かを知ることによっていくつかのコードを削除または追加するような、ある種のランタイム最適化です。
ランタイムコードの変更(実行時にプログラム自体のコードを変更するプログラム)の正当な(スマートな)使用について考えられますか?
最新のオペレーティングシステムでは、検出を回避するためにウイルスがこの手法を使用しているため、これを実行するプログラムを嫌うようです。
私が考えることができるすべては、コンパイル時に知ることができない実行時に何かを知ることによっていくつかのコードを削除または追加するような、ある種のランタイム最適化です。
回答:
コードの変更には多くの有効なケースがあります。実行時にコードを生成すると、次の場合に役立ちます。
時々、コードは実行時にコードに変換されます(これは動的バイナリトランスレーションと呼ばれます):
コード変更を使用して、命令セットの制限を回避できます。
コード変更のその他のケース:
これはコンピュータグラフィックス、特に最適化のためのソフトウェアレンダラで行われています。実行時に多くのパラメータの状態が検査され、ラスタライザコードの最適化されたバージョンが生成されます(多くの条件を排除する可能性があります)。これにより、三角形などのグラフィックプリミティブをより高速にレンダリングできます。
ASMの命令セットは、あなたが可能性がいくつかの必要な指示、欠けているので、一つの正当な理由があるの構築自分自身を。例:x86では、レジスタ内の変数への割り込みを作成する方法はありません(たとえば、axの割り込み番号で割り込みを作成します)。オペコードにコード化されたconst番号のみが許可されました。自己変更コードを使用すると、この動作をエミュレートできます。
一部のコンパイラは、静的変数の初期化にこれを使用して、後続のアクセスの条件付きのコストを回避していました。つまり、最初に実行されたときに何もしないでコードを上書きすることにより、「このコードを1回だけ実行する」ことを実装しています。
多くの場合があります:
一部のOSのセキュリティモデルでは、自己変更コードはroot / admin権限なしでは実行できないため、汎用的に使用することはできません。
ウィキペディアから:
厳格なW ^ Xセキュリティが適用されたオペレーティングシステムで実行されているアプリケーションソフトウェアは、書き込みが許可されているページで命令を実行できません。オペレーティングシステム自体のみがメモリに命令を書き込み、後でそれらの命令を実行できます。
そのようなOSでは、Java VMのようなプログラムでさえ、JITコードを実行するためにroot / admin特権が必要です。(詳細については、http://en.wikipedia.org/wiki/W%5EXを参照してください)
合成OSは、基本的には、部分的にAPI呼び出しに対するあなたのプログラムを評価し、結果をOSのコードを置き換えます。主な利点は、多くのエラーチェックが廃止されたことです(プログラムがOSに愚かなことをするように要求しない場合、チェックする必要がないため)。
はい、それはランタイム最適化の例です。
何年も前に、ある朝、自己修正コードのデバッグに費やしました。1つの命令が次の命令のターゲットアドレスを変更しました。つまり、分岐アドレスを計算していました。それはアセンブリ言語で書かれていて、プログラムを1命令ずつ実行したときに完全に機能しました。しかし、プログラムを実行すると失敗しました。結局、マシンがメモリから2つの命令をフェッチしており、(命令がメモリに配置されているため)変更中の命令がすでにフェッチされていたため、マシンが変更されていない(正しくない)バージョンの命令を実行していた。もちろん、デバッグしているときは、一度に1つの命令しか実行していませんでした。
自己修正コードはテスト/デバッグが非常に厄介で、マシンの動作(ハードウェアであろうと仮想であろうと)に関する想定が隠されていることがよくあります。さらに、システムは、(現在)マルチコアマシンで実行されているさまざまなスレッド/プロセス間でコードページを共有することはできません。これは、仮想メモリなどの多くの利点を無効にします。また、ハードウェアレベルで行われたブランチ最適化を無効にします。
(注-私はJITを自己変更コードのカテゴリに含めていません。JITはコードの1つの表現から別の表現に変換しています。コードを変更するわけではありません)
全体として、それは単に悪い考えです-本当にきちんと、本当にあいまいですが、本当に悪いです。
もちろん-8080バイトと〜512バイトのメモリしかない場合は、そのような方法に頼らなければならない可能性があります。
自己変更コード(実際には「自己生成」コード)のもう1つの理由は、パフォーマンスのためにジャストインタイムコンパイルメカニズムを実装することです。たとえば、代数式を読み取り、一連の入力パラメータでそれを計算するプログラムは、計算を述べる前に式をマシンコードに変換する場合があります。
ハードとソフトウェアの間に論理的な違いがないという古い栗を知っています...コードとデータの間に論理的な違いがないとも言えます。
自己変更コードとは何ですか?値を実行ストリームに入れて、データではなくコマンドとして解釈できるようにするコード。もちろん、関数型言語には、実際には違いはないという理論的な見方があります。eは、命令型言語とコンパイラー/インタープリターで、同等のステータスであると推定せずに、これを簡単に行うことができると言っています。
私が言及しているのは、データがプログラムの実行パスを変更できるという実際的な意味です(ある意味でこれは非常に明白です)。私は、プログラムがコマンドからコマンドに移動するのと同じように、解析から状態への移動(および他の変数の変更)で移動するテーブル(データの配列)を作成するコンパイラーコンパイラーのようなものを考えています。 、プロセス内の変数を変更します。
したがって、コンパイラがコードスペースを作成し、完全に別個のデータスペース(ヒープ)を参照する通常の場合でも、データを変更して実行パスを明示的に変更できます。
1つの使用例は、ウイルス対策プログラムをテストするための正規のDOS実行可能COMファイルであるEICARテストファイルです。
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
実行可能ファイルには、エンコード可能な命令の数を大幅に制限する[21h-60h、7Bh-7Dh]の範囲の印刷可能/入力可能なASCII文字のみを含める必要があるため、自己コード変更を使用する必要があります。
詳細はこちら
DOSでの浮動小数点演算ディスパッチにも使用されます
一部のコンパイラはCD xx
、x87浮動小数点命令の代わりに0x34-0x3Bの範囲のxxで出力します。CD
は命令のオペコードなのでint
、x87コプロセッサが使用できない場合は、割り込み34h-3Bhにジャンプしてソフトウェアでその命令をエミュレートします。それ以外の場合、割り込みハンドラーはこれらの2バイトをに置き換える9B Dx
ため、後の実行はエミュレーションなしでx87によって直接処理されます。
継続的に更新されるデータベースに対して統計分析を実行します。私の統計モデルは、使用可能になる新しいデータに対応するためにコードが実行されるたびに作成および再作成されます。
これが使用できるシナリオは学習プログラムです。ユーザー入力に応じて、プログラムは新しいアルゴリズムを学習します。
Javaでそれを行う方法についての質問があります:Javaコードの自己修正の可能性は何ですか?
これの最良のバージョンはLispマクロかもしれません。単なるプリプロセッサであるCマクロとは異なり、Lispを使用すると、プログラミング言語全体にいつでもアクセスできます。これはlispの最も強力な機能であり、他の言語には存在しません。
私は決して専門家ではありませんが、Lispの人の1人に話してもらいます!彼らがLispが周りで最も強力な言語であり、賢い人々が彼らがおそらく正しいというわけではないと言うのには理由があります。