Как правильно использовать VirtualFreeEx при попытке ввести DLL

также, найдите комментарий //, который разбивает закрытие фигурной скобки

if (1==1) { //echo "it is true"; }

, закрывающая фигурная скобка не будет правильно закрывать условный раздел, а php не будет правильно обработать оставшуюся часть кода.

-1
задан R Smith 15 January 2019 в 21:32
поделиться

1 ответ

Вы вообще не обрабатываете ошибки. OpenProcess(), VirtualAllocEx(), WriteProcessMemory(), CreateRemoteThread(), все эти функции могут потерпеть неудачу, вы должны справиться с этим. И GetLastError() имеет значение, только если они действительно терпят неудачу.

В CreateRemoteThreadInject(), если CreateRemoteThread() завершается успешно, вы не ждете завершения потока, прежде чем пытаться освободить выделенную память. И вы закрываете HANDLE для процесса перед тем, как использовать HANDLE для освобождения выделенной памяти. И вы не закрываете HANDLE, возвращенное CreateRemoteThread().

Вы делаете вещи в правильном порядке в Injectstuff(), но вам все еще не хватает адекватной обработки ошибок, а также вы не выделяете достаточно памяти для нулевого терминатора в строке пути DLL.

Но почему у вас две функции, выполняющие по существу одно и то же? Единственная реальная разница между ними заключается в том, что Injectstuff() запрашивает у OpenProcess() больше разрешений, чем ему действительно нужно, тогда как CreateRemoteThreadInject() запрашивает только те конкретные разрешения, которые ему действительно необходимы.

Кстати, использование system() для выполнения команд echo совершенно бесполезно. Вы должны просто написать std::cout или std::cerr вместо этого, и flush, если необходимо. Нет необходимости выкладывать системный командный процесс для выполнения его команды echo.

Вместо этого попробуйте что-то вроде этого:

void DisplayLastError(const char *operation, int err)
{
    std::cerr << "Error ";
    if (err) std::cerr << err << " ";
    std::cerr << operation << std::endl;
}

void DisplayLastError(const char *operation)
{
    DisplayLastError(operation, GetLastError());
}

bool CreateRemoteThreadInject(DWORD IDofproc, const char * dll)
{
    if (!IDofproc)
        return false;

    LPVOID pLoadLibrary = (LPVOID) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
    if (!pLoadLibrary)
    {
        DisplayLastError("getting LoadLibrary pointer");
        return false;
    }

    HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, IDofproc);
    if (!hProcess)
    {
        DisplayLastError("opening the process");
        return false;
    }

    LPVOID pMemory = VirtualAllocEx(hProcess, NULL, strlen(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (!pMemory)
    {
        DisplayLastError("allocating memory");
        CloseHandle(hProcess);
        return false;
    }

    if (!WriteProcessMemory(hProcess, pMemory, dll, strlen(dll) + 1, NULL))
    {
        DisplayLastError("writing to allocated memory");
        VirtualFreeEx(hProcess, pMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return false;
    }

    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibrary, pMemory, 0, NULL);
    if (!hThread)
    {
        DisplayLastError("creating remote thread");
        VirtualFreeEx(hProcess, pMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return false;
    }

    WaitForSingleObject(hThread, INFINITE);

    DWORD dwExitCode = 0;
    GetExitCodeThread(hThread, &dwExitCode);

    CloseHandle(hThread);

    VirtualFreeEx(hProcess, pMemory, 0, MEM_RELEASE);
    CloseHandle(hProcess);

    if (!dwExitCode)
    {
        DisplayLastError("loading dll", 0);
        return false;
    }

    MessageBox(NULL, TEXT("Injected"), TEXT(""), MB_OK);
    return true;
}

bool Injectstuff(DWORD processId, char* dllpath)
{
    std::cout << "Process ID: " << processId << std::endl;
    return CreateRemoteThreadInject(processId, dllpath);
}

Кроме того, обратите внимание, что код, необходимый для определения, успешно ли LoadLibraryA() работает или не работает должным образом, только когда целевой процесс является 32-разрядным. Функция, переданная в CreateRemoteThread(), должна всегда возвращать 32-битный DWORD, а LoadLibraryA() возвращает 32-битный HMODULE при вызове в 32-битном процессе, но возвращает 64-битный HMODULE, когда вызов в 64-битном процессе. Поток не может вернуть 64-битный код завершения, и GetExitCodeThread() не может получить 64-битный код выхода, поэтому возвращенный HMODULE будет усечен, что может привести к неточным результатам. Таким образом, не совсем уместно использовать LoadLibraryA() напрямую в качестве функции потока при внедрении в 64-битный процесс, если вы не заботитесь о результате загрузки. Если вам это нужно, вы можете вместо этого внедрить небольшой поток функций, который косвенно вызывает LoadLibrary() и сохраняет результат по адресу памяти, который инжектор может затем прочитать из использования ReadProcessMemory(), когда поток завершится. Или используйте другую технику впрыска .

0
ответ дан Remy Lebeau 15 January 2019 в 21:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: