Domanda

È possibile utilizzare windows ganci o altri metodi per fare l'iniezione di codice c#?Ho visto un sacco di cose su di iniezione di codice, ma tutti sono fatti in C/C++.Non so una di queste lingue e hanno un momento davvero difficile tradurre.Qualcuno ha qualche idea su come fare questo?

È stato utile?

Soluzione

Kevin, è possibile.È possibile creare una biblioteca con finestra gancio proc utilizzando C++gestito.Tutto quello che dovete fare è quello di iniettare questo gancio in alcune applicazioni l'utilizzo di standard di WinAPI (SetWindowsHookEx etc.).All'interno di questo gancio si può chiamare, Sistema: a:AppDomain::CurrentDomain->metodo Load per caricare l'assembly in applicazione di destinazione del dominio di applicazione.Quindi è possibile chiamare i metodi definiti nell'assemblaggio con l'utilizzo di riflessione.Per esempio, Snoop utilizza questo metodo.

Altri suggerimenti

Mike di Stallo ha questo esempio, che utilizza CreateRemoteThread.Ha il vantaggio di non richiedere alcun C++.

EDIT: Mi sembra di aver frainteso la domanda ....Ho avuto l'impressione che la domanda riguardava l'iniezione di codice nel processo corrente.


Io adesione al partito piuttosto in ritardo, ma ho appena usato esattamente questo un paio di settimane fa:

Un delegato contiene i campi privati IntPtr _methodPtr e IntPtr _methodPtrAux, che rappresentano il corpo dell'indirizzo di memoria.Impostando il campo di via (riflessione) per valori specifici, è possibile modificare l'indirizzo di memoria a cui il PEI sarà di puntamento.
Utilizzando queste informazioni, è possibile effettuare le seguenti operazioni:

  1. Creare un array con l'assemblea di byte, che devono essere eseguiti
  2. Spostare il delegato del metodo puntatore al byte in questione
  3. Chiamare il delegato
  4. Profitto ???

(Naturalmente, è possibile modificare il _methodPtr-valore a qualsiasi indirizzo di memoria-anche in spazio kernel, ma questo potrebbe richiedere privilegi di esecuzione).


Ho un lavoro codice di esempio qui, se vuoi:

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

Che può essere utilizzato come segue:

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

Naturalmente, potrebbe anche scrivere il seguente metodo:

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

Lo stesso potrebbe essere fatto per i metodi esistenti (non delegati) via di riflessione:

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


Utilizzare qualsiasi codice a vostro rischio e pericolo. Gli esempi di codice deve essere compilato con l' /unsafe-opzione del compilatore.

È possibile controllare CInject per l'iniezione di codice in .NET assembly al sito CodePlex http://codeinject.codeplex.com/.Non è necessario avere alcuna conoscenza di iniezione di codice per iniettare il codice quando si utilizza CInject.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top