4

ここで説明するには複雑すぎる理由から、x86のサブセットであるプラットフォームでx86GCCでコンパイルされたLinuxプログラムを実行する必要があります。このプラットフォームには%gsレジスタがありません。つまり、GCCは%gsレジスタの存在に依存しているため、エミュレートする必要があります。

現在、プログラムが%gsレジスタにアクセスしようとしたときに例外をキャッチし、それをエミュレートするラッパーがあります。しかし、これは犬が遅いです。ELFのオペコードに同等の命令で事前にパッチを適用して、トラップアンドエミュレートを回避する方法はありますか?

4

2 に答える 2

4

オプションを使用してコードをコンパイルしてみました-mno-tls-direct-seg-refsか?私のGCCマニュアルページ(i686-apple-darwin10-gcc-4.2.1)から:

   -mtls-direct-seg-refs
   -mno-tls-direct-seg-refs
       Controls whether TLS variables may be accessed with offsets from
       the TLS segment register (%gs for 32-bit, %fs for 64-bit), or
       whether the thread base pointer must be added.  Whether or not this
       is legal depends on the operating system, and whether it maps the
       segment to cover the entire TLS area.

       For systems that use GNU libc, the default is on.
于 2011-08-02T04:38:21.403 に答える
3

(これは、Adam Rosenfieldsソリューションが適用できないことを前提としています。これ、または同様のアプローチが、おそらくそれを解決するためのより良い方法です。)

%gsレジスタをエミュレートする方法については説明していませんが、プログラムに関する特別な知識がない限り、一般的にすべての使用法にパッチを適用するのは難しいでしょう。一般的なケース)パッチで変更できます。もちろん、%es =%gsのようなものを使用している場合は、比較的簡単なはずです。

これが何らかの形で機能するようにできると仮定すると、戦略はELFファイルの実行可能セクションをスキャンし、GSレジスタを使用または変更する命令にパッチを適用することです。それは少なくとも次の指示です:

  • GSセグメントオーバーライドプレフィックスを持つすべての命令(65分岐命令を想定します。この場合、プレフィックスは他の何かを示します)
  • push gs0F A8
  • pop gs0F A9
  • mov r/m16, gs8C /r
  • mov gs, r/m168E /r
  • mov gs, r/m64REX.W 8E /r)(64ビットモードをサポートしている場合)

そして、セグメントレジスタを許可する他の命令(私はそれ以上ではないと思いますが、100%確信はありません)。

これはすべて、インテル®64およびIA-32アーキテクチャーソフトウェア開発者マニュアルの結合ボリューム2Aおよび2B:命令セットリファレンス、AZからのものです。命令の接頭辞が他の接頭辞である場合とそうでない場合があることに注意してください。したがって、バイトシーケンスを盲目的に検索するのではなく、ライブラリを使用して命令のデコードを行う必要があります。

上記の手順のいくつかは、比較的簡単に変換call my_patchまたは類似する必要がありますが、2バイトに収まり、一般的に機能するものを見つけるのに苦労する可能性があります。int XXCD XX)は、割り込みベクトルを設定できる場合は良い候補かもしれませんが、現在使用している方法よりも高速になるかどうかはわかりません。もちろん、パッチが適用された命令を記録し、(ハンドラーが受け取る)リターンアドレスに応じて割り込みハンドラー(またはその他)の反応を変える必要があります。

-128..127バイト以内にスペースが見つかった場合は、トランポリンをセットアップし、JMP rel8EB cb)を使用してトランポリン(通常は別のJMP、ただし今回はターゲットアドレス用のスペースがあります)にジャンプして、命令を処理できる場合があります。エミュレーションを行い、パッチを適用した%gsの使用法に従って命令に戻ります。

最後に、トラップアンドエミュレートコードを実行したままにして、思いもよらなかった可能性のあるケース(たとえば、自己変更コードや挿入コード)をキャッチすることをお勧めします。このようにして、未処理のケースをログに記録し、ソリューションに追加することもできます。

于 2011-08-02T12:31:10.323 に答える