8

コマンド ライン ユーティリティを C# アプリケーションに埋め込みたいので、そのバイトを配列として取得し、別のファイルとしてディスクに保存することなく実行可能ファイルを実行できます (実行可能ファイルを別のファイルとして保存することを回避し、一時ファイルを任意の場所に書き込みます)。

バイトストリームだけから実行可能ファイルを実行する方法が見つかりません。ウィンドウはディスク上にある必要がありますか、それともメモリから実行する方法はありますか? Windowsでディスク上にある必要がある場合、.NETフレームワークで何らかの仮想ドライブ/ファイルを作成し、そのファイルを実行可能ファイルのメモリストリームにマップする簡単な方法はありますか?

4

4 に答える 4

11

高レベルの管理された環境に実装される、非常に低レベルのプラットフォーム固有の機能を求めています。何でも可能ですが、誰も簡単だとは言いませんでした...

(ところで、一時ファイルの管理が面倒だと思う理由がわかりません。BCLがそれを行います:http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename.aspx


  1. 実行可能ファイルを保持するのに十分なメモリを割り当てます。もちろん、マネージ ヒープに常駐することはできないため、この演習のほとんどすべてと同様に、PInvoke が必要です。(実際には、夢中になりすぎないように、C++/CLI をお勧めします)。割り当てられたメモリ ページに適用する属性ビットに特に注意してください。属性ビットを間違えると、ギャップのあるセキュリティ ホールが開いたり、DEP によってプロセスがシャットダウンされたりします (つまり、クラッシュします)。http://msdn.microsoft.com/en-us/library/aa366553(VS.85).aspxを参照してください。

  2. アセンブリのリソース ライブラリで実行可能ファイルを見つけ、固定ハンドルを取得します。

  3. Memcpy() マネージド ヒープの固定領域からネイティブ ブロックへのコード。

  4. GCHandle を解放します。

  5. VirtualProtectを呼び出して、実行可能メモリ ブロックへのさらなる書き込みを防止します。

  6. VirtualAlloc から取得したハンドルと、DUMPBIN または同様のツールで表示されるファイル内のオフセットに基づいて、プロセスの仮想アドレス空間内の実行可能ファイルの Main 関数のアドレスを計算します。

  7. 必要なコマンド ライン引数をスタックに配置します。( Windows Stdcall 規則)。もちろん、すべてのポインターは、ネイティブまたは固定された領域を指している必要があります。

  8. 計算されたアドレスにジャンプします。おそらく _call (インライン アセンブリ言語) を使用するのが最も簡単です。

  9. 通常の方法で LoadLibrary を呼び出すことによって修正される絶対的なジャンプが実行可能イメージに含まれていないことを神に祈ってください。(もちろん、ステップ #3 で LoadLibrary の頭脳を再実装したいと思わない限り)。

  10. @eax レジスタから戻り値を取得します。

  11. バーチャルフリーを呼び出します。

手順 5 と 11 は、finally ブロックで実行するか、IDisposable パターンを使用する必要があります。


もう 1 つの主なオプションは、RAM ドライブを作成し、そこに実行可能ファイルを書き込んで実行し、クリーンアップすることです。自己変更コードを書こうとしないので、少し安全かもしれません (これはいずれにせよ困難ですが、コードが自分のものではない場合は特にそうです)。しかし、動的コード インジェクション オプションよりもさらに多くのプラットフォーム API 呼び出しが必要になることはほぼ確実です。当然のことながら、すべての呼び出しに C++ または PInvoke が必要です。

于 2009-11-15T21:18:47.410 に答える
2

このホワイト ペーパーの「イン メモリ」セクションを参照してください。これはリモート DLL インジェクションの観点からのものですが、概念は同じである必要があることに注意してください。

リモート ライブラリ インジェクション

于 2009-08-03T19:55:00.510 に答える
1

RAM ディスクを作成するか、コードをメモリにダンプしてから実行することは、どちらも可能ですが、非常に複雑なソリューションです (マネージ コードではより複雑になる可能性があります)。

実行可能ファイルである必要がありますか? アセンブリとしてパッケージ化する場合は、メモリ ストリームから Assembly.Load() を使用できます - 数行の簡単なコードです。

または、本当に実行可能ファイルでなければならない場合、一時ファイルを書き込むことの実際の何が問題なのですか? 一時ファイルにダンプし、実行し、終了するのを待ってから一時ファイルを削除するには、数行のコードが必要です。削除する前にディスクキャッシュから取り出せない場合もあります! 単純で明白な解決策が最善の解決策である場合もあります。

于 2009-08-03T19:45:13.603 に答える
-1

これは、Vista+ では明示的に許可されていません。XP で文書化されていない Win32 API 呼び出しを使用してこれを行うことができますが、Vista+ ではこれが壊れていました。これは大規模なセキュリティ ホールであり、それを使用するのはマルウェア作成者だけだったからです。

于 2010-05-11T17:51:59.843 に答える