Frage

Können Sie Windows-Hooks oder andere Methoden verwenden, um Code-Injection mit C# durchzuführen?Ich habe viel über Code-Injection gesehen, aber alles wird in C/C++ gemacht.Ich kenne keine dieser Sprachen und es fällt mir wirklich schwer, zu übersetzen.Hat jemand eine Idee, wie man das macht?

War es hilfreich?

Lösung

Kevin, es ist möglich.Sie können eine Bibliothek mit Window-Hook-Proc mithilfe von verwaltetem C++ erstellen.Alles, was Sie tun müssen, ist, diesen Hook mithilfe der Standard-WinAPI (SetWindowsHookEx usw.) in eine Anwendung einzuschleusen.Innerhalb dieses Hooks können Sie die Methode System::AppDomain::CurrentDomain->Load aufrufen, um Ihre Assembly in die AppDomain der Zielanwendung zu laden.Anschließend können Sie in Ihrer Assembly definierte Methoden mithilfe von Reflektion aufrufen.Zum Beispiel, Schnüffler verwendet diese Methode.

Andere Tipps

Mike Stall hat dieses Beispiel, das CreateRemoteThread verwendet.Es hat den Vorteil, dass kein C++ erforderlich ist.

BEARBEITEN: Ich scheine die Frage falsch interpretiert zu haben ...Ich hatte den Eindruck, dass es bei der Frage um die Code-Injektion in den aktuellen Prozess ging.


Ich steige ziemlich spät in die Party ein, aber genau das habe ich erst vor ein paar Wochen genutzt:

Ein Delegat enthält die privaten Felder IntPtr _methodPtr Und IntPtr _methodPtrAux, die die Speicheradresse des Körpers darstellen.Indem man das Feld (über Reflektion) auf bestimmte Werte setzt, kann man die Speicheradresse ändern, auf die das EIP zeigt.
Mit diesen Informationen kann man Folgendes tun:

  1. Erstellen Sie ein Array mit Assembly-Bytes, die ausgeführt werden sollen
  2. Verschieben Sie den Methodenzeiger des Delegaten auf die betreffenden Bytes
  3. Rufen Sie den Delegierten an
  4. Gewinn???

(Natürlich können Sie das ändern _methodPtr-Wert an eine beliebige Speicheradresse senden – sogar im Kernel-Bereich, dies erfordert jedoch möglicherweise entsprechende Ausführungsrechte).


Wenn Sie möchten, habe ich hier ein funktionierendes Codebeispiel:

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;
}

Was wie folgt verwendet werden kann:

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

Natürlich könnte man auch die folgende Methode schreiben:

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();
    }
}

Das Gleiche könnte wahrscheinlich durch Reflektion mit vorhandenen Methoden (nicht Delegierten) gemacht werden:

// 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);


Die Verwendung jeglichen Codes erfolgt auf eigene Gefahr. Die Codebeispiele müssen mit kompiliert werden /unsafe-Compiler-Schalter.

Sie können CInject für die Code-Injection in .NET-Assemblys auf der CodePlex-Site ausprobieren http://codeinject.codeplex.com/.Sie müssen keine Kenntnisse über Code-Injektion haben, um Code einzuschleusen, wenn Sie CInject verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top