Вопрос по c++ – Вызов функции во вставленной DLL

5

Я хочу вызвать функцию в удаленном процессе внедренной DLL, которую я создал.

Я успешно ввел мою DLL с:

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

DllMain выполняется, а DLL работает в режиме ожидания. То, что я хотел бы сделать, это как-то вызвать удаленно загруженную DLL, чтобы выполнить некоторую работу.

Я попытался экспортировать функцию следующим образом:

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

и затем выполнить функцию следующим образом:

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

но это приводит к краху.

Как я могу решить это?

Оба возвращают 0. GetModuleHandle пытается получить дескриптор модуля в хост-процессе, в который я его не загрузил. André
Что возвращает GetModuleHandle? Что возвращает GetProcAddress? David Heffernan

Ваш Ответ

2   ответа
13

призваниеGetModuleHandle как у вас получится база DLL, как она отображается в вашем процессе (если вообще). Итак, что вам нужно сделать, это сначала экспортировать функцию в DLL. Вы можете сделать, как вы сделали, или создать.def файл как показаноВот, После этого:

In Theory

  1. Inject the DLL to the target process and get the base address it was loaded at
  2. Inject the DLL to the current process. Use GetProcAddress to find the offset between the exported function and the base of the DLL.
  3. Add this offset to the base address obtained from step 1. CreateRemoteThread at this location.

In Practice

Выполняя инъекцию DLL, вы можете получить базу загрузки DLL в цель.

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 будет основой введенной DLL. У меня тогда есть другая функция:

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;
  }
}

Сначала это загружает полезную нагрузку в наше собственное виртуальное адресное пространство. После этого, мы можем использоватьGetProcAddress чтобы получить адрес экспортируемой функции. Отсюда мы можем получить смещение функции от базы DLL. Добавление этого смещения кhInjected мы получили раньше, скажут нам, гдеCreateRemoteThread звонок должен быть сделан. Таким образом, вы можете сделать звонок так:

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;
}

Это весь код, который вырван изстарый проект у меня есть, Вы можете взять код и делать с ним все, что хотите, но я знаю, что если бы я сейчас переписал код, я бы сделал многое по-другому.

3

Ответ Майка работает, если вы вводите 32-битную DLL в 32-битный процесс.

Если вы хотите внедрить 64-битную DLL в 64-битный процесс, вы не можете получить базовый адрес DLL изGetExitCodeThread так как он даст только 32 младших бита 64-битного адреса.

Чтобы получить правильный адрес в этом случае, вы должны написать блок кода в процессе, который вызываетLoadLibrary (сохраняя результат в определенном месте в памяти процесса), выполните этот блок кода (используяCreateRemoteThread), а затем зачитать адрес из этого места, используяReadProcessMemory.

Вы можете найти более подробную информацию для этого здесь (включая PowerShell и код ASM) здесь: http://clymb3r.wordpress.com/2013/05/26/implementing-remote-loadlibrary-and-remote-getprocaddress-using-powershell-and-assembly/

Затем вы можете вычислить смещение для вашей экспортируемой функции так же, как описывает Майк, но следите, чтобы сохранить разницу в 64-битном значении, а не в DWORD (32-битном).

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