6

C++ で実装しなければならない RPC コードについて考えていたのですが、それをネットワーク経由で同じバイナリ コードに送信するのが安全かどうか (およびどの仮定の下で) 疑問に思いました (それがまったく同じであり、それらが同じ上で実行されていると仮定します)。建築)。ここで仮想メモリが違いを生むはずです。

いずれにせよ悪い設計なので、好奇心から尋ねていますが、理論的に可能かどうか (そして、プログラムに含まれる可能性のある関数以外の静的データへの他の種類のポインターに拡張可能かどうかを知りたいです) )。

4

6 に答える 6

6

一般に、多くの理由で安全ではありませんが、機能するケースは限られています。まず、データ ストリームの整合性を確保するために、プロトコルで何らかの署名または暗号化を使用していると仮定します。そうでない場合は、関数ポインターを渡すことによってのみ悪化する深刻なセキュリティ上の問題が既に発生しています。

まったく同じプログラム バイナリが接続の両端で実行されている場合、関数が共有ライブラリではなくメイン プログラム (または静的ライブラリからリンクされたコード) にある場合、およびプログラムが位置としてビルドされていない場合-independent executable (PIE) の場合、関数ポインターは両端で同じになり、ネットワークを介して渡すことが機能するはずです。これらは、プログラムを使用する際に文書化する必要がある非常に厳しい条件であり、非常に脆弱であることに注意してください。たとえば、誰かが一方のソフトウェアをアップグレードし、同時に接続のもう一方のバージョンをアップグレードするのを忘れた場合、事態は恐ろしく危険なほどに壊れます。

高レベルのコマンド構造または抽象 RPC フレームワークを優先して、このタイプの低レベル RPC を完全に回避しますが、本当にそうしたい場合は、関数名を渡して、dlsymまたは同等の関数を使用して検索することをお勧めします。それらをアップします。シンボルがライブラリではなくメイン プログラム バイナリに存在する場合、プラットフォームによっては、-rdynamic(GCC) または同様のオプションを使用して で使用できるようにする必要がありますdlsymlibffiこれを抽象化するための便利なツールでもあります。

dlsymまた、またはへの依存を避けたい場合は、シンボル名を関数ポインタにマッピングする線形テーブルまたはハッシュ テーブルlibffiとして、独自の「シンボル テーブル」をバイナリにハードコーディングしておくことができます。static constこの目的で ELF で使用されるハッシュ テーブル形式は、理解と実装が非常に簡単なので、それに基づいて実装することを検討してください。

于 2012-10-24T23:48:54.710 に答える
1

正式な保証をお探しの場合は、お手伝いできません。使用しているコンパイラと OS のドキュメントを参照する必要がありますが、必要な保証が見つかるとは思えません。ただし、一部の特殊な組み込みシステム OS を除きます。

ただし、問題なく動作することを 99.99% 確信している 1 つのシナリオを提供できます。

  • ウィンドウズ
  • 32 ビット プロセス
  • 関数は、再配置情報を持たないモジュールにあります
  • 問題のモジュールは、クライアント側で既にロードおよび初期化されています
  • 問題のモジュールは両側で 100% 同一です
  • 非常にクレイジーなことをしないコンパイラ (たとえば、MSVC と GCC はどちらも問題ないはずです)

DLL 内の関数を呼び出す場合、問題が発生する可能性があります。上記のリストによると、モジュール (=DLL) には再配置情報が含まれていない可能性があります。これにより、もちろん再配置が不可能になります (これが必要です)。残念ながら、これは、「優先読み込みアドレス」が他の何かによって使用されている場合、DLL の読み込みが失敗することも意味します。ですから、それは一種の危険です。

ただし、関数が EXE にある場合は問題ありません。32 ビット EXE は再配置情報を必要とせず、ほとんどの場合含まれません (MSVC の既定の設定)。ところで: ASLR はここでは問題ではありません。なぜなら、a) ASLR は移動したいというタグが付けられたモジュールのみを移動し、b) ASLR は再配置情報なしでは 32 ビット Windows モジュールを移動できなかったからです。

上記のほとんどは、関数が両側で同じアドレスを持つことを確認するだけです。残っている唯一の質問-少なくとも私が考えることができる-は、バイトパターンが目的の関数のアドレスを取得した場合と同じでしょうか? これは確かに C++ 標準では保証されていませんが、現在の実際のコンパイラで問題が発生することはないと思います。

