2012-04-07 13 views
5

Quiero llamar a una función en un proceso remoto de una DLL inyectada que he creado.Función de llamada en DLL inyectado

me han inyectado con éxito mi DLL con:

CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA"), pLibRemote, 0, NULL); 

El DllMain se ejecuta y la DLL se ejecuta en un modo stand-by. Lo que me gustaría hacer es llamar de alguna manera a la DLL cargada remotamente para hacer algo de trabajo.

He intentado exportar la función como esta:

extern "C" __declspec(dllexport) void MyFunc(void) 

y después de ejecutar la función como esta:

CreateRemoteThread(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("mydll"), "MyFunc"), NULL, 0, NULL); 

pero da lugar a un accidente.

¿Cómo puedo solucionar esto?

+0

¿Qué devuelve GetModuleHandle? ¿Qué devuelve GetProcAddress? –

+0

Ambos devuelven 0. GetModuleHandle intenta obtener un control de un módulo en el proceso de host donde no lo he cargado. –

Respuesta

13

Llamando GetModuleHandle ya que tendrá la base de la DLL, ya que se asigna a su proceso (si es que lo hace). Entonces, lo que debe hacer es primero asegurarse de exportar la función en la DLL. Puede hacer lo que ha hecho o crear un archivo .def como se muestra en here. A partir de entonces:

En Teoría

  1. inyectar la DLL para el proceso de destino y obtener la dirección de base que se cargó a
  2. Inyectar el DLL para el proceso actual. Use GetProcAddress para encontrar el desplazamiento entre la función exportada y la base de la DLL.
  3. Agregue este desplazamiento a la dirección base obtenida del paso 1. CreateRemoteThread en esta ubicación.

En la práctica

Al hacer su inyección de DLL, es posible que usted pueda obtener la base de que el archivo DLL se carga en el objetivo.

HMODULE hInjected; 

hThread = CreateRemoteThread(hProcess, NULL, 0, 
     (LPTHREAD_START_ROUTINE)(GetProcAddress(hMod, 
     "LoadLibraryW")), lpAddress, 0, NULL); 

// Locate address our payload was loaded 
if(hThread != 0) { 
    WaitForSingleObject(hThread, INFINITE); 
    GetExitCodeThread(hThread, (LPDWORD)&hInjected); 
    CloseHandle(hThread); 
} 

hInjected será la base de la DLL inyectado. Entonces tengo otra función:

void* GetPayloadExportAddr(LPCWSTR lpPath, HMODULE hPayloadBase, LPCSTR lpFunctionName) { 
    // Load payload in our own virtual address space 
    HMODULE hLoaded = LoadLibrary(lpPath); 

    if(hLoaded == NULL) { 
    return NULL; 
    } else { 
    void* lpFunc = GetProcAddress(hLoaded, lpFunctionName); 
    DWORD dwOffset = (char*)lpFunc - (char*)hLoaded; 

    FreeLibrary(hLoaded); 
    return (DWORD)hPayloadBase + dwOffset; 
    } 
} 

Lo que esto hace es cargar primero la carga en nuestro propio espacio de direcciones virtuales. Luego, podemos usar GetProcAddress para obtener la dirección de la función exportada. A partir de esto, podemos obtener el desplazamiento de la función desde la base de la DLL. Agregar este desplazamiento al hInjected que obtuvimos antes nos dirá dónde debe realizarse la llamada CreateRemoteThread. Por lo que podría hacer una llamada de este modo:

BOOL InitPayload(HANDLE hProcess, LPCWSTR lpPath, HMODULE hPayloadBase, HWND hwndDlg) { 
    void* lpInit = GetPayloadExportAddr(lpPath, hPayloadBase, "Init"); 
    if(lpInit == NULL) { 
    return FALSE; 
    } else { 
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, 
     lpInit, hwndDlg, 0, NULL); 

    if(hThread == NULL) { 
     return FALSE; 
    } else { 
     CloseHandle(hThread); 
    } 
    } 

    return TRUE; 
} 

Este es todo el código que se arrancó de un old project I have. Puede tomar el código y hacer lo que quiera con él, pero sé que si tuviera que volver a escribir el código ahora, haría muchas cosas de manera diferente.

2

La respuesta de Mike funciona si está inyectando una DLL de 32 bits en un proceso de 32 bits.

Si desea inyectar un archivo DLL de 64 bits en un proceso de 64 bits, no puede obtener la dirección base del archivo DLL desde GetExitCodeThread, ya que solo le proporcionará los 32 bits inferiores de la dirección de 64 bits.

Para obtener la dirección correcta en este caso, debe escribir un bloque de código en el proceso que se llama LoadLibrary (almacenando el resultado en un lugar específico en la memoria de proceso), ejecutar este bloque de código (usando CreateRemoteThread), y luego vuelva a leer la dirección desde esa ubicación usando ReadProcessMemory.

Puede encontrar más detalles de esta aquí (incluyendo PowerShell y el código ASM) aquí: http://clymb3r.wordpress.com/2013/05/26/implementing-remote-loadlibrary-and-remote-getprocaddress-using-powershell-and-assembly/

A continuación, puede calcular el offset a su función exportada de la misma manera Mike describe, pero cuidado para almacenar la diferencia en un valor de 64 bits, y no en un DWORD (que es de 32 bits).