Сбой удаленного потока при вызове LoadLibrary с ошибкой 87 - PullRequest
1 голос
/ 31 декабря 2011

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

Я использовал ollyDebug, чтобы попытаться увидеть, что идет не так, и заметил две вещи ...

  1. Мои строки (имя DLL и имя функции) правильно передаются в удаленный поток
  2. Поток завершается с ошибкой в ​​LoadLibrary с кодом lasterror 87 "ERROR_INVALID_PARAMETER"

Мое лучшее предположение заключается в том, что каким-то образом удаленный поток не может найти LoadLibrary (это потому, что компоновщик сделан с уважением к моему процессу ???, просто предположение ...)

Что я делаю не так?

Это код для функции дистанционного управления:

static DWORD WINAPI SetRemoteHook (DATA *data)
{
  HINSTANCE dll;
  HHOOK WINAPI hook;
  HOOK_PROC hookAdress;

  dll = LoadLibrary(data->dll);

  hookAdress = (HOOK_PROC) GetProcAddress(dll,data->func);
  if (hookAdress != NULL)
  {
    (hookAdress)(); 
  }
  return 1;
}

Edit:

Это часть, в которой я выделяю память для удаленного процесса:

typedef struct
{
    char* dll;
    char* func;
} DATA;

char* dllName = "C:\\Windows\\System32\\cptnhook.dll";  
char* funcName = "SetHook";
char* targetPrgm = "mspaint.exe";
Data lData;
lData.dll = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(dllName), MEM_COMMIT, PAGE_READWRITE );
lData.func = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(funcName), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, lData.func, funcName, sizeof(char)*strlen(funcName), &v );
WriteProcessMemory( explorer, lData.dll, dllName, sizeof(char)*strlen(dllName), &v );
rDataP = (DATA*) VirtualAllocEx( explorer, 0, sizeof(DATA), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, rDataP, &lData, sizeof(DATA), NULL );

Edit: Похоже, проблема в том, что удаленный поток вызывает «мусорный» адрес вместо базового адреса LoadLibrary. Возможно ли Visual Studio связана с адрес удаленного процесса LoadLibrary неправильный?

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

Должен ли я добавить код вызывающей функции? Кажется, делает свою работу как код выполняется в удаленном потоке с правильными параметрами ...

Код скомпилирован под VS2010.

data - это простая структура с символами * в именах. (Поскольку явное написание строк в коде привело бы к указателям на мой исходный процесс).

Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 02 января 2012

Сбой с ERROR_INVALID_PARAMETER означает, что существует проблема с переданными параметрами.

Поэтому следует взглянуть на data->dll, который представляет единственный рассматриваемый параметр.

Он инициализированздесь:

lData.dll = VirtualAllocEx(explorer, 0, sizeof(char) * (strlen(dllName) + 1), MEM_COMMIT, PAGE_READWRITE);

Итак, давайте добавим проверку, действительно ли выделение памяти, ссылка на которую должна быть сохранена в lData.dll, действительно прошло успешно.

if (!lData.dll) {
  // do some error logging/handling/whatsoever
}

ИмеяСделав это, вы могли обнаружить, что вызов как осуществленный не удался, потому что (дословно из MSDN для VirtualAllocEx()):

Функция завершается ошибкой, если вы пытаетесь зафиксировать страницу, которая не была зарезервирована.Результирующий код ошибки: ERROR_INVALID_ADDRESS.

Поэтому вы можете изменить четвертый параметр рассматриваемого вызова в соответствии с рекомендациями (снова дословно из MSDN):

Резервироватьи зафиксируйте страницы за один шаг, вызовите VirtualAllocEx с помощью MEM_COMMIT |MEM_RESERVE.

PS: повторите это упражнение для вызова для выделения lData.func.; -)

0 голосов
/ 06 января 2012

Вполне возможно, что LoadLibrary фактически использует псевдоним LoadLibraryW (в зависимости от настроек проекта), который является версией Unicode. Всякий раз, когда вы используете Windows API со строками «char» вместо «TCHAR», вы должны явно использовать имена версий ANSI. Это предотвратит отладку, когда код написан, а также в будущем для вас или кого-либо еще в случае, если проект когда-нибудь переключится на Unicode.

Итак, в дополнение к решению этой ужасной проблемы с неопределенной строкой, обязательно используйте:

LoadLibraryA(data->dll);
...