WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!

Pages:     || 2 | 3 | 4 | 5 |
-- [ Страница 1 ] --

Михаил Фленов Сан кт- Петербург -БХВ-Петербург» 2003 УДК 681.3.068x800.92Delphi ББК 32.973.26-018.1 Ф69 Флеиов М. Е. Профаммирование в Delphi глазами хакера. — СПб.: БХВ-Петербург, 2003. - 368 с: ил.

ISBN 5-94157-351-0 В книге вы найдете множество нестандартных приемов программирования на языке Delphi, его недокументированные функции и возможности. Вы узнаете, как создавать маленькие шуточные программы. Большая часть книги посвящена программированию сетей, приведено множество полезных примеров. Для понимания изложенного не нужно глубоких знаний, даже начальных сведений о языке Delphi хватит для работы над каждой темой. Если вы ни разу не программировали, то на прилагаемом к книге компактдиске в каталоге vr-online вы найдете полную копию сайта автора и электронную версию его книги "Библия Delphi". Это поможет вам научится программировать без каких-либо начальных знаний. Прочитав книгу и дополнительную информацию, предоставленную на компакт-диске, вы можете пройти путь от начинающего программиста до продвинутого пользователя и познать хитрости хакеров и профессиональных программистов. Для программистов на языке Delphi УДК 681.3.068x800.92Delphi ББК 32.973.26-018.1 Группа подготовки издания: Главный редактор Зам. главного редактора Зав. редакцией Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производством Екатерина Кондукова Анатолий Адаменко Григорий Добин Дмитрий Лещев Натальи Караваевой Елена Самсонович Игоря Цырульникова Николай Тверских Н Лицензия ИД Ne 02429 от 24.07.00. Подписано в печать 25.06.03. 1 Формат 70х100 /1в. Печать офсетная. Усл. печ. л. 29,7. Тираж 3000 экз. Заказ № 978. "БХВ-Петербург", 198005. Санкт-Петербург, Измайловский пр., 29. Гигиеническое заключение на продукцию, товар Ng 77,99.02.953.Д.001537.03.02 от 13.03.2002 г. выдано Департаментом ГСЭН Минздрава России. Отпечатано с готовых диапозитивов в Академической типографии "Наука" РАН 199034. Санкт-Петербург, 9 линия, 12. ISBN 5-94157-35I-0 С ФленовМ. Е., 2003 О Оформление, иапательство "БХВ-Пстербург", Содержание ВВЕДЕНИЕ Благодарности О книге Кто такой Хакер? Как им стать? ГЛАВА 1. МИНИМИЗАЦИЯ И НЕВИДИМОСТЬ 1.1. Сжатие запускных файлов 1.2. Без окон, без дверей 1.3. Шаблон минимального приложения 1.4. Прячем целые программы 1.5. Оптимизация программ ЗАКОН № 1 ЗАКОН №2 ЗАКОН № 5 ЗАКОН №6 ЗАКОН №7 Итог ГЛАВА 2. ПРОСТЫЕ ШУТКИ 2.1. Летающий Пуск 2.2. Полный контроль над кнопкой Пуск 2.3. Контролируем системную палитру 2.4. Изменение разрешения экрана 2.5. Маленькие шутки Программное изменение состояния клавиш Num Lock, Caps Lock и Scroll Lock Как программно потушить монитор? Запуск системных CPL-файлов Программное управление устройством для чтения компакт-дисков Отключение сочетания клавиш ++ 1 1 2 6 13 13 16 22 27 28 30 30 34 35 36 37 39 39 45 49 52 58 58 59 59 60 * IV Содержание Отключение сочетания клавиш + Удаление часов с панели задач Исчезновение чужого окна Установка на рабочий стол своих собственных обоев 2.6. Шутки с мышкой Безумная мышка ГЛАВА 3. СИСТЕМА 3.1. Подсматриваем пароли, спрятанные под звездочками 3.2. Мониторинг исполняемых файлов 3.3. Клавиатурный шпион 3.4. Работа с чужыми окнами 3.5. Дрожь в ногах 3.6. Найти и уничтожить 3.7. Переключающиеся экраны 3.8. Безбашенные окна 3.9. Вытаскиваем из системы пароли ЗЛО. Изменение файлов 3.11. Работа с файлами и директориями ГЛАВА 4. ПРОСТЫЕ ПРИЕМЫ РАБОТЫ С СЕТЬЮ 4.1. Немного теории 4.1.1. Сетевые протоколы — протокол IP 4.1.3. Транспортные протоколы — быстрый UDP 4.1.4. Медленный, но надежный TCP 4.J.5. Прикладные протоколы — загадочный NetBIOS 4.1.6. NetBEUI 4.1.7. Сокеты Windows 4.1.8. Протокол IPX/SPX 4.2. Их разыскивают бойцы 139-го порта 4.3. Сканер портов 4.4. Против лома нет приема 4.5. Пинг-понг по-нашему 4.6. Чат для локальной сети 4.7. Сканирование сети в поиске доступных ресурсов 4.8. Ваша собственная почтовая мышка 4.9. Троянский конь 4.9.1. Серверная часть 4.9.2. Клиентская часть 61 61 62 62 64 64 67 67 73 83 84 89 92 93 97 106 110 116 133 133 136 137 138 140 141 141 141 142 146 150 156 162 167 171 176 177 Содержание V 4.10. Посылаем файлы в сеть 4.11. Персональный FTP-сервер 4.12. Простейший TELNET-клиент ГЛАВА 5. СЕТЬ НА НИЗКОМ УРОВНЕ 5.1. Основные функции WinSock 5.1.1. Инициализация WinSock 5.1.2. Подготовка разъема 5.2. Самый быстрый сканер портов 5.2.1. Время и количество 5.3. IP-config собственными руками 5.4. Получение информации о сетевом устройстве 5.5. Продолжаем знакомиться с WinSock 5.6. Работа с NetBIOS 5.7. Определение локального/удаленного IP-адреса 5.8. Работа с ARP 5.9. Изменение записей ARP-таблицы 5.9.1. Добавление ARP-записей 5.9.2. Удаление ARP-записей 5.10. Работа с сетевыми ресурсами ГЛАВА 6. ЖЕЛЕЗНАЯ МАСТЕРСКАЯ 186 192 199 207 207 208 212 213 216 225 229 235 237 242 245 251 252 257 261 6.1. Общая информация о компьютере и ОС 273 6.1.1. Платформа компьютера 276 6.1.2. Информация о процессоре 277 6.1.3. Информация о платформе Windows 277 6.2. Информация о памяти 280 6.3. Информация о дисках 282 6.4. Частота и загрузка процессора 286 6.4.1. Частота процессора 286 6.4.2. Загрузка процессора 290 6.5. Работа с СОМ-портом 292 6.6. Работа с LPT-портом 296 6.7. Определение размера файла 301 6.8. Получение информации обустройстве вывода 302 6.9. Работа с типами файлов 309 6.9.1. Получение информации о типе файлов 309 6.9.2. Связывание своей программы с пределенным типом файлов....313 6.10. Работа со сканером VI Содержание ГЛАВА 7. ПОЛЕЗНОЕ 7.1. Конвертер 7.2. Изменение параметров окна 7.3. Создание ярлыков 7.4 Управление ярлыками 7.5. Прозрачность окон 7.6. Написание plug-in модулей 7.6.1. Создание программы для работы с plug-in 7.6.2. Создание plug-in модуля СПИСОК ЛИТЕРАТУРЫ И РЕСУРСЫ ИНТЕРНЕТА ОПИСАНИЕ КОМПАКТ-ДИСКА 323 323 326 328 335 337 341 341 346 351 Введение Благодарности В самом начале любой книги авторы любят кого-нибудь благодарить. Честно сказать, я никогда не понимал этих вещей, но решил не отступать от данной традиции и поблагодарить. Своих родителей за то, что они произвели меня на свет. Если бы не они, не было бы этой книги, по крайней мере в моем исполнении. Своего кота Партизана (так его зовут) за то, что разбил раковину в ванной комнате, и мне пришлось оторваться от дел, чтобы поставить новую. Благодаря этому происшествию я на короткое время отдохнул от компьютера, за которым провожу как минимум 10 часов в сутки. Свою дочь за то, что регулярно залазила ко мне на колени и беспорядочно била по клавиатуре (когда я начинал писать эту книгу, ей еще не было 2 лет). Этим она сбивала меня с мысли, и приходилось снова настраиваться на работу. Если бы не она, книга вышла бы намного раньше. Свою жену. За что? Да за все. Давыдова Дениса — главного редактора "Игромании". Когда-то он был редактором игровой части в журнале "Хакер", и мне повезло, что я начинал свою писательскую деятельность в журнале именно с ним. Журнал тогда только начинал свое развитие, и Денис уделял мне достаточно много времени. Я программист и выжать из себя пару литературных строк в то время вообще не мог (да и сейчас я в этом деле не гений, у меня в школе по русскому и литературе всегда было 3 с большим минусом), а Денис мне дал пинок, от которого я, можно сказать, начал свою карьеру. Покровского Сергея aka SINtez — главного редактора журнала "Хакер". После того как Давыдов Денис ушел из журнала, я какое-то время стал меньше публиковаться, но потом меня, можно так сказать, взял под крыло Сергей. Сначала я стал вести рубрику "Hack-Faq", а потом и "Кодинг", которая очень быстро развилась и получила популярность.

2_ Введение Я могу еще очень долго перечислять людей, которым я благодарен в своей жизни, поэтому перечислю коротко: воспитателям в детсаде, учителям в школе, преподавателям в институте, всей команде журнала "Хакер" и всем моим друзьям за то, что они меня терпят, вероятно любят, и по возможности помогают. Ну и самое главное, я хочу поблагодарить всех моих читателей за то, что они читают мои опусы. А вам отдельное спасибо за то, что вы приобрели эту книгу.

О книге Как вы наверно уже поняли, я заядлый программист и в течение всей книги не буду блистать литературным стилем. Зато я постараюсь поделиться своими знаниями и надеюсь рассказать вам что-то новое. В течение всей книги я буду рассказывать вам про программирование для хакера. Я буду достаточно часто использовать один термин — "кодинг ". Что это такое? Под этим словом мы будем как и все подразумевать слово программирование. А вот под словом "хакер" лично я подразумеваю немного другой смысл, чем другие. Я считаю, что хакер — это профессионал в компьютерной сфере, но не обязательно доставляющий много неприятностей другим людям своими знаниями. Так вот, в этой книге я постарался показать много интересных вещей с точки зрения сетевого программистапрофессионала, а не взломщика. Более подробно о понятии "хакер" рассказано в следующем разделе. Я попробовал привести как можно больше нестандартных приемов программирования, недокументированные функции и возможности, а главное — продемонстрирую вам приемы работы с сетью в операционной системе Windows. В книге приведено максимальное количество примеров на языке программирования Delphi. Для этого я написал множество шуточных программ и сетевых приложений. Чистой теории будет мало, зато практических занятий — хоть отбавляй. Для понимания книги вам понадобятся хотя бы начальные знания среды Delphi и сносное умение общаться с компьютером и мышкой. Что касается сетевого программирования, то его я опишу полностью, начиная от основ и закачивая сложными примерами. Так что тут начальные знания желательны, но не обязательны. Если вы начинающий программист, то могу посоветовать для получения основ прочитать мою книгу по Delphi и посетить мой сайт www.cydsoft.com/vr-online, где выложено достаточно много полезной информации. Если вы ожидали увидеть в данной книге примеры и описания вирусов, то вы сильно ошиблись. Ничего разрушительного я делать и рассказывать не буду. Я занимаюсь созиданием, а не разрушением. Чего и вам советую.

Введение 3_ Для эффективной работы с книгой вам понадобятся хотя бы начальные знания Delphi. Вы должны уметь создавать простое приложение, знать, что такое циклы и как с ними работать. Не помешают знание адресации, указателей и для чего они нужны. Я постарался облегчить вам задачу, описав все как можно проще. Большинство кода расписано очень подробно, и в тексте программ вы найдете максимум комментариев, которые помогут получать наслаждение от чтения кода вместо обычной головной боли. Эта книга построена не так, как многие другие. В ней нет длинных и нудных теоретических рассуждений, а только максимум примеров и исходного кода. Ее можно воспринимать как практическое руководство к действию. Программисты в чем-то похожи на врачей: если врач теоретически знает симптомы болезни, но на практике не может точно различить отравление от аппендицита, то такого врача лучше не подпускать к больному. Точно так же и программист: если он знает, как работает протокол, но не может с ним работать, то его сетевые программы никогда не будут работать правильно. Это сравнение приведено здесь не просто так. В 2002 году я попал в больницу с температурой и болями в области живота. Меня положили в хирургическое отделение и хотели вырезать аппендицит. Я пролежал три дня, и ни один врач не решался меня отправить на операцию, но в то же время никто не знал, откуда у меня боли, и почему температура под вечер поднимается до 39 градусов. На третий день вечером я сбежал из больницы, потому что у моей мамы был день рождения. На нем присутствовап знакомый врач (по специализации акушер), который, осмотрев меня, сказал пить по I таблетке через каждые 12 часов (не будем уточнять, что это был за препарат) и выписываться из больницы. Может, кто-то не поверит, но после первой таблетки температура упала, а после второй я вообще плясал, как Борис Моисеев. Результат: врачи перепутали отравление с аппендицитом и чуть не лишили меня моего аппендикса. А ведь могли же вырезать — по ошибке или просто ради интереса. Этот случай еще больше закрепил мое отношение к практике. Ничто не может привести к такому пониманию предмета, как хорошее практическое занятие, потому что когда вы можете ощутить все своими руками, то никакая теория становится не нужна. Еще один пример из жизни. В 2000 году я проходил обучение в МГТУ им. Баумана на нескольких курсах Microsoft SQL Server. Курсы были очень хорошие, и преподаватель старался все очень подробно и легко преподнести. Но сам курс был поставлен корпорацией как теоретический, с небольшим добавлением лабораторных работ. В результате нам очень хорошо объяснили, ЧТО может делать SQL Server. Но когда после курса я столкнулся с реальной проблемой, я понял, что не знаю, КАК сделать что-либо. Приходилось снова открывать книгу, которую выдали в центре обучения (она была 4_ Введение предоставлена Microsoft, и конечно же на английском языке), и, читая обширную теорию и маленькие практические примеры, разбираться с реальной задачей. Уж лучше бы я узнал на курсах, как практически выполнять примеры из жизни, а не что можно теоретически выполнить, потому что такое обучение, по-моему, только пустая трата времени. Несмотря на это, я не противник теории и не пытаюсь сказать, что теория не нужна. Просто нужно описывать, КАК решить задачу и рассказывать, ЗАЧЕМ мы делаем какие-то определенные действия. После этого, когда вы будете сталкиваться с подобными проблемами, вы уже будете знать, как сделать что-то, чтобы добиться определенного результата. Именно практических руководств и просто хороших книг с разносторонними примерами не хватает на полках наших магазинов. Я надеюсь, что моя работа восполнит хотя бы небольшой пробел в этой сфере и поможет вам в последующей работе и решении различных задач программирования. Итак, книга будет содержать громадное количество примеров, и несмотря на свое название может пригодиться всем, потому что в ней будут описываться разные программистские приемы, которые используются в ежедневной практике. Изложение будет разбито на 7 частей (читай — глав): 1. "Минимизация и невидимость". В этой главе я описал приемы, которые могут помочь вам минимизировать размер кода программы, оптимизировать скорость работы и сделать свою программу невидимой. Невидимыми должны быть не только вирусы и трояны, но и большое количество абсолютно безобидных и полезных программ. Программыпланировщики чаще всего работают в системе невидимо для пользователя, потому что им незачем отображаться на экране. Такие программы появляются только в определенные моменты, а в остальное время абсолютно незаметны. 2. "Простые приколы". Несмотря на название, материал этой главы нужен не только для создания программ, которые будут делать что-то интересное и веселое, но и для нормальных приложений. Функции, которые будут рассматриваться, создавались для специальных целей и по первоначальному замыслу не имели "дополнительных" возможностей. Я же описал эти функции с точки зрения создания различных программ-приколов (абсолютно безобидных). 3. "Система". Эта глава посвящена системному программированию. Под этим понятием я понимаю программирование, связанное с Windows. Здесь опять же будет очень много интересного и полезного, и все будет приправлено множеством примеров. 4. "Простые приемы работы с сетью". Здесь я описал множество сетевых утилит и постарался дать максимум полезной информации по сетевому программированию. Для примеров будут использоваться компоненты, Введение которые предоставляет нам оболочка Delphi, поэтому и примеры будут простыми. 5. "Сеть на низком уровне". В этой главе описаны приемы программирования сетевых приложений без использования компонентной модели Delphi. Вся работа будет происходить только на низком уровне, с использованием WinSock API и других сетевых API-интерфейсов. 6. "Железная мастерская". В этой части я описал множество примеров работы с компьютерным "железом". Я показал, как можно определять содержимое компьютера, и вы научитесь получать информацию об основных устройствах. Помимо этого, достаточно подробно будет описана работа с СОМ-портами (RS-232), которые часто используются на предприятиях для работы с различным оборудованием. В своей жизни я сталкивался по работе с несколькими промышленными предприятиями, и на всех хоть где-то использовались программы, которые через СОМ-порт собирали данные с внешних устройств или просто наблюдали за работой оборудования. 7. "Полезности". В этой главе собрана информация, которую я хотел вам рассказать, но она не подошла под тематику других глав. Именно поэтому у этой главы нет определенной темы, и я ее назвал просто "Полезности". Здесь собраны различные программы и приемы, которые могут пригодиться вам в будущем. Все примеры, которые описаны в книге, можно найти на компакт-диске в директории примеры. Несмотря на это я советую все описанное создавать самостоятельно и обращаться к готовым файлам, только если возникли какие-то проблемы, чтобы сравнить и найти ошибку. Любая информация после практической работы откладывается в памяти намного лучше, чем прочтенные сто страниц теории. Это еще одна из причин, по которой книга построена на основе большого количества примеров и исходного кода. Даже если вы решили воспользоваться готовым примером, обязательно досконально разберитесь с ним. Попробуйте изменить какие-то параметры и посмотреть на результат. Можете попытаться улучшить программы, добавив какие-то возможности. Только так вы сможете понять принцип работы используемых функций или алгоритмов. Помимо этого, на компакт-диске можно найти следующие директории: П Headers — здесь находятся все необходимые заголовочные файлы, которые нужно будет подключать к Delphi для компиляции некоторых примеров. О Source — здесь я выложил исходные коды своих простых программ, чтобы вы могли ознакомиться с реальными приложениями. Их немного, но посмотреть стоит.

