Любой хакер думает о том, как сократить размер своей программы. Это же не солидно иметь вирь или троян размером в пару мегабайт. Чем больше размер кода, тем дольше он загружается в память и больше отбирает ресурсов, что очень легко может выдать твое творение. Если при написании офисных приложений мы можем забыть про оптимизацию размера, то для вирусов, троянов и твоих приколов размер кода критичен.
ПОЧЕМУ КОД БОЛЬШОЙ? :
В рубрике кодинг журнала Хакер мы рассказываем тебе про язык программирования Delphi. Программы созданные им получаются достаточно большого размера. С чем это связано? А с тем, что Delphi является объектным языком. В нем каждый элемент выглядит как объект, который обладает своими свойствами, методами и событиями.
Любой объект вполне автономен и может работать без твоего ведома. Это значит, что тебе нужно только подключить его к своей форме, изменить нужные свойства и все готово. После этого все будет работать без какого-либо внешнего вмешательства.
Но в этом есть и свои недостатки. В объектах реализовано большинство возможных действий, которые ты можешь производить с ним. Но реально, в любой программе мы пользуемся двумя-тремя из всех этих свойств. Все остальное для программы лишний груз, который нафиг никому не нужен.
КАК ЖЕ ТОГДА БЫТЬ? :
Но как же тогда создать компактный код, чтобы мой троян занимал минимум места на винте и как можно меньше светился в памяти? У тебя есть несколько вариантов:
1. Не использовать визуальную библиотеку VCL (для любителей Visual C++ это библиотека MFC), которая упрощает программирование. В этом случае придется все делать вручную и работать только с WinAPI. Код в этом случае получается очень маленьким и быстрым. Но тут ты лишаешься визуальности и можешь ощутить весь гемор программирования на чистом WinAPI.
Если ты регулярно читаешь Х, то в ноябре 2001 года ты должен был увидеть пример проги на чистом WinAPI в рубрике кодинг. Там наш запускной файл получился размером всего в 8 кило. И это притом, что при использовании VCL он увеличивается до 300 кило.
2. Сжимать программы с помощью компрессоров. Такой код сжимается в несколько раз и программа с использованием VCL может превратиться из 300 кило в 30-50. Главное преимущество тут в том, что ты не лишаешься возможностей объектности и можешь спокойно забыть про пятна....
В этой статье я постараюсь, как можно подробнее рассмотреть оба этих метода.
РУЧНОЙ КОДИГ :
Ручной кодинг (программирование без использования объектов и визуальности) похож на ручной секс (это когда ты удовлетворяешь себя вручную в отсутствии очаровашки). В обоих случаях эффект есть, но его приходится добиваться очень долго и удовольствия от ручного метода намного меньше :). Но что поделать, иногда приходится идти на такие извращения ради создания компактных примочек.
Если ты хочешь создать программу маленького размера, то ты должен забыть про все удобства. Ты не сможешь подключать визуальные формы или другие примочки написанные дядей Борманом для упрощения жизни программера. Только API функции и ничего больше.
РУЧНОЙ КОДИГ В DELPHI :
Для того, чтобы создать маленькую прогу в Delphi, нужно создать новый проект и зайти в менеджер проектов (меню View->Project Manager). Здесь нужно удалить все формы, чтобы остался только файл самого проекта (по умолчанию его имя Project1.exe). Никаких модулей в проекте не должно быть.
Рисунок 1. Project Manager
Теперь щелкни правой кнопкой по имени проекта и выбери из появившегося меню пункт "View Source" (или из главного меню Project выбери View Source). В редакторе кода откроется для редактирования файл проекта Project1.dpr. Если ты уже удалил все модули, то его содержимое должно быть таким:
program Project1;
uses
Forms;
{$R *.res}
begin
Application.Initialize;
Application.Run;
end.
Я удалил все визуальные формы и теперь могу скомпилировать абсолютно пустой проект. Я решил попробовать сделать это. После компиляции я выбрал из меню Project пункт "Information for Project1". Передо мной появилось окно с информацией о проекте.
Рисунок 2. Окно информации о проекте
В правой части окна должны быть описаны используемые пакеты. Мы все удалили, значит там точно должна красоваться надпись "None". А вот с левой стороны должна быть описана информация о скомпилированном коде. Самая последняя строка показывает размер файла и у меня он равен 370688 байт. Ничего себе пельмень!!! Мы же ничего еще не писали. Откуда же тогда такой большой код?
ОТКУДА НОКИ РАСТУТ? :
Давай разберем, что осталось в нашем проекте, чтобы обрезать все, что еще не обрезано.
Сразу обрати внимание, что в разделе uses подключен модуль Forms. Это объектный модуль, написанный дядей Борманом, а значит, его использовать нельзя. Между begin и end используется объект Application. Его тоже использовать нельзя.
Все накладки большого кода, даже у пустой проги, как раз и связаны с объектом Application. Хотя мы используем только два метода Initialize и Run, при компиляции в запускной файл попадает весь объект TApplication, а он состоит из сотен, а может и тысяч строчек кода.
Чтобы избавится от накладных расходов нужно заменить модуль Forms на Windows. А между begin и end вообще все можно удалять. Самый минимальный код проги будет выглядеть так:
program Project1;
uses Windows;
Begin
end.
Снова откомпилируй проект. Зайди в окно информации и посмотри на размер получившегося файла. У меня получилось 8192 байта. Вот это уже по человечески.
Рисунок 3. Информации о проекте
КОДИНГ НА WinAPI :
Заготовка минимальной программы с использованием WinAPI готова. Теперь ты можешь смело добавлять свой код. Мне только надо объяснить тебе какие модули можно подключать к своему проекту в раздел uses. Тут все очень просто и не займет много времени.
Если при установке Delphi ты не отключал копирование исходников библиотек, то перейди в диру, куда ты засандолил Delphi. Здесь перейди в папку "Source", затем в "Rtl" и наконец "Win". Вот здесь расположены исходники модулей, в которых описаны все API функции Windows. Именно эти модули ты можешь подключать к своим проектам, если хочешь получить маленький код. Если ты подключишь что-то другое, то я уже не гарантирую тебе минимум размера твоей проги (хотя есть и исключения).
Сразу лови пример. Если ты хочешь, чтобы в твоей программе были возможности работы с сетью, то тебе нужно подключить к нему библиотеку сокетов. Среди модулей WinAPI есть файл с именем winsock.pas. Значит, ты должен в раздел uses написать winsock (расширение писать не надо) и твоя программа сможет работать с сетью.
ПУСТЬ ВСЕГДА БУДЕТ ... :
Пока что я описал минимальный проект, в который можно добавлять свой код. Но код, который ты вставишь, выполниться один раз и программа выгрузится из памяти. А что если тебе надо, чтобы твоя программа постоянно висела в окнах? Для этого используй следующий шаблон для своих прог:
program Project1;
uses Windows;
var
Msg: TMsg;
Begin
//Сюда можешь добавлять свой код
// Дальше идет код, который заставит прогу висеть в
// памяти вечно и не будет сильно грузить систему.
while GetMessage( Msg, HInstance, 0, 0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
end.
МАЛЕНЬКИЙ КОД В VISUAL C++ :
Многие заблуждаются, говоря, что программы созданные в Visual С++ уже получаются маленькими. Это действительно на 90% заблуждение. Сам язык С++ является объектным и страдает теми же недостатками, что и Delphi. Это значит, что именно на С++ код будет получаться очень большим.
Даже если ты создал новый проект и, откомпилировав его, получил очень маленький код, то это не значит, что программа получилась компактной. Реально твоя прога использует динамические библиотеки mfcХХ.dll. Здесь ХХ - это номер версии MFC (Microsoft Foundation Classes). Вся библиотека занимает около 2 мегов на диске. В результате твоя прога будет состоять из размера запускного файла плюс размер библиотеки MFC. Нехило? В Delphi тоже можно так мухлевать, если установить в свойствах проекта компиляцию с динамической загрузкой bpl (Borland Pascal Library) библиотек.
Рисунок 4. Создания проекта в Visual C++
Чтобы реально создать маленький код на Visual C++ нужно также использовать только WinAPI и никаких объектов. Для этого, при создании нового проекта ты выбрать тип "Win32 Application". В этом случае, ты как и в Delphi ощутишь все прелести и корявости кодинга на WinAPI. Если ты до этого момента относился к Билу параллельно, то после пару часов кодинга на WinAPI ты вступишь в партию ненавистников M$ :).
СЖАТИЕ ПРОГРАММ :
Если тебя не устраивает кодинг на чистом WinAPI, то твоим лучшим другом должна стать какая-нибудь прога для сжатия размера файлов. Я очень люблю ASPack, которую ты можешь забрать по адресу www.cydsoft.com/vr-online/download.htm. Она прекрасно сжимает запускные файлы .exe и динамические библиотеки .dll.
Рисунок 5. Главное окно ASPack
Я не буду объяснять установку ASPack, потому что там абсолютно ничего сложного нет. Только одно нажатие на кнопке "Next" и все готово. Теперь запусти установленную прогу и ты увидишь окно, как на рисунке 5. Главное окно состоит из нескольких закладок:
1. Open File.
2. Compress.
3. Options.
4. About.
5. Help.
На закладке "Open File" есть только одна кнопка - "Оpen". Нажми на нее и выбери файл, который ты хочешь сжать. Как только ты выберешь файл, программа перескочит на закладку "Compress" и начнет сжатие.
Рисунок 6. Сжатие файла
Сжатый файл сразу перезаписывает существующий, а старая несжатая версия сохраняется на всякий случай под тем же именем, только с расширением bak.
Настроек у проги не так уж много, и с ними ты сможешь разобраться без меня. Уж лучше я расскажу тебе, как все работает.
Рисунок 7. Настройки ASPack
ASPACK ПОД НОЖОМ ПОТАЛОГОАНАТОМА :
Давай разберемся, как работает сжатие. Сначала весь код программы сжимается архиватором. Если ты думаешь, что он какой-то навороченный, то сильно ошибаешься. Для сжатия используется простой архиватор типа WinZIP, только оптимизированный для сжатия байт-кода.
После этого, в конец сжатого кода добавляется код разархиватора, который будет все это дело разжимать обратно. И в самом конце ASPack изменяет заголовок запускного файла так, чтобы при старте, сначала запускался разархиватор.
Теперь, когда ты запустишь сжатую прогу, сначала запуститься разархиватор, который разожмет байт-код программы и аккуратно выложит его в памяти машины. Как только этот процесс пройдет, разархиватор передаст управление твоей проге.
Некоторые умники сейчас ляпнут, что из за расходов на распаковку программа будет работать медленней!!! Я бы не сказал, что ты это заметишь. Даже если и будут какие-то потери, то они будут неощутимы. Это потому что архивация хорошо оптимизирована под байт-код. К тому же, размер проги уменьшится, а значит, она загрузится в память намного быстрее. В результате потери на скорости неощутимы даже с секундомером.
ARCHIVING COMPLETE :
Конечно же, кодинг на WinAPI слишком сложный, но программы получаются очень маленького размера, и никакой архиватор не сможет сжать байт-код до такой степени. А если еще и сжать прогу написанную на WinAPI, то ее размеры будут меньше некуда.
При нормальном кодинге с использованием всех навороченных фишек типа визуальности и объектности код получается большим, но его можно сжать на 60-70% спец архиватором. К тому же такой код писать намного легче и быстрее.
В любом случае, архивирование - необходимая любому хакеру фишка. Сжатый код труднее взломать, потому что не каждый disassembler сможет прочитать упакованные команды. Так что, помимо уменьшения размера ты получаешь защиту способную отпугнуть большинство крякеров. Конечно же, профи не отпугнешь даже большим Билом :), но крякер средней паршивости не будет мучиться со сжатым байт-кодом.
На этом архивирование считаю законченным. Несмотря на небольшой размер выделенного мне места, я смог рассказать тебе достаточно инфы, чтобы ты смог начать уже сейчас писать маленький код. На этом и закончим сегодняшний урок оптимизации. Надеюсь, что еще увидимся.