Реферат: Защищаем Perl: шунт в мозг, или зверская нейрохирургия
asm
jmp RunPerlOrig; //Делаемпереход (jump)
end;
end;
exports RunPerl;
begin
//Расположенный здесь код будет выполняться при каждом запуске DLL
end.
Ассемблерная вставка делает переход, куда надо. Теперь ругательные сообщения прекратились, и изменений в работе Perl не видно. Зато мы достигли важного результата: наша dll стала полноправным членом (если не мозгом) исполняемого процесса Perl.exe. Дальнейшее становится делом техники (точнее, системных вызовов Windows API и нескольких "точечных" замен в таблице импорта Perl56.dll). Вы можете взять готовый код [1] и посмотреть, что у меня получилось.
Какие системные функции необходимо перехватывать?
Технология динамически компонуемых библиотек (DLL) существенно облегчает модификацию Windows-приложений (закрытый исходный код компенсируется тем, что все названия функций и точки их входа не только хорошо видны, но и доступны для изменения). Просматривать статический импорт DLL или EXE удобно при помощи утилиты dumpbin.exe из студии разработки Microsoft.
Пример вызова этой утилиты из командной строки:
dumpbin.exe /imports perl.exe
Программа выдаст список DLL и их функций, которые импортирует программа из этих DLL. Вот полезный нам фрагмент вывода этой утилиты:
Microsoft (R) COFF Binary File Dumper Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file perl.exe
File Type: EXECUTABLE IMAGE
Section contains the following imports:
...
Perl56.dll
402038 Import Address Table
4020C0 Import Name Table
0 time date stamp
0 Index of first forwarder reference
3C3 RunPerl
...
Замечание: Из этого листинга мы видим, что программа импортирует библиотеку Perl56.dll Это большая и "тяжелая" динамическая библиотека, которая поддерживает все функции Perl; Perl.exe же фактически является небольшим загрузчиком для этой библиотеки, только лишь запуская ее единственную функцию RunPerl. Смысл такого разделения, видимо, в том, что при завершении работы Perl.exe система выгружает библиотеку из памяти лишь через несколько секунд, если к ней не будет новых обращений. Поскольку все запущенные копии Perl.exe используют только одну копию библиотеки, система экономит время на выгрузках-загрузках (при условии, конечно, что эта библиотека постоянно "висит" в памяти). Замечу, что экономии памяти от такого разделения не происходит, т.к. общие страницы всех запущенных копий одного и того же исполняемого файла система по любому помещает на одни и те же физические адреса.
Аналогично мы можем выяснить импорт библиотеки Perl56.dll (список функций, конечно же, окажется гораздо длиннее). Дальнейшие выяснения, на какие функции надо ставить "жучок", мы произведем опытным путем - мы примерно знаем (а если не знаем, то посмотрим), :-) какие API-функции должна импортировать скомпилированная в системе Windows простейшая тестовая C-программа, которая выполняет нужные нам действия. Другой вариант - выяснить это при помощи специальных "лоботомических инструментов": например, Numega SoftICE или Numega Bounds Checker (их рассмотрение выходит за рамки этой статьи). Я приведу лишь результат своих изысканий: нужные нам функции - это CreateProcessA (запуск приложения) из библиотеки KERNEL32.dll и функция fopen (открытие файла на чтение или на запись) из библиотеки MSVCRT.dll.
"За кадром" остались такие специальные вопросы, как формат таблицы импорта Windows-программы. Отчасти эту информацию можно получить в комментариях исходного кода [1], а отчасти - из литературы. Кстати, полезные для начинающих хакеров источники (например, книги Криса Касперски, Джеффри Рихтера и Мэтта Питрека) можно скорее найти в сети Internet, чем в книжных магазинах, где их почему-то очень быстро раскупают. :-)
Заключение