Est-ce que Windows Forms ont moins d'autorisations que les applications de la console?

voix
0

J'ai créé une bibliothèque pour injecter des fichiers DLL dans les processus en utilisant une variété de méthodes. Je le tester avec une interface graphique utilisant Windows Forms.

Toutes les méthodes fonctionnent comme prévu, sauf lors de l'utilisation QueueUserAPC. Lorsque je tente d'utiliser cette méthode, le processus que je me injecte une DLL dans les accidents.

J'ai créé une application console de base pour tester cette méthode en dehors d'un Windows Form et cela a fonctionné comme prévu sans le plantage du processus. En outre, ma vérification d'erreur me dit que la DLL est injectait sans aucune erreur lors de l'utilisation de la méthode QueueUserAPC à partir d'un formulaire Windows, cependant, le processus se bloque encore.

J'ai le sentiment que la raison pour laquelle le processus se bloque lorsque vous utilisez un Windows Form est de ne pas faire avec le code de la méthode QueueUserAPC et plus sur les autorisations d'un formulaire Windows. Cependant, je peux me tromper si je vais inclure le code de la méthode ci-dessous.

PInvoke

[DllImport(kernel32.dll, SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessPrivileges dwDesiredAccess, bool bInheritHandle, int dwProcessId);

[DllImport(kernel32.dll, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport(kernel32.dll, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

[DllImport(kernel32.dll, SetLastError = true)]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, MemoryAllocation flAllocationType, MemoryProtection flProtect);

[DllImport(kernel32.dll, SetLastError = true)]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, int lpNumberOfBytesWritten);

[DllImport(kernel32.dll, SetLastError = true)]
public static extern bool QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData);

[DllImport(kernel32.dll, SetLastError = true)]
public static extern void CloseHandle(IntPtr handle);

[DllImport(kernel32.dll, SetLastError=true)]
public static extern void VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, MemoryAllocation dwFreeType);

public enum MemoryAllocation
{
    Commit = 0x1000,
    Reserve = 0x2000,
    Release = 0x8000,
    AllAccess = Commit | Reserve
}

public enum MemoryProtection
{
    PageReadWrite = 0x04,
    PageExecuteReadWrite = 0x40
}

public enum ThreadAccess
{
    SuspendResume = 0x02,
    GetContext = 0x08,
    SetContext = 0x010,
    AllAccess = SuspendResume | GetContext | SetContext
}

Méthode QueueUserAPC

public static class MQueueUserAPC
{
    public static bool Inject(string dllPath, string processName)
    {
        // Get the pointer to load library

        var loadLibraryPointer = GetProcAddress(GetModuleHandle(kernel32.dll), LoadLibraryA);

        if (loadLibraryPointer == IntPtr.Zero)
        {
            return false;
        }

        // Get the handle of the specified process

        var processId = Process.GetProcessesByName(processName)[0].Id;

        var processHandle = OpenProcess(ProcessPrivileges.AllAccess, false, processId);

        if (processHandle == IntPtr.Zero)
        {
            return false;
        }

        // Allocate memory for the dll name

        var dllNameSize = dllPath.Length + 1;

        var dllMemoryPointer = VirtualAllocEx(processHandle, IntPtr.Zero, (uint) dllNameSize, MemoryAllocation.AllAccess, MemoryProtection.PageReadWrite);

        if (dllMemoryPointer == IntPtr.Zero)
        {
            return false;
        }

        // Write the dll name into memory

        var dllBytes = Encoding.Default.GetBytes(dllPath);

        if (!WriteProcessMemory(processHandle, dllMemoryPointer, dllBytes, (uint) dllNameSize, 0))
        {
            return false;
        }

        // Call QueueUserAPC on each thread

        foreach (var thread in Process.GetProcessesByName(processName)[0].Threads.Cast<ProcessThread>())
        {
            var threadId = thread.Id;

            // Get the threads handle

            var threadHandle = OpenThread(ThreadAccess.SetContext, false, (uint) threadId);

            // Add a user-mode APC to the APC queue of the thread

            QueueUserAPC(loadLibraryPointer, threadHandle, dllMemoryPointer);

            // Close the handle to the thread

            CloseHandle(threadHandle);
        }

        // Close the previously opened handle

        CloseHandle(processHandle);

        // Free the previously allocated memory

        VirtualFreeEx(processHandle, dllMemoryPointer, dllNameSize, MemoryAllocation.Release);

        return true;
    }  
}

