DLL-инъекция с помощью CreateRemoteThread

Если вы посмотрите на следующий рабочий код простой DLL-инъекции:

  //Open the target process with read , write and execute priviledges
   Process = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, FALSE, ID); 

   //Get the address of LoadLibraryA
   LoadLibrary = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); 

   // Allocate space in the process for our DLL 
   Memory = (LPVOID)VirtualAllocEx(Process, NULL, strlen(dll)+1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 

   // Write the string name of our DLL in the memory allocated 
   WriteProcessMemory(Process, (LPVOID)Memory, dll, strlen(dll)+1, NULL); 

   // Load our DLL 
   CreateRemoteThread(Process, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibrary, (LPVOID)Memory, NULL, NULL); 

   //Let the program regain control of itself
   CloseHandle(Process); 

Меня смущает то, что GetProcAddress возвращает адрес LoadLibraryA fucntion текущего процесса, как вы можете передать его как параметр CreateRemoteThread и ожидать целевой процесс, чтобы запустить его?

Ответ 1

Он работает случайно. Это очень распространенная авария, Microsoft прилагает большие усилия, чтобы библиотеки DLL операционной системы, такие как kernel32.dll, имели базовый адрес, который не конфликтует с другими DLL. Дальнейшее расширение kernel32.dll, загружаемое очень рано при инициализации процесса, настолько низкое, что он должен бороться, чтобы получить свой предпочтительный базовый адрес.

Вы легко сбежате. Примечательно, что в прошлом этот имел неправильный код, появилось обновление безопасности XP, в результате чего gdi32.dll переместился и запустил много машин при загрузке. Правильный путь довольно болезнен, CreateToolhelp32Snapshot() + Module32First/Next(), чтобы найти смещение перемещения, не является большой радостью. Честно говоря, вы, вероятно, не должны этого делать, если операционная система "такая странная".

Ответ 2

LoadLibraryA живет в kernel32.dll, модуле, который всегда загружается в каждый процесс и также может быть загружен по одному и тому же адресу в каждом процессе.

Ответ 3

Рандомизация пространственного расположения адресов (ASLR) - это функция предотвращения уязвимостей, выполняемая Windows, и позволяет перемещать адреса, чтобы помочь злоумышленникам определить адрес для использования чего-либо в памяти (останавливает жесткое кодирование адресов/смещений), Однако модули Windows только изменяют свои адреса за сеанс.

Если у вас есть процесс, который использует kernel32.dll(не все процессы используют kernel32.dll, и я объясню это дальше через несколько минут), адрес для подпрограммы может быть 55AA1122 в качестве примера (что неверный пример адрес). Теперь следующий процесс с kernel32.dll будет иметь тот же адрес для 55AA1122 для той же самой процедуры, что и предыдущий.... Только если процессы имеют одну и ту же архитектуру.

32-разрядные процессы будут иметь одинаковые адреса для экспорта kernel32.dll, среди других экспорта модулей Windows (например, NTDLL, USER32 и т.д.). 64-битные процессы будут иметь разные адреса для 32-битных процессов, однако для 64-битных процессов все будут иметь одинаковые адреса для модулей Windows!

Создание удаленных потоков не было "случайностью", Microsoft намеренно реализовала его. Зачем? Microsoft много использует его во время самих Windows, а также для асинхронных вызовов процедур. Microsoft также часто исправляет проблемы для своих подпрограмм как антиреверсивный трюк, или если они теряют исходный код для своих собственных проектов, ха-ха.

Теперь, когда ядро ​​kernel32.dll загружается в процесс, оно загружается только в процессы, которые используют API Win32. Это включает 99% программ в мире, однако можно скомпилировать собственный процесс, который не будет его использовать. Однако это заставит вас полностью использовать API-интерфейс Native API и API Win32, а процесс Windows, называемый smss.exe, выполняет именно это. Вы также можете скомпилировать Native DLL, которые даже не имеют обычной процедуры запуска DLL API API.

Короче говоря, адреса для модулей модуля Windows меняются один раз за загрузку. Он будет поддерживать то же самое до следующей перезагрузки и так далее. 32-разрядные процессы имеют свои собственные общие адреса модулей Windows для каждого процесса, а также 64-битные процессы. Таким образом, вы не можете использовать адрес LoadLibraryA для 64-разрядного процесса, ориентируясь на DLL-инъекцию для 32-разрядного процесса, если вы не используете 32-разрядный адрес Kernel32.dll LoadLibraryA. Лучшей идеей было бы использовать LdrLoadDll в любом случае, или просто инъекцию кода оболочки в отражающий DLL загрузчик.