Сбой удаленного потока при вызове LoadLibrary с ошибкой 87
Я пытаюсь создать удаленный поток, который будет загружать DLL, которую я написал, и запускать функцию из нее. DLL работает нормально (проверено), но по какой-то причине удаленный поток завершается ошибкой, и процесс, в котором он был создан, перестает отвечать.
Я использовал ollyDebug, чтобы попытаться увидеть, что идет не так, и заметил две вещи...
- Мои строки (имя DLL и имя функции) передаются в удаленный поток правильно
- Сбой потока в LoadLibrary с кодом последней ошибки 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;
}
Редактировать:
Это часть, в которой я выделяю память для удаленного процесса:
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 );
Редактировать: похоже, проблема в том, что удаленный поток вызывает "мусорный" адрес вместо базового адреса LoadLibrary. Возможно, Visual Studio неправильно связала адрес удаленного процесса LoadLibrary?
Редактировать: когда я пытаюсь запустить тот же самый точный код, что и локальный поток (я использую дескриптор к текущему процессу в CreateRemoteThread), все это работает просто отлично. Что может вызвать это?
Должен ли я добавить код вызывающей функции? Кажется, он выполняет свою работу, поскольку код выполняется в удаленном потоке с правильными параметрами...
Код скомпилирован под VS2010.
data - это простая структура с символами char* в именах. (Поскольку явное написание строк в коде привело бы к указателям на мой исходный процесс).
Что я делаю неправильно?
2 ответа
Сбой с 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
,;-)
Вполне возможно, что LoadLibrary фактически использует псевдоним LoadLibraryW (в зависимости от настроек проекта), который является версией Unicode. Всякий раз, когда вы используете Windows API со строками "char" вместо "TCHAR", вы должны явно использовать имена версий ANSI. Это предотвратит отладку, когда код будет написан, а также в будущем для вас или кого-либо еще в случае, если проект когда-либо переключится на Unicode.
Итак, в дополнение к исправлению этой ужасной проблемы с неопределенной строкой, обязательно используйте:
LoadLibraryA(data->dll);