Необходимо получить адрес страницы памяти на которую указывает селектор FS в ринг3. Нашел несколько возможных способов: 1) Как делает OllyDbg просто через вызова GetThreadSelectorEntry и получает FS 003B 32bit 7FFDE000(FFF). 2) Парсинг GDT не подошел изза отсутствия доступа (т.к. ring0) Есть ли дополнительные возможности вручную пропарсив, каталог страниц найти указатель на эту страницу памяти, не используя апи?
То есть на парсинг GDT доступа нет, а на парсинг каталога страниц - есть? Как так? А чем первый не подходит?
lhc645 Эт не подходит как как используется адресация с селектором. n0name А вот так, если читать внимательнее то последняя строчка это вопрос, а не утверждение, и там не написано что доступ на каталог страниц есть. А первый не подходит т.к. апи, а надо вручную получить адрес не используя функций и адресацию через FS.
Если предположить, что _некоторые_ апи таки можно использовать, а также что в fs лежит селектор, определяющий сегмент, в начале которого лежит TEB – то можно использовать следующее единственно очевидное в таких ужасающих условиях решение: получить карту памяти посредством VirtualQuery (либо готовиться обрабатывать исключения) и проверить верхние валидные адреса на наличие относимых к TEB данных: [XXXXX018] = XXXXX000 (как уже было сказано), текущий esp лежит в пределах StackBase\StackLimit, XXXXXzzz.StaticUnicodeBuffer == "bla-bla-bla" (в этом буфере, видимо, должна находится строка после вызова XxxXxxA апи (не XxxXxxW)).
Планировщик при переключении на новый тред загружает 6-й декриптор(KGDT_R3_TEB) в GDT, устанавливая базу сегмента равной адресу страницы с TEB из ETHREAD. Тоесть значение там уникально для потока. Для одного потока база сегмента там одна, для другого другая. А значит что для определения базы этого сегмента не достаточно селектора, нужен есчо описатель потока. Описатель определяет права доступа к обьекту, через него можно эту инфу получить, соответственно это ThreadDescriptorTableEntry, ну есчо читая из тела обьекта ThreadBasicInformation. Для иного случая можно былобы прочитать регистр Cr2, который содержит линейный адрес к которому произошло обращение для #PF(из юзермода через мехонизм исключений, диспетчер получает его значение), предварительно вызвав его. Тогда камень сам бы выполнил суммирование базы сегмента и смещения в нём. Вот только страница с TEB залочена, изменить атрибуты нельзя(ну без хака..). И хардварный останов нельзя поставить(в Dr* нужно загрузить линейный адрес, который и нужно найти %). Есчо можно дескрипторный кэш прочитать из регистра Fs. Только тут некоторые проблемы есть. Во первых значение там меняется почемуто на многопроцессорной машине, почему не понятно. Хотя можно пару десятков итераций заюзать, хотябы на одной должна быть сохранена часть дескриптора. Просто Push Fs. Поимеем в стеке часть базы. Во вторых дескрипторный кэш не возможно удалённо получить в юзермоде(в ядре без хака тоже, KeContextToKframes() налаживает маску на сегментные регистры, хак рулит..), тоесть это поле уникально для потока и из другого его не считать(NtGetContextThread не поможет ). Это сигнатурный поиск TEB. Лучше заюзать проверку по Cid.UniqueProcess, в других случаях(чтото отличное от TEB) юзается маркер - пишем его в память, а потом ищем в ней. Это шадова буфер. Код (Text): SwitchToThread() ; хм.. ... YieldExecution() ; до! push es push KGDT_R3_TEB or RPL_MASK pop es mov eax,es:[TEB.Tib.Self] pop es
Folk Acid Вам поиск в гугле: http://tinyurl.com/yjp7ebl Разве ктото упомянул линус.. Чёто у меня в маздае ядрышко по другому адресу, дма контроллер адресует тока 16М и у него нет режима память-память.. хоть жёсткий диск юзой, какая разница ведь IOPL не поднять, IOPM не доступна. И камень другой, он те инструкции не знает. И что вобще за док, погонь полная пять букоф на строницу ппц, фтопку вместе с Рустовской. Шлак ёпт.)
CrystalIC >Есчо можно дескрипторный кэш прочитать из регистра Fs. [..] Просто Push Fs. Поимеем в стеке часть базы. Напомни, пожалуйста, модель твоего P4. Просто "push fs" обычно уменьшает значение указателя стека и кладёт в нижнюю половину дворда селектор, а верхнюю половину либо вообще не изменяет, либо обнуляет. Но чтобы часть часть дескрипторного кэша при этом светилась – первый раз слышим.
Sol_Ksacap Не обнуляет. Мы этот вопрос много обсуждали, например на вирустеке с приблежёнными . На XP на двуядерном пне четвёрки сохраняется в стеке старшая часть сегментных регистров - это дескрипторный кэш. Зависимость по которой значения сохраняемые неизвестна, можно считать рандомным, но очень часто при сохранении регистра Fs сохраняется старшая часть базы сегмента, селектор которого загружен в этот регистр. Непостояноство вероятно вносится вторым ядром, вне зависимости от аффинитета. Знакомый проверял на 7-ке и томже камне - сохраняются нули. Щас проверили на AMD 64 X2 Dual Core 4400 +, XP3 также обнулено. Мы не понимаем сути мехонизма.
CrystalIC Насколько я знаю, речь шла про многократный 'push fs' и осмотр стека после этих операций. Я не проверял на своей машине, но, судя по всему, некоторые процессоры не обнуляют два старших байта при выполнении 'push fs'. В результате то, что ты видел -- просто мусор в стеке, оставшийся после выполнения предыдущих ф-ий. Для чистоты эксперимента стоит посмотреть значения в стеке до выпонения 'push fs' и после. Тогда станет понятно, что там такое.
и это не смотря на то, что в манах интела сказано, что как минимум для GS/FS должно обнулять старшю часть дворда при внесении в стек
Mika0x65 Да причём тут стек. Блиа буду дома выложу стопяцот байтный дамп. Это не стек и не сторонние драйвера(у меня всё чисто, ядро отпарсено вручную). Хотя я не проверял/разбирался в мехонизме мне стыдно - просто лень, иных вопросов куча. Что часть дескриптора сохраняет это однозначно(или вы меня долбоёбом считаете, типо не знаю что в стек кладётся..). Gs плвнировщег обнуляет. При возникновении хардварных прерываний маска не налаживается(програмно до, но по ходу мехонизм аппаратный). Впрочем странно что ктото этим интересуется, почемуто мы домоле что про сегментацию уже все забыли давно.. Нормально применима всяко техника которая чётко определена, это чисто теоретический мкхонизм и по тому интересен. По сути вопроса - всяко дейстив в третем кольце защиты есть изврощение, там всё ограничено. Единственно необходимый к рассмотрению это режим ядра. В этом случае можно говорить про таблицы директорий, хотя мы читали и из юзермода физическую память непосредственно, но это всё хлам. Легальному приложению нет смысла скрывать контекст и системные вызовы, руткитам не нужен юзермод.
Во стек И камень Тока не нужно бред про савапконтекст, сепшены при доступе к стеку и прочую белиберду, тотже результат при залоченной памяти и запрещённых прерываниях. А вобщем за всё время только один раз у меня возникла необходимость в манипуляциях с регистром Fs. Это в экземплс для полуприватной техники IDP http://paste.org.ru/?004aur Иначе смысла нет какието махинации с этим регистром проводить, вобще незачем, можно тупо все треды перечислить, открыть и получить ссылки ли память сканить.
CrystalIC А что было в стеке до 'push fs'? Я полагаю, что там было что-то вроде: 0012ХХХХ 001AXXXX 7C92XXXX и т.д.
Нули, поток один. Когдато проверялось через например Pop Ds, затем юзалось прерывание, обработчик делал Push Ds в ядерный стек, затем значение с вешины стека логировалось и выполнялся возврат.