|
На старт!
Первую из своих статей я решил посветить этой вещи, которую многие начинающие кодеры совсем не умеют использовать. Обычно все используют статический импорт, который выглядит так:
{ импорт по специфицированному имени }
procedure ImportByName;external 'MYDLL' name 'MYEXPORTPROC';
{ импорт по индексу }
procedure ImportByOrdinal; external 'MYDLL' index 10;
{ импорт по оригинальному имени }
procedure MyExportFunc1; external 'MYDLL';
Использование же динамической загрузки процедур зачастую имеет очень важное значение, ведь при статической загрузке, если какая-то dll'ка или процедура в dll'ке не найдены, то прога сразу вылетит с сообщением об ошибке и все. Хороший пример - допустим пишешь ты хорошенького такого троя ( ну или прикол какой ), который должен работать и под 9*/Me, и под 2k/Xp, и естественно ты будешь использовать 'RegisterServiceProcess' из kernel32.dll, но так как под 2k/XP нет этой процедуры, то твоя прога просто сдохнет. А так как сейчас эти системы очень распространены ( лично у меня XP и Me ), то становится обидно как-то. И что? Вообще отказаться от резидентности? Или писать две версии - резидентную для 9*/Me и не резидентную для 2k/XP? Так вот динамическая загрузка, при которой мы сами можем следить за всем, и при необходимости обрабатывать ошибку, помогает избавится от таких глупых вопросов.
Поехали!!!
Описывается это так:
uses WinTypes, WinProcs, ... ; //Содержат нужные нам для API функции
type
TProc = procedure(a,b:byte);//Объявлеем свой тип процедуры с нужными параметрами
var
ProcHandle : THandle; //Хэндл через который мы будем обращаться к dll'ке
ImportProc : TProc;
begin
ProcHandle:=LoadLibrary('kernel32'); //загружаем dll'ку, если не указать расширение, то считается что это dll или exe файл
if ProcHandle>=32 then //если хэндл меньше 32, то значит произошла ошибка при загрузке dll'ки
begin
@ImportProc:=GetProcAddress(ProcHandle,'RegisterServiceProcess');//Получаем адрес процедуры
if @ImportProc<>nil then // Проверяем не произошла ли ошибка во время получения адреса процедуры
ImportProc(0,1); //Выполняем саму процедуру
end;
FreeLibrary(ProcHandle); //Память не резиновая - выгружаем dll'ку из памяти
end;
Ну хватит теории. Теперь напишим прогу, которая будет уметь запускать выбранные процедуры из выбранных dll'ек, в общем аналог RunDLL32.
Для начала создай в Delphi проект, и сразу сохрани, обозвав по людски, к примеру, DLL Loader (когда куча проектов, а у всех имена unit1, unit2, project1, project2... в общем ты понял). Теперь кинь на него два edit'a, два button'a и один OpenDialog. В один edit будем вводить имя dll'ки, в другой имя процедуры. OpenDialog и один из батонов - для того чтоб не вводить весь путь ручками, еще по одному батону, как раз таки и будет происходить выполнение процедуры из dll'ки.
Обработчик первого батона, это тот который мы помещаем для удобства - чтоб путь ручками не писать, должен быть такой:
procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then Edit1.Text:=OpenDialog1.FileName;
end;
Обработчик второго батона должен быть таким:
procedure TForm1.Button2Click(Sender: TObject);
begin
If ((Edit1.Text='') or (Edit2.Text='')) then ShowMessage('Одно из полей не заполнено.')
else ILoadProcedureFromDll(PChar(Edit1.text),PChar(Edit2.text),true);
end;
Здесь мы проверяем все ли поля заполнены, и если да, то вызываем процедуру, которая подгружает длл'ку, и если все пучком, то выполняет из этой длл'ки нужную процедуру. Два первых параметра - имя файла и имя процедуры для импорта, а третий параметр указывает, выдавать ли сообщение об ошибке, если что-то не так.
procedure ILoadProcedureFromDll(DLLName,ProcedureName:PChar;ShowErrorMessage:boolean);
begin
ProcHandle:=LoadLibrary(DLLName);
if ProcHandle>=32 then
begin
@Proc:=GetProcAddress(ProcHandle,ProcedureName);
if @Proc<>nil then proc else
if ShowErrorMessage
then MessageBox(0,PChar('Ошибка при загрузке процедуры '+ProcedureName),'Error',MB_ICONERROR);
end
else MessageBox(0,PChar('Ошибка при загрузки файла '+DLLName),'Error',MB_ICONERROR);
FreeLibrary(ProcHandle);
end;
Злоключение
Теперь твои трояны будут работать не только под 9* и Me, но также они будут радовать и юзеров XP и 2k. Только одно уточнение: для того чтоб прога стала резидентной - RegisterServiceProcess надо вызывать с параметрами (0,1). Либо так:
asm
push 1
push 0
call ImportProc
end;
The End...
Перейти к рубрике --> Pascal & Delphi |