Comment je l'utilise dans mon formulaire Windows / Application console

var injector = new Injector();

if(Injector.QueueUserAPC(dllPath, processName))
{
    MessageBox.Show(No error was raised);
}

Je suppose que ce que je demande est faire Windows Forms ont moins d'autorisations que les applications de la console et si oui, comment pourrais-je configurer mon formulaire Windows afin que je ne cours pas dans le problème du plantage du processus en essayant l'utilisation QueueUserAPC.

Si vous souhaitez tester la bibliothèque , je l' ai sur Github avec des instructions sur la façon de l' utiliser.

Créé 20/10/2018 à 03:29
source utilisateur
Dans d'autres langues...                            


1 réponses

voix
1

processus se bloque parce que vous appelez VirtualFreeExpour la mémoire, où vous stockez nom de dll ( dllMemoryPointer). quand LoadLibrarycommencer à utiliser cette mémoire , il peut être déjà pas valide. APC - ce qui est asynchrone appel de procédure, de sorte que vous ne pouvez pas savoir, au point où vous appelez VirtualFreeEx, sont LoadLibrarydéjà exécutés ou en cours, ou même pas commencer.

sur les autorisations - bien sûr pas. si vous avez pas d' autorisation - vous ne parvenez pas simplement processus ouvert ou threads en cours. comme rien Result arrive. que vous avez obtenu l' accident dans le processus cible, visa versa confirmé que vous disposez des autorisations.

aussi besoin de comprendre que tous les threads en cours seront en état alertable, après que vous injectez APC à elle. si possible, en dépit de cette APC sera mise en file avec succès - il ne sera jamais appelé. injecter à toutes les discussions en cours, en espérant qu'au moins l' un d'entre eux seront en voie d'état alertable mal. tout d' abord peut - être pas, à la deuxième - certains fils de travail peuvent être ne pas concevoir pour les appels LoadLibrarydu tout - dire thread ne peut avoir aucun contexte d'activation, de se connecter à csrss, peut - être une autre. tout cela peut aussi produire des effets ou accident non défini. et enfin c'est tout simplement pas efficace.

l'injection par l' intermédiaire QueueUserAPCutile dans le cas où vous créer procédé lui - même (dans l' état suspendu) et injecter apc au fil du processus initial avant de le reprendre. ce sera le travail (comment minimum jusqu'à ce que) parce que nouveau thread en cours commence l' exécution en mode utilisateur toujours de LdrInitializeThunk(où il initialize processus et / ou appelez charge code dll) et avant saut au point d'entrée réel toujours (dans toutes les fenêtres existantes versions) appel ZwTestAlert. exactement à ce stade , votre APC appel sera exécuté. mais strictement parlant c'est pas 100% de manière correcte, parce que nous utilisons LoadLibrary[W/A]comme APC point d'entrée. mais ce sera si APC exceuted trop tôt, quand kernel32.dllpas encore cartographié pour traiter ou encore non initialisé? de toute évidence cet accident. dans les fenêtres claires ne doit pas être cette situation (apc sera appelé après le processus de complètement initialisé, tous dll statique chargé, juste avant le point d'entrée appel exe). mais possible que certains pilotes d' injecter du code auto pour traiter via APC appel (dire sur la cartographie kernel32.dll événement) et la force APC exécution à ce stade. comme résultat seul moyen fiable à 100% utilisent ici ZwQueueApcThreadpour shellcode, qui sera appeler seulement ntdll api, dll charge par l' intermédiaire LdrLoadDllet dll lui - même ont l' importation statique que de ntdll.dll

Créé 20/10/2018 à 07:33
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more