Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #58, СЕНТЯБРЬ 2005 г.

Windows на страже порядка

Deeoni$

Спецвыпуск: Хакер, номер #058, стр. 058-004-5


Получив адрес LoadLibrary в нашем процессе, его можно запросто использовать в удаленном. Как это становится возможным? kernel32.dll, содержащая функцию загрузки DLL, всегда проецируется на один и тот же диапазон адресов, поэтому в разных процессах точки входа в API-функцию будут совпадать. Конечно, теоретически ОС может загрузить что угодно и куда угодно, но на практике kernel32.dll находится всегда в одном и том же месте. Взглянем на этот маленький листинг:

С первой проблемой покончено, возьмемся за вторую. Ее суть заключается в том, что строка с полным именем библиотеки находится в адресном пространстве нашего процесса. Это нехорошо, так как мы передаем этот параметр удаленному потоку в другом процессе, а по этому адресу может быть что угодно. Приложение из-за этого сразу загнется, издав предсмертное сообщение о необрабатываемом исключении.

Все это решается очень просто. Нужно разместить эту злосчастную строку в адресном пространстве удаленного процесса и при вызове CreateRemoteThread передавать именно смещение в чужом процессе. В этом деле поможет такая функция API:

LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);

Единственным примечательным параметром функции является hProcess, который должен содержать хэндл другого процесса. После выделения памяти нужно записать туда строку с полным именем DLL, для чего пригодится WriteProcessMemory:

BOOL WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten);

Параметр hProcess идентифицирует удаленный процесс, lpBaseAddress и lpBuffer определяют адреса в адресных пространствах удаленного и локального процесса, a nSize - число передаваемых байтов. По адресу, на который указывает параметр lpNumberOfBytesWritten, возвращается число фактически считанных или записанных байтов.

Теперь немного (коротко и ясно) обобщим сказанное. Первым делом мы выделяем блок памяти в адресном пространстве удаленного процесса при помощи VirtualAllocEx. Затем копируем в полученный блок строку с полным именем библиотеки функцией WriteProcessMemory, после чего получаем GetProcAdress'ом адрес LoadLibraryA или LoadLibraryW внутри Kernel32. И, в конце концов, вызываем CreateRemoteThread, создавая удаленный поток в требуемом процессе, который вызовет соответствующую LoadLibrary и передаст ей адрес выделенного участка памяти.

На этом этапе DLL внедрена в удаленный процесс, а ее функция DllMain получила уведомление DLL_PROCESS_ATTACH и может приступить к выполнению нужного кода. Когда DllMain вернет управление, удаленный поток выйдет из LoadLibrary и вернется в функцию BaseThreadStart, которая в свою очередь вызовет ExitThread и завершит этот поток.

Назад на стр. 058-004-4  Содержание  Вперед на стр. 058-004-6