Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Как загрузить форму из памяти


Автор: Monty 24.10.2003, 19:15
На это меня натолкнула одна статья по защите программ http://www.delphikingdom.com/mastering/safe/add.htm

О защите: я пытался затирать адреса из готовой программы .... тем самым программа умирала .... и переименовывать тоже нельзя! .... Единственно что я добился, это то что DeDe (Дельфи Декомпилер), не может "разковырять" программу из памяти smile.gif ....... а тут хорошая идея wink.gif ..... с шифровкой проблем нет, фантазия богата, но вот как загрузить расшифрованную форму? Вот это задача smile.gif

Автор: <Spawn> 25.10.2003, 10:50
Monty А если сохранить расшифрованый exe где нить в директории винды и оттуда запустить? Конечно это можно обнаружить, но я думаю вряд ли тебе удасться написать загрузчик для твоей задачи.

Автор: Monty 25.10.2003, 11:59
Да нет, мне всего лишь надо запустить форму из DFM ...... я знаю что так можно smile.gif .... а ты понял что я хочу все зашифровать tounge.gif
Шифруются _только_ формы и их надо загружать самому (как-то), но уже расшифрованые! wink.gif

Есть ли в природе функция похожия на CreateFormFromStream ? smile.gif

Автор: Dmitry V.Abramov 25.10.2003, 15:48
Monty DFM - это результат сохранения TForm. TForm - наследник TComponent. TComponent умел сохраняться и восстанавливаться в поток еще в Delphi1.
Код
 TStream = class(TObject)
...
   function ReadComponent(Instance: TComponent): TComponent;
   function ReadComponentRes(Instance: TComponent): TComponent;
   procedure WriteComponent(Instance: TComponent);
   procedure WriteComponentRes(const ResName: string; Instance: TComponent);
   procedure WriteDescendent(Instance, Ancestor: TComponent); virtual;
   procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TComponent);
...
 end;


Примеры есть в самом TForm.pas или в Classes.pas в классах TWriter/TReader.

Автор: Monty 25.10.2003, 16:11
Dmitry V.Abramov тогда я могу обойтись этими функциями? т.е. этой ReadComponentRes

Автор: Monty 25.10.2003, 16:27
Не выходит ..... можно скромный пример? smile.gif

Автор: Dmitry V.Abramov 25.10.2003, 19:33
Monty Так ведь привел бы свой "не выходимый"... - стало бы понятно, куда у тебя мысли думают. И писать, опять же, меньше бы пришлось...

Автор: Monty 25.10.2003, 23:40
Dmitry V.Abramov
Код
.......
FS := TFileStream.Create('c:\test.dfm', fmOpenRead);
FS.ReadComponent(Form2);
.........

Как то так smile.gif

Автор: Monty 25.10.2003, 23:45
Ааа ...... точно! Не правильно! smile.gif

Автор: Dmitry V.Abramov 26.10.2003, 01:55
Monty Правильно что неправильно smile.gif Для DFM надо ReadComponentRes().

Автор: Monty 26.10.2003, 18:11
Dmitry V.Abramov Проблема была в том что у новых версий дельфей новый формат DFM, а для ReadComponentRes() нужен старый smile.gif ......... и вот так работает:
Код
 FS := TFileStream.Create('d:\Unit2.dfm', fmCreate);
 FS.WriteComponent(Form2);
 FS.Free;
 FS := TFileStream.Create('d:\Unit2.dfm', fmOpenRead);
 FS.ReadComponent(Form2); /// ReadComponentRes вызывает ошибку :-|
 FS.Free;

Автор: Monty 26.10.2003, 18:16
А такой вопрос smile.gif .... Когда происходит чтении DFM файла? А то я думаю если прочтется зашифрованый DFM то вызовет ошибку smile.gif ..... случайно не в момент создании формы Application.CreateForm(TForm1, Form1) ? :-\ ......

Автор: Monty 26.10.2003, 18:28
Цитата(Monty @ 26.10.2003, 17:11)
Dmitry V.Abramov Проблема была в том что у новых версий дельфей новый формат DFM, а для ReadComponentRes() нужен старый smile.gif ......... и вот так работает:
Код
 FS := TFileStream.Create('d:\Unit2.dfm', fmCreate);
 FS.WriteComponent(Form2);
 FS.Free;
 FS := TFileStream.Create('d:\Unit2.dfm', fmOpenRead);
 FS.ReadComponent(Form2); /// ReadComponentRes вызывает ошибку :-|
 FS.Free;

