BugTraq.Ru
Русский BugTraq
https://bugtraq.ru/library/internals/shut.html

Задраить все форточки!
Tanaka
Опубликовано: dl, 25.11.01 22:44

    Как-то раз, я торопился домой, а моя любимая Windows NT никак не хотела выключаться. "Ну же, давай, дохни, родимая," - в нетерпении понукал я машину но тщетно. Особенно меня бесило то, что никаких разумных причин таких тормозов не наблюдалось. К внешним устройствам обращения нет, машина не свопится. Сколько же нужно операций процессору, чтобы выключить машину? Очевидно, дядюшка Билли просто решил оттянуться с "Мириндой" или пробовал новый "Дью". Итак, надо мной откровенно издевались, а мне лишь оставалось в бессильной злобе скрипеть зубами. Немыслимое унижение, а главное от кого?! И в ярости я поклялся отмстить!!!

- За это ти умрешь, как подлий шакал!

    Снедаемый жаждой мести, я деятельно приступил к поискам. Что же происходит, когда умирают Винды? Увы, в Инете никаких умных мыслей и рассуждений по этому поводу я не нашел. А нашел я буржуинское предложение купить прогу, что выключает машину. И всего за каких-то жалких 50$!

- За дэвушку, спортсмэнку, камсамолку, я прошу всэго каких-то 25 баранов!

Окончательно убитый, я еще немного меланхолично пощелкал мышью в разных окошках и с печальным вздохом нажал Ctrl-D.

- Нэ надо, слюшай!
- Сам нэ хачу!

    Как всем известно, есть такая хорошо задокументированная функция ExitWindowsEx(), а еще есть плохо задокументированная функция ZwShutDownSystem(). Логично предположить, что эти функции взаимосвязаны и в конце концов ExitWindowsEx() передает управление ZwShutDownSystem(). Попробовал, обе функции прекрасно выключают Windows, только первая делает это долго, а вторая быстро. Казалось бы все понятно: именно в ExitWindowsEx() и происходят все ненужные нам паузы. Ага, щас!

- И передает ее влюбленному джигиту.
- Нэт, и пэрэдает ее кунакам влюбленного джигита.

    При штатном останове функция ZwShutDownSystem() вообще не вызывается! Давайте рассмотрим, что же происходит при вызове ZwShutDownSystem().

BOOL ZwShutDownSystem(DWORD arg);

где arg - некий параметр, может быть и адресом и числом.
0x00 - Shutdown
0x01 - Reboot
0x02 - Poweroff

    Из ntdll.dll сразу же происходит обращение в ядро (ntoskrnl.exe). Далее, система последовательно дергает кучу других "shutdown". А именно,

...
call _ExShutdownSystem
...
call _IoshutdownSystem
...
call _CmShutdownSystem
...
call _MmShutdownSystem
...
call _IoShutdownSystem
...
call _DbgUnloadImageSymbols
...

Как говорится, без комментариев. И, наконец, "здравствуй железо"

call __imp__HalReturnToFirmware

    После короткой возни в hall.dll, все заканчивается короткой командой ... нет, не "Пли!", нет, и не "Режь!", а

out DX, AL

Как я ее понял, в 64 порт пишут значение 0xfe. По-видимому, это останов процессора. А может и нет! Кто знает, напишите мне, пожалуйста! Заметим, что SoftIce работает до самого конца! То есть, скорее всего выгрузки драйверов не происходит. Но вернемся к нашему единственному барану, а именно к функции ExitWindowsEx(). Здесь процедура и проще, и ... сложнее! Я еще раз оценил юмор компании Microsoft.

- Ха! Шютник! Будишь рэзать свой невеста, мэня нэ забудь позвать!

    Вся работа ExitWindowsEx() сводится к добавлению к своим двум аргументам (один из которых по официальной версии не используется) еще одного (всегда 0x00) и вызову функции ExitWindowsWorker() теперь уже с тремя аргументами (один из которых по официальной версии не используется, а другой всегда 0x00).
    В ExitWindowsWorker() после короткой проверки вызывается

