0

私はしばらくの間、関数を動的にc ++にロードする方法を探していましたが、ようやく理解できたと思います。計画は次のとおりです。

  1. 関数を文字列としてC++に渡します(ソケット接続、ファイルなどを介して)。
  2. 文字列をファイルに書き込みます。
  3. C++プログラムにファイルをコンパイルして実行させます。エラーがある場合は、キャッチして返送してください。
  4. 新しい関数で新しく実行されたプログラムに、関数のメモリ位置を現在実行中のプログラムに渡してもらいます。
  5. 関数の場所を関数ポインター変数に保存します(関数は常に同じ戻り型と引数を持つため、これによりポインターの宣言が簡単になります)。
  6. 関数ポインタを使用して新しい関数を実行します。

問題は、ステップ4の後、新しいプログラムを実行し続けたくないということです。これを頻繁に実行すると、実行中の多くのプログラムがスレッドを吸い上げるためです。新しいプログラムを閉じるが、新しい関数が保存されているメモリの場所を保持する方法はありますか?使用中に上書きしたり、他のプログラムで利用したりしたくありません。

他のステップについても何か提案があれば、それもありがたいです。これと同様のことを行う他のライブラリがあるかもしれません、そしてそれらを推薦するのは良いです、しかしこれは私が調べたいアプローチです—それの達成のためでなければ、そうする方法を知るための知識のために。

編集:ダイナミックリンクライブラリを知っています。これは、C++での動作をよりよく理解するために私が主に調査しているものです。

4

5 に答える 5

6

これがどのように機能するのかわかりません。新しいプログラムを実行すると、それは別のプロセスになるため、そのプロセススペース内のアドレスは元のプロセスでは意味がありません。

それだけでなく、呼び出したいコードは元のプロセスにも存在しないため、元のプロセスで呼び出す方法はありません。

Nickが彼の回答で述べているように、DLL /共有ライブラリが必要であるか、元のプロセスが問題の関数によって操作される新しいプロセスにデータを送信してから送り返すことができるように、何らかの形式のプロセス間通信を設定する必要があります。元のプロセスに。

于 2012-05-28T00:30:16.367 に答える
3

ダイナミックリンクライブラリはどうですか?

これらは、実行時にリンク/リンク解除/置換できます。

または、プロセス間で本当に通信したい場合は、名前付きパイプを使用できます。

編集-名前付き共有メモリを作成することもできます。

于 2012-05-28T00:28:43.267 に答える
2

ステップ4の場合、2つのプロセスが異なる仮想メモリ空​​間を使用するため、あるプロセスから別のプロセスにメモリ位置(アドレス)を直接渡すことはできません。1つのプロセスが他のプロセスでメモリを使用することはできません。したがって、2つのプロセスを通じて共有メモリを作成する必要があります。関数をこのメモリにコピーすると、新しくプロセスを閉じることができます。共有メモリの場合、Windowsの場合は、名前付き共有メモリの作成 http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspxになります。

その後も、関数を再度コピーするための別のメモリスペースを作成します。割り当てられた通常のメモリには読み取り/書き込みプロパティしかなく、プログラマーを実行すると、CPUが例外を生成するという考え方です。

したがって、Windowsの場合は、VirtualAllocを使用して、フラグPAGE_EXECUTE_READWRITE(http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887 (v=vs.85).aspx)を使用してメモリを割り当てる必要があります。 )。

void* address = NULL;
address= VirtualAlloc(NULL,
        sizeof(emitcode),
        MEM_COMMIT|MEM_RESERVE,
        PAGE_EXECUTE_READWRITE);

関数をにコピーした後、で関数をaddress呼び出すことができますがaddress、スタックのバランスを保つように十分に注意する必要があります。

于 2012-05-28T00:48:19.993 に答える
2

ダイナミックライブラリは、問題に最適です。また、別のプロセスを起動することを忘れてください。それ自体は別の問題ですが、上記の投稿に加えて、仮想割り当てを正しく実行した場合は、同じ「ローダー」内で関数を呼び出すだけで、心配する必要はありません。同じRAMサイズのバインドされたスタックを実行するためです。

本当の問題は次のとおりです。

1-ロードする関数をメインプログラムからオフラインでコンパイルします。

2-コンパイラによって生成されたバイナリから関連するコードを抽出します。

3-文字列をロードします。

1と2では、IDEのプッシュボタンだけでなく、コンパイラフラグオプション、リンカなどを含むコンパイラスイート全体を深く理解する必要があります。

1と2で問題がない場合は、std::stringまたは純粋なchar*以外のものを使用することが有害である理由を知っておく必要があります。

話全体を続けることはできますが、これはハッカー/クラッカーのやり方であり、通常のユーザーにダイナミックライブラリの使用を強くお勧めします。これが存在する理由です。

于 2012-05-28T03:23:56.087 に答える
0

通常、これをコードインジェクションと呼びます...

基本的に、最新のオペレーティングシステムでは、セキュリティのために初期ロードが実行された後に実行のために何かにアクセスすることは禁止されているため、OS全体で検証されたダイナミックライブラリにフォールバックする必要があります。

つまり、有効なコンパイル済みコードがある場合、その効果を本当に実現したい場合は、関数をメモリにロードしてから、システム固有の方法で実行可能ファイルとして定義(NXビットをクリア)する必要があります。

しかし、明確にしましょう。関数はコードの位置に依存しない必要があり、シンボルを解決するために動的リンカーの助けはありません...それは仕事の難しい部分です。

于 2018-08-21T15:49:29.657 に答える