Я опять ошибся smile.gif ...... вот так надо:
Код
 FS := TFileStream.Create('d:\Unit2.dfm', fmCreate);
 FS.WriteComponentRes('TForm2', Form2);
//  FS.WriteComponent(Form2);
 FS.Free;
//  Exit;
 FS := TFileStream.Create('d:\Unit2.dfm', fmOpenRead);
 FS.ReadComponentRes(Form2);
 FS.Free;

smile.gif

Автор: Dmitry V.Abramov 26.10.2003, 18:51
Monty Да. В CreateForm. Там же видно, что конкретно загрузкой из ресурса заведует InternalReadComponentRes. Зашифрованные dfm'ы он не загрузит. А зачем? Пусть грузит обычные, но НЕ ТЕ, что ты будешь использовать в дальнейшем. Ты же, прежде чем начать работу, прибьешь изначально груженные формы и переоткроешь на их месте свои (зашифрованные). На 80% нынешних мега-кул-ксацкепов этого должно хватить.

Автор: Monty 26.10.2003, 21:01
Dmitry V.Abramov понятно smile.gif ..... вот столкнулся еще с проблемой sad.gif ......
Код
 FS := TFileStream.Create('Unit2a.dfm', fmOpenRead);
 FS.ReadComponentRes(Form2);
 FS.Free;

Unit2a.dfm это форма с Edit'om ...... если на Form2 нет этого компонента, то программа ругается что "Class TEdit not found" ....... как это можно решить? Так как я хочу в _пустую_ форму загрузить зашифрованую с кучей компонентов smile.gif

Многие кулхацкеры так и ломают, грузят ДеДе смотрят адрес Кнопки REGISTER и меняют джамп smile.gif)
Интересно будет увидеть лицо того кто в ДеДе не увидет ни одной формы biggrin.gif .....примитивную CRC уже давно сделал .... думаю поставить вторую НЕ явно ;)

Автор: Dmitry V.Abramov 26.10.2003, 21:34
Monty А вот это уже из другой оперы - из Runtime Form Designing... Сразбегу не готов ничего путного советовать. Но уверен, что все ответы можно найти в ($DELPHI)\Source\Rtl

По поводу отсутствия форм вообще - это сразу натолкнет на мысль о другом методе хрюка - bpx CreateDialogParam и идти на последний адрес в стеке. Вот когда в .exe наличествует (якобы) интересующая форма и кнопке прописан OnClick event и по этому адресу вычисляется нечто жуткое, то гарантировано энное время на осознание того, что это "фальшивка". И есть шанс, что это осознание так и не придет.

Автор: Monty 26.10.2003, 23:10
Dmitry V.Abramov я придумал, а что если убрать все события присвоенные элементам в "доступной формы" wink.gif ...... тогда мне ненадо прятать формы, а событие буду присваивать сам в коде ..........

Я еще знаю что DeDe умеет находит *.PAS модули и дизассамблировать sad.gif .... это я уже не знаю как решить ...... удаление PACKAGEINFO не очень помогает hmmm.gif

Автор: Monty 27.10.2003, 05:06
Прятанье формы БЕСПОЛЕЗНО!
Еще раз почитаю статью про то как работает DeDE http://xtin.km.ru/view.shtml?id=123 ..... и надо что то придумать .... т.к. он находит имена и адрес всех процедур! sad.gif

Автор: <Spawn> 27.10.2003, 08:16
Monty Не можешь кинуть пожалста етот DEDE, т.к. в ближайшем будущем я думаю начаьб проект, в котором нужно будет делать какую то защиту. Тож не помешало бы поэксперементировать.

Автор: Dmitry V.Abramov 27.10.2003, 10:52
Цитата(Monty @ 27.10.2003, 05:06)
Прятанье формы БЕСПОЛЕЗНО!
Еще раз почитаю статью про то как работает DeDE http://xtin.km.ru/view.shtml?id=123 ..... и надо что то придумать .... т.к. он находит имена и адрес всех процедур! sad.gif

Перестал что-либо понимать... Только что обсуждали, что спрятать форму очень даже полезно...

Все имена и адреса он найти либо не может, либо он стал умнее чем IDA. Второе маловероятно. Принципиально не должны находиться имена процедур (не методов!) в секции implementation (не объявленные в interface). А если немного постараться, то и сам код процедур не найдет.

Где хостится этот DeDE? Уже любопытно стало...