...
call imp_CsrClientCallServer
...

    Итак, остается констатировать неутешительный факт: остановка Windows отдана на откуп подсистеме, взаимодействие с которой происходит через LPC-механизм.

- В маем доме нэ выражаться!
- А что я сказал?

    Благодаря господину Охапкину (поистине великий гуру!), формат функции CsrClientCallServer() известен:

int CsrClientCallServer(DWORD length, DWORD opcode, DWORD zero, PVOID message),

где length - длина чего-то, но не всего сообщения;
opcode - не то флаги, не то идентификатор внутри подсистемы;
zero - неизвестно что, но всегда ноль;
message - буфер данных для отправки сообщения в подсистему.

    При вызове ExitWindowsEx() аргументы CsrClientCallServer() имеют следующие значения:
length - всегда 0x10;
opcode - для NT4.0 всегда 0x00030a00, для Win2000 всегда 0x00030400
zero - всегда 0x00;
message - мне известно только то, что 11-ое и 12-ое слова буфера (считая от нуля) - это параметры ExitWindowsEx(). Остальное можно занулить, и тем не менее все будет работать.

    Итак, можно перегружать (restart), завершать сеанс (log off) и выключать Windows (shut down или power off), используя CsrClientCallServer() с соответствующим 11 словом. Например, 0x08 - Power off 0x00 - Log off 0x02 - Reboot и т. д.

    "Ну хорошо, это в NT4.0, а как насчет Windows 2000?" - спросит читатель и будет совершенно прав. В Win2000 дядюшка Билли уже не так добр и открыт, как в старые добрые времена. Многие функции из user32.dll больше не экспортируются в том числе и функция ExitWindowsWorker() (хотя по-прежнему вызывается). Перед отправкой сообщение в подсистему происходят еще какие-то действия внутри win32k.sys. В остальном все очень похоже, разве, как уже было сказано, opcode изменился. Что касается ZwShutDownSystem(), то мне удалось выяснить только, что в определенный момент происходит проход по спискам драйверов, и где-то на середине Soft-Ice намертво падает.
    Между прочим, один почтенный старец поведал мне старое предание о том, что где-то под Рязанью в отшельническом скиту живет могучий богатырь Евлампий. Дескать, сей буй-тур Евлампий Батькович доходил под Soft-Ice до самого до краю двухтысячных Виндов. Более того, он знает как работает команда hboot. Коли сыщется кто-то, кто ведает о сем достойном муже, не сочтите за труд, черкните письмецо.
   Чтобы проистрюллировать (или пролюлистрировать?) свои исследования прилагаю исходник shut.cpp. Прога тестилась на серверах NT4.0 (SP4, SP6) и на Win2000 (SP2). На выбор Вы можете выключать Винды быстро (особенно это приятно там, где стоит Exchange), или обычным способом.

- Будем ждать. Сдавай!

    Да, кстати, чуть не забыл. Биллофобам и окноненавистникам, думаю, будет приятно узнать, что если с помощью CsrClientCallServer() отправить подряд два сообщения с 11-ым словом 0x08 (см. исходник), то сервера как NT4.0, так и Win2000 падают довольно специфическим способом: пустой экран, мышь работает, Soft-Ice работает, но больше ничего сделать нельзя, Task Manager не вызывается.

- Нычего ж нэ сдэлал, только вошел! Обыдно, слюшай!

Минут 15 ничего не менялось, дальше мое терпение истощилось и я нажал Reset. Вот, пожалуй, и все. Если есть вопросы, замечания или предложения, пишите по адресу tanaka@rambler.ru или смотрите на нашем сайте teamz.nm.ru

P.S.
Послушайте, мне тут такую вещь показали!!! Оказывается, что если нажать кнопочку "Start", потом в менюшке выбрать "Shut down ...", потом из выпадающего окошка выбрать "Shut down", а потом нажать кнопочку "OK" ... Сейчас я Вам продемонстрирую. И что удивительно, все раб...



обсудить  |  все отзывы (0)

[27586; 30; 7.6]




  Copyright © 2001-2024 Dmitry Leonov Design: Vadim Derkach