найти загруженную dll с помощью CreateToolHelp32Snapshot, найти функцию в dll и затем вызвать ее, GetProcAddress

Я пытаюсь получить дескриптор функции в .dll. Я создаю CreateToolHelp32Snapshot, а затем перечисляю модули, пока не найду тот, который мне нужен, из этой .dll я хочу найти конкретную функцию. Как мне правильно вызвать GetProcAddress(), чтобы получить функцию в «этой» .dll, а не в другом экземпляре, который может быть запущен?

Продолжением вышеприведенного вопроса будет: хорошо, у меня есть дескриптор функции, как мне ее вызвать?

РЕДАКТИРОВАТЬ: Как уже было указано. Я уже нахожусь в адресном пространстве стороннего приложения. Если getprocaddress не будет работать, как мне получить точку входа для функции, используя readprocessmemory и необходимое смещение?

Спасибо.

HANDLE h_th_32snap =  CreateToolhelp32Snapshot(0x8u, pid);
if( h_th_32snap == INVALID_HANDLE_VALUE )
  {
    printError( TEXT("CreateToolhelp32Snapshot (of modules)") );
    return( FALSE );
  }

  // Set the size of the structure before using it.
  me32.dwSize = sizeof( MODULEENTRY32 );

  // Retrieve information about the first module,
  // and exit if unsuccessful
  if( !Module32First( h_th_32snap, &me32 ) )
  {
    printError( TEXT("Module32First") );  // show cause of failure
    CloseHandle( h_th_32snap );           // clean the snapshot object
    return( FALSE );
  }

  // Now walk the module list of the process,
  // and display information about each module

  BYTE *d_pointer_qtgui4_dll = 0x0;
  do
  {
    _tprintf( TEXT("\n\n     MODULE NAME:     %s"),   me32.szModule );
    _tprintf( TEXT("\n     Executable     = %s"),     me32.szExePath );
    _tprintf( TEXT("\n     Process ID     = 0x%08X"),         me32.th32ProcessID );
    _tprintf( TEXT("\n     Ref count (g)  = 0x%04X"),     me32.GlblcntUsage );
    _tprintf( TEXT("\n     Ref count (p)  = 0x%04X"),     me32.ProccntUsage );
    _tprintf( TEXT("\n     Base address   = 0x%08X"), (DWORD) me32.modBaseAddr );
    _tprintf( TEXT("\n     Base size      = %d"),             me32.modBaseSize );

    if(!wcsncmp(me32.szModule, L"QtGui4.dll", 255))
    {

              FARPROC test = GetProcAddress(GetModuleHandle( L"QtGui4.dll"),"?rowsInserted@QListView@@MAEXABVQModelIndex@@HH@Z");

    }

  } while( Module32Next( h_th_32snap, &me32 ) );

  CloseHandle( h_th_32snap );

Грег, мне было бы интересно узнать, почему это неправильно? Ошибок не выдает, но и не работает!

прототип функции:

QWidget * QWidget::find ( WId id )   [static];

Моя попытка назвать это:

hDLL = GetModuleHandle( L"QtGui4.dll");
if (hDLL != NULL)
{

   func pointer_find = (func)GetProcAddress(hDLL,"?find@QWidget@@SAPAV1@PAUHWND__@@@Z");

   if (!pointer_find)
   {
      // handle the error
      FreeLibrary(hDLL);       
      //return SOME_ERROR_CODE;
   }
   else
   {
      // call the function
       widget = pointer_find(my_hwnd);
   }
}

person flavour404    schedule 06.01.2011    source источник
comment
Это в вашем приложении или вы автоматизируете второе приложение?   -  person Greg Domjan    schedule 06.01.2011
comment
пытается автоматизировать второе приложение.   -  person flavour404    schedule 06.01.2011


Ответы (2)


Невозможно, GetProcAddress() требует дескриптор модуля. HMODULE действителен только внутри процесса, в котором он был получен. Вам придется делать то же самое, что и GetProcAddress(), повторяя IAT, чтобы найти точку входа. И применить смещение базового адреса. Это очень сложно сделать для другого процесса, поскольку вы не можете напрямую получить доступ к памяти для чтения IAT. Требуется ReadProcessMemory.

Внедрение кода в целевой процесс — единственный разумный подход. Что также необходимо для того, чтобы сделать то, что, как я полагаю, вы захотите сделать дальше, вызвать функцию. Методы внедрения кода хорошо освещены на codeproject.com.

person Hans Passant    schedule 06.01.2011
comment
Я уже в адресном пространстве процесса (это все внутри внедренной dll), и я хорошо знаком с readprocessmemory, чего я раньше не делал, так это того, что я в основном спрашивал, как получить точку входа для функции. Итак, используя readprocessmemory, как мне найти и вызвать функцию? - person flavour404; 06.01.2011
comment
Это не то, что говорит ваш код. Используйте 0 для второго аргумента CreateToolHelp32Snapshot(). Если вы уже находитесь внутри процесса, то почему бы просто не вызвать LoadLibrary + GetProcAddress? ReadProcessMemory совершенно не нужен. - person Hans Passant; 06.01.2011

Если вы находитесь в процессе, вы почти у цели.

GetModuleHandle получит текущий загруженный дескриптор модуля, по сравнению с LoadLibrary, который загрузит модуль (и увеличит количество ссылок). Просто нужен правильный прототип для функции.

typedef void __thiscall (QListView::*rowsInserted)(class QModelIndex const &,int,int);

rowsInserted test = (rowsInserted)GetProcAddress(GetModuleHandle( L"QtGui4.dll"),"?rowsInserted@QListView@@MAEXABVQModelIndex@@HH@Z");

//QListView *object
if( test && object )
  (object.*test)(my_QModelIndex, int_x, int_y);
person Greg Domjan    schedule 06.01.2011
comment
Грег, правильный прототип защищен: virtual void __thiscall QListView::rowsInserted(class QModelIndex const &,int,int) - так что мне просто нужно пройти (test(my_QModelIndex, int_x, int_y) и будет ли это делать? - person flavour404; 07.01.2011
comment
ну, вы, вероятно, не должны вызывать защищенные функции, если только вы не наследуете это как базу, и в этот момент мне интересно, как вы добрались до загрузки этой функции... но я обновлю пример, насколько смогу - person Greg Domjan; 07.01.2011
comment
Грег спасибо. Из всего, что я прочитал, функция QWidget::find(hwnd), но я думаю, что мой проект настроен неправильно, так что в итоге у меня работают два экземпляра. Я прибегаю, чтобы увидеть, работает ли вышеизложенное и дает ли мне то, что я хочу, мне просто нужно получить искаженное имя для функции поиска, а затем я проверю его. Вся эта штука с Qt действительно сбивает с толку, я только хочу поймать виджет Qt (окно) и получить доступ к паре методов. - person flavour404; 07.01.2011
comment
Грег. Я расширил свой вопрос, пытаясь вызвать более простую функцию QWidget::find, для которой требуется только один параметр (hwnd), но я снова делаю что-то не так... Интересно узнать, почему моя подпись неверна. спасибо - person flavour404; 10.01.2011