Введение • Soft — в этой директории вы найдете инсталляционный пакет программы Adobe Acrobat Reader 5.0. Если у вас нет этой программы, то вы должны ее установить, чтобы можно было читать документацию, расположенную на диске. П vr-oniine — полная копия сайта автора, а это 100 Мбайт документации, полезной информации, исходных кодов и компонентов. Здесь же вы можете найти мою книгу "Библия Delphi" в электронном виде. В ней вы найдете необходимые основы для понимания материала книги, которую вы держите в руках, и даже если вы еще ни разу не видели Delphi, то после прочтения электронной или бумажной версии "Библии Delphi" вы сможете понять все описанное далее. • документация — дополнительная документация, которая может понадобиться для понимания некоторых глав. • Иконки — в этой директории вы найдете большую коллекцию иконок, которые вы сможете использовать в своих программах. Эту коллекцию я подбирал достаточно долго, и все иконки хорошего качества. О компоненты — дополнительные компоненты, которые будут использоваться в примерах книги. О Программы — программы, которые пригодятся при программировании. Среди них Header Convert — программа, которая конвертирует заголовочные файлы с языка С на Delphi, и ASPack — программа сжатия исполняемых файлов.

Кто такой Хакер? Как им стать?

Прежде чем приступить к практике, я хочу "загрузить" вашу голову небольшой теорией. А именно: прежде чем читать книгу, вы обязаны знать, кто такой хакер в моем понимании. Если вы будете подразумевать одно, а я другое, то мы не сможем понять друг друга. В мире полно вопросов, на которые большинство людей не знают правильного ответа. Мало того, люди используют множество слов, даже не догадываясь о их настоящем значении. Например, многие сильно заблуждаются в понимании термина "хакер". Однако каждый вправе считать свое мнение наиболее правильным. И я не буду утверждать, что именно мое мнение единственно верное, но оно отталкивается от действительно корректного и правильного понятия. Прежде чем начать обсуждать то, что известно всем, я должен уйти в историю и вспомнить, как все начиналось. А начиналось все еще тогда, когда не было даже международной сети Интернет. Понятие "хакер" зародилось, когда только начинала распространяться первая сеть ARPAnet. Тогда это понятие обозначало человека, хорошо разби Введение рающегося в компьютерах. Некоторые даже подразумевали под хакером человека, помешанного на компьютерах. Понятие ассоциировали со свободным компьютерщиком, человеком, стремящимся к свободе во всем, что касалось его любимой "игрушки". Именно благодаря этому стремлению и стремлению к свободному обмену информацией и началось такое бурное развитие всемирной сети. Именно хакеры помогли развитию Интернет и создали FIDO. Благодаря им появились бесплатные UNIX-подобные системы с открытым исходным кодом, на которых сейчас работает большое количество серверов. В те времена еще не было вирусов, и не внедрилась практика взломов сетей или отдельных компьютеров. Образ хакера-взломщика появился немного позже. Но это только образ. Настоящие хакеры никогда не имели никакого отношения к взломам, а если хакер направлял свои действия на разрушение, то это резко не приветствовалось виртуальным сообществом. Настоящий хакер — это творец, а не разрушитель. Так как творцов оказалось больше, чем разрушителей, то истинные хакеры выделили тех, кто занимается взломом, как отдельную группу, и назвали их крэкерами (взломщиками) или просто вандалами. И хакеры, и взломщики являются гениями виртуального мира. И те и другие борются за свободу доступа к информации. Но только крэкеры взламывают сайты, закрытые базы данных и другие источники информации. Если крэкер совершает взлом исключительно ради свободы информации, то это еще можно простить, но если это делается ради собственной наживы, ради денег или минутной славы, то такого человека можно назвать только преступником (кем он по закону и является!). Как видите, хакер — это просто гений. Все, кто приписывает этим людям вандализм, сильно ошибаются. Истинные хакеры никогда не используют свои знания во вред другим. Теперь давайте разберемся, как стать настоящим хакером. Это обсуждение поможет вам больше узнать об этих людях. 1. Вы должны знать свой компьютер и научиться эффективно им управлять. Если вы будете еще и знать в нем каждую железку, то это только добавит к вашей оценке по "хакерству" большой жирный плюс. Что я подразумеваю под умением эффективно управлять своим компьютером? Это значит знать все возможные способы каждого действия и в каждой ситуации уметь использовать наиболее оптимальный. В частности, вы должны научиться пользоваться "горячими" клавишами и не дергать мышь по любому пустяку. Нажатие клавиш выполняется быстрее, чем любое, даже маленькое, перемещение мыши. Просто приучите себя к этому, и вы увидите все прелести работы с клавиатурой. Лично я использую мышку очень редко, а стараюсь всегда применять клавиатуру.

Введение Маленький пример на эту тему. Мой начальник всегда копирует и вставляет из буфера с помощью кнопок на панели инструментов или команд контекстного меню, которое появляется при щелчке правой кнопкой мыши. Но если вы делаете так же, то, наверно, знаете, что не везде есть кнопки Копировать, Вставить или такие же пункты в контекстном меню. В таких случаях мой начальник набирает текст вручную. А ведь можно было бы воспользоваться копированием/вставкой с помощью горячих клавиш ++ или +/+, которые достаточно универсальны и присутствуют практически во всех современных приложениях. 2. Вы должны досконально изучать все, что вам интересно о компьютерах. Если вас интересует графика, то вы должны изучить лучшие графические пакеты, научиться рисовать в них любые сцены и создавать самые сложные миры. Если вас интересуют сети, то старайтесь узнать о них все. Если вы считаете, что уже знаете все, то купите книгу по данной теме потолще и поймете, что сильно ошибались. Компьютеры — это такая вещь, в которой невозможно знать все!!! Хакеры — это, прежде всего, профессионалы в каком-нибудь деле. И тут даже не обязательно должен быть компьютер. Хакером можно стать в любой области, но я буду рассматривать только компьютерных хакеров. 3. Желательно уметь программировать. Любой хакер должен знать как минимум один язык программирования. А лучше знать даже несколько языков. Лично я рекомендую всем изучить для начала Delphi. Он достаточно прост, быстр, эффективен, а главное, это очень мощный язык. Но сие не значит, что не надо знать другие языки. Вы можете научиться программировать на чем угодно, даже на языке Basic (использовать его не советую, но знать не помешало бы). Хотя я не очень люблю Visual Basic за его ограниченность, неудобства и сплошные недостатки, я видел несколько великолепных программ, который были написаны именно на этом языке. Глядя на них, сразу хочется назвать их автора Хакером, потому что это действительно виртуозная и безупречная работа. Создание из ничего чего-то великолепного как раз и есть искусство хакерства. Хакер — это созидатель, человек, который что-то создает. В большинстве случаев это относится к коду, но можно создавать и графику, и музыку. Все это тоже относится к хакерскому искусству. Но даже если вы занимаетесь компьютерной музыкой, знание программирования повысит ваш уровень. Сейчас создавать свои программы стало уже не так сложно, как раньше. С помощью Delphi можно создавать простенькие утилиты за очень короткое время. Так что не поленитесь и изучите программирование. А я на протяжении всей книги буду показывать то, что необходимо знать программисту-хакеру, и в том числе множество интересных приемов и примеров.

Введение 4. Не тормози прогресс. Хакеры всегда боролись за свободу информации. Если вы хотите быть хакером, то тоже должны помогать другим. Хакеры обязаны способствовать прогрессу. Некоторые делают это через написание программ с открытым кодом, а кто-то просто делится своими знаниями. Открытая информация не значит, что вы не можете зарабатывать деньги. Это никогда не возбранялось, потому что хакеры тоже люди и тоже хотят кушать и должны содержать свою семью. Но деньги не должны быть главным в вашей жизни. Самое главное - это созидание, процесс созда— ния. Вот тут проявляется еще одно отличие хакеров от крэкеров — хакеры "создают", а крэкеры "уничтожают" информацию. Если вы написали какую-нибудь уникальную шуточную программу, то это вас делает хакером. Но если вы написали вирус, который уничтожает диск, то это вас делает крэкером, я бы даже сказал, "преступником". В борьбе за свободу информации может применяться даже взлом, но только не в разрушительных целях. Вы можете взломать какую-нибудь программу, чтобы посмотреть, как она работает, но не убирать с нее систем зашиты. Нужно уважать труд других программистов, потому что защита программ — это их хлеб. Если в программах не будет защиты, то программисту не на что будет есть. Представьте себе ситуацию, если бы вы украли телевизор. Это было бы воровство и преследовалось по закону. Многие люди это понимают и не идут на преступления из-за боязни наказания. Почему же тогда крэкеры спокойно ломают программы, не боясь закона? Ведь это тоже воровство. Лично я приравниваю взлом программы к воровству телевизора с полки магазина и считаю это одним и тем же. 5. Не придумывай велосипед. Тут опять действует созидательная функция хакеров. Они не должны стоять на месте и обязаны делиться своими знаниями. Например, вы написали какой-то уникальный код, поделитесь им с другими, чтобы людям не пришлось создавать то же самое. Вы можете не выдавать все секреты, но должны помогать другим. Ну а если к вам попал код другого человека, то не стесняйтесь его использовать (с его согласия!). Не выдумывайте то, что уже сделано другими и обкатано пользователями. Если каждый будет создавать колесо, то никто и никогда не создаст повозку. 6. Хакеры — не просто отдельные личности, а целая культура. Но это не значит, что все хакеры одеваются одинаково и выглядят как китайцы — все на одно лицо. Каждый из них — это отдельный индивидуум и не похож на других. Не надо копировать другого человека. То, что вы удачно скопируете кого-то, не сделает вас продвинутым хакером. Только ваша индивидуальность может сделать вам имя.

Введение Если вас знают в каких-то кругах, то это считается очень почетным. Хакеры — это люди, добывающие себе славу своими знаниями и добрыми делами. Поэтому любого хакера должны знать. Как вам узнать, являетесь ли вы хакером или нет? Очень просто: если о вас говорят как о хакере, то вы и есть хакер. Жаль, что такого добиться очень сложно, потому что большинство считает хакерами взломщиков. Поэтому чтобы о вас заговорили, как о хакере, нужно что-то взломать. Но это неправильно, и не надо поддаваться на этот соблазн. Старайтесь держать себя в рамках и добиться славы только добрыми делами. Это намного сложнее, но что поделаешь. Никто не говорил, что будет просто. Некоторые считают, что правильно надо произносить "хэкер", а не "хакер". Это так, но только для английского языка. У нас в стране оно обрусело и стало "хакером". Мы — русские люди, и давайте будем любить свой язык и следовать его правилам. Напоследок советую почитать статью "Как стать хакером" на сайте www.sekachev.ru. Эта статья написана знаменитым хакером по имени Eric S. Raymond. С некоторыми его взглядами я не согласен, но в большинстве своем она также отражает дух хакерства. Тут же возникает вопрос: " Почему же автор относит к хакерскому искусству написание шуточных и сетевых программ?" Попробую ответить на этот вопрос. Во-первых, хакеры всегда пытались доказать свою силу и знания методом написания каких-либо интересных, веселых программ. В эту категорию я не отношу вирусы, потому что они несут в себе разрушение, хотя тоже бывают с изюминкой и юмором. Зато простые и безобидные шутки всегда ценились в узких кругах. Этим хакер показывает не только свои знания особенностей операционной системы, но и старается заставить ближнего своего улыбнуться. Не секрет, что многие хакеры обладают хорошим чувством юмора, и он поневоле ищет своего воплощения. Я советую шутить с помощью безобидных программ. Ну а сетевое программирование неразделимо с понятием хакер с самого его рождения. Хакеры получили распространение благодаря сети, пониманию ее функционирования и большому вкладу в развитие Интернета. Ну и последнее. Я уже сказал, что любой хакер должен уметь программировать на каком-нибудь языке программирования. Некоторые заведомо считают, что если человек хакер, то он должен знать и уметь программировать на языке ассемблера. Это не так. Знание ассемблера желательно, но не обязательно. Я люблю Delphi, и он позволяет мне сделать все, что я захочу. А главное, что я могу сделать это быстро и качественно. Я по образованию экономист-менеджер и 6 лет проучился в институте по этой специальности. Но даже до этого я знал, что заказчик всегда прав. Почему-то в компьютерной области стараются избавиться от этого понятия. Например, Microsoft делает упор на программистов, пытаясь научить их Введение 1 -\ писать определенные программы, не объясняя, зачем это нужно пользователям. Многие тупо следуют этим рекомендациям и не задумываются о необходимости того, что они делают. Тут же приведу простейший пример. Сейчас все программисты вставляют в свои продукты поддержку XML, и при этом никто из них не задумывается о необходимости этого. А ведь не всем пользователям этот формат нужен, и не во всех программах он востребован. Следование рекомендациям Microsoft не означает правильность • действий, потому что заказчик не Билл Гейтс, а ваш потребитель. Поэтому надо всегда делать то, что требует конечный пользователь. Я вообще рекомендую не обращать внимания на корпорацию Microsoft, потому что считаю ее только тормозом прогресса. И это тоже можно доказать на примере. Сколько технологий доступа к данным придумала MS? Просто диву даешься: DAO, RDO, ODBC, ADO, ADO.NET, и это еще не полный список. Корпорация MS регулярно выкидывает на рынок что-то новое, но при этом сама этим не пользуется. При появлении новой технологии все программисты кидаются переделывать свои программы под новый стандарт и в результате тратят громадные ресурсы на постоянные переделки. Таким образом, конкуренты сильно тормозят, a MS движется вперед, потому что не следует своим собственным рекомендациям и ничего не переделывает. Если программа при создании использовала для доступа к данным DAO, то можно спокойно оставить ее работать через DAO и не переделывать на ADO, потому что пользователю все равно, каким образом программа получает данные из базы, главное, чтобы данные были. Программисты и хакеры навязывают другим свое мнение о любимом языке программирования как о единственно приемлемом, и делают это обычно успешно, потому что заказчик очень часто ничего не понимает в программировании. На самом же деле заказчику все равно, на каком языке вы напишете программу, его интересуют только сроки и качество. Лично я могу обеспечить минимальные сроки написания приложения вкупе с хорошим качеством, только работая на Delphi. Такое же качество на VC++ я (да и любой другой программист) смогу обеспечить только в значительно большие сроки. Вот когда заказчик требует минимальный размер или наивысшую скорость работы программы, тогда я берусь за ASM и С. Но это бывает очень редко, потому что сейчас носители информации уже практически не испытывают недостатка в размерах, и компьютеры работают в миллионы раз быстрее первых своих предков. Таким образом, размер и скорость программы уже не являются критичными, и на первый план ставится скорость и качество выполнения заказа. Итак, на этой деловой ноте мы закончим вводную лекцию и перейдем к практическим упражнениям по воинскому искусству, где часто главное — скрытность и победа минимальными силами.

