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 и завершит этот поток. |