Здравствуйте, Аноним, Вы писали:
А>Если бы для ntdll не применялась ASLR, то ASLR бы эффективно отсутствовала – какой смысл рандомизировать что-то, если известна база хоть одного исполняемого модуля? Да ещё такой модуль как ntdll, ух. А>Дело в другом. При создании секции для образов применяется ASLR и фиксятся релоки. Кроме того, соответствующим образом изменяется база в заголовке (для секции!). Когда такая секция мапится, система пытается отобразить её по выбранному ранее адресу (который редко совпадает с адресом в PE-хидере в файле на диске). Если это удаётся, возвращается STATUS_SUCCESS, а если нет, то маппирование происходит по другому адресу – и возвращается STATUS_IMAGE_NOT_AT_BASE (говорящий о том, что нужно пофиксить релоки перед использованием имаджа). А>Так что способ узнать дефолтный рандомизированный адрес "промапить и прочитать из хидера" полностью валиден. Кстати, юзермодный загрузчик проверяет необходимость применения релоков к первичному модулю процесса именно таким способом – сравнивает базу в заголовке с заполненным ядром полем Peb->ImageBase.
не смотрел как в других процессов, но на начальной стадии загрузки (Phase1Initialization) если промапить что-то другое на ImageBase ntdll — то будет бсод с кодом PROCESS1_INITIALIZATION_FAILED (6b).
>не смотрел как в других процессов
Мы смотрели дизасм когда-то – создание объекта "процесс" окончиться неудачей. Ntdll должна быть промаплена во всех процессах по одному и тому же адресу (основная причина, как нам кажется – ядерные колбеки). (Здесь нет противоречий – относительно указанной в дисковом файле базы образ может быть релоцирован).
>Редко какой ехе имеет таблицу релоков.
Готовы поспорить, что если сейчас пропарсить %windir% и %ProgramFiles% на нашей системе, то окажется, что более 91.21% экзешников имеют релоки ;)
>Но вообще сама идея ASLR под винду полный уг, учитывая что список модулей с базами и именами вычитывается из PEB'а кодом в несколько десятков строчек, без использования каких либо API.
Нет-нет-нет. Само собой разумеется, что локально можно узнать базы модулей (в т.ч. ядерных). ASLR не предназначена (никогда не предназначалась!) против локальных атак. Но она является бампером для удалённых попыток выполнить код (т.е. она должна предотвратить возникновение ситуации, когда один сможет вот так вот начать листать базу данных лоадера). И в этом плане здесь всё ok.
А>Пробовал открыть ZwOpenFile (дальше хотел мапить и посмотреть ImageBase) — но не получилось, при открытии произошла ошибка STATUS_OBJECT_PATH_NOT_FOUND (если не ошибаюсь).
какой путь передавали в ZwOpenFile ? надо бы "\\SystemRoot\\system32\\ntdll.dll", DOSовские симлинки (те которые \??\) на этом этапе еще не подмонтированы.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
А>>>Вопрос простой — если драйвер имеет Start = 0 (то есть SERVICE_BOOT_START) как можно получить базу ntdll.dll ? А>>>Пробовал открыть ZwOpenFile (дальше хотел мапить и посмотреть ImageBase) А>>К начальному вопросу. Вот получит один путь к ntdll, откроет его и промапит – а что толку? Будет получена база для этого промапленного вида, не совпадающая с общесистемной базой – разве нет? O>База, по которой ntdll грузится, находится в ее PE хидере. Виндовый ASLR ее вроде пока еще не релокейтит.
Вы абсолютно правы. Если загрузчик не сможет промапить ntdll на адрес который находиться PE хедере — будет бсод.
база модуля ntdll
От:
Аноним
Дата:
14.07.10 21:07
Оценка:
Доброе время суток!
Вопрос простой — если драйвер имеет Start = 0 (то есть SERVICE_BOOT_START) как можно получить базу ntdll.dll ?
Пробовал открыть ZwOpenFile (дальше хотел мапить и посмотреть ImageBase) — но не получилось, при открытии произошла ошибка STATUS_OBJECT_PATH_NOT_FOUND (если не ошибаюсь). Пробовал делать слепок модулей ZwQuerySystemInformation — но не повезло.
Заранее спасибо!
Re[2]: база модуля ntdll
От:
Аноним
Дата:
14.07.10 21:33
Оценка:
Здравствуйте, ononim, Вы писали:
А>>Пробовал открыть ZwOpenFile (дальше хотел мапить и посмотреть ImageBase) — но не получилось, при открытии произошла ошибка STATUS_OBJECT_PATH_NOT_FOUND (если не ошибаюсь). O>какой путь передавали в ZwOpenFile ? надо бы "\\SystemRoot\\system32\\ntdll.dll", DOSовские симлинки (те которые \??\) на этом этапе еще не подмонтированы.
Вы правы, передавал "\\SystemRoot\\system32\\ntdll.dll" — опробовал "\\Device\\HarddiskVolume1\\Windows\\system32\\ntdll.dll" — заработало, но тепер другой вопрос постает: как получить этот путь динамически?
Здравствуйте, x64, Вы писали:
А>>...как получить этот путь динамически?
x64>Не понял, зачем динамически? Вот это ("\\SystemRoot\\system32\\ntdll.dll") по идее должно работать в boot-time.
Вот это ("\\SystemRoot\\system32\\ntdll.dll") работать не будет.
AB>Вот это ("\\SystemRoot\\system32\\ntdll.dll") работать не будет.
Давненько не имел дела с boot-time. А почему, кстати? Ссылка \SystemRoot там уже есть, сформирована чуть по-другому (ARC-имя), но это вроде не смертельно. Что ещё?
Здравствуйте, x64, Вы писали:
AB>>Вот это ("\\SystemRoot\\system32\\ntdll.dll") работать не будет.
x64>Давненько не имел дела с boot-time. А почему, кстати? Ссылка \SystemRoot там уже есть, сформирована чуть по-другому (ARC-имя), но это вроде не смертельно. Что ещё?
Если посмотреть то ошибка возвращается в nt!ObpLookupObjectName, при повторном прохождении по символьной ссылке.
Вот вам call-stack:
при открытие символьной ссылки "\ArcName\multi(0)disk(0)rdisk(0)partition(1)" уже возвращает STATUS_OBJECT_NAME_NOT_FOUND(C0000034) и по этому не пройдет.
AB>при открытие символьной ссылки "\ArcName\multi(0)disk(0)rdisk(0)partition(1)" уже возвращает STATUS_OBJECT_NAME_NOT_FOUND(C0000034) и по этому не пройдет.
Да, всё верно, эта ссылка \ArcName\multi(0)disk(0)rdisk(0)partition(1) будет создана чуть позже. Автору в таком случае остаётся одно из двух:
1. Подождать, пока эта ссылка не будет создана и распарсить её рекурсивно (начиная, тем не менее, с \SystemRoot). Ждать тут, по идее, недолго.
2. Учитывая, что сами девайсы томов к этому моменту уже созданы, можно попытаться сопоставить \ArcName\multi(0)disk(0)rdisk(0)partition(1) девайсу тома \Device\HarddiskVolume1. По идее, ничего сложного, только не забыть учесть различные шины типа \ArcName\scsi(0)... и прочие.
Это более-менее документированные варианты. Возможно, ещё есть способы покопаться в блоке загрузчика, но это недокументировано и я не помню, чтобы там было что-то, что помогло бы при решении этой задачи. Есть другие идеи?
Здравствуйте, x64, Вы писали:
AB>>при открытие символьной ссылки "\ArcName\multi(0)disk(0)rdisk(0)partition(1)" уже возвращает STATUS_OBJECT_NAME_NOT_FOUND(C0000034) и по этому не пройдет.
x64>Да, всё верно, эта ссылка \ArcName\multi(0)disk(0)rdisk(0)partition(1) будет создана чуть позже. Автору в таком случае остаётся одно из двух:
x64>1. Подождать, пока эта ссылка не будет создана и распарсить её рекурсивно (начиная, тем не менее, с \SystemRoot). Ждать тут, по идее, недолго. x64>2. Учитывая, что сами девайсы томов к этому моменту уже созданы, можно попытаться сопоставить \ArcName\multi(0)disk(0)rdisk(0)partition(1) девайсу тома \Device\HarddiskVolume1. По идее, ничего сложного, только не забыть учесть различные шины типа \ArcName\scsi(0)... и прочие.
x64>Это более-менее документированные варианты. Возможно, ещё есть способы покопаться в блоке загрузчика, но это недокументировано и я не помню, чтобы там было что-то, что помогло бы при решении этой задачи. Есть другие идеи?
Есть. Например взять SharedUserData->NtSystemRoot и там будет C:\Windows, открыть символьную ссылку \Global??\C: и получить \Device\HarddiskVolumeX прилипить оставшийся путь от SharedUserData->NtSystemRoot (то есть Windows) ну и прилепить system32\ntdll.dll — вот вам путь
AB>Есть. Например взять SharedUserData->NtSystemRoot и там будет C:\Windows, открыть символьную ссылку \Global??\C: и получить \Device\HarddiskVolumeX прилипить оставшийся путь от SharedUserData->NtSystemRoot (то есть Windows) ну и прилепить system32\ntdll.dll — вот вам путь
x64>>Это ты в boot-time собрался всё проделывать? AB>а что плохого?
Вариант-то сам по себе неплохой (хотя в официальной документации о SharedUserData ни слова и это подозрительно), но всё же хотелось бы иметь некоторую уверенность:
1. Что \Global??\C: всегда будет готова к этому моменту.
2. Что формат KUSER_SHARED_DATA не будет меняться в будущих версиях.
По поводу п.2 есть такой комментарий:
//
// WARNING: This structure must have exactly the same layout for 32- and
// 64-bit systems. The layout of this structure cannot change and new
// fields can only be added at the end of the structure (unless a gap
// can be exploited). Deprecated fields cannot be deleted. Platform
// specific fields are included on all systems.
//
// Layout exactness is required for Wow64 support of 32-bit applications
// on Win64 systems.
//
// The layout itself cannot change since this structure has been exported
// in ntddk, ntifs.h, and nthal.h for some time.
//
Надеюсь, что это всё так и останется и в Windows 8 ничего не сломают =)
Здравствуйте, x64, Вы писали:
x64>Вариант-то сам по себе неплохой (хотя в официальной документации о SharedUserData ни слова и это подозрительно), но всё же хотелось бы иметь некоторую уверенность:
x64>1. Что \Global??\C: всегда будет готова к этому моменту. x64>2. Что формат KUSER_SHARED_DATA не будет меняться в будущих версиях.
x64>По поводу п.2 есть такой комментарий:
x64>
x64>//
x64>// WARNING: This structure must have exactly the same layout for 32- and
x64>// 64-bit systems. The layout of this structure cannot change and new
x64>// fields can only be added at the end of the structure (unless a gap
x64>// can be exploited). Deprecated fields cannot be deleted. Platform
x64>// specific fields are included on all systems.
x64>//
x64>// Layout exactness is required for Wow64 support of 32-bit applications
x64>// on Win64 systems.
x64>//
x64>// The layout itself cannot change since this structure has been exported
x64>// in ntddk, ntifs.h, and nthal.h for some time.
x64>//
x64>
x64>Надеюсь, что это всё так и останется и в Windows 8 ничего не сломают =)
SharedUserDat — должно быть в WDK.
насчет первого пункта — лучшая уверенность, это почитать книгу "Внутреннее устройство Microsoft Windows", глава 5 — там о загрузке системы. (если не ошибаюсь)
второй — ну сейчас работает на всех осях.
Здравствуйте, ononim, Вы писали:
AB>>Вот это ("\\SystemRoot\\system32\\ntdll.dll") работать не будет. O>а пробовали? O>кстати, загляните в \\REGISTRY\\MACHINE\\SYSTEM\\Setup
пробовал и как сказал х64 не работает.
а вот \\REGISTRY\\MACHINE\\SYSTEM\\Setup смотрел, но на ХР можно изменить информацию. Тоже видел эту ветку
Re: база модуля ntdll
От:
Аноним
Дата:
16.07.10 14:30
Оценка:
А>Вопрос простой — если драйвер имеет Start = 0 (то есть SERVICE_BOOT_START) как можно получить базу ntdll.dll ? А>Пробовал открыть ZwOpenFile (дальше хотел мапить и посмотреть ImageBase)
К начальному вопросу. Вот получит один путь к ntdll, откроет его и промапит – а что толку? Будет получена база для этого промапленного вида, не совпадающая с общесистемной базой – разве нет?
А>>Вопрос простой — если драйвер имеет Start = 0 (то есть SERVICE_BOOT_START) как можно получить базу ntdll.dll ? А>>Пробовал открыть ZwOpenFile (дальше хотел мапить и посмотреть ImageBase) А>К начальному вопросу. Вот получит один путь к ntdll, откроет его и промапит – а что толку? Будет получена база для этого промапленного вида, не совпадающая с общесистемной базой – разве нет?
База, по которой ntdll грузится, находится в ее PE хидере. Виндовый ASLR ее вроде пока еще не релокейтит.
Как много веселых ребят, и все делают велосипед...
Re[4]: база модуля ntdll
От:
Аноним
Дата:
17.07.10 04:53
Оценка:
Если бы для ntdll не применялась ASLR, то ASLR бы эффективно отсутствовала – какой смысл рандомизировать что-то, если известна база хоть одного исполняемого модуля? Да ещё такой модуль как ntdll, ух.
Дело в другом. При создании секции для образов применяется ASLR и фиксятся релоки. Кроме того, соответствующим образом изменяется база в заголовке (для секции!). Когда такая секция мапится, система пытается отобразить её по выбранному ранее адресу (который редко совпадает с адресом в PE-хидере в файле на диске). Если это удаётся, возвращается STATUS_SUCCESS, а если нет, то маппирование происходит по другому адресу – и возвращается STATUS_IMAGE_NOT_AT_BASE (говорящий о том, что нужно пофиксить релоки перед использованием имаджа).
Так что способ узнать дефолтный рандомизированный адрес "промапить и прочитать из хидера" полностью валиден. Кстати, юзермодный загрузчик проверяет необходимость применения релоков к первичному модулю процесса именно таким способом – сравнивает базу в заголовке с заполненным ядром полем Peb->ImageBase.
А>Если бы для ntdll не применялась ASLR, то ASLR бы эффективно отсутствовала – какой смысл рандомизировать что-то, если известна база хоть одного исполняемого модуля? Да ещё такой модуль как ntdll, ух.
Хм, ntdll и правда релокейтится. Но вообще сама идея ASLR под винду полный уг, учитывая что список модулей с базами и именами вычитывается из PEB'а кодом в несколько десятков строчек, без использования каких либо API.
А>Дело в другом. При создании секции для образов применяется ASLR и фиксятся релоки. Кроме того, соответствующим образом изменяется база в заголовке (для секции!). Когда такая секция мапится, система пытается отобразить её по выбранному ранее адресу (который редко совпадает с адресом в PE-хидере в файле на диске). Если это удаётся, возвращается STATUS_SUCCESS, а если нет, то маппирование происходит по другому адресу – и возвращается STATUS_IMAGE_NOT_AT_BASE (говорящий о том, что нужно пофиксить релоки перед использованием имаджа).
Спасибо, я сам когдато писал загрузчик PE имаджей который делал все вышеописанное.
А>Так что способ узнать дефолтный рандомизированный адрес "промапить и прочитать из хидера" полностью валиден. Кстати, юзермодный загрузчик проверяет необходимость применения релоков к первичному модулю процесса именно таким способом – сравнивает базу в заголовке с заполненным ядром полем Peb->ImageBase.
Редко какой ехе имеет таблицу релоков.
Как много веселых ребят, и все делают велосипед...