Question

Pouvez-vous utiliser des hooks Windows ou d’autres méthodes pour effectuer une injection de code avec c# ?J'ai vu beaucoup de choses sur l'injection de code mais toutes sont réalisées en C/C++.Je ne connais aucune de ces langues et j’ai vraiment du mal à traduire.Quelqu'un a-t-il des idées sur la façon de procéder ?

Était-ce utile?

La solution

Kevin, c'est possible.Vous pouvez créer une bibliothèque avec un processus de hook de fenêtre en utilisant le C++ managé.Tout ce que vous avez à faire est d'injecter ce hook dans une application utilisant WinAPI standard (SetWindowsHookEx etc.).À l’intérieur de ce hook, vous pouvez appeler la méthode System::AppDomain::CurrentDomain->Load pour charger votre assembly dans l’AppDomain de l’application cible.Ensuite, vous pouvez appeler des méthodes définies dans votre assembly en utilisant la réflexion.Par exemple, Espionner utilise cette méthode.

Autres conseils

Mike Stall a cet échantillon, qui utilise CreateRemoteThread.Il a l’avantage de ne nécessiter aucun C++.

MODIFIER: Il me semble avoir mal interprété la question....J'avais l'impression que la question concernait l'injection de code dans le processus actuel.


Je rejoins la fête assez tard, mais je viens d'utiliser exactement ceci il y a quelques semaines :

Un délégué contient les champs privés IntPtr _methodPtr et IntPtr _methodPtrAux, qui représentent l'adresse mémoire du corps.En définissant le champ (via réflexion) sur des valeurs spécifiques, on peut modifier l'adresse mémoire vers laquelle l'EIP pointera.
En utilisant ces informations, on peut effectuer les opérations suivantes :

  1. Créez un tableau avec des octets d'assemblage, qui doivent être exécutés
  2. Déplacez le pointeur de méthode du délégué vers les octets en question
  3. Appeler le délégué
  4. Profit ???

(Bien sûr, vous pouvez modifier le _methodPtr-value à n'importe quelle adresse mémoire -- même dans l'espace du noyau, mais cela peut nécessiter des privilèges d'exécution appropriés).


J'ai un exemple de code fonctionnel ici, si vous voulez :

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

Qui peut être utilisé comme suit :

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

Bien entendu, on pourrait également écrire la méthode suivante :

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

La même chose pourrait probablement être faite avec les méthodes existantes (et non avec les délégués) via la réflexion :

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


Utilisez n'importe quel code à vos propres risques. Les exemples de code doivent être compilés avec le /unsafe-commutateur du compilateur.

Vous pouvez consulter CInject pour l'injection de code dans les assemblys .NET sur le site CodePlex http://codeinject.codeplex.com/.Vous n'avez pas besoin d'avoir des connaissances en injection de code pour injecter du code lorsque vous utilisez CInject.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top