Мануал по созданию компактного кода Delphi

Источник: codingrus
Kest

Автор: Horrific aka Фленов Михаил
Любой хакер думает о том, как сократить размер своей программы. Это же несолидно иметь вирь или троян размером в пару мегабайт. Чем больше размер кода, тем дольше он загружается в память и больше отбирает ресурсов, что очень легко может выдать твое творение. Если при написании офисных приложений мы можем забыть про оптимизацию размера, то для вирусов, троянов и твоих приколов размер кода критичен.

Почему код большой?

В рубрике кодинг мы рассказываем тебе про язык программирования 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). Никаких модулей в проекте не должно быть. 

Теперь щелкни правой кнопкой по имени проекта и выбери из появившегося меню 
пункт "View Source" (или из главного меню Project выбери View Source). В 
редакторе кода откроется для редактирования файл проекта Project1.dpr. Если ты 
уже удалил все модули, то его содержимое должно быть таким:

program Project1;

uses

Forms;

{$R *.res}

begin

Application.Initialize;

Application.Run;

end. 

Я удалил все визуальные формы и теперь могу скомпилировать абсолютно пустой 
проект. Я решил попробовать сделать это. После компиляции я выбрал из меню 
Project пункт "Information for Project1". Передо мной появилось окно с 
информацией о проекте. 

В правой части окна должны быть описаны используемые пакеты. Мы все удалили, 
значит там точно должна красоваться надпись "None". А вот с левой стороны должна 
быть описана информация о скомпилированном коде. Самая последняя строка 
показывает размер файла, и у меня он равен 370688 байт. Ничего себе пельмень!!! 
Мы же ничего еще не писали. Откуда же тогда такой большой код?

Откуда ноги растут?

Давай разберем, что осталось в нашем проекте, чтобы обрезать все, что еще не 
обрезано. Сразу обрати внимание, что в разделе uses подключен модуль Forms. Это 
объектный модуль, написанный дядей Борманом, а значит его использовать нельзя. 
Между begin и end используется объект Application. Его тоже использовать нельзя.

Все накладки большого кода, даже у пустой проги, как раз и связаны с объектом 
Application. Хотя мы используем только два метода Initialize и Run, при 
компиляции в запускной файл попадает весь объект TApplication, а он состоит из 
сотен, а может и тысяч строчек кода. 

Чтобы избавиться от накладных расходов, нужно заменить модуль Forms на Windows. 
А между begin и end вообще все можно удалять. Самый минимальный код проги будет 
выглядеть так:

program Project1;

uses Windows;

Begin

end. 

Снова откомпилируй проект. Зайди в окно информации и посмотри на размер 
получившегося файла. У меня получилось 8192 байта. Вот это уже по-человечески.

Кодинг на 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) библиотек.

Чтобы реально создать маленький код на Visual C++, нужно также использовать 
только WinAPI и никаких объектов. Для этого при создании нового проекта ты 
должен выбрать тип "Win32 Application". В этом случае ты, как и в Delphi, 
ощутишь все прелести и корявости кодинга на WinAPI. Если ты до этого момента 
относился к Биллу параллельно, то после пары часов кодинга на WinAPI ты вступишь 
в партию ненавистников M$ :). 

Сжатие программ

Если тебя не устраивает кодинг на чистом WinAPI, то твоим лучшим другом должна 
стать какая-нибудь прога для сжатия размера файлов. Я очень люблю ASPack, 
которую ты можешь забрать по адресу www.cydsoft.com/vr-online/download.htm. Она 
прекрасно сжимает запускные файлы .exe и динамические библиотеки .dll. 

Я не буду объяснять установку ASPack, потому что там абсолютно ничего сложного 
нет. Только одно нажатие на кнопке "Next", и все готово. Теперь запусти 
установленную прогу и ты увидишь окно. Главное окно состоит из нескольких 
закладок:

Open File

Compress

Options

About

Help

На закладке "Open File" есть только одна кнопка - "Оpen". Нажми на нее и выбери 
файл, который ты хочешь сжать. Как только ты выберешь файл, программа перескочит 
на закладку "Compress" и начнет сжатие.

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

Настроек у проги не так уж много, и с ними ты сможешь разобраться без меня. Уж 
лучше я расскажу тебе, как все работает.

Aspack под ножом патологоанатома

Давай разберемся, как работает сжатие. Сначала весь код программы сжимается 
архиватором. Если ты думаешь, что он какой-то навороченный, то сильно 
ошибаешься. Для сжатия используется простой архиватор типа WinZIP, только 
оптимизированный для сжатия байт-кода. 

После этого в конец сжатого кода добавляется код разархиватора, который будет 
все это дело разжимать обратно. И в самом конце ASPack изменяет заголовок 
запускного файла так, чтобы при старте сначала запускался разархиватор. 

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

Некоторые умники сейчас ляпнут, что из-за расходов на распаковку программа будет 
работать медленней!!! Я бы не сказал, что ты это заметишь. Даже если и возникнут 
какие-то потери, то они будут неощутимы. Это потому, что архивация хорошо 
оптимизирована под байт-код. К тому же, размер проги уменьшится, а значит она 
загрузится в память намного быстрее. В результате потери на скорости неощутимы 
даже с секундомером. 

Archiving complete

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

При нормальном кодинге с использованием всех навороченных фишек типа 
визуальности и объектности код получается большим, но его можно сжать на 60-70% 
спецархиватором. К тому же такой код писать намного легче и быстрее. 

В любом случае архивирование - необходимая любому хакеру фишка. Сжатый код 
труднее взломать, потому что не каждый disassembler сможет прочитать упакованные 
команды. Так что, помимо уменьшения размера, ты получаешь защиту, способную 
отпугнуть большинство крякеров. Конечно же, профи не отпугнешь даже большим 
Билом :), но крякер средней паршивости не будет мучиться со сжатым байт-кодом.

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


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=30212