Автор: Dmitry V.Abramov 27.10.2003, 11:03
Интереса ради - проверь, сколько процедур он найдет вот в этом:
Код
{$APPTYPE CONSOLE}
program superbred;

procedure print2; forward;

procedure bred;
begin
 writeln('Bred!');
end;

procedure print;
asm
       db      '34$4556789@',0,0C1h
       lea     eax, [print2+(-00343536h)]
       lea     eax, [eax+00343536h]
@@1:
       mov     [esp], eax
end;

procedure print2;
begin
 writeln('DeDE?');
end;

procedure bred2;
var
 Proc: procedure;
 i: PInteger;
 N: integer;
 P: PChar;
 S: string;

begin
 writeln(PInteger(@bred)^);

 SetString(S, PChar(@print), integer(@print2) - integer(@print));
 P := PChar(S);
 writeln(P);

 S[1] := #255;

 writeln(P+21);

 Proc := pointer(PChar(S));
 P := pointer(@@Proc);
 N := integer(P);
 bred;
 if N = 0 then Halt;
 Proc := PPointer(P)^;
 Proc;
end;

begin
 bred2;

end.

Накорябано наспех и неряшливо. Главное что работает и выдает в конце строчку 'DeDE?'. А вот видит ли ДеДЕ процедуру print2 ?

Автор: Monty 27.10.2003, 11:57
Этим {$APPTYPE CONSOLE} все сказано только оконные smile.gif ....... может я и сам не совсем разобрался, НО убрав OnClick с формы, НО оставив процедуру в Уните и он всеравно нашел! Он ищет события присвоенные элементам и процедуры и т.д. в унитах .......

Вот сам виновник всего происходящего здесь smile.gif
http://m0nty.nm.ru/soft/DeDe%20v3.5/DeDe.3.50.03.1625.exe.only.rar ....... разберитесь с ним wink.gif .... руки уже опустились sad.gif

Автор: Monty 27.10.2003, 12:04
Dmitry V.Abramov вот что он нашел

user posted image

Но я сразу скажу что толком им пользоваться не умею smile.gif

Автор: Dmitry V.Abramov 28.10.2003, 20:14
Цитата(Monty @ 27.10.2003, 11:57)
Этим {$APPTYPE CONSOLE} все сказано только оконные smile.gif .......

Что именно этим сказано? Для доказательства нераспознования обычных процедур этого примера предостаточно. И это все, что он должен был сказать... Нужны окна? Убери {$APPTYPE CONSOLE} и замени writeln() на ShowMessage.

Цитата
НО убрав OnClick с формы, НО оставив процедуру в Уните и он всеравно нашел!


Похоже, что у нас проблемы с терминологией... Ты оставил процедуру или метод ? Оставил в юните или в реализации класса? Я тебе об использовании процедур для "скрытности", ты мне об открытости всех методов формы...

Нашел метод-обработчик, оставленный в published секции и обложенный всей возможной RTTI??? Потрясающая наглость с его стороны... smile.gif

Цитата
Он ищет события присвоенные элементам и процедуры и т.д. в унитах .......

Он читает RTTI и добросовестно пользуется тем, о чем ты сам ему подробно рассказываешь, порождая потомков от TPersistent.

Не хочешь никому ничего рассказывать? Не наследуйся от TPersistent и не используй {$M+}

Автор: Dmitry V.Abramov 28.10.2003, 20:33
Цитата(Monty @ 27.10.2003, 12:04)
Dmitry V.Abramov вот что он нашел

Картинка, увы, говорит лишь, что судя по великоватым адресам, ты пользуешься D7.

Скачал DeDE. Добротное изделие. Далеко ушло от CodeRevenger'a с которого начиналось...

От superbred он грохнулся с окошком "Stream Error". У меня D6.

Если убрать
Код
writeln(PInteger(@bred)^);
то загружает. Рассказывает про используемые юниты. Процедуры print2 он НЕ ВИДИТ. И более того - даже зная где она находится, я не смог на нее выйти в его встроенном дизассемблере - сказывается его повышенная интеллектуальность...

Сдается мне, что именно это и предполагалось, рассказывалось и показывалось примером.

Автор: Monty 28.10.2003, 22:58
Dmitry V.Abramov спасибо smile.gif .... теперь буду знать, ну а метод не скрыть? я пробовал как то затирать это все в откомпилированной программе, но она теряла свою работоспособность smile.gif

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)