Как правильно использовать VirtualFreeEx при попытке ввести DLL - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь сделать DLL-инжектор, но в функциях есть ошибки параметров.

Я попытался изменить переменную на char *, я подтвердил, что идентификатор процесса правильный, я не могу скомпилировать его в x64 или x86, потому что я использую блоки кода, но программу, которую я пытаюсь Он был создан с блоками кода, DLL работает с другими инжекторами, я подтвердил, что путь к DLL правильный.

void EchoLastError()
{
    std::string ToExecute;
    std::stringstream Command;
    Command << "echo " << GetLastError();
    ToExecute = Command.str();
    system(ToExecute.c_str());
    Command.str(std::string());
}
BOOL CreateRemoteThreadInject(DWORD IDofproc, const char * dll)
{
    HANDLE Process;
    LPVOID Memory, LoadLibrary;
    if (!IDofproc)
    {
        return false;
    }
    Process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, IDofproc);

    EchoLastError();

    system("pause");
    LoadLibrary = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

    Memory = (LPVOID)VirtualAllocEx(Process, NULL, strlen(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    WriteProcessMemory(Process, (LPVOID)Memory, dll, strlen(dll) + 1, NULL);

    CreateRemoteThread(Process, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibrary, (LPVOID)Memory, NULL, NULL);
    EchoLastError();
    CloseHandle(Process);

    VirtualFreeEx(Process, (LPVOID)Memory, 0, MEM_RELEASE);
    EchoLastError();
    MessageBox(NULL, "Injected", "", MB_OK);

    return true;
}



//other
bool Injectstuff(DWORD processId, char* dllpath)
{
    std::stringstream kds;
    kds << "echo Process ID: " << processId;
    std::string dl = kds.str();
    system(dl.c_str());
    EchoLastError();
    HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
    EchoLastError();
    system("pause");
    if (hTargetProcess)
    {
        LPVOID LoadLibAddress = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
        EchoLastError();
    system("pause");
        LPVOID LoadPath = VirtualAllocEx(hTargetProcess, 0, strlen(dllpath), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        EchoLastError();
    system("pause");
        HANDLE RemoteThread = CreateRemoteThread(hTargetProcess, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibAddress, LoadPath, 0, 0);
        EchoLastError();
    system("pause");
        WaitForSingleObject(RemoteThread, INFINITE);
        EchoLastError();
    system("pause");
        VirtualFreeEx(hTargetProcess, LoadPath, strlen(dllpath), MEM_RELEASE);
        EchoLastError();
    system("pause");
        CloseHandle(RemoteThread);
        CloseHandle(hTargetProcess);
        return true;
    }
    return false;
}

Первая функция печатает 87 на VirtualFreeEx, вторая печатает 6 на VirtualFreeEx. Как я могу это исправить? Я использую компилятор GNU GCC.

1 Ответ

0 голосов
/ 16 января 2019

Вы вообще не обрабатываете ошибки. 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(), когда поток завершится. Или используйте другой метод инъекции .

...