Глава Минимизация и невидимость Что самое главное при написании программ-приколов? Ну конечно же, невидимость. Программы, созданные в этой и следующих главах, будут незаметно сидеть в системе и выполнять нужные действия при наступлении определенного события. Это значит, что программа не должна появляться на панели задач или в списке запущенных программ в окне, выдаваемом при нажатии ++. Так что прежде чем начать что-то писать, нужно узнать, как спрятать свое творение от чужого глаза. Помимо этого, программы-при колы должны иметь маленький размер. Приложения, создаваемые Delphi, достаточно "весомые". Даже простейшая программа, выводящая одно окно, отнимет более 200 Кбайт на диске. Если вы захотите отослать такую шутку по электронной почте, то отправка и получение письма с вашей программой отнимет лишнее время у вас и получателя. Это не очень приятно, поэтому в этой главе я познакомлю вас с тем, как можно уменьшить размер программ, создаваемых в Delphi, 1.1. Сжатие запускных файлов Самый простой способ уменьшить размер приложения — использование программы для сжатия файлов. Лично я очень люблю ASPack, которую вы можете скачать с адреса www.cydsoft.com/vr-online/download.htm или скопировать с компакт-диска из директории программы (файл установки называется ASPack.exe). Она прекрасно сжимает исполняемые файлы *.ехе и динамические библиотеки *.dll. Я не буду подробно описывать процесс установки ASPack, потому что там абсолютно нет ничего сложного. Только одно нажатие на кнопке Next, и все готово! Теперь запустите установленную программу, и вы увидите окно, изображенное на рис. 1.1. Главное окно имеет нескольких вкладок: • Open File;

О Compress;

Глава П Options;

• About;

• Help. S)ASPack2.11 W 3 E E DLc m t t o i 2 X. L o pes r n R gsee to. e it r d U R GS E E N E ITRD 30 davs Version 2. " p n File | C m rsj O t n ] A ot j Hp j Oe o pes po s b u e i l Fe i t in t n i no ai ro Oe I pn i Project! ee x Fl nm ie a e жi Ht r soy i Fl me ( eoe cm rso) 34 02 bt * ie b f r o pesn 6 3 ye i Fl se ( fe c m rso] 154 П 2 bytes ie z at r o pesn i i i Project! еке Рис, 1.1. Главное окно ASPack На вкладке Open File есть только одна кнопка — Open. Нажмите на нее и выберите файл, который вы хотите сжать. Как только вы выберете файл, программа перейдет на вкладку Compress и начнет сжатие (рис. 1.2).

Versign 2L Registered to: UNREGISTERED 30 days OpenFile Compiess j Options | Aboui j Help Compression Progress Go! Compression File Size TestM Project1.exe Рис. 1.2. Сжатие файла Минимизация и невидимость Сжатый файл сразу перезаписывает существующий, а старая несжатая версия сохраняется на всякий случай под тем же именем, но с расширением bak. Настроек у ASPack не так уж много (рис. 1.3), и с ними вы сможете разобраться без моей подсказки. Лучше я расскажу вам, как это работает.

Vetiion 21. O e Fl j C m es O t n | A o t | H l | pn ie o ps po s b u e i i p, f? C m rs r s u e j ' o pes e o c s ue Wdw DLo d i s no s L l e e i I P D ae b c u c p [ b k H ] Г P sre eta d t e t akp o y a e r ev xr aa e 1 A t r n after l a i g 7 uo u o dn г Ad i t c n n mn d no ot t eu e Г' 'м ', • Гч-п, I ! Unregistered veision Options aie not javed S ci n nm et s a e o',1 Lnug 7, agae Po c. x r e1ee il Рис. 1.З. Настройки ASPack Давайте разберемся, как работает сжатие. Сначала весь код программы сжимается архиватором. Если вы думаете, что он какой-то "навороченный", то сильно ошибаетесь. Для сжатия используется обычный архиватор, только оптимизированный для сжатия двоичного кода. После этого в конец сжатого кода добавляется код разархиватора, который будет программу разжимать обратно. И в самом конце ASPack изменяет заголовок исполняемого файла так, чтобы при старте сначала запускался разархиватор. Теперь, когда вы запускаете сжатую программу, сначала заработает разархиватор, который разожмет бинарный код программы и аккуратно разместит его в памяти компьютера. Как только этот процесс закончится, разархиватор передаст управление вашей программе. Некоторые считают, что из-за расходов на распаковку программа будет работать медленней!!! Я бы сказал, что вы не заметите разницу. Даже если и будут какие-то потери, то они будут неощутимы (по крайней мере, на современных компьютерах). Это происходит потому, что архивация хорошо оптимизирована под двоичный код. И по сути дела, распаковка происходит только один раз и в дальнейшем никакого влияния на работу программы не оказывает. В результате потери в скорости из-за сжатия будут неощутимы. При нормальном программировании с использованием всех "навороченных" возможностей типа визуальности и объектного программирования код Глава получается большим, но его можно сжать на 60-70% специальным архиватором. А писать такой код намного легче и быстрее. Еще одно "за" использование сжатия — заархивированный код труднее взломать, потому что не каждый disassembler сможет прочитать упакованные команды. Так что помимо уменьшения размера вы получаете защиту, способную отпугнуть большинство взломщиков. Конечно же, профессионала не отпугнешь даже этим, но взломщик средней руки не будет мучиться со сжатым двоичным кодом. На компакт-диске в директории \Примеры\Глава l\Screensl вы можете найти файлы приведенных цветных рисунков.

1.2. Без окон, без дверей...

Следующий способ уменьшить размер программы заключается в ответе на вопрос: "Из-за чего программа, созданная Delphi, получается большой?" Ответ очень прост: Delphi является объектным языком. В нем каждый элемент выглядит как объект, который обладает своими свойствами, методами и событиями. Любой объект вполне автономен и многое умеет делать без ваших указаний. Это значит, что вам нужно только подключить его к своей форме, изменить нужным образом свойства, и приложение готово! И оно будет работать без какого-либо прописывания его деятельности. Но в объектном программировании есть и свои недостатки. В объектах реализовано большое количество действий, которые вы и пользователь сможете производить с ним. Но реально в любой программе мы используем два-три из всех этих свойств. Все остальное — для программы лишний груз, который никому не нужен. Но как же тогда создать компактный код, чтобы программа занимала минимум места на винчестере и в оперативной памяти? Тут есть несколько вариантов. 1. Не использовать VCL (для любителей Visual C++ — это библиотека MFC), которая упрощает программирование. В этом случае весь код придется набирать вручную и работать только с WinAPI. Программа в таком случае получается очень маленькой и быстрой. Но таким образом вы лишаетесь простоты визуального программирования и можете ощутить все неудобства программирования с помощью чистого WinAPI. 2. Сжимать готовые программы с помощью компрессоров. Объектный код сжимается в несколько раз, и программа, созданная с использованием VCL, может превратиться из монстра в 300 Кбайт в скромного по размерам "зверя", весящего всего 30—50 Кбайт. Главное преимущество состоит в том, что вы не лишаетесь возможностей объектного программирования и можете спокойно забыть про неудобства WinAPI.

Минимизация и невидимость Второй метод мы уже обсудили выше, поэтому стается только описать первый вариант. Если вы хотите создать программу действительно маленького размера, то должны забыть про все удобства. Вы не сможете подключать визуальные формы или другие удобные модули, написанные фирмой Borland для упрощения жизни программиста. Только API-функции самого Windows и ничего больше. Для того чтобы создать маленькую программу в Delphi, нужно создать новый проект (по умолчанию Delphi при открытии сама создаст новый файл проекта, но вы всегда можете создать новое приложение, выбрав File\New\ Application), и зайти в менеджер проектов (меню View\Project Manager). Здесь нужно удалить все модули и формы (пункт Unit, он выделен на рис. 1.4), чтобы остался только файл самого проекта (по умолчанию его имя Projectl.exe). Никаких модулей в проекте не должно быть. Более подробно о создании шаблона см. в разд. 1.3.

