C++注入dll导出函数

问题描述 投票:0回答:1

我试图在 Windows .exe 进程中注入 dll,例如 notepad.exe,注入工作正常,但是当 dll 已经注入到进程中并且我尝试调用导出的函数时,它告诉我没有这样的函数dll 中的函数。

注射器

#include <Windows.h>
#include <stdio.h>
#include <cassert>
#include <TlHelp32.h> // Para enumerar módulos en el proceso remoto

// Función para obtener el handle del módulo cargado remotamente
HMODULE GetRemoteModuleHandle(HANDLE hProcess, const wchar_t* moduleName) {
    HMODULE hModule = nullptr;
    MODULEENTRY32 me = { sizeof(me) };

    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetProcessId(hProcess));
    if (hSnapshot == INVALID_HANDLE_VALUE)
        return nullptr;

    if (Module32First(hSnapshot, &me)) {
        do {
            if (_wcsicmp(me.szModule, moduleName) == 0) {
                hModule = me.hModule;
                break;
            }
        } while (Module32Next(hSnapshot, &me));
    }

    CloseHandle(hSnapshot);
    return hModule;
}

int main(int argc, const char* argv[]) {
    if (argc < 3) {
        printf("Usage: Inyector <pid> <dllPath>\n");
        return 0;
    }

    auto pid = atoi(argv[1]);

    // Abrir el proceso objetivo
    HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD, FALSE, pid);
    if (!hProcess) {
        printf("Error opening process (%u)\n", GetLastError());
        return 1;
    }

    // Reservar memoria en el proceso objetivo
    auto p = VirtualAllocEx(hProcess, nullptr, 1 << 12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    assert(p);

    // Escribir la ruta de la DLL en la memoria del proceso
    WriteProcessMemory(hProcess, p, argv[2], strlen(argv[2]) + 1, nullptr);

    // Crear un hilo remoto que cargue la DLL usando LoadLibraryA
    auto hThread = CreateRemoteThread(hProcess, nullptr, 0,
        (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA"), p, 0, nullptr);

    assert(hThread);
    WaitForSingleObject(hThread, INFINITE);

    // Obtener el handle del módulo cargado en el proceso remoto
    HMODULE remoteModule = GetRemoteModuleHandle(hProcess, L"mydll.dll");
    if (!remoteModule) {
        printf("Error: No se pudo encontrar el módulo remoto\n");
        return 1;
    }

    // Calcular la dirección de la función exportada en el proceso remoto
    auto funcAddr = (LPVOID)GetProcAddress(GetModuleHandle(L"mydll.dll"), "MyFunc");
    if (!funcAddr) {
        printf("Error: No se pudo encontrar la función 'MyFunc'\n");
        return 1;
    }

    // Ajustar la dirección de la función para el proceso remoto
    uintptr_t remoteFuncAddr = (uintptr_t)funcAddr - (uintptr_t)GetModuleHandle(L"mydll.dll") + (uintptr_t)remoteModule;

    // Crear un hilo remoto para llamar a MyFunc
    auto hFuncThread = CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)remoteFuncAddr, nullptr, 0, nullptr);
    if (!hFuncThread) {
        printf("Error: No se pudo ejecutar la función remota (%u)\n", GetLastError());
    }
    else {
        printf("Función remota ejecutada con éxito.\n");
    }

    // Limpiar
    CloseHandle(hFuncThread);
    CloseHandle(hThread);
    CloseHandle(hProcess);

    return 0;
}

DLL

#include <windows.h>


// Exportar la función
extern "C" __declspec(dllexport) void MyFunc(long parm1) {

    for (int i = 1; i <= 10; i++) {
        // Mostrar un cuadro de mensaje en cada iteración
        MessageBox(
            NULL,                                // Ventana padre (NULL para ninguna)
            L"Este es un mensaje de prueba",     // Texto del mensaje
            L"Iteración del MessageBox",         // Título del cuadro de mensaje
            MB_OK | MB_ICONINFORMATION           // Botón OK con un ícono de información
        );
    }

}

// Función opcional para el punto de entrada de la DLL
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Injection process and calling the exported dll fucnion

Checking the name of the exported dll function with Visual Studio's developer tool

可能发生什么事?

c++ c dll dllexport
1个回答
0
投票

仔细检查 DLL 以确保函数确实按照您期望的方式导出。它可能会导出为

"_MyFunc“
甚至
"_MyFunc@4"
,具体取决于您的编译器设置。

但是,即使您可以实现此功能,您导出的 DLL 函数也不符合

CreateRemoteThread()
所期望的签名,因此以这种方式调用 DLL 函数是未定义的行为。 将签名更改为:

extern "C" __declspec(dllexport) DWORD WINAPI MyFunc(LPVOID parm1) {
    ...
    return 0;
}

然后使用

.def
文件按照您想要的方式导出函数。

© www.soinside.com 2019 - 2024. All rights reserved.