Можно ли использовать pipe для совместного использования Dll в разных процессах? - PullRequest
0 голосов
/ 27 июля 2010

Прежде чем перейти к моему вопросу, позвольте мне объяснить, что именно я делаю. У меня есть основной процесс, скажем, ProcessA, я подключил ProcessA, а также ввел dll (скажем, myDll.dll) в пространство процессов ProcessA.Now.в какой-то момент ProcessA запускает другой процесс, который является ProcessB. Оба процесса A и B находятся в совершенно разных пространствах памяти процесса. Я хочу поделиться myDll.dll (который вставлен в процесс processA) в ProcessB (на самом деле это пространство процесса ProcessB).Это может быть сделано с использованием метода трубопровода или любого другого подходящего метода.заранее спасибо.

1 Ответ

1 голос
/ 27 июля 2010

Код DLL будет автоматически передаваться различным процессам. Только для оптимизации вы должны выбрать хороший базовый адрес DLL (см. http://msdn.microsoft.com/en-US/library/f7f5138s.aspx).

Для обмена данными между процессами вы можете, например, использовать объекты общей памяти или просто поместить некоторые переменные, которые вам нужны, в раздел, который вы пометили как общий (см. http://support.microsoft.com/kb/100634 и http://msdn.microsoft.com/en-us/library/h90dkhs0.aspx для подробности). Чтобы пометить раздел «.SHAREDSECTIONNAME» как общедоступный, вы можете использовать

#pragma comment(linker, "/section:.SHAREDSECTIONNAME,RWS")

Чтобы не было конфликтов при записи / чтении из общей памяти, вы должны использовать именованное событие или мьютекс точно так же, как и во всех других случаях многопроцессорной связи.

ОБНОВЛЕНО на основе комментария: если вы создаете дочерний процесс самостоятельно, вы получаете дескриптор дочернего процесса с полными правами. Таким образом, у вас достаточно прав для заражения DLL в отношении CreateRemoteThread API. Вот рабочий код на C, который запускает CMD.EXE и внедряет MyTest.dll в адресное пространство:

#include <Windows.h>

int main()
{
    STARTUPINFO si = { sizeof(STARTUPINFO) };
    PROCESS_INFORMATION pi = {0};
    TCHAR szCommandLine[4096] = TEXT("CMD.EXE");
    BOOL bIsSuccess;
    DWORD dwStatus;
    LPCTSTR pszLibFile = TEXT("C:\\Oleg\\MyTest\\Release\\MyTest.dll");
    PTSTR pszLibFileRemote = NULL;
    HANDLE hThread = NULL;
    int cb;
    HMODULE hModule = NULL;

    bIsSuccess = CreateProcess (NULL, szCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);

    // Calculate the number of bytes needed for the DLL's pathname
    cb  = (1 + lstrlen(pszLibFile)) * sizeof(TCHAR);

    __try {
        PTHREAD_START_ROUTINE pfnThreadRtn;

        // Allocate space in the remote process for the pathname
        pszLibFileRemote = (PTSTR) VirtualAllocEx (pi.hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
        if (pszLibFileRemote == NULL) __leave;  // error

        // Copy the DLL's pathname to the remote process's address space
        if (!WriteProcessMemory (pi.hProcess, pszLibFileRemote, (PVOID) pszLibFile, cb, NULL)) __leave;

        // Get the real address of LoadLibraryW in Kernel32.dll
        // Real address of Kernel32.dll in dwProcessId and in our Process MUST be the same !!!
        // Remote Process MUST have Kernel32.dll loaded (SMSSS.EXE and System havn't)!!!
#ifdef UNICODE
        pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress (GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
#else
        pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress (GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");
#endif
        if (pfnThreadRtn == NULL) __leave;

        // Create a remote thread that calls LoadLibraryW(DLLPathname)
        hThread = CreateRemoteThread (pi.hProcess, NULL, 0, pfnThreadRtn, (LPVOID)pszLibFileRemote, 0, NULL);
        if (hThread == NULL) __leave;

        dwStatus = ResumeThread (pi.hThread);

        // Wait for the remote thread to terminate
        if (WaitForSingleObject (hThread, INFINITE) != WAIT_OBJECT_0) __leave;

        GetExitCodeThread (hThread, (PDWORD)&hModule);

        // hModule is the address in the destination process (CMD.EXE)
        // of the injected DLL
        // You can verify that it is really loaded for example with respect of 
        // Process Explorer (http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx)
    }
    __finally {
        // Free the remote memory that contained the DLL's pathname
        if (pszLibFileRemote != NULL)
            bIsSuccess = VirtualFreeEx (pi.hProcess, pszLibFileRemote, 0, MEM_RELEASE);

        if (hThread != NULL)
            bIsSuccess = CloseHandle (hThread);

        if (pi.hProcess != NULL)
            bIsSuccess = CloseHandle (pi.hProcess);

        if (pi.hThread != NULL)
            bIsSuccess = CloseHandle (pi.hThread);
    }

    return 0;
}
...