подскажите на каком этапе запуска процесса в его адресном прострастве появляется ntdll.dll и какая очередность дальнейшей подгрузки библиотек. вот ms-rem писал: 1) Разбор параметров переданных в CreateProcessW, открытие исполнимого файла и определение его типа. На этом этапе определяется является ли запускаемый файл dos или win16 файлом (для них запускается ntvdm.exe и wowexec.exe соответственно), для .bat и .cmd файлов запускается cmd.exe. В дальнейшем будем считать, что запускается обычный win32 PE файл. 2) Производиться открытие исполнимого файла с помощью ZwOpenFile. 3) Из открытого файла создается секция с атрибутом SEC_IMAGE с помощью вызова ZwCreateSection. 4) С помощью ZwQuerySection извлекаются атрибуты стека и точки входа запускаемого процесса. 5) Создается объект нового процесса с помощью ZwCreateProcess. На уровне ядра в этот момент происходит создание адресного пространства и структуры EPROCESS. Важно заметить, что в этот момент процесс еще не имеет своих потоков и не может исполняться. 6) Происходит установка приоритета процесса с помощью ZwSetInformationProcess. 7) С помощью ZwQueryInformationProcess извлекается выданный системой адрес PEB нового процесса. 8) Производиться заполнение PEB и дуплицирование хэндлов ввода-вывода (только для консольных программ). В этот момент многократно вызывается ZwAlocateVirtualMemory, ZwReadVirtualMemory и ZwWriteVirtualMemory. 9) Производиться выделение памяти под стек первичного потока и подготовка его стартового контекста. 10) С помощью ZwCreateThread создается первичный поток. 11) Подсистема win32 (csrss.exe) информируется о старте нового процесса через LPC сообщения. На верхнем уровне этим заведует функция CsrClientCallServer, которая в свою очередь вызывает ZwRequestWaitReplayPort. 12) Первичный поток запускается на исполнение с помощью ZwResumeThread. но о подгрузке библиотек в АП процесса ничего нету. ведь таблица импорта заполняется с помощью LdrGetProcedureAddress ?
пролистай двусвязный список в пебе - там дллки в порядке загрузки расположены обычно это нтдлл, твой ехе и кернел32.длл (вроде бы так)
Проецирует нтдлл ядро при создании процесса: NtCreateProcessEx -> PspCreateProcess -> MmInitializeProcessAddressSpace -> PsMapSystemDll При запуске первого потока в процессе блок загрузчика есчо не создан(PEB.Ldr = NULL), адресное пространство выглядит аналогичным как у процесса System. Первый поток начинает исполнять диспетчер апк, отсюда выполняется инициализация загрузчика(ядро ставит обработчик апк LdrInitializeThunk): LdrInitializeThunk -> LdrpInitialize -> LdrpInitializeProcess Именно последняя процедура выделяет хип под блок данных загрузчика, подгружает kernel32.dll и пр. Там что описано по пунктам слишком обобщено, на самом деле всё гораздо сложнее, код загрузчика занимает значительную часть нтдлл.
Один мог бы узреть порядок загрузки dll самостоятельно, загрузив тот же блокнот в WinDbg, выставив опцию [Debug - Event Filters - Load Module: Enabled] и сделав [.restart /f]. Таким образом можно будет "остановиться" сразу после загрузки ntdll.dll ядром, ещё до того, как начал выполняться какой-либо юзермодный код (хорошее время, чтобы сделать [bu LdrInitializeThunk]). (Здесь нужно учесть, что контекст, который покажет WinDbg при первом останове — это не начальный юзермодный контекст, но тот контекст, который будет у потока уже после отработки APC (т.е. после загрузки и инициализации библиотек)).