質問
Windows フックまたはその他の方法を使用して C# でコード インジェクションを行うことはできますか?コードインジェクションについてはたくさんのことを見てきましたが、それらはすべて C/C++ で行われます。私はどちらの言語も分からないので、翻訳するのに本当に苦労しています。これを行う方法について何かアイデアがある人はいますか?
解決
ケビン、それは可能です。マネージド C++ を使用して、ウィンドウ フック プロシージャを使用してライブラリを作成できます。標準の WinAPI (SetWindowsHookEx など) を使用してこのフックをアプリケーションに挿入するだけです。このフック内で System::AppDomain::CurrentDomain->Load メソッドを呼び出して、アセンブリをターゲット アプリケーションの AppDomain にロードできます。その後、リフレクションを使用してアセンブリで定義されたメソッドを呼び出すことができます。例えば、 詮索 はこの方法を使用します。
他のヒント
マイク・ストールは このサンプル, 、CreateRemoteThreadを使用します。C++ を必要としないという利点があります。
編集: 質問を誤解していたようです...。質問は現在のプロセスへのコードインジェクションに関するものだと思いました。
私はかなり遅れてパーティーに参加しましたが、数週間前にまさにこれを使用したばかりです。
デリゲートにはプライベートフィールドが含まれます IntPtr _methodPtr
そして IntPtr _methodPtrAux
, 、本体のメモリアドレスを表します。(リフレクションを介して) フィールドを特定の値に設定することにより、EIP が指すメモリ アドレスを変更できます。
この情報を使用すると、次のことが可能になります。
- 実行されるアセンブリバイトを含む配列を作成します
- デリゲートのメソッド ポインターを問題のバイトに移動します。
- 代表者に電話する
- 利益 ???
(もちろん変更も可能です) _methodPtr
-value を任意のメモリ アドレスに設定できます (カーネル空間内でも可能ですが、これには適切な実行権限が必要な場合があります)。
必要に応じて、ここに実際に動作するコード例があります。
public static unsafe int? InjectAndRunX86ASM(this Func<int> del, byte[] asm)
{
if (del != null)
fixed (byte* ptr = &asm[0])
{
FieldInfo _methodPtr = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo _methodPtrAux = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic | BindingFlags.Instance);
_methodPtr.SetValue(del, ptr);
_methodPtrAux.SetValue(del, ptr);
return del();
}
else
return null;
}
これは次のように使用できます。
Func<int> del = () => 0;
byte[] asm_bytes = new byte[] { 0xb8, 0x15, 0x03, 0x00, 0x00, 0xbb, 0x42, 0x00, 0x00, 0x00, 0x03, 0xc3 };
// mov eax, 315h
// mov ebx, 42h
// add eax, ebx
// ret
int res = del.InjectAndRunX86ASM(asm_bytes); // should be 789 + 66 = 855
もちろん、on は次のメソッドを記述することもできます。
public static unsafe int RunX86ASM(byte[] asm)
{
Func<int> del = () => 0; // create a delegate variable
Array.Resize(ref asm, asm.Length + 1);
// add a return instruction at the end to prevent any memory leaks
asm[asm.Length - 1] = 0xC3;
fixed (byte* ptr = &asm[0])
{
FieldInfo _methodPtr = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo _methodPtrAux = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic | BindingFlags.Instance);
_methodPtr.SetValue(del, ptr);
_methodPtrAux.SetValue(del, ptr);
return del();
}
}
おそらく、リフレクションを介して既存のメソッド (デリゲートではない) に対しても同じことを行うことができます。
// UNTESTED //
Action new_method_body = () => { };
MethodInfo nfo = typeof(MyType).GetMethod( ..... );
IntPtr ptr = nfo.MethodHandle.Value; // ptr is a pointer to the method in question
InjectX86ASM(new_method_body, new byte[] { ......., 0xC3 }); // assembly bytes to be injected
int target = new_method_body.Method.MethodHandle.Value.ToInt32();
byte[] redirector = new byte[] {
0xE8, // CALL INSTRUCTION + TARGET ADDRESS IN LITTLE ENDIAN
(byte)(target & 0xff),
(byte)((target >> 8) & 0xff),
(byte)((target >> 16) & 0xff),
(byte)((target >> 24) & 0xff),
0xC3, // RETURN INSTRUCTION
};
Marshal.Copy(redirector, 0, ptr, redirector.Length);
コードは自己責任で使用してください。 コード例は次のようにコンパイルする必要があります。
/unsafe
-コンパイラスイッチ.
CodePlex サイトで .NET アセンブリへのコード挿入のための CInject をチェックアウトできます。 http://codeinject.codeplex.com/. 。CInject を使用する場合、コードを挿入するためにコード インジェクションに関する知識は必要ありません。