49


19

*自己修正コード*の実際の使用はありますか?

ワーム/ウイルスを構築するためにそれらが使用されることができることを私は知っています、しかし私はプログラマーが自己修正コードを使わなければならないかもしれないいくつかの正当な理由があるかどうか疑問に思いました。

何か案は? 仮説的な状況も大歓迎です。

14 Answer


48


"http://ja.wikipedia.org/wiki/Self-modifying_code[self-modifying code]"のウィキペディアのエントリには素晴らしいリストがあります。

_ . 状態依存ループの*半自動最適化* . 実行時コード生成、またはアルゴリズムの特殊化 特定の呼び出しで記述されたキー比較を実行するためのコードを準備する一般的なソートユーティリティなどのランタイムまたはロードタイム(たとえば、リアルタイムグラフィックスの分野で一般的です)。 . オブジェクトのインライン状態*の変更、または高レベルのシミュレーション クロージャーの構築。 . *ロード時に通常行われる、サブルーチンアドレス呼び出しのパッチ適用 動的ライブラリ、または各呼び出しで、サブルーチンの内部参照をパラメーターにパッチして、実際のアドレスを使用するようにします。 これが「自己修正コード」と見なされるかどうかは、用語の場合です。 . 遺伝的プログラミングのような*進化的計算システム*。 . コードを非表示にして、リバースエンジニアリングを防止します。 逆アセンブラーまたはデバッガー。 . ウイルス/スパイウェアスキャンソフトウェアによる検出を回避するためのコードの非表示 など。 . ローリングパターンで(一部のアーキテクチャで)メモリの100%を満たす オペコードの繰り返し、すべてのプログラムとデータの消去、または*バーンインハードウェア*。 . 実行時に解凍および実行されるコードの圧縮 たとえば、メモリまたはディスク容量が限られている場合。 . 一部の非常に限られた命令セットには、使用する以外のオプションはありません 特定の機能を実現するための自己修正コード。 たとえば、「負の場合に減算および分岐」命令のみを使用する「1命令セットコンピュータ」マシンは、間接コピーを実行できません(Cプログラミングの「* a = ** b」と同等のもの)。自己修正コードを使用せずに . * fault-tolerance *の変更手順 _

自己修正コードを使用してハッカーを阻止することについてのポイントについて:

いくつかのファームウェアアップデートの過程で、DirectTVはゆっくりとスマートカードにプログラムを組み立てて、未払いのチャンネルを違法に受け取るためにハッキングされたカードを破壊しました。 詳細については、http://www.codinghorror.com/blog/archives/001125.html [Black Sunday Hack]でJeffのCoding Horrorの記事を参照してください。


12


私は自己修正コードが次の目的で使われているのを見ました。

  1. プログラムがその場で自分自身のためにより多くのコードを書くようにすることによる速度最適化

  2. リバースエンジニアリングをより難しくするための難読化


11


RAMが限られていた昔は、メモリを節約するために自己修正コードが使用されていました。 今日、例えば UPXのようなアプリケーション圧縮ユーティリティは、アプリケーションの圧縮イメージをロードした後に自身のコードを解凍/修正するために使用されます。


6


Commodore 64は多くのレジスタを持たず、1Mhzプロセッサを持っているからです。 値によってオフセットされたメモリアドレスを読み取る必要があるときは、ソースを変更する方が簡単です。

@リーダー:LDA $ C000 STA $ D020 INCリーダー1 JMPリーダー

とにかく自己修正コードを書いたのはこれが最後です:-)


6


それは本当に本当にクールだ、そして時々それは十分な理由です。


6


1960年代のアセンブリ言語は、スタックなしで関数呼び出しを実装するために自己修正コードを使用しました。

クヌース、v1、1ed p.182:

MAX100  STJ   EXIT   ;Subroutine linkage
        ENT3  100    ;M1. Initialize
        JMP   2F
1H      CMPA  X,3    ;M3. Compare
        JGE   *+3
2H      ENT2  0,3    ;M4. Change m
        LDA   X,3    ;(New maximum found)
        DEC3  1      ;M5. Decrease k
        J3P   1B     ;M2. All tested?
EXIT    JMP   *      ;Return to main program

_ このコーディングをサブルーチンとして含む大規模なプログラムでは、単一の命令「JMP MAX100」により、レジスタAがロケーションX + 1〜X + 100の現在の最大値に設定され、最大の位置がrI2に表示されます。 。 この場合のサブルーチンリンケージは、命令 "MAX100 STJ EXIT"と後で "EXIT JMP *"によって実現されます。 Jレジスタの動作方法のため、出口命令はMAX100への最初の参照が行われた場所の次の場所にジャンプします。 _

_編集:_ここで簡単な説明をしていても、何が起こっているのかわかりにくいかもしれません。 「+ MAX100 STJ EXIT 」の行では、「 MAX100 」は命令のラベルであり(したがって、プロシージャ全体のラベルです)、「 STJ 」はジャンプレジスタを格納することを意味します(先ほどの_from _)、「 EXIT + は、「EXIT」というラベルの付いたメモリロケーションがSTOREのターゲットであることを意味します。 `+ EXIT +、後で見るのは最後の命令のラベルです。 だからコードを上書きしている! ただし、多くの命令(ここでは「+ STJ 」を含む)は、命令語のオペランド部分のみを暗黙的に上書きします。 したがって、「 JMP 」は変更されずに残り、「 * +」はダミートークンになります。実際にそこに置く意味はないため、上書きされるだけです。

'' '' '

自己修正コードは、レジスタ間接アドレッシングが利用できない場合でも使用されますが、それでも必要なアドレスはレジスタのすぐそばにあります。 PDP-1 LISP:

dap .+1  ;deposit address part of accumulator in (IP+1)
lac xy   ;load accumulator with (ADDRESS) [xy is a dummy symbol, just like * above]

これらの2つの命令は、ロード命令のオペランドを変更することにより、「+ ACC:=(ACC)+」を実行します。

このような変更は比較的安全で、アンティークのアーキテクチャでは必要なものです。


5


たくさんの理由 私の頭の上から:

  • 実行時クラスの構築とメタプログラミング たとえば、SQLテーブルへの接続を取得し、そのテーブルに特化したクライアントクラスを生成するクラスファクトリを持つ(列のアクセサ、メソッドの検索など)。

  • それからもちろん、有名なbitbltの例と、正規表現の類似物があります。

  • JITを追跡するRT情報に基づいた動的最適化

  • 付加的環境におけるアダスタイルジェネリック関数のサブタイプ特殊化

    • マルクスQ


5


人工知能?


4


動的リンクは一種の自己修正(絶対および/または相対ジャンプ位置へのパッチ適用)です。 これは通常、O / Sのプログラムローダーによって行われます。


3


http://en.wikipedia.org/wiki/Artificial_neural_network[Neural networks]は自己修正コードの一種です。

それから evolutionary algorithmがあります。