そうは言っても、セキュリティと堅牢性が本当に重要ではない状況を除いて、それを行うことはお勧めしません.

于 2012-10-25T00:11:36.540 に答える
1

ネットワーク経由でポインターを送信できる RPC の形式を知りません (少なくともint最初にキャストするようなことはしません)。送信側で変換intし、それを遠端でポインターに戻すと、他の任意のポインターをポインターに変換するのとほとんど同じにintなります。逆参照しようとすると、未定義の動作になります。

通常、RPC 関数にポインターを渡すと、それはマーシャリングされます。つまり、ポインターが指すデータは、パッケージ化され、送信され、メモリに格納され、渡されたデータのローカル コピーへのポインターになります。反対側の機能。これは、IDL が少し醜くなる理由/方法の一部です。ポインターを渡すとき/渡す場合に、ネットワークを介して送信するデータの量を把握する方法を IDL に伝える必要があります。ほとんどの人は、ゼロで終わる文字列について知っています。他のタイプの配列の場合は、通常、データのサイズを (何らかの方法で) 指定する必要があります。

于 2012-10-24T23:32:35.707 に答える
1

それは何へのポインタですか?

静的プログラムメモリへのポインタですか?その場合は、オフセットではなくアドレスであることを忘れないでください。そのため、最初に 2 つのアドレスを適切に変換する必要があります。

第二に、それが静的メモリの一部でない場合 (つまり、実行時ではなくビルド時に作成された静的に割り当てられた配列)、実際にはまったく不可能です。

最後に、2 つのコードが同じであることをどのように確認していますか? 両方のバイナリ ビットが同一ですか (例: diff -a binary1 binary2)。ビットが同一であっても、各マシンの仮想メモリ管理によっては、プログラム全体のプログラム メモリ セグメントが 1 つのページに存在しない場合や、複数のページの配置がシステムごとに異なる場合があります。

どのようにスライスしても、これは本当に悪い考えです。これが、メッセージ パッシングと API の目的です。

于 2012-10-24T23:30:46.297 に答える
1

これはシステムに大きく依存します。各プロセスが実行するたびに同じアドレスで実行されていると考えるような仮想アドレス指定を備えたシステムでは、これは実行可能コードに対して適切に機能する可能性があります。ASLR に関する Darren Kopp のコメントとリンクは興味深いものです。ウィキペディアの記事をざっと読むと、Linux と Windows のバージョンは実行可能コードではなくデータに重点​​を置いていることが示唆されます。 ASLR 対応にリンクされています。」

それでも、「同じバイナリコード」は静的リンクによって最も確実に保証されます-異なる共有オブジェクト/ライブラリがロードされている場合、またはそれらが異なる順序でロードされている場合(おそらく動的ロードが原因です-dlopen構成ファイルまたはコマンドライン引数の異なる順序によって駆動されます)など)おそらく満腹です。

于 2012-10-24T23:31:16.590 に答える
1

ネットワーク経由でポインターを送信することは、一般的に安全ではありません。主な理由は次の 2 つです。

  • 信頼性: データ/関数ポインターは、別のマシン上の同じエンティティ (データ構造または関数) を指していない場合があります。これは、プログラムまたはそのライブラリーの場所が異なるか、メモリ内で動的に割り当てられたオブジェクトが原因です。再配置可能なコード + ASLR は、設計を壊す可能性があります。少なくとも、静的に割り当てられたオブジェクトまたは関数を指す場合は、プラットフォームが Windows の場合はイメージ ベースに対してオフセットを送信するか、どの OS でも同様のことを行う必要があります。
  • セキュリティ: ネットワークが開いていて、ハッカーがいる (またはネットワークに侵入した) 場合、彼らは最初のマシンになりすまして 2 番目のマシンをハングまたはクラッシュさせ、サービス拒否を引き起こしたり、任意のコードを実行してアクセスしたりすることができます。機密情報にアクセスしたり、改ざんしたり、マシンをハイジャックして、スパムを送信したり、他のコンピューターを攻撃したりする悪意のあるボットに変えたりします。もちろん、こちらにも対策・対策はありますが・・・

私があなたなら、違うものをデザインします。また、送信されたデータが重要ではないか暗号化されていることを確認し、受信側が使用する前に必要な検証を行うため、バッファオーバーフローや恣意的な実行はありません。

于 2012-10-24T23:58:04.497 に答える