I Project Manager (Ptojecti.

Files Щ ProjectGroupi H--JP Project!.exe zl New Remove ' Adiwrfe Path D: \Program FilesVB orland\D elpN6\Piojects D: \Progr am FilesVB orland\D elpN6\Piojeds D:\Program Files\BotlandM}elphi6\Projecls Рис. 1.4. Project Manager Теперь нужно щелкнуть правой кнопкой мыши на имени проекта и выбрать из появившегося контекстного меню пункт View Source или в главном меню Project выбрать пункт View Source. В редакторе кода откроется файл проекта Projectl.dpr. Если вы уже удалили все модули, то его содержимое должно быть таким: program Project1;

uses Forms;

18 ( R *.res} $ begin Application.Initialize;

Application-Run;

end.

Глава Теперь можно скомпилировать абсолютно пустой проект. Для этого надо выбрать в меню Project пункт Compile Project или нажать сочетание клавиш +. После компиляции выберите в меню Project команду Information for Projectl. Появится окно с информацией о проекте. Окно, которое появилось передо мной, вы можете увидеть на рис. 1.5.

Po rm r ga S uc c m i d o re o p : l e C d, size: ' oe D t sz : aa i e Initial sa k size: tc Fl sz : ie i e 1 fe 3 ns i 321 bt s 2 3 2 ye 77 bt s 0 7 ye 1 3 4bt s 6 8 ye 3 0 6 bt s 7 6 8 ye P ca e Ue ~ akg s sd ( oe Nn) rStatus""" • " " —" i Project! Successful C m e. o pd l i Help Рис. 1.5. Окно информации о проекте В правой части окна должны быть описаны используемые пакеты. Так как вы все удалили, значит, там должна красоваться надпись None. А вот с левой стороны должна быть описана информация о скомпилированном коде. Самая последняя строка показывает размер файла, и у меня он равен 370 688 байт. Ничего себе "пустая программа"!!! Мы же ничего еще не написали. Откуда же тогда такой большой код? Давайте разберемся, что осталось в нашем проекте, чтобы обрезать все то, что еще не обрезано. Сразу обратите внимание, что в разделе uses подключен модуль Forms. Это объектный модуль, написанный "дядей Борландом", а значит, его использовать нельзя, потому что именно он увеличивает размер нашей программы. Между командами begin и end используется объект Application. Этот объект тоже использовать не надо, так как он не заботится о "фигуре" программы. Большой объем, который появляется даже у пустой программы, как раз и связан с объектом Application, который объявлен в модуле Forms. Хотя мы Минимизация и невидимость использовали только два метода i n i t i a l i z e и Run, при компиляции в ехефайл попадает весь объект Triplication, а он состоит из сотен, а может и тысяч строчек кода. Чтобы избавиться от накладных расходов, нужно заменить модуль Forms на windows, который описывает только WinAPI. Этот модуль связан с объектами Delphi, и его подключение является обязательным, иначе вы не сможете вызвать ни одной функции из набора WinAPI. А между begin и end вообще все можно удалить. В итоге самый минимальный (с учетом использования модуля windows) код программы будет выглядеть так: program Projectl;

uses Windows;

begin end. Снова откомпилируйте проект. Откройте окно информации и посмотрите на размер получившегося файла. У меня получилось 8 192 байта (рис. 1.6). Вот это уже по-человечески.

- r ga - - - Po r m' S ошсе compiled: Code size: Data size: Initial stack size: File size 22 ines 3696 bytes 1945 bytes 16384 bytes 8192 bytes Packages Used • (None] Status' — -~ Pfojecti Successfully Compiled.

ж Рис. 1.6. Окно информации о проекте Заготовка минимальной программы с использованием WinAPI готова. Теперь вы можете смело добавлять свой код. Мне нужно только объяснить вам, какие модули можно подключать к своему проекту в раздел uses. Тут все очень просто и не займет много времени. Если при установке Delphi вы не отключали копирование исходников библиотек, то перейдите в директорию, куда вы установили Delphi. Здесь перейдите в папку Source, затем в Rtl и, наконец, Win. Если вы отключили копирование исходников, то вставьте компакт-диск с Delphi и ищите эти Глава директории там. В них расположены исходники модулей, в которых описаны все API-функции Windows. Именно эти модули вы должны подключать к своим проектам, если хотите получить маленький код. Если вы подключите что-то другое, то я уже не гарантирую минимум размера вашей программы (хотя есть и исключения). Сразу же рассмотрим пример. Если вы хотите, чтобы в вашей программе были возможности работы с сетью, то вам нужно подключить к проекту библиотеку сокетов. Среди модулей WinAPI есть файл с именем winsock.pas. Значит, вы должны в разделе uses написать winsock (расширение писать не надо), и ваша программа сможет работать с сетью. Пока что я описал минимальный проект, в который можно добавлять свой код. Но код, который вы вставите, выполнится один раз, и программа выгрузится из памяти. А что, если вам надо, чтобы программа постоянно висела в памяти и что-то делала? Для этого нужно использовать следующий шаблон для своих программ: program Projectl;

uses Windows;

var Msg : TMsg;

Begin //Сюда можно добавлять свой код //Дальше идет код, который заставит программу висеть в //памяти вечно и не будет сильно загружать систему while GetMessagef Msg, HInstance, 0, 0) do begin TranslateMessage(msg);

DispatchMessage(msg);

end;

end.

Сейчас я не буду описывать этот шаблон, потому что дальше мы подробно обсудим написание полноценного шаблона минимального приложения. Там и будут описаны функции, которые используются в этом примере. Самое интересное, что такое минимальное приложение будет не видно в системе. Мы не создавали никаких окон, значит, на экране ничего отображаться не будет. Программа не будет иметь фокуса ввода, поэтому в панели задач тоже незачем что-то отображать.

Минимизация и невидимость Файл Параметры Вид Завершение работы Справке f ^ p o i i e c c b l IБыстродействие ( С_еть J Пользователи!

40 108 КБ ot 14 124 КБ 00 3 864 КБ 00 ? 3 f KR 7t m D Отображать процессы всех пользователей [ Завершить процесс Процессов: 29.;

Загрузка ЦП: 19% Выделение памяти: 129056КБ ( devldr32.exe LvAgent.exe msmsgs.exe ctFmon.exe drwebscd.exe Spidet.exe Directcd.exe AHQTB.EXE Spidernt.exe nvsvc32.exe spoolsv.exe exptorer.exe svchost.exe svchost.exe delphi32.exe svchost.exe svchost.exe Миша Миша Миша Миша Миша Миша Миша Миша SYSTEM SYSTEM SYSTEM Миша LOCAL SERVICE NETWORK SERVICE Миша SYSTEM SYSTEM 4V4TFM 00 00 00 00 00 00 00 00 00 00 00 00 00 3 072 КБ 1 852 КБ 892 КБ 1 660 КБ 2 624 Кб 2 316 КБ 4 096 КБ Z 740 КБ 1804 КБ 1320 КБ 4 248 КБ 14 720 КБ 3 420 KB 2 444 КБ Рис. 1.7. Закладка "Процессы" Windows XP У нас получилась не программа, а процесс. Именно поэтому его можно заметить в Windows 2000/XP только с помощью программ, которые умеют отображать все процессы, запущенные в системе. В Windows 2000/XP при нажатии ++ появляется Диспетчер задач Windows (рис. 1.7). В Диспетчере есть вкладка Процессы, где и можно найти такую программу. Вообще-то на этой вкладке можно найти любую работающую программу, и от ее инспекторского взора спрятаться очень тяжело. Так что достаточно только назвать исполняемый файл не сильно вызывающе, и простой пользователь ничего не заподозрит, потому что список процессов достаточно большой, и я не думаю, что он знает хотя бы половину из них. В Windows Эх при нажатии кнопок ++ такая программа пока еще будет видна. Чтобы окончательно скрыть ее из виду, нужно добавить следующий код:

procedure RegisterServiceProcess;

external 'kernel32.dll' name 'RegisterServiceProcess';

Здесь Объявлена недокументированная процедура RegisterServiceProcess, которая есть в ядре kernel32.dll. Эта процедура делает нашу программу процессом в системе Windows 9x. Строку с описанием процедуры нужно добавить сразу после раздела uses.

Глава Чтобы вызвать эту процедуру, нужно написать следующий код в любом месте программы (желательно в начале): asm push I push 0 call RegisterServiceProcess;

end;

В Delphi есть встроенный ассемблер, вы можете прямо среди кода на Паскале писать код на ассемблере. В примере, показанном выше, использован ассемблер для вызова процедуры RegisterServiceProcess. Инструкции языка ассемблера нужно заключать между словами asm и and;

. В примере используется три инструкции. В первой в стек поднимается число i с помощью операции push. Во второй строке в стек поднимается значение о. Эти два числа, поднятые в стек, являются переменными для процедуры RegisterServiceProcess. To же самое можно было бы сделать и с помощью вызова функции Паскаля RegisterServiceProcess (О, 1), но мне захотелось показать вам, как работает встроенный ассемблер. Да и тогда пришлось бы изменить описание процедуры RegisterServiceProcess, которая регистрирует программу как процесс и в Windows 9x делает программу невидимой в списке запущенных программ, который вы вызываете нажатием ++. В последней инструкции ассемблера вызывается процедура RegisterServiceProcess С П М Щ Ю оператора c a l l. ОО Ь Теперь наша программа не будет видна и в Windows 9x Только вы должны учитывать, что этот код прекрасно работает в Windows 9x, но выдаст ошибку в Windows 2000/XP, потому что в его ядре нет функции RegisterServiceProcess. Поэтому вы должны знать, в какой системе будет запускаться программа и можно ли использовать процедуру RegisterServiceProcess.

1.3. Шаблон минимального приложения Сейчас нам пора написать хороший шаблон минимального приложения, который мы будем использовать в этой книге для написания наших программ-приколов. Для этого надо познакомиться с внутренностями Windows и его WinAPI. Запустите уже полюбившийся Delphi. Как всегда, сразу откроется новый проект. Так как мы очень часто будем делать минимальные программы, то нам абсолютно не нужны никакие формы, и их надо удалить. Щелкните View\Project Manager. Появится окно менеджера проектов. Выделите Unitl и нажмите кнопку Remove для удаления лишней формы (рис. 1.9).

Минимизация и невидимость Ь Delphi Б - Project File E i S ac j V w Eoe t & n C m o e t d t b s lools Wd w dt e r h e r j c u o p n n aa a e i no j I dbE^Diess j DataSndt Action A tv C nr l ci e o to Mn eu O j c e ut be W n le OnActiyale OnCanResize OrOck/' ['~ OnPose ' ' QnCloseQueiy QnConslrained OnContextPoptj OnDeate OnDNClick OnDeactivate DnDestroy Object TreeView Shift+A!t+Fl 1 i=| To-Do List Alignment Palette Browser Shift+ctrl+B Code Explorer Component List %* Window List.,, Alt+O Debug Windows Desktops rU Toggle Form/Unit j ? Forms New Edit Window Toolbars Рис. 1.8. Вызов менеджера проектов F12 CM+F12 Shift+F |Рго|ес(2. Files Щ ProiectGtoupi В ЩЗ Project2.eKe Ш, •%$ Urriti Path 3 New X Remove D APiogiam FilesSB otland'xD elphi6\Ptojects D: \Program FilesSB orlandSD elphi6\Projects DAPtogramFilesVBoilandSDelphiG^Projects f'ef\ Remove D:\Program Files\Borland\Delphi6\Projects\Unitl.pas?

["""jj!gEZ]| Np Рис. 1.9. Удаление ненужной формы Теперь выбираем в меню Project пункт View Source. Если все в норме, то в редакторе кода вы увидите код вашего проекта. Оставляем только первую строчку program Projecti, а все остальное удаляем и вместо этого пишем Глава следующее (комментарии, строки текста, которые идут после символов //, естественно, можно опускать): Листинг 4$ ;

\}Щ1К>НмпЩ uses windows, messages, sysutils;

f R *.RES} $ var Instance: HWnd;

WindowClass: TWndClass;

Handle: HWnd;

msg: TMsg;

//Процедура выхода из программы procedure DoExit;

begin Halt;

end;

//Функция обработки событий Windows function WindowProc (Hwn,msg,wpr,lpr: longint): longint;

stdcall, begin result:=defwindowproc(hwn,msg,wpr,lpr);

if msg=wm_destroy then DoExit;

if msg=wmKeyDown then if wpr-VK_ESCAPE then poExit;

end;

//Отсюда начинается выполнение программы begin //Получаем описатель модуля instance :^GetModuleHandle(nil);

Минимизация и невидимость //Заполняем структуру WindowClass WindowClass. style :=CS_HRedraw or CS_VRedraw;

WindowClass.Lpfnwndproc:=@windowproc;

WindowClass.Hinstance:=Instance;

WindowClass.HbrBackground:= color_btnface;

WindowClass.LpszClassName:='DX';

WindowClass.Hcursor:=LoadCursor(0,IDC_ARROW);

//Регистрируем новый класс RegisterClass (WindowClass);

//Создаем окно Handle:=CreateWindowEx (0,'DX', ",WS_POPUP, 1,1, 200, 200,0, 0,Instance, nil) ;

ShowWindow(Handle, SW_SHOW);

UpdateWindow (Handle);

//Здесь можно производить инициализацию //Цикл обработки сообщений while (GetMessage(msg, 0, 0, 0)) do begin translatemessage(msg) ;

dispatchmessage (msg);

end;

end. Теперь давайте подробно разберем листинг 1.1. После старта программа начинает выполнение с первого begin (это место обозначено соответствующим комментарием). Первой строкой кода идет вызов WinAPI-функции GetModuieHandie. Она возвращает указатель модуля, который сохраняется в переменной instance. Этот указатель нам пригодится немного позже. Далее заполняется структура WindowClass. Эта структура используется при создании нового класса окна. Для минимального приложения нам понадобиться заполнить следующие поля: • style — стиль окна;

• Lpfnwndproc — сюда нужно записать указатель на процедуру, которая будет вызываться на все пользовательские или системные события;

Глава D Hinstance — указатель, который мы получили в первой строчке кода;

• HbrBackground — цвет фона (в принципе, он необязателен, но я решил покрасить фон системным цветом кнопок);

П LpszciassName — имя создаваемого класса;

• Hcursor — курсор. Сюда зафужается стандартный курсор-стрелка. Все. структура готова, и мы можем зарегистрировать новый класс будущего ОКНа. ДЛЯ ЭТОГО ВЫЗЫВаеТСЯ WinAPI-фуНКЦИЯ R e g i s t e r C l a s s (WindowClass) ;

.

Теперь в системе есть описание вашего будущего окна. Почему будущего? Да потому, что само окно мы пока не создали. Для этого нужно еще вызвать функцию CreateWindowEx: CreateWindowEx (0,'DK','',WS_POPUP, 1,1, 200, 200,0,0, instance, n i l ) ;

. У нее достаточно много параметров, и давайте посмотрим на них подробнее: 1. Расширенный стиль окна. Нам он не нужен, поэтому у меня первый параметр равен нулю. 2. Имя класса. Мы зарегистрировали класс ох, значит, и здесь мы должны указать именно этот класс. 3. Имя окна. При программировании графики имя окна не нужно, потому что окно будет полноэкранным. 4. Стиль окна. Нас интересует простейшее WS_POPUP ОКНО. 5. Следующие четыре параметра — это левая и правая позиция, ширина и высота окна. Если указать все равными нулю, то значения будут выбраны по умолчанию. 6. Главное окно по отношению к создаваемому. Наше окно само по себе главное, поэтому я указываю 0. 7. Меню. 8. Это снова erfpfntkm, полученный после вызова GetModuieHandie. 9. Параметры окна. Этот параметр используется при создании многодокументных окон, поэтому я указываю нуль (nil). После создания окна его надо отобразить. Делается это с помощью вызова процедуры Showwindow. У этой процедуры использовано два параметра: 1. Созданное окно. 2. Параметры отображения окна. Здесь указано SW^SHOW, чтобы просто активизировать и отобразить окно. Остальные значения параметра можно посмотреть в файле справки по WinAPI-функциям (Help/Windows SDK). И последняя подготовительная функция — updatewindow. Это просто прорисовка созданного окна. Теперь разберемся с циклом обработки сообщений. Функция GetMessage ожидает пользовательского или системного сообщения, и как только оно Минимизация и невидимость наступает, возвращает true (истина). Полученное сообщение преобразуется в необходимый вид с помощью transiatemessage и отправляется обработЧИКу Сообщений С П М Щ Ю вызова функции dispatchmessage. ОО Ь В каждой программе должна быть процедура обработки сообщений. Какая именно? Мы указали ее при создании класса окна в свойстве windowciass.Lpfnwndproc. Я ее назвал windowProc — стандартное имя, используемое по умолчанию. Сама же процедура должна выглядеть приблизительно как в листинге 1.1. В процедуре-обработчике событий желательно всегда делать вызов функции defwindowproc. Эта функция ищет в системе обработчик полученного сообщения, установленный по умолчанию. Это очень важно, тогда вам не придется самому писать то, что может сделать ОС. После этого можно начинать обработку полученного сообщения. Это происходит с помощью сравнивания параметра msg со стандартными событиями. Например, если msg равно wmdestroy, то это значит, что программа хочет уничтожиться, и тогда в обработчике можно освободить выделенную под программу память. В обработчике есть еще два сравнения. Если msg равно wmKeyDown, т. е. пользователь нажал какую-то клавишу, то проверяется, не является ли она клавишей — выражение wpr - VKESCAPE — И В случае его истинности приложение также завершает свою работу. Вот и все, с шаблоном мы разобрались. Если вы сейчас запустите созданную программу, то перед вами появится пустое окно черного цвета. Чтобы его закрыть, просто нажмите +, потому что никаких кнопок на нем нет. Если вы захотите сделать это окно невидимым, то просто уберите из кода функцию showwindow, которая отображает окно на экране. После этого ваша программа сразу же станет невидимой в системе. Можно так же изменить второй параметр этой процедуры. Сейчас он равен SWSHOW, НО МОЖНО указать SWHIDE, чтобы спрятать окно. В принципе указание параметра SWHIDE внешне равносильно отсутствию вызова процедуры. Чуть позже мы еще встретимся с процедурой showwindow, и не один раз. На компакт-диске в директории \Примеры\Глава l\Minimum\ вы можете увидеть исходник этого примера.

1.4. Прячем целые программы Написание программ маленького размера достаточно сложное занятие. Чаще всего нам нужно просто написать какой-то пример, в котором размер файла не имеет особого значения, а невидимость обеспечить необходимо. В таком случае стратегия написания невидимой программы будет немного другой, и мы ее сейчас рассмотрим на практике.

2 Зак. Глава Создайте новый проект в Delphi. Перенесите на форму одну только кнопку и измените ее свойство Caption на спрятать. При нажатии этой кнопки наше приложение будет прятаться. Теперь создайте обработчик события onclick для этой кнопки и там напишите: procedure TForml.ButtonlClick(Sender: TObject);

begin ShowWindow(Handle,SW_HIDE);

ShowWindow(Application.Handle,SW_HIDE);

end;

Здесь использована уже знакомая функция ShowWindow. Как я уже говорил, эта процедура выводит окно. В качестве второго параметра процедуре в обоих случаях передается значение SW_HIDE, которое заставляет делать окно невидимым. При первом вызове процедуры в качестве первого параметра указано Handle — свойство, в котором хранится указатель текущего (в данном случае главного) окна, чтобы сделать его невидимым. При втором вызове указано Application.Handle — указатель всего приложения. Теперь приложение становится абсолютно невидимым. Точнее сказать, видимым, но только на вкладке Процессы в окне Диспетчер задач indows. Как я уже говорил, большинство пользователей никогда не заглядывает на эту вкладку, потому что разобраться там в чем-то очень тяжело. Достаточно дать вашей программе какое-нибудь наименее вызывающее имя, и она станет абсолютно незаметной. Тут же вспоминается случай, когда несколько лет назад я написал своего первого трояна, с помощью которого подшучивал над своим начальником. Я приблизительно таким же образом спрятал программу и дал ей название internat32.exe. В системе Windows 95/98 есть такой сервис, как internat.exe, и он присутствует всегда. Именно поэтому появление нового сервиса internat32 ни у кого не вызвало подозрений. Мой начальник долго искал причину, по которой на его компьютере исчезает звук и сам компьютер перегружается, но ничего не нашел. Его компьютер даже рассматривали компьютерщики нашей фирмы, и даже они ничего не нашли. Просто никто не обращал внимания на такой неприглядно названный файл. На компакт-диске в директории \Примеры\Глава l\Hide App\ вы можете увидеть исходник этого примера.

1.5. Оптимизация программ Вся наша жизнь — это борьба с тормозами и нехваткой времени. Каждый день мы тратим по несколько часов на оптимизацию. Каждый из нас старается оптимизировать все, что попадает под руку. А вы уверены, что вы это делаете правильно? Может быть, есть возможность что-то сделать еще лучше?

Минимизация и невидимость Я понимаю, что все сейчас разленились и выполняют свои обязанности спустя рукава. Лично я до такой степени привык, что за меня все делает компьютер, что даже забыл, как выглядит шариковая ручка. Недавно мне пришлось писать заявление на отпуск на простой бумаге, так я забыл, как пишется буква "ю". Пришлось подглядывать, как она выглядит на клавиатуре. Это не шутка. Это прогресс, благодаря которому я все делаю на компьютере. Даже для того, чтобы написать текст из двух строк, мы включаем свой компьютер и загружаем MS Word, тратя на это драгоценное время. А может, легче было бы написать этот текст вручную? Я вас понимаю — несолидно!!! Программисты — так это вообще "полное бесстыдство", как говорил один из моих преподавателей: "Тра-та-та". Если они считают, что их творение (в виде исходного кода) никто не увидит, и можно писать что угодно, так это они ошибаются. С этой точки зрения программы с открытым исходным кодом в большом преимуществе, потому что они намного чище и быстрей. Создавая код, мы ленимся его оптимизировать не только с точки зрения размера, но и с точки зрения скорости. Глядя на такие творения, хочется ругаться матом, только программа от этого лучше не станет. Хакеры далеко не ушли. Если раньше, глядя на программиста или хакера, создавался образ прокуренного, заросшего и немытого молодого человека, то сейчас это цифровое существо, залитое пивом "Балтика" по самые уши, за которое все выполняют машины. Вам медсестра в поликлинике не говорила, что у вас вместо крови одно только пиво льется? Не, я ничего против пива не имею, я и сам его люблю, но надо же и меру знать. Все это — деградация по методу MS!!! Мы берем в руки мышку и начинаем тыкать ей где попало, забывая про клавиатуру и горячие клавиши. Я считаю, что надо бороться с этим. В последнее время меня самого посещает такая лень, что я убираю клавиатуру, запускаю экранную клавиатуру и начинаю работать только мышкой. Осталось только покрыть мое тело шерстью и посадить в клетку к таким же ленивым шимпанзе. Не надо тратить большие деньги на модернизацию компьютера!!! Начните лучше улучшения с себя. Давайте оптимизируем свою работу и то, что мы делаем, и тогда компьютер заработает намного быстрее. Изначально эта часть книги задумывалась как рассказ об оптимизации кода программ, но впоследствии я перенес в нее свой "труд", который можно найти и в Интернете на моем сайте, потому что оптимизировать надо все. Я буду говорить про теорию оптимизации, а ее законы действуют везде. По тем же законам вы можете оптимизировать свой распорядок дня, чтобы успевать все сделать, и свою ОС, чтобы она работала быстрей. Но основа все же будет относиться к коду программ. Здесь будет описано немного больше информации, чем в статье, которую можно увидеть на сайте, или в одноименной главе моей книги "Библия Delphi ".

Глава Как всегда я постараюсь давать как можно больше реальных примеров, чтобы вы смогли убедится в том, что вам не вешают очередную лапшу на уши, и смогли применить все сказанное на практике. Начну с законов, которые работают не только в программировании, но и в реальной жизни. Ну а напоследок я оставлю только то, что может пригодиться при оптимизации кода.

ЗАКОН № Оптимизировать можно все. Даже там, где вам кажется, что все и так работает быстро, можно сделать еще быстрее.

Это действительно так. И этот закон очень сильно проявляется в программировании. Идеального кода не существует. Даже простую операцию сложения 2 + 2 тоже можно оптимизировать. Чтобы достичь максимального результата, нужно действовать последовательно и желательно в том порядке, в котором описано ниже. Помните, что любую задачу можно решить хотя бы двумя способами (или больше), и ваша задача — выбрать наилучший метод, который обеспечит желаемую производительность и универсальность.

ЗАКОН № Первое, с чего нужно начинать, — это с поиска самых слабых и медленных мест. Зачем начинать оптимизацию с того, что и так работает достаточно быстро/ Если вы будете оптимизировать сильные места, то можете нарваться на неожиданные конфликты. Да и эффект будет минимален.

Тут же я вспоминаю пример из своей собственной жизни. Где-то в 1995 году меня посетила одна невероятная идея — написать собственную игру в стиле Doom. Я не собирался ее делать коммерческой, а хотел только потренировать свои мозги на сообразительность. Четыре месяца невероятного труда, и нечто похожее на движок уже было готово. Я создал один голый уровень, по которому можно было перемещаться, и с чувством гордости побежал по коридорам. Никаких монстров, дверей и атрибутики на нем не было, а тормоза ощущались достаточно значительные. Тут я представил себе, что будет, если добавить монстров и атрибуты, да еще и наделить все это AI.... Вот тут чувство собственного достоинства поникло. Кому нужен движок, который при разрешении 320x200 (тогда это было круто!) в голом виде тормозит со страшной силой? Вот именно.... Понятное дело, что мой виртуальный мир нужно было оптимизировать. Целый месяц я бился над кодом и вылизывал каждый оператор моего движка.

Минимизация и невидимость 31_ Результат — мир стал прорисовываться на 10% быстрей, но тормозить не перестал. И тут я увидел самое слабое место — вывод на экран. Мой движок просчитывал сцены достаточно быстро, а пробоиной был именно вывод изображения. Тогда еще не было шины AGP, и я использовал простую PCI-видеокарту от S3 с 1 Мбайтом памяти. Пара часов колдовства, и я выжал из PCI все возможное. Откомпилировав движок, я снова загрузился в свой виртуальный мир. Одно нажатие клавиши "вперед", и я очутился у противоположной стены. Никаких тормозов, сумасшедшая скорость просчета и моментальный вывод на экран. Как видите, моя ошибка была в том, что вначале я неправильно определил слабое место своего движка. Я месяц потратил месяц на оптимизацию математики, и что в результате? Мизерные 10% прироста в производительности. Но когда я реально нашел слабое звено, то смог повысить производительность в несколько раз. Именно поэтому я говорю, что надо начинать оптимизировать только со слабых мест. Если вы ускорите работу самого слабого звена вашей программы, то, может быть, и не понадобится ускорять другие места. Вы можете потратить дни на оптимизацию сильных сторон и увеличить производительность только на 10% (что может оказаться недостаточным), или несколько часов на улучшение слабой части, и получить улучшение в 10 раз!.. Слабые места компьютера Меня поражают люди, которые гонятся за мегагерцами процессора и сидят на доисторической видеокарте от S3, жестком диске на 5400 оборотов и с 32 Мбайтами памяти. Посмотрите в корпус своего компьютера и оцените его содержимое. Если вы увидели, что памяти у вас не более 64 Мбайт, то встаньте и громко произнесите: "Уважаемый DIMM, команда выбрала вас. Вы сегодня — самое слабое звено, и должны покинуть мой компьютер". После этого покупаете себе 128, а лучше 256, а еще лучше 512 Мбайт памяти и наслаждаетесь ускорением работы Delphi, Photoshop и других "тяжелых" программ. В данном случае наращивание сотни мегагерц у процессора даст более маленький прирост в скорости. Если вы используете тяжелые приложения при нехватке памяти, то процессор начинает тратить слишком много времени на загрузку и выгрузку данных. Ну а если в вашем компьютере достаточно оперативной памяти, то процессор уже занимается только расчетами и не расходуется по лишним загрузкам-выгрузкам. То же самое с видеоадаптером. Если видеокарта у вас слабенькая, то процессор будет просчитывать сцены быстрей, чем они будут выводиться на экран. А это грозит простоями и минимальным приростом производительности.

Глава ЗАКОН № Следующим шагом вы должны разобрать все операции по косточкам и выяснить, где происходят регулярно повторяющиеся операции. Начинать оптимизацию нужно именно с них.

Опять начнем рассмотрение этого закона с программирования. Допустим, что у вас есть следующий код (приведена просто логика, а не реальная программа):

1. А:=А*2;

2.

Б:=1| 3. Х:=Х+М[Б];

4. Б:=Б+1;

5. Если Б<100 то перейти на шаг 3. Любой программист скажет, что здесь слабым местом является первая строка, потому что там используется умножение. Это действительно так. Умножение всегда выполняется дольше, и если заменить его на сложение (А:=А+А) ИЛИ еще лучше на сдвиг, то вы выиграете пару тактов процессорного времени. Но только пару тактов, и для процессора это будет незаметно. Теперь посмотри еще раз на наш код. Больше ничего не видишь? А я вижу. В этом коде используется цикл: "Пока Б<100, будет выполняться операция Х:=Х+М[Б|". Это значит, что процессору придется выполнить 100 переходов с шага 5 на шаг 3. А это уже немало. Как можно здесь что-то оптимизировать? Очень легко. Здесь у нас внутри цикла выполняется две строки: 3 и 4. А что, если мы внутри цикла размножим их 2 раза:

1. Б : = 1 | 2. Х:=Х+М[Б];

3. Б:=Б+1;

4. Х:=Х+М[Б];

5. Б:=Б+1;

6. Если Б<50 то перейти на шаг 3;

Здесь я разложил цикл на более маленький. Вторую и третью операцию я повторил два раза. Это значит, что за один проход цикла я выполню два раза строки 3 и 4, и только после этого перейду на строку 3, чтобы повторить операцию. Такой цикл уже нужно повторить только 50 раз (потому что за один раз выполняется два действия). Это значит, что я сэкономил 50 операций переходов. Неплохо? А это уже несколько сотен тактов процессорного времени.

Минимизация и невидимость А что, если внутри цикла написать строки 2 и 3 десять раз? Это значит, что за один проход цикла строки 2 и 3 будут вычисляться 10 раз, и мне понадобится повторить такой цикл только 10 раз, чтобы получить в результате 100. А это уже экономия 90 операций переходов. Недостаток этого подхода — увеличился код моей программы, зато повысилась скорость, и очень значительно. Этот подход очень хорош, но им не стоит злоупотреблять. С одной стороны, увеличивается скорость, а с другой — увеличивается размер. А большой размер — это враг любой программы. В любом деле главное — разумная достаточность. Чем больше вы увеличиваете код ради оптимизации скорости, тем меньше результирующий эффект от оптимизации. В жизни таких примеров намного больше. Любую циклическую операцию можно оптимизировать. Хотите пример? Пожалуйста. Допустим, у вашего провайдера Интернета есть несколько телефонов доступа. Вы каждый день перезваниваете на каждый из них в надежде найти свободный. Начинающий тут же скажет, что провайдер обязан оптимизировать свои пулы модемов в один, чтобы не надо было трезвонить по всем номерам сразу. Но опытный пользователь должен знать, что не у каждого пользователя хорошая связь с любой телефонной станцией города. Поэтому провайдеры держат пулы на разных станциях, чтобы вы могли выбрать тот, с которым связь лучше. Поставьте программу-дозвонщик (таких сейчас полно в Интернете), которая сама будет перебирать номера телефонов. А теперь другой пример — вам на 1 час досталась карточка какого-то нового провайдера. Заносить ее в программу дозвона не имеет смысла, потому что вы можете больше никогда не позвонить ему. Из-за этой одноразовой операции вам придется перенастраивать свой дозвонщик на нового провайдера и потом обратно, а выигрыш практически нулевой, потому что пока вы меняете настройки, уже можно было дозвониться стандартными средствами Windows. Отсюда сразу же напрашивается вывод — нужно правильно выбирать средства для выполнения необходимых задач.

ЗАКОН № (Этот закон — расширение предыдущего.) Оптимизировать одноразовые операции — это только потеря времени. Сто раз подумай, прежде чем начать мучиться с редкими операциями.

Полгодика назад я прочитал рассказ в Интернете "Записки жены программиста" (http://www.exler.ru/novels/wife.htm). Очень даже некислый и жизненный рассказ. Когда я его читал, у меня было ощущение, что его написала моя жена. Слава "Красной Шапочке", что она на такую подлость не способна. Так вот там была такая ситуация. Очаровательная девушка выходит замуж за программиста, и им надо разослать приглашения на свадьбу. Вместо того чтобы набрать их на печатной Глава машинке, программист кричит, что он крутой, и пишет специальную программу. Ее написание заняло один день, и столько же — ее отладка. Главная ошибка — неправильная оптимизация своего труда. Легче набрать шаблон в любом текстовом редакторе и потом только менять фамилии приглашенных на этот траурный день (это я сужу по себе). Но даже если нет текстового редактора, писать программу действительно нет смысла. Затраты большие, а пользоваться ей будешь только один раз. Здесь действительно легче будет даже набрать на печатной машинке. Получается, что одноразовые операции оптимизировать просто бессмысленно. Затраты в этом случае себя не окупают, поэтому не стоит тратить свои нервы на этот бессмысленный труд. В самом начале этого раздела я раскритиковал вас как человека, который ленится хоть что-нибудь делать. Так вот именно здесь вы можете проявлять свою врожденную леность в полном объеме. В данном случае крутым считается не тот, кто целый день промучился и ничего не добился, а тот, кто выполнил свою работу наиболее быстро и эффективно. И эти две вещи путать нельзя.

ЗАКОН № Нужно знать внутренности компьютера и принципы его работы. Чем лучше вы знаете, каким образом компьютер будет выполнять ваш код, тем лучше вы сможете его оптимизировать.

Этот закон относится только к программированию. Тут трудно привести полный набор готовых решений, но некоторые приемы я постараюсь описать. 1. Старайтесь поменьше использовать вычисления с плавающей запятой. Любые операции с целыми числами выполняются в несколько раз быстрее. 2. Операции умножения и тем более деления также выполняются достаточно долго. Если вам нужно умножить како-то число на 3, то для процессора будет легче три раза сложить одно и то же число, чем выполнить умножение. А как же тогда экономить на делении? Вот тут нужно знать математику. У процессора есть такая операция, как сдвиг. Вы должны знать, что процессор думает в двоичной системе, и числа в компьютере хранятся именно в ней. Например, число 198 для процессора будет выглядеть как 11000110. Теперь посмотрим, как работают операции сдвига. Сдвиг вправо — если сдвинуть число 11000110 вправо на одну позицию, то последняя цифра исчезнет, и останется только 1100011. Теперь введите это число в калькулятор и переведите его в десятичную систему. Ваш результат должен быть 99. Как видите — это ровно половина числа 198.

Минимизация и невидимость Вывод: когда вы сдвигаете число вправо на одну позицию, то вы делите его на 2. Сдвиг влево — возьмем то же самое число 11000110. Если сдвинуть его влево на одну позицию, то с правой стороны освободится место, которое заполняется нулем — 110001100. Теперь переведите это число в десятичную систему. Должно получится 396. Что оно вам напоминает? Это 198, умноженное на 2. Вывод: когда вы сдвигаете число вправо, то вы делите его на 2;

когда сдвигаете влево, то умножаете его на 2. Так что используйте эти сдвиги везде, где возможно, потому что сдвиги работают в десятки раз быстрее умножения и деления. 3. При создании процедур не обременяйте их большим количеством входных параметров. Перед каждым вызовом процедуры ее параметры поднимаются в специальную область памяти (стек), а после входа изымаются оттуда. Чем больше параметров, тем больше расходы на общение со стеком. Тут же нужно сказать, что вы должны действовать аккуратно и с самими параметрами. Не вздумайте пересылать процедурам переменные, которые могут содержать данные большого объема в чистом виде. Лучше передать адрес ячейки памяти, где хранятся данные, а внутри процедуры работать с этим адресом. Вот представьте себе ситуацию, когда вам нужно передать текст размером в один том "Войны и мира".... Перед входом в процедуру программа попытается вогнать все это в стек. Если вы не увидите его переполнения, то задержка точно будет значительная. 4. В самых критичных моментах (как, например, вывод на экран) можно воспользоваться языком Assembler. Даже встроенный в Delphi или C++ ассемблер намного быстрее штатных функций языка. Ну а если скорость в каком-то месте уж слишком критична, то код ассемблера можно вынести в отдельный модуль. Там его нужно откомпилировать с помощью компиляторов TASM или MASM и подключить к своей программе. Ассемблер достаточно быстрая и компактная вещь, но писать достаточно большой проект только на нем — это очень сложно. Поэтому я советую им не увлекаться и использовать его только в самых критичных для скорости местах.

ЗАКОН № Для сложных расчетов можно заготовить таблицы с заранее рассчитанными результатами и потом использовать эти таблицы в реальном режиме времени. Когда появился первый Doom, игровой мир поразился качеству графики и скорости работы. Это действительно был шедевр про грамм и стекой мысли, потому что компьютеры того времени не могли рассчитывать трехмерную графику в реальном времени. В те годы еще даже и не думали о ЗО-ускорителях, Глава и видеокарты занимались только отображением информации и не выполняли никаких дополнительных расчетов. Как же тогда программистам игры Doom удалось создать трехмерный мир? Секрет прост, как и все в этом мире. Игра не просчитывала сцены, все сложные математические расчеты были рассчитаны заранее и занесены в отдельную базу, которая запускалась при старте программы. Конечно же занести все возможные результаты невозможно, поэтому база хранила основные результаты. Когда нужно было получить расчет значения, которого не было в заранее рассчитанной таблице, то бралось наиболее приближенное число. Таким образом, Doom получил отличную производительность и достаточное качество ЗО-картинки. С выходом программы Quake игровой мир опять поразился качеству освещения и теней в сценах виртуального мира Quake. Расчет света очень сложная задача, не говоря уже о тенях. Как же тогда программисты игры смогли добиться такого качества сцен и в то же время высокой скорости работы игры? Ответ опять будет таким же — за счет таблиц с заранее рассчитанными значениями. Через некоторое время игровая индустрия поразилась еще больше. Когда вышел Quake 3, в котором освещение рассчитывалось в реальном времени, то его мир оказался немного неестественным и даже Half-Life, который вышел позже и на движке старого Quake, выглядел намного естественнее и привычнее. Это получилось в результате того, что мощности компьютера не хватило для полных расчетов в реальном времени, а округления и погрешности пошли не на пользу игровому окружению.

ЗАКОН № Лишних проверок не бывает.

Чаще всего оптимизация может привести к нестабильности исполняемого кода, потому что для увеличения производительности некоторые убирают ненужные на первый взгляд проверки. Запомните, что ненужных проверок не бывает! Если вы думаете, что какая-то нестандартная ситуация может и не возникнуть, то она не возникнет только у вас. У пользователя, который будет использовать вашу программу, может возникнуть все, что угодно. Он обязательно нажмет на то, на что не нужно, или введет неправильные данные. Обязательно делайте проверки всего того, что вводит пользователь. Делайте это сразу же и не ждите, когда введенные данные понадобятся. Не делайте проверки в цикле, а выносите за его пределы. Любые лишние операторы if внутри цикла очень сильно влияют на производительность, поэтому по возможности проверки нужно делать до или после цикла. Циклы — это слабое место любой программы, поэтому оптимизацию надо начинать именно с них и стараться не вставлять в них лишние проверки.

Минимизация и невидимость 37_ Внутри циклических операций не должно выполняться ничего лишнего — ведь это будет повторено много раз!..

Итог Если вы прочитали этот раздел внимательно, то можете считать, что с основами оптимизации вы уже знакомы. Но это только основы, и тут есть куда развиваться. Я бы мог рассказать больше, но не вижу особого смысла, потому что оптимизация — это процесс творческий, и в каждой отдельной ситуации к нему можно подойти с разных сторон. И все же те законы, которые я сегодня описал, действуют в 99,9% случаев. Если вы хотите познать теорию оптимизации в программировании более глубоко, то вам нужно больше изучать принципы работы процессора и операционных систем. Главное, что законы вы уже знаете, а остальное придет со временем.

Глава Простые шутки Теперь можно приступать к написанию простых программ -при колов в Windows. Так как эта ОС самая распространенная, то и приколы в ней самые ценные. Я думаю, что любой компьютерщик с удовольствием подкинет своему другу какую-нибудь веселую программку, которая введет жертву в легкий шок. В каждом из нас заложено еще при рождении стремление к превосходству. Все мы хотим быть лучшими, и программисты часто показывают свое превосходство с помощью написания чего-то уникального, интересного и вызывающего. Чаще всего в виде самовыражения выступают программы-приколы. Хотя мои программы не будут вредоносными, но все же они должны быть кому-нибудь подброшены. Поэтому человека, которому должна быть подкинута программа, я буду называть жертвой. Большинство приколов этой главы основаны на простых функциях WinAPI. Хотя я и сказал, что начальные знания Delphi желательны, но все же весь используемый в книге код я постараюсь расписывать очень подробно. Особый упор сделан на используемые в примерах WinAPI-функции. Если некоторые возможности Delphi вы используете каждый день, то функции WinAPI можете использовать достаточно редко, поэтому я даже не надеюсь, что вы знаете их все.

2.1. Летающий Пуск Вспоминаю, как я первый раз увидел Windows 95. Мне так понравилась кнопка Пуск, что я ее полюбил до глубины Выключить компьютер. Вскоре в нашем институте обновили парк машин, и на них тоже поставили. Windows 95. Мне так захотелось приколоться над бедными однокурсниками, что я написал программку, которая подбрасывала кнопку Пуск. Сказано — сделано, написал и запустил на всех машинах. С каждым взлетом кнопки Пуск ламеры испуганно взлетали вместе с ней. А через некоторое время я увидел и в Интернете подобный прикол.

Глава Сейчас я повторю свой старый подвиг и покажу вам, как самому написать такую программу. Так что усаживайтесь поудобнее, наша кнопка Пуск взлетает на высоту 100 пикселей! Но прежде чем начать, нужно подготовить картинку с изображением кнопки Пуск. Для этого вы можете нарисовать ее своими руками в любом графическом редакторе. Ну а если вы IBM-совместимый человек, то можете нажать клавишу , чтобы запомнить содержимое экрана в буфере обмена, а потом выполнить вставку содержимого буфера в любом графическом редакторе. Далее простыми манипуляциями вырезать изображение кнопки и сохранить его в отдельном файле. Создайте новый проект в Delphi. Сразу сохраните его. Теперь изменим параметры окна. Для этого перейдем в Инспектор объектов (Object Inspector). Здесь параметр BorderStyie устанавливаем равным bsNone, чтобы у окна не было никаких обрамлений. Параметру Formstyie задаем значение fsstayOnTop, чтобы окно всегда располагалось поверх других. Все, форма готова. Теперь нужно бросить на форму компонент image с палитры компонентов Additional. На форме появится соответствующий компонент с именем imagei. Щелкните на нем и снова переходите в окно Инспектора объектов. Параметр Left и тор задайте равными 0, чтобы картинка располагалась точно в левом верхнем углу формы (рис. 2.1). \<- Delphi 6 - ProjectZ е Edit ^earch # w Eroject R n C m o e t Q t o s T os J d w H l Й e u o p n n aa a e o l * n o e i p Sa d r Additional | Win321 S se j D t A c s | D t C nr l 1 t n ad y t m aa c e s aa o tos -•*> д и н 4 и Андп Ш Anchors AutoSize Center S Constraints Cursor DragCursor DragKind DragMode Enabled Height Рис. 2. 1. Форма будущей программы Простые шутки Теперь дважды щелкните справа от параметра Picture в окне Инспектора объектов (или выделите параметр, нажмите кнопку с тремя точками), и перед вами появится окно, позволяющее загрузить в компонент картинку (рис. 2.2). Нажмите кнопку Load и выберите файл, в котором была сохранено изображение кнопки Пуск. После этого установите свойство AutoSize у imagei равным true, чтобы компонент стал размером с рисунок.

F e i a t 1 c t i w e p se ? > c » o 6 oos h n a t e O 1 C ne K acl Рис. 2.2. Загрузка картинки Help Хорошо. Форма почти готова. Осталось только поправить ширину и высоту самого окна, чтобы оно было размером с картинку. Однако и высота, и ширина не может быть меньше, чем размер кнопок на обрамлении (даже если их удалить). Но и это мы победим! Теперь щелкните на форме и на закладке Events Инспектора объектов. Дважды щелкните справа в строке события onshow, чтобы создать обработчик события. Он будет вызываться при показе окна. В нем мы напишем следующее. procedure TForml.FormShow(Sender: TObj ect);

begin Width:=51,-//Установить ширину окна Height:=21;

//Установить высоту Left:=-100;

//Убрать окно за левую границу экрана end;

Глава Здесь устанавливаются значения ширины и высоты окна. В визуальном редакторе есть проблемы с установкой этих значений, а так мы программно можем задать то, что нам нужно. Ваши значения могут быть другими, все зависит от того, какого размера получилось изображение вашей кнопки. Моя вышла габаритами 21 х 51. Теперь перенесите на форму компонент Timer с палитры компонентов System. В его свойствах нужно изменить значение interval. По умолчанию оно равно 1 000 миллисекунд (1 секунда). Для нас больше подойдет 10 000 миллисекунд (10 секунд). Не интересно, если Пуск будет летать каждую секунду. С такими темпами он может даже не успеть приземлиться. Теперь перейдите на вкладку Events и дважды щелкните справа в строке события onTimer. Будет создан обработчик события, который будет вызываться каждые 10 секунд (значение свойства interval). Здесь мы развернем центр управления полетом кнопки Пуск. В этом обработчике напишите следующее: донг 2.1. Обработчик события OnTimer procedure TForml.TimerlTimer(Sender: TObject);

var i:Integer;

h:THandle;

begin Visible:=true;

//Сделать окно видимым //Установить верхнюю позицию окна в левый нижний угол экрана Тор:^Screen.Height-Height;

Left:=l;

//Создается пустой указатель h, который будет использоваться для задержки h:=CreateEvent(nil, t r u e, f a l s e, ' e t ' ] ;

//Сейчас будем поднимать кнопку //От 1 до 80 выполнять действия от begin до end for i : = l t o 80 do begin //Увеличить значение верхней позиции окна.с кнопкой Top:=Screen.Height-Height-i*5;

Repaint;

//Перерисовать окно Простые шутки WaitForSingleObject(h,15);

//Задержка в 5 миллисекунд end;

//Дальше идет опускание кнопки. Алгоритм тот же, //просто выполнение идет в обратном порядке for i::=80 downto 1 do begin Top: =Screen. Height-Height-.!*5;

Repaint;

WaitForSingleObject(h,15) ;

end;

Closehandle(h);

//Уничтожается указатель h Visible:=false;

//Прячется окно, end;

Я постарался снабдить этот листинг подробными комментариями, так что, надеюсь, вы разберетесь с приведенными кодом. В принципе программа готова, и ее можно запускать. Но если вы сделаете это сейчас, то она появится в TaskBar, что абсолютно недопустимо для программы-прикола. Давай напишем код, который спрячет наше приложение от грозного взгляда Панели задач. Для этого выберите пункт меню View Source из меню Project. Перед вами появится исходный текст самого проекта. Сравните его с листингом 2.2, и недостающее допишите.

Листинг 2-2. Скрытие проЩ|эйЩ|||^ЙЩйН©о1|ЩРЛЭ^ program P r o j e c t l ;

uses Forms, Windows,//Это добавлен модуль Windows Unitl in 'Unitl.pas' fForml};

{$R *.RES} //Далее добавлена новая переменная var EStyls : integer;

•^ * ' * i 44 begin Application.Initialize;

//Далее идет установка невидимости приложения EStyle:=GetWindowLong(application.Handle, GWL_EXSTYLE) SetWindowLong(Application.Handle, GWL_EXSTYLE, EStyle or WS_EX_TOOLWINDOW>;

//Остальное не менять Application.CreateForm(TForml, Forml);

Application.Run;

end.

Глава Чтобы вам было проше разобраться, изменения выделены комментариями.

Рис. 2.3. Результат Все. Играйте на здоровье. Только будьте осторожны. Слабонервные ламеры при виде летающей кнопки могут уйти в бессознательное состояние на пару десятков лет. Нашатырь тут уже не поможет, так что за побочные действия отвечать будете сами. Единственный недостаток такого простого способа — он будет эффективен только под определенными версиями Windows, так как в Windows XP кнопка имеет другой вид. Хотя кто вам мешает нарисовать кнопку в стиле ХР? Действуйте. На компакт-диске в директории \Примеры\Глава 2\Кнопка Пуск вы можете увидеть пример работающей программы и цветные версии рисунков этого раздела.

Простые шутки 2.2. Полный контроль над кнопкой Пуск В предыдущем примере я смухлевал и подбрасывал на экране бутафорию, а реальная кнопка оставалась на месте без изменений. Сейчас я покажу вам, как можно получить доступ к самой кнопке Пуск, управлять ей и изменять ее вид (последнее будет доступно только в Windows 95/98/МЕ). Стартовая кнопка — это не что иное, как простое окно с картинкой, ну выглядит оно таким образом! Чтобы получить к ней доступ, нужно знать идентификатор этого окна. Как его можно получить? С помощью APIфункции Findwindow. У этой функции два параметра: первый — это имя класса окна, а второй — это имя окна. Кнопка Пуск имеет имя класса SheiijirayWnd. Точнее сказать, это класс всей панели задач. Имя нам знать необязательно, потому что если его не указать, то Findwindow укажет нам на первое найденное окно указанного класса. Спешу вас обрадовать, что в Windows есть только одно окно такого класса, и это именно панель задач. Чтобы получить доступ к картинке кнопки на панели задач, можно воспользоваться более продвинутой функцией — FindwindowEx. Эта функция позволяет нам получить доступ к любому элементу на окне. У нее уже есть четыре параметра: 1. Окно, на котором нужно искать элемент управления. 2. Элемент управления на- этом окне, с которого нужно начинать поиск. Если здесь указать 0, то поиск будет начинаться с самого первого элемента управления. 3. Класс элемента управления. В нашем случае это кнопка, значит, нужно указать Button. 4. Имя. Если указать нуль n i l, то будет происходить поиск всех элементов подобного класса. Итак, чтобы получить контроль над кнопкой Пуск, нужно написать следующий код: StartBtnWnd:=FindWindow('Shell_TrayWnd', nil);

StartBtnBmp:=FindWindowEx(StartBtnWnd, 0, 'Button', nil) ;

Здесь в первой строчке отыскивается окно панели задач. Результат поиска сохраняется в переменной startBtnwnd. Во второй строчке находим саму кнопку Пуск внутри найденной панели задач. Результат этого поиска будет Храниться В переменной StartBtnBmp. Теперь запускаем Delphi и готовимся шкодить. Создайте новый проект и обработчик события для формы oncreate. В этом обработчике напишите те две строчки, которые указаны выше. Теперь поднимитесь немного выше и найдите в коде раздел private в описании. Добавьте туда две переменные.

Глава private { Private declarations } StartBtnWnd, StartBtnBmp: hWnd;

Вот теперь у нас есть идентификатор окна нужной кнопки и идентификатор картинки, и мы готовы приступить к управлению кнопкой Пуск. Давайте сделаем это! Заготовьте рисунок кнопки размером где-то 51 х 21. Мою заготовку вы можете увидеть на рис. 2.4.

Лш*ЛШШЛЯЖЛ WLftM Рис. 2.4. Новая картинка для кнопки Пуск Теперь перенесите на форму один компонент image с палитры компонентов Additional. Перейдите в окно Инспектора объектов и дважды щелкните справа свойства Picture. Перед вами должно появиться окно для загрузки картинки. Нажмите кнопку Load, найдите заготовленную для кнопки картинку и откройте ее. Image I. Picture Г" Eecfease to 16 colors when paste OK I Cancel Help Рис. 2.5. Загрузка картинки Простые шутки И последнее: перенесите на форму пять кнопок и назовите их так: 1. Изменить картинку. 2. Отключить. 3. Включить. 4. Спрятать картинку. 5. Спрятать панель. Все!!! Приготовления закончены. На рис. 2.6 вы можете видеть форму программы, которая получилась у меня. Осталось только заставить эти кнопки выполнять то, что на них написано.

Отключить ВКЛЮЧИТЬ Спрятать картинку Спрятать панель.

Рис. 2.6. Форма будущей программы Сейчас мы применим несколько приемов самбо к кнопке Пуск. Начнем с изменения рисунка кнопки. Для этого создайте обработчик события Onclick для кнопки Изменить картинку и напишите в нем следующее: procedure TForml.ButtonlClick(Sender: TObject);

begin SendMessage(StartBtnBmp, BM_SetImage, 0, Imagel.Picture.Bitmap.Handle);

end;

Здесь использована WinAPI-функция SendMessage, которая посылает системное сообщение. У этой функции есть четыре параметра: 1. Окно, которому надо послать сообщение,— указан идентификатор окнакнопки. 2. Тип сообщения — указано BM_setimage, что заставит окно изменить картинку. 3. Третий параметр сообщения — он равен нулю. 4. Четвертый параметр сообщения — указатель на картинку, которую надо подставить.

Глава Просто и со вкусом. Программа отправила это сообщение системе — окну кнопки Пуск. Это окно, увидев сообщение о том, что надо изменить картинку, беспрекословно выполняет указание. На рис. 2.7 вы можете увидеть результат работы данной маленькой программы. Жаль, что этот прием работает только в Windows 9x '•••••*$tjj Корзина Щ О принтеры узкие Обзор Рис. 2.7. Результат изменения картинки Описанные дальше приемы работают в любом Windows — мы научимся включать и отключать кнопку Пуск. Создайте обработчики событий onclick для кнопок Выключить и Включить. В первом напишите следующее: procedure TForml.Button2Click(Sender: TObject);

begin EnableWindow(StartBtnWnd, false);

end;

Во втором обработчике события (для кнопки Включить) введите следующее: procedure TForml.Button3Click(Sender: TObject);

begin EnableWindow(StartBtnWnd, true);

end;

В обоих случаях использована одна и та же функция Enabiewindow. Эта функция делает окно доступным и отключает его в зависимости от переданных ей параметров. Первый параметр — идентификатор окна. Во втором вы собственно и указываете — включить окно (true) или отключить (false). Если его отключить, то кнопка перестанет реагировать на нажатия, и сколько бы вы не щелкали по ней, реакции никакой не будет. Можете хоть монитор мышкой проткнуть, никакого меню вы не увидите.

Простые шутки Теперь научимся прятать кнопку и всю панель задач. Создайте обработчик события onclick для кнопки Спрятать картинку и напишите следующее: procedure TForml.Button4Click(Sender: TObject);

begin ShowWindow(StartBtnBmp, SW_HIDE);

end;

Здесь опять использована функция showwindow. В качестве второго параметра указано SW_HIDE, чтобы спрятать окно. Чтобы показать его снова, нужно указать параметр SW_SHOW. В качестве первого параметра указан указатель на картинку. Как видите, с помощью данной функции можно прятать не только окна, но и компоненты. Только эти компоненты должны быть оконными и должны иметь возможность иметь указатель на себя типа hwnd. Теперь спрячем всю панель. Для этого создайте обработчик события onclick для кнопки Спрятать панель и напишите в нем следующее: procedure TForml.ButtonSClick(Sender: TObject);

begin ShowWindow(StartBtnWnd, SW_HIDE);

end;

Здесь используется тот же прием, что и для предыдущей кнопки, только в качестве первого параметра функции showwindow указан идентификатор всей панели. На компакт-диске в директории \Примеры\Глава 2\Кнопка Пуск2 вы можете найти пример этой программы. На компакт диске в директории \Примеры\Глава 2\ Кнопка Пуск2 вы можете увидеть цветные версии рисунков этого раздела.

2.3. Контролируем системную палитру Системная палитра достаточно интересный объект для программиста, который хочет написать какую-нибудь шуточную программу. Изменив всего один системный цвет, изменяется внешний вид всех программ. Попробуем написать программу, которая будет хаотично менять основные цвета системной палитры. Для нашей программы нам понадобится одна кнопка и таймер. На кнопке (Buttoni) напишите Анимация палитры. Вид формы не имеет значения — в нашем примере мы делаем упор на изменение палитры, а не на интерфейс. У таймера установите свойство Enabled равным false, чтобы по умолчанию он был выключен. При нажатии кнопки мы его включим и начнем изменения палитры. Свойство interval у таймера нужно задать большим 5 Глава (меньше не рекомендуется). Внешне палитра меняется достаточно долго (1-3 секунды, в зависимости от количества открытых программ и версии Windows). Если пример будет запускаться в Windows XP, то интервал лучше увеличить до 10 секунд, т. е. установить значение 10000. Итак, для изменения системного цвета существует функция setsysCoiors. У нее всего три параметра: 1. Сколько цветов мы хотим изменить. 2. Номера цветов в системной палитре для изменения. 3. Новые значения цветов. Допустим, что вы хотите поменять пятый цвет на красный. В этом случае нужно дать такую команду:

SetSysColorsU, 5, clRed);

Но менять так все цвета неудобно, и мы пойдем по пути прогресса — автоматизируем процесс. По нажатию первой кнопки Анимация палитры запустим таймер: procedure TForml.ButtonlClick(Sender: TObject);

begin Timerl.Enabled:=true;

end;

Теперь создадим обработчик события срабатывания таймера (для этого просто дважды щелкните по нему). Здесь мы напишем код смены палитры: procedure TForml.TimerlTimer(Sender: TObject);

const SySColorArray: array [0..13] of Integer = (COLOR_ACTIVEBORDER, COLOR_ACTIVECAPTION, COLOR_APPWORKSPACE, COLOR_BACKGROUND, COLOR_BTNFACE, COLOR_BTNTEXT, COLGR_CAPTIONTEXT, COLOR_INACTIVEBORDER, COLOR_INFOTEXT, COLORJ4ENU, COLOR_MENUTEXT, COLOR_WINDOW, COLORJtflNDOWFRAME, COLOR_WINDOWTEXT);

ColorArray:array [0..10] of TColor = (clAqua, clBlack, clBlue, clYellow, clFuchsia, clGreen, clNavy, clRed, clSilver, clWhite, clSkyBlue);

begin SetSysColors(1, SySColorArray[random(13)], ColorArray[random(10)]);

end;

Простые шутки После объявления имени процедуры и перед ее началом (там, где всегда объявляются переменные) объявлено несколько констант. Константы — почти те же самые переменные, только их значения нельзя изменять в процессе работы программы — в каком виде объявлены, так и останутся. Обе константы объявлены как массивы. Массив — это просто набор данных, в котором каждому элементу присвоен индекс. Массив в Delphi обозначается как array. Чтобы объявить переменную или константу г типа массив нужно описать ее следующим образом:

г: array [длина массива] of тип данных;

длина массива может быть записана, например, с помощью индексов первого и последнего элементов через две точки, например, массив из 12 элементов можно записать как [0..11] или [I..12]. В первом случае нумерация элементов начнется с 0, во втором — с 1. Эквивалентными будут записи 12-элементного массива [0..11] и [12]. Чтобы присвоить значение отдельному элементу массива, нужно написать следующий код:

г[4]:=значение;

Вот так можно присвоить элементу массива с индексом 4 какое-нибудь значение.

Первый массив syscoiorArray — это массив из 14 целых чисел. Так как этот массив — константа, то при его определении необходимо поставить в конце знак равно и в скобках перечислить значения всех элементов массива. В качестве элементов перечислены системные цвета, которые будут меняться (COLOR_ACTIVEBORDER, COLOR_ACTIVECAPTION И Т. Д.). Мы будем СЛуЧЭЙным образом выбирать из этого массива имя системного цвета и присваивать ему новое значение. Что такое COLOR_ACTIVEBORDER, COLORACTIVECAPTION И Т. Д.? ЭТО системные константы. Под каждой из них спрятано целое число. Например, COLOR_ACTIVEBORDER — это обычное число 10. Каждое такое число означает номер системного цвета. Я мог бы использовать вместо констант числа, но читать такой код будет неудобно. Вторая константа coiorArray — массив из 10 цветов. Из него мы будем выбирать случайным образом элемент и присваивать его в качестве значения системного цвета. Код процедуры очень прост и состоит только из вызова функции Setsyscoiors. В качестве параметра указываются следующие значения: 1. 1 — за один раз будет меняться только один системный цвет.

2. SySColorArray[random(13)] — ИЗ массива SySColorArray выбирается случайный элемент — системный цвет, который будет изменен. Функция random (13) выдает случайное число от 0 до 1.

Глава 3. coiorArray[random(Ю) ] — выбирается из массива coiorArray случайное значение цвета от 0 до 10 с помощью вызова функции random(10). Это значение будет присвоено системному цвету — кандидату на изменение. Теперь можете построить проект и насладиться переливающимся всеми цветами радуги монитором. На компакт-диске в директории \Примеры\Глава 2\Palette вы можете увидеть пример этой программы.

2.4. Изменение разрешения экрана Сейчас мы напишем пример, который сможет узнавать у системы возможные видеорежимы и заставит компьютер перейти на любой из них. Для примера нам понадобиться на форме один компонент ListBox и две кнопки. При нажатии первой кнопки мы будем спрашивать у системы все возможные варианты видеорежимов и записывать их в ListBox. При нажатии второй кнопки мы будем делать активным режим, выделенный в списке ListBox. Можете расположить все компоненты как угодно, а можете сделать, как я (рис. 2.8).

Р Forml * Перечислить вцдеорежимы Установить видеорежим Рис. 2. 8. форма будущей программы Итак, на первой кнопке напишите что-нибудь типа Перечислить видеорежимы, а на второй — Установить видеорежим. Теперь форма выглядит более солидно и можно приступать к программированию.

Простые шутки Прежде чем написать код, надо объявить массив из переменных типа TDevMode, в котором мы будем сохранять параметры найденных видеорежимов. Для этого найдите раздел private и запишите в нем:

private ( Private declarations } modes:array[0..255] of TDevMode;

public { Public declarations } Таким образом мы объявили массив из 255 элементов типа TDevMode. Для начала создадим обработчик события onclick для кнопки считывания возможных видеорежимов и напишем в нем следующий текст: procedure TForml.ButtonlClick(Sender: TObject);

var i: Integer;

begin ListBoxl.Items.Clear;

i : 0;

= while EnumDisplaySettings(nil, i, Modes[i]) do begin ListBoxl.Items.Add(IntToStr(Modes[i].dmBitsPerPel)+' ' + IntToStr(Modes[i].dmPelsWidth)+' ' + IntToStr(Modes[i].dmPelsHeight)+ ' ' + IntToStr(Modes[i].dmDisplayFrequency));

Inc(i);

end;

end;

В первой строке кода очищается содержимое списка ListBox с помощью вызова метода ListBoxl. items.Clear. В следующей строке обнуляется переменная i, которая будет использоваться в качестве простого счетчика и указывать, какой по счету видеорежим нам нужен. Дальше вызывается функция EnumDispiaySettings, которая перечисляет доступные системе видеорежимы. У этой функции три параметра: 1. Устройство, для которого надо перечислять режимы. Здесь нужно что-то указывать только если в системе несколько мониторов. Если вы простой смертный и пользуетесь одним монитором, то можно смело указывать n i l. 2. Здесь указывается индекс режима, который нам нужен. В приведенном коде указана переменная i, которая перед каждым вызовом будет увеличиваться на 1, а значит мы будет каждый раз получать следующий по счету режим.

Глава 3. Переменная типа TDevMode, в которую нужно записать параметры режима. Сюда подставляется очередной элемент массива. Вызов функции происходит между операторами while и do:

while EnumDisplaySettings{nil, i, Modes[i]) do Это значит, что пока результат вызова функции EnumDispiaySettings не станет ошибкой, будут выполняться операторы цикла, размещенные между begin и end. В этом цикле добавляется строка в список ListBox, в которой записаны параметры найденного режима, и счетчик i увеличивается на единицу. Когда добавляется новый элемент в список ListBox, то в качестве строки передается следующая информация:

Modes[i].dmBitsPerPel - глубина (количество бит на пиксель) цвета найденного режима. Modes[i].dmPelsWidth - ширина экрана. Modes[i].dmPelsHeight - высота экрана. Modes[i].dmDisplayFrequency - частота развертки.

Можно теперь запустить этот промежуточный вариант нашей программы и нажать на кнопку Перечислить видеорежимы. Список ListBox должен заполниться строками, содержащими информацию о найденных видеорежимах (рис. 2.9).

Перечислить вщеорежммы Установить видеорежим 86 04 06 480 860407 4G0 860407 482 860407 485 860408 485 8604010 480 860401 0 482 830206 200 830207 200 830207 202 8302 07 205 8302 06 243 8302 07 240 83 0207 242 8302 07 245 84 03 06 000 84 03 07 000 8403 07 002 84 03 07 005 8403 06 860 64 03 07 350 84 03 07 — — zl Рис. 2.9. Результат перечисления доступных видеорежимов Все строки разбиты как бы на четыре колонки: 1. Глубина (количество бит на пиксель) цвета найденного режима.

Простые шутки 2. Ширина экрана. 3. Высота экрана. 4. Частота развертки. При нажатии кнопки Смена режима мы должны установить выделенный в списке режим. Для этого в обработчике нажатия второй кнопки пишем следующий код: procedure TForml.Button2Click(Sender: TObject);

begin Modes[ListBoxl.Itemlndex].dmFields : DM_BITSPERPEL or = DM_PELSWIDTH or DM_PELSHEIGHT or DM_DISPLAYFLAGS or DM_DISPLAYFREQUENCY;

ChangeDisplaySettings(Modes[ListBoxl.Itemlndex], CDSJJPDATEREGISTRY);

end;

Свойство ListBoxi. itemindex указывает на выделенный элемент в списке. Это значит, что для того чтобы найти нужную структуру для выделенного Элемента В МаССИВе Modes, Надо записать Modes[ListBoxi.Itemindex]. Все достаточно просто, потому что элементы в списке ListBoxi находятся в том же порядке, что и соответствующие структуры TDevMode в массиве Modes.

Прежде чем менять видеорежим, надо в структуре Modes заполнить свойство dmFields, в котором указывается, что именно нужно поменять. Здесь вы можете указать сочетание следующих флагов: 1. 2. 3. 4. 5.

DM_PELSWIDTH — будет меняться количество бит на пиксель. ~~ будет меняться ширина экрана. DM_PELSHEIGHT — будет меняться высота экрана. DM_DISPLAYFREQUENCY — будет меняться частота развертки.

DMBITSPERPEL DMDISPLAYFLAGS — изменить флаги дисплея.

Если вы хотите поменять только глубину цвета, то в свойство dmFields достаточно указать только DM_BITSPERPEL. Я буду менять все, поэтому перечислил все флаги через оператор or, который объединяет все в одно целое. После заполнения этого свойства можно вызывать процедуру ChangeDisplaySettings. У нее два параметра: 1. Структура ТИПа TDevMode. 2. Способ перехода. В качестве способа перехода можно указать одно из следующих значений: 1.0 — если просто поставить нуль, то разрешение экрана изменится динамически.

56 2. 3.

Глава 2 CDSJJPDATEREGISTRY — в этом случае разрешение также изменится динамически, но с обновлением параметров в реестре.

CDSTEST — если указать это значение, то произойдет только проверка возможности переключения видеорежима. Реального переключения не будет. Очень интересный эффект происходит при смене видеорежима, если указать в качестве способа 0. В этом случае режим меняется, но окна не реагируют на эту смену и остаются в том же положении. Посмотрите на рис. 2.10, на котором я сменил режим на меньший, и при этом исчезла панель задач Windows с кнопкой Пуск. Она просто не отреагировала на смену режима. На рис. 2.11 показан экран, на котором, наоборот, режим изменен на больший, и панель так же не отреагировала и осталась намного выше нижней части экрана.

Некоторые считают, что если часто менять разрешение экрана, то можно испортить или спалить монитор. Да, это верно, но только для старых моделей. Современные мониторы защищены от такой примитивной атаки, так что сделанный на этом эффекте вирус не принесет большого вреда.

Qaa lot* Be H ao» Jf™ > tt u SM J Xca! Da Cm ] d E n IHS n mDt ca a o m b u t tU A t t i i I В Е ]ADO | I n M a n ! WabSarvcetllnt»*! С - fapttott J v t Em] i 321024 7 9 К 6 321152864 60 321152861 n 321152 861 75 Й 1 1 5 2 8 6 1 85 321152 864 100 32 1280 960 60 элгвдэбо 70 '31290 360 12 12 1290 960 75 J 2 ' 290 9 C № 6 Э212В0102 60 Э212В0102 70 321290102 72 321290102 75 321290102 95 321 SOU ЭХ) 60 3216001200 70 3216001200 Color CoUnrx TSPEPPEL Dr L 0);

DH^PELSHIDTH Рис. 2. 1 0. Побочный эффект смены разрешения экрана на меньшее Простые шутки Рис. 2. 1 1. Побочный эффект смены разрешения экрана на большее Но если включить свою соображалку на большие обороты, то можно придумать какой-нибудь более бьющий по нервам прикол. Например, многие мониторы выводят черный экран с надписью об ошибке, если попытаться установить неправильные параметры видеорежима. Это значит, что можно написать программу, которая будет менять режим на недопустимый, и поместить ее в автозагрузку. Тогда при каждой загрузке компьютера программа будет менять видеорежим, монитор автоматом будет уходить в "даун", и пользователь не сможет некоторое время нормально работать. На компакт-диске в директории \Примеры\Глава 2\Video Mode вы можете увидеть пример этой программы. На компакт-диске в директории \Примеры\Глава 2\Video Mode вы можете увидеть цветные версии рисунков этого раздела.

Глава 2.5. Маленькие шутки В этом разделе собраны шутки, обсуждение которых не стоит большого раздела.

Программное изменение состояния клавиш Num Lock, Caps Lock и Scroll Lock Можно устроить настоящую цветомузыку на клавиатуре. Для этого надо создать форму с кнопкой и таймером. При нажатии кнопки нужно запустить таймер: procedure TForm2.ButtonlClick(Sender: TObject);

begin Timer1.Enabled:=true;

end;

Теперь создайте обработчик события срабатывания таймера и в нем напишите следующее: procedure TForml.Timer2Timer(Sender: TObject);

begin Timerl.Tag := (Timerl.Tag + 1) mod 4;

SetState(VK_NUMLOCK, Timerl.Tag * 1);

SetState(VK_SCROLL, Timerl.Tag - 2);

SetState(VK_CAPITAL, Timerl.Tag = 3);

end;

Тут в основном простая арифметика, для вычисления лампочку какой кнопки сейчас зажечь, а какой потушить. Самым интересным является вызов процедуры s e t s t a t e. Она должна менять состояние клавиш. Но этой процедуры нет среди стандартных библиотек в Delphi, ее нужно написать. Эта процедура выглядит следующим образом: procedure SetState(key: Integer;

Value: Boolean);

var KeyState: TKeyboardState;

begin GetKeyboardState(KeyState);

KeyState[key] := Integer(Value);

SetKeyboardState(KeyState) ;

end;

Процедуру нужно разместить выше, чем обработчик события для второго таймера, потому что она не относится к объекту окна и должна быть описана раньше, чем будет использоваться. Все процедуры, которые не являются Простые шутки объектными, должны описываться до того, как начнут использоваться, иначе компилятор Delphi их не найдет, и во время компиляции произойдет ошибка. В процедуре s e t s t a t e всего три строчки. В первой программа получает текущее состояние клавиатуры С П М Щ Ю WillAPI-функции GetKeyboardState. ОО Ь Результатом будет переменная-массив Keystate. Во второй строчке изменяется состояние нужной клавиши. И в последней строке происходит установка нового состояния клавиатуры С П М Щ Ю SetKeyboardState. ООЬ Пример закончен. Можете запустить его и наслаждаться результатом. Процедуру s e t s t a t e можно использовать и просто так, без таймера. Достаточно добавить эту процедуру в свой проект выше того места кода, где она будет использоваться. Теперь, чтобы изменить состояние, нужно вызвать процедуру Setstate и указать ей в первом параметре код нужной клавиши, а во втором — значение true или false (включено или выключено). Вот несколько примеров: Setstate(VK_NUMLOCK, true);

Setstate(VK_SCROLL, false);

Setstate(VK_CAPITAL, true);

Как программно потушить монитор?

Не знаю, как программно, а огнетушителем тушиться за пять сек :). Я даже помню, как в детстве получил значок юного огнетушителя, тьфу, пожарника :). А если серьезно, то команда системе выглядит так: SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 0). Чтобы "зажечь", измените последний параметр на - 1.

Запуск системных CPL-файлов Для этого сначала добавьте в раздел uses модуль SheiiApi, чтобы вы могли использовать функцию sheiiExecute. Теперь напишите следующий код: SheiiExecute(Application.Handle, Pchar ('Open'), PcharfRundll32.exe1), Pchar ('shell32, Control_RunDLL f ilename. cpl • ), ",SW_SHOWNORMAL);

Функция SheiiExecute запускает указанную в параметре программу. Например, нам нужно запустить Rundll32.exe. В качестве параметра нужно передать текст ВОТ такого ВИДа: shell32,Control_RunDLL filename.cpl. А вот такой код отобразит окно настроек сети Интернет: SheiiExecute(Application.Handle, Pchar('Open1), 3 З к 978 а.

w Глава Pchar{'shell32,Control_RunDLL i n e t c p l. c p l ' ), PcharCRundll32.exe'),,SW_SHOWNORMAL);

Следующая строка отобразит окно настроек экрана: ShellExecute(Application.Handle, Pchar{'Open'), PcharCRundll32.exe ), *',SW_SHOWNORMAL);

Pchar ( ' s h e l l 3 2, ControlRunDLL d e s k. c p l ' ), Программное управление устройством для чтения компакт-дисков Следующий код запускает бесконечный цикл, в котором каждые 5 секунд открывается или закрывается CD-ROM: var OpenParm: TMCIJDpen_Parms;

GenParm: TMCI_Generic_Parms;

SetParm: TMCI_Set_Parms;

DI : Cardinal;

OK: boolean;

begin OK:=false;

OpenParm.lpstrDeviceType := 'CDAudio';

repeat mciSendCommand(0, mci_Open, mci_Open_Type, Longint(QOpenParm));

DI := OpenParm.wDevicelD;

mciSendCommand(DI, mci_Set, mci_Set_Door_Open, Longint(@SetParm));

mciSendCommand(DI, mci_Set, mci_Set_DoorClosed, LQngint (@SetParm)) ;

mciSendCoitrmand(DI, mci_Close, mci_Notify, Longint (@GenParm) );

sleep(5000);

until OK;

end;

В первой строчке кода переменной ок присваивается значение false. Потом запускается цикл repeat,. u n t i l, который будет выполняться, пока эта переменная не станет равной true. Но так как нигде и никто не изменяет значение этой переменной, то она всегда будет равна false, и цикл получится бесконечным. Перед началом цикла необходимо еще заполнить параметр lpstrDeviceType структуры OpenParm. Сюда нужно занести значение CDAudio, что и будет указывать на необходимость работы с CD-ROM. Ну а дальше запускается цикл, в котором поочередно то открывается дверца, то закрывается. В конце цикла ставится задержка в пять секунд Простые шутки sieeptsooo}, чтобы CD-ROM успел "увидеть" диск после того, как закрылась беспокойная дверца. Для работы этого примера в раздел uses MMSystem.

необходимо добавить модуль Отключение сочетания клавиш ++ В Windows 9x это можно сделать достаточно просто с помощью следующего кода: var i:integer;

begin i : 0;

= SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, Si, 0);

end;

Отключение сочетания клавиш + Опять же можно привести небольшой код для Windows 9x.

var i:integer;

begin i := 0;

SystemParametersInfo(SPI_SETFASTTASKSWITCH, 1, @i, 0);

end;

Удаление часов с панели задач Это можно сделать почти так же, как мы работали с кнопкой Пуск. Нужно сначала найти окно панели задач. Потом на нем найти окно тгауВаг, на котором уже найти часы. После этого часики легко убираются функцией showwindow, которой нужно передать в качестве первого параметра указатель на окно часов, а во втором параметре нужно указать SWHIDE.

var Wnd:THandle;

begin Wnd := FindWindow('Shell_TrayWnd', nil);

Wnd := FindWindowEx(Wnd, HWND(0),'TrayNotifyWnd1, nil);

Wnd : = FindWindowEx(Wnd, HWND(0), ' T r a y C l o c k W C l a s s \ ShowWindow(Wnd, end;

SW_HIDE);

nil);

Глава Исчезновение чужого окна Как работать с чужими окнами, будет более подробно обсуждаться в следующих главах книги. Но все же я покажу вам один интересный прикол, связанный с исчезновением чужих программ: var n:HWND;

begin while true do begin h:=GetForegroundWindow;

ShowWindow(h,SW_HIDE) ;

Sleep(2000);

end;

end;

В этом примере запускается бесконечный цикл while, внутри которого выполняются следующие шаги: О Идентификатор активного окна GetForegroundWindow присваивается переменной п.

П ОКНО Прячется С ПОМОЩЬЮ фуНКЦИИ ShowWindow.

О Делается задержка в 2 секунды, чтобы пользователь попытался что-то сделать.

Установка на рабочий стол своих собственных обоев Делается это проще некуда:

SystemParametersinfo(SPI_SetDeskWallPaper, 0, PChar(TempStr), SPIFJJpdatelniFile);

Функция SystemParametersinfo имеет следующие параметры: • Действие, которое надо выполнить. Этих действий очень много, и описывать все нереально. Но самые интересные я приведу: • SPI_SETDESKWALLPAPER — установить собственные обои. Путь к файлу с обоями должен быть передан в третьем параметре;

• SPI_SETDOUBLECLICKTIME — время двойного щелчка. Количество миллисекунд между первым и вторым щелчком мышкой нужно указать во Простые шутки втором параметре. Попробуйте указать здесь число меньше 10, и я думаю, что вы никогда не успеете кликнуть дважды, чтобы между кликами прошло менее 10 миллисекунд. Таким образом, практически отключается возможность двойного щелчка;

• SPISETKEYBOARDDELAY — во втором параметре устанавливается задержка между нажатиями клавиш на клавиатуре при удерживании кнопки;

SPI_SETMOUSEBUTTONSWAP — если во втором параметре 0, то используется стандартное расположение кнопок мышки, иначе кнопки меняются местами, как для левши.

• • Второй параметр зависит от состояния первого. • Третий параметр зависит от состояния первого. • На месте четвертого параметра устанавливаются флаги, в которых указывается, что надо делать после выполнения действия. Возможны следующие варианты: • SPIFJJPDATEINIFILE — обновить пользовательский профиль;

• SPIF_SENDCHANGE — сгенерировать WMSETTINGCHANGE сообщение;

• SPIFSENDWININICHANGE — то же самое, что и предыдущий параметр. Если функция выполнилась удачно, то она вернет число не равное нулю, иначе функция вернет нуль. Пример кода, который меняет клавиши мышки местами:

//Установить мышь для левши SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, 1, 0, SPIF_SENDWININICHANGE);

//Вернуть на родину SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, 0, О, SPIF_SENDWININICHANGE);

Запрет кнопки Закрыть в заголовке окна Почти в каждом окне Windows есть кнопка Закрыть — это такой крестик в правом верхнем углу. С помощью нескольких строк кода ее легко можно сделать недоступной. var SysMenu: HMenu;

begin SysMenu := GetSystemMenu(Handle, False);

Windows.EnableMenuItem(SysMenu, SCCLOSE, MF_DISABLED or MF_GRAYED) ;

end;

Глава В первой строке мы получаем указатель на системное меню. Во второй пользуемся функцией EnableMenuItem из модуля Windows, чтобы отключить кнопку х.

2.6. Шутки с мышкой Безумная мышка Вот код интересного прикола, связанного с вездесущим указателем "графического манипулятора" (это так мышку по науке зовут). var OK: boolean;

begin OK:=false;

repeat randomize;

setcursorpos(random(Screen.Width-1),random(Screen.Height-1});

sleep (5000);

until OK;

end;

Здесь запускается уже знакомый вам бесконечный цикл, в котором положение указателя мышки переносится в случайную позицию с помощью WinAPI-функции setcursorpos. Этой функции нужно передать два параметра в виде целых чисел — координат х и Y НОВОЙ ПОЗИЦИИ указателя. В приведенном примере передаются случайные числа от 0 до значений разрешения экрана.

Мышеловка Можно ограничить свободу перемещения курсора. Попробуйте выполнить следующий код: procedure TForml.ButtonlClick(Sender: TObject);

var cr:TRect;

begin cr:=Rect(0,0,100,100);

ClipCursor(@cr);

end;

В первой строке кода инициализируется переменная сг типа TRect. Туда заносится прямоугольная область размером 100 на 100 пикселей. Во второй Простые шутки строчке эта область становится диапазоном движения мышки. После этого указатель мыши окажется запертым в левом верхнем углу в квадрате размером 100 х 100 пикселей. Дальше мышка, даже при всем желании пользователя (да и своем тоже!), выбраться не сможет. А вот еще один интересный трюк: procedure TForml.ButtonlClick(Sender: TObject) ;

var cr:TRect;

begin cr:=Rect'(0, 0, 1, 1);

ClipCursor(@cr);

end;

Здесь размер области движения мыши равен 1 пикселю по горизонтали и вертикали. В результате мышь просто замирает в в этом пикселе. Такая вот виртуальная мышеловка.

Изменчивый указатель Есть такая интересная WindowsAPI-функция — setsystemcursor. У нее есть два параметра. • Курсор, который надо изменить. Чтобы указать на системный курсор, МОЖНО ИСПОЛЬЗОваТЬ ФУНКЦИЮ G e t C u r s o r.

П Вид системного курсора, который нужно установить. Здесь можно указать одно из следующих значений: • OCR_NORMAL — нормальный курсор в виде стрелки;

• OCRIBEAM — курсор, используемый для выделения текста;

• OCR_WAIT — большие песочные часы;

• OCR_CROSS — крестик;

• OCRJJP — стрелка вверх;

• OCRSIZE — курсор изменения размера;

• OCR_ICON — значок;

• OCR_SIZENWSE или OCR_SIZENESW — курсор, используемый для растягивания объекта;

• OCRSIZEWE — курсор горизонтального изменения размера;

• OCR SIZENS — курсор вертикального изменения размера;

Глава • • • OCR_SI2EALL — курсор горизонтального и вертикального изменения размера;

OCRSIZENO — интернациональный несимвольный курсор;

— маленькие песочные часы со стрелкой.

OCR_APPSTARTING И сразу же небольшой пример изменения текущего вида указателя мыши: procedure TForml.ButtonlClick(Sender: TObject);

begin SetSystemCursorfGetCursor, OCR_CROSS|;

end;

Этот код изменяет текущий курсор на крестик, который используется при графическом выделении.

Глава Система В этой главе мы рассмотрим разные системные утилиты. Сюда вошли примеры программ, способных следить за происходящим в системе. Это уже не просто создание программ-приколов, это уже работа с системой. Как я уже говорил, любой хакер — это профессионал, и он должен знать и уметь оперировать с внутренностями той операционной системы, в которой он работает. При создании главы я подразумевал, что вы находитесь в Windows, программируете и работаете в ОС. В данной главе я попробую научить вас лучше понимать эту систему. Но не бойтесь, вас не будут загружать теорией, будут только практические занятия. Если вы уже читали мои труды, то знаете мой стиль. Я всегда говорю, что только практика дает знания, а теория — загружает мозги. Грош цена тем знаниям, которые не знаешь как применить на практике. Такие знания быстро забываются. Именно поэтому все главы этой книги наполнены практическими примерами, и эта — не исключение. Я покажу несколько интересных примеров, и мы подробно разберем их. Таким образом, мы осветим некоторые особенности работы с ОС Windows, и вы поймете, как применять эти особенности на практике. Надеюсь, что это вам поможет в работе.

3.1. Подсматриваем пароли, спрятанные под звездочками Как увидеть пароль, спрятанный под звездочками? Иногда так раздражает набирать одно и то же по несколько раз: то раскладка не та, то нажат. Для того чтобы открыть взгляду набираемое, есть очень много разных специальных программ. Но вы же не думаете, что я буду вас отправлять к таким программам в своей книге? Конечно же, мы сейчас разберем, как самому написать подобную программу. Программа будет состоять из двух частей. Первый файл — запускаемый, будет загружать другой файл — динамическую библиотеку — в память.

Глава Эта библиотека будет регистрироваться в системе в качестве обработчика системных сообщений. Этот обработчик будет ждать, пока пользователь не щелкнет в каком-нибудь окне кнопкой мышки, удерживая клавишу . Как только такое событие произойдет, мы сразу же должны будем получить текст этого окна и конвертировать его из звездочек в нормальный текст. На первый взгляд все выглядит сложным, но реально вы сможете реализовать все за десять минут. Для этого примера я написал dll-файл, создание которого будет сейчас расписано на ваших глазах. Ничего особо визуального мы сегодня делать не будем — только сухое программирование. Для начала создадим новый проект. Но не обычное приложение, какие мы использовали до этого, а проект динамической библиотеки (dll). Для этого нужно выбрать команду File/New/Other (для Delphi 5 — просто File/New). Перед вами откроется окно, как на рис 3.1. Найдите элемент DLL Wizard и дважды щелкните на нем. Delphi создаст пустой проект динамической библиотеки. Сразу же нажмите кнопку Save, чтобы сохранить проект. В качестве имени введите hackpass, так же будет названа и библиотека.

К New Items Projects j Business |,WebSnap j WebSetvice* • j N e w ' | ActiveX j MuJtitiet | hackpass | Forms | -.Софа Dialogs Application Batch File CLX Application CLXData Module CLX Form CLX Frame Component Console Application D t Mde aa o u l С I,-ay С inherif * Г U« • ae Pa F F ag o m ce mi k r OK Cancel Control Panel Control Panel Application Module Help Рис. З. 1. Создание новой динамической библиотеки Теперь сотрите весь код, который написал Delphi, и вставьте следующее (листинг 3.1).

Система library hackpass;

uses Windows, Messages;

var SysHook : HHook = 0;

Wnd : Hwnd = 0;

function SysMsgProc(code : integer;

wParam : word;

lParam : longint) : longint;

stdcall;

begin //Передаем сообщение другим ловушкам в системе CallNextHookEx(SysHook, Code, wParam, lParam);

//Проверяем сообщение if code = HC_ACTION then begin //Получаем идентификатор окна, сгенерировавшего сообщение Wnd := TMsg(Pointer(lParam)").hwnd;

//Проверяем тип сообщения. //Если была нажата левая кнопка мыши //и удержана кнопка Control, то... if TMsg (Pointer (lParam)A ).message = WMLBUTTONDOWN then 1 if ( (TMsgtPointerUParam)' ).wParam and MK_CONTROL) = MK_CONTROL) then begin //Убрать в окне, отправившем сообщение, звездочки SendMessage(Wnd, em_setpasswordchar, 0, 0);

//Перерисовать окно InvalidateRect(Wnd, nil, true);

end;

end;

end;

//Процедура запуска procedure RunStopHook{State begin //Если State = true, то... if State=true then Boolean) export;

stdcall;

70 begin //Запускаем ловушку SysHook := SetWindowsHookEx(WH_GETMESSAGE, @SysMsgProc, HInstance, 0);

end е1зе//Иначе begin //Отключить ловушку UnhookWindowsHookEx(SysHook) ;

SysHook := 0;

end;

end;

exports RunStopHook index 1;

begin end.

Глава Самое основное в нашей библиотеке — это процедура RunStopHook. Ей передается только один параметр. Если он равен true, то регистрируется ловушка, которая будет ловить все сообщения, предназначенные Windows. Для ЭТОГО ИСПОЛЬЗуеТСЯ ФУНКЦИЯ SetWindowsHookEx. У ЭТОЙ фуНКЦИИ ДОЛЖНО быть четыре параметра: 1. Тип ловушки. Указан WH_GETMESSAGE, такая ловушка ловит все сообщения. 2. Указатель на функцию, которой будут пересылаться сообщения Windows. 3. Указатель на приложение. 4. Идентификатор потока. Если параметр равен нулю, то используется текущий. В качестве второго параметра указано имя функции sysMsgProc. Она так же описана в этой dll, но ее мы рассмотрим чуть позже. Значение, которое возвращает фунКЦИЯ SetWindowsHookEx, сохраняется В Переменной SysHook. Оно нам понадобится, когда мы будем отключать ловушку. Если наша процедура RunStopHook получила в качестве параметра значение false, то нужно отключить ловушку. Для этого вызывается процедура unhookwindowsHookEx, которой передается значение переменной SysHook. Это то значение, которое мы получили при создании ловушки. Процедура RunStopHook объявлена как экспортная: exports RunStopHook index 1;

Pages:     || 2 | 3 | 4 | 5 |



© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.