Делаю CreateRemoteThread для чужого ехе-шника(естествеено перед этим делаю virtualalloc+writeprocessmemory). Почему адрес, с которого начинается выполнение созданного удаленного потока, лежит внутри страничного имиджа одной из dll, загруженных чужим процессом? Как вообще такое может быть?
Когда PE-модуль загружается, в нём могут присутствовать discardable-секции, память под такие секции сразу же освобождается после использования секции загрузчиком, что приводит к образованию, скажем так, дырки в образе загруженного модуля. Проверь, в какое именно место .dll-модуля ты записал свой код. Ну и вообще, с чего ты взял-то, что в образ записал свой код, как смотрел?
Запустил ехе-шник через createprocess с параметром DEBUG_ONLY_THIS_PROCESS. Мне пришел отладочный евент LOAD_DLL_DEBUG_EVENT - там передается база dll(lpBaseOfDll). Делаю ReadProcessMemory(....., lpBaseOfDll, DllDosHeader, .....) получаю _lfanew, делаю ReadProcessMemory(..., lpBaseOfDll+DllDosHeader._lfanew, DllImageNTHeaders, ...) получаю DllImageNTHeaders.OptionalHeader.SizeOfImage. И потом почему-то при создании удаленного потока, его стартовый адрес находится между lpBaseOfDll и lpBaseOfDll+DllImageNTHeaders.OptionalHeader.SizeOfImage, при этом dll ессно не выгружалась. Как такое бываeт - не понимаю?????
Deader Название dll со стартовым адресом предлагаете угадать? Если в системе нет проактивок, то я ставлю на ntdll . Поток в режиме пользователя должен именно с неё стартовать. Если же под стартовым адресом понимается то, что возвращается ThreadQuerySetWin32StartAddress (то, что указывается в eax пользовательского контекста при создании потока), то есть проактивки, которые его подменяют (хотя eip стратового контекста они могут точно так же подменять).
Сорри, но я чет не понял ничего. Проактивок нету. Ну да, в каждый юзермодный процесс всегда сразу грузятся kernel и ntdll. Но почему поток, внедренный с помощью createremotethread, должен стартовать с ntdll? Как вообще когда перед createremotethread я выделяю память(virtualallocex) - как она выделяется в том месте, куда загружен ntdll?
причем вот еще какая странность - когда я делаю CreateRemoteThread, то указываю там один стартовый адрес, а в отладочном событии CREATE_THREAD_DEBUG_EVENT мне приходит уже совсем другой стартовый адрес CreateThread.lpStartAddress. Почему так?
Deader Так. Ещё раз с нуля. Когда Вы вызываете CreateRemoteThread, инициализируется стартовый контекст нового потока. В стартовом контексте eip указывается равным адресу RtlUserThreadStart в ntdll, а не тому, который указан в параметре CreateRemoteThread. Т.е. пользовательский поток обязан стартовать из ntdll, которая проводит начальную инициализацию потока (вызовы DllMain загруженных dll, инициализация TLS, SEH и т.п.). Тот же адрес, который передаётся параметром CreateRemoteThread, записывается в регистр eax стартового контекста потока. После выполнения начальной инициализации ntdll вызывает процедуру, указанную при вызове CreateRemoteThread, используя это значение eax.
Все так и есть как сказал l_inc - оказывается в событии CREATE_THREAD_DEBUG_EVENT всегда указывается адрес RtlUserThreadStart из ntdll, а не тот, который в параметре CreateRemoteThread. l_inc спасибо ОГРОМНОЕ !!! Прояснили очень важный ньюанс, о котором я понятия не имел.