![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запись процедуры или функции в файл. [D7, WinXP]
Bios_ © (2005-08-11 14:27:00)Кодеры. Как записать процедуру или функцию в файл? Очень нужно,
заранее спасибо!
Наиль (2005-08-15 21:50:00) [1]Полностью согласен.
Надеюсь, теперь все знают, что так делать нельзя :-)
Eraser (2005-08-15 21:46:00) [2]Наиль © (15.08.05 21:41) [24]
Опять же это подходит только для Demo-версий, что вобщем не желательно, т.к. обязательно найдётся конкурент, который распространяет такую же прогу, но без урезаной функциональности до регистрации.
+ всё равно кто-нибудь выложит ключ на каком-нибудь crackway.com
Наиль (2005-08-15 21:41:00) [3]Предполагается, что функция расшифровывается всегда, если есть ключ. Верность расшифровки проверяется хешем. При этом, как писал Касперски, лучший хеш для такого случая 2-байтовый (10битный). Таким образом, злоумышленик получит слишком много ключей соответсвующий хешу, но не сможет подобрать верный.
Eraser (2005-08-15 21:29:00) [4]Наиль © (15.08.05 21:25) [22]
Вот я и говорю, что если функция используется, то защита есть. А если только проверяется, то защиты не получится. К примеру, в бухгалтерской программе расчёт производится по определёной формуле. Зашифруем функцию и программа будет бесполезной до её (функции) расшифровки.
Это всё конечно хорошо, но тут есть слабое место... а именно где определяется условие - расшифровывать или нет ф-ю.
Наиль (2005-08-15 21:25:00) [5]Eraser © (15.08.05 21:00) [21]
Вот я и говорю, что если функция используется, то защита есть. А если только проверяется, то защиты не получится. К примеру, в бухгалтерской программе расчёт производится по определёной формуле. Зашифруем функцию и программа будет бесполезной до её (функции) расшифровки. Сколько лет пишу программы, и не создал ни одного вируса. А вопрос защиты тут многим интересен. Полезно знать, что не стоит делать, пытаясь защитить свою программу.
Eraser (2005-08-15 21:00:00) [6]Наиль © (15.08.05 20:54) [20]
Защита сомнительная и громоздкая... да и к тому же большенство защит такого рода опять же взламываются подправлением условного перехода на безусловный, при проверке возвращаемого значения закриптованой ф-ии.
Вообще на виросописательством повеяло ;-))
Наиль (2005-08-15 20:54:00) [7]Раз уж я заговорил о защите, то такой способ в принципе может сработать.
К примеру в программе используется формула. Тогда её нужно вынести в отдельную функцию. Хранить её можно в зашифрованом виде, скажем, в ресурсах. На компьютере пользователя создаётся первая половина ключа, вторая половина создаётся создателем программы из первой половины. Далее пользователь используя половинки, активизирует программу. Т.е. происходит расшифровывание и использование формулы.
Этот способ обладает естественным недостатком. При выполнении программы (первая лицензионная копия) функция оказывается в памяти в открытом виде. А дальше, Вы уже знаете, что делать :-) (не лицензионная копия).
Если же, в ваше программе не используются формулы. То вам придётся, создать свою, постояно её сравнивать с неким оригиналом. В таком случае, нет ни какой защиты, т.к. злоумышленику не составит большого труда, добится положительного результата сравнения.
P.S. Касперски - мой любимый писатель.
Юрий Зотов (2005-08-13 11:49:00) [8]Вот пример исполнения кода в стеке с вызовом ShowMessage из этом коде. В данном случае буфер, хранящий исполняемый код копируется из тела программы, но понятно, что его можно заполнить и из файла, и вообще откуда угодно.
type
TShowMsg = procedure(const Msg: string);
TCallShowMsg = procedure(ShowMsg: TShowMsg; const Msg: string);
procedure CallShowMsg(ShowMsg: TShowMsg; const Msg: string);
begin
ShowMsg(Msg)
end;
procedure ExecuteCodeInsideStack(Buff: string; const Msg: string);
begin
TCallShowMsg(@Buff[1])(@ShowMessage, Msg)
end;
procedure TForm1.FormDblClick(Sender: TObject);
var
L: Cardinal;
S: string;
begin
L := Cardinal(@ExecuteCodeInsideStack) - Cardinal(@CallShowMsg);
SetLength(S, L);
CopyMemory(@S[1], @CallShowMsg, L);
ExecuteCodeInsideStack(S, 'OK')
end;
Юрий Зотов (2005-08-13 11:16:00) [9]> Наиль © (13.08.05 08:24) [15]
Об этом приеме еще лет 5 тому назад писал Крис Касперски в журнале "Программист". Вот эта статья:
http://reversing.by.ru/Manual/SelfMod.htm?extract=1123808127
Для компилятора Delphi прием работает, это давно проверено. Естественно, проблема перемещаемого кода остается и ее нужно как-то обходить - именно по этой причине "задача становиться действительно не выполнимой, при вызове любой процедуры или функции внутри загружаемой". Говоря точнее, задача НЕ становится невыполнимой, но выполнять ее приходится необычными способами.
> злобная танька (13.08.05 09:31) [16]
Ответ см. в упомянутой статье, в подразделе "Подводные камни перемещаемого кода".
Leonid Troyanovsky (2005-08-13 11:14:00) [10]
> злобная танька (13.08.05 09:31) [16]
> > Наиль © (13.08.05 08:24) [15]
> а если передавать в загруженную функцию адрес вызываемой
> из неё процедуры/функции? прокатит?
Адрес возврата и так есть - в стеке.
Главная проблема в том, что тело функции не должно содержать
ссылок на глобальные символы, адресных переходов да и многого
другого. Напрямую можно вызывать лишь функции kernel,
(но, именно напрямую, т.е., предварительно определив их
адрес путем GetAddressProc). Все остальные адреса внешних
функций должны определятся из кода.
--
Regards, LVT.
злобная танька (2005-08-13 09:31:00) [11]> Наиль © (13.08.05 08:24) [15]
а если передавать в загруженную функцию адрес вызываемой из неё процедуры/функции? прокатит?
Наиль (2005-08-13 08:24:00) [12]Не зависимо от целей, можно утверждать, что если что-то сохраняется, то должно и сохраняться. Если только для анализа, то лучше всё-таки пользоваться Debuger'ом. Если же для того, чтобы загрузить и выполнить, то задача становиться действительно не выполнимой, при вызове любой процедуры или функции внутри загружаемой.
Когда я впервые пришёл на этот сайт, то обнаружил исходники математического анализатора, который компилирует введёную формулу в память и вызывает полученую формулу. Более того, автор кратко объясняет приципы работы такой программы. Позже - найти эти исходники удалось только в "Королевстве". Я был потрясён. Но факт остаётся фактом. Функцию можно загрузить в память и выполнить. Но лёгко это делается, только математических формул.
evvcom (2005-08-12 09:05:00) [13]
> Подозреваю, что это не которое подобие защиты. Часть функций
> программы храниться отдельно. Если регистрация прошла успешно,
> то они грузятся в память и вызываются.
Очень сомневаюсь в этом, но если это так, то задача в общем случае сложновата не только для новичка.
Наиль (2005-08-12 08:59:00) [14]Очепятка: Read(Fun -> Read(Fun^
Наиль (2005-08-12 08:57:00) [15]Подозреваю, что это не которое подобие защиты. Часть функций программы храниться отдельно. Если регистрация прошла успешно, то они грузятся в память и вызываются. Если нет, то программа не функциоиональна.
Пример:
Var
fs:TFileStream;
Fun:Pointer;
Begin
...
fs.Read(Fun,FunSize);
Button1.onClick:=TNotifyEvent(Fun);
...
End;
evvcom (2005-08-12 08:27:00) [16]
> чтобы оный символ не
> экспортировался, иначе его адрес может быть невалиден
А подробнее можно? Чего-то не вижу причины этого.
Leonid Troyanovsky (2005-08-11 19:57:00) [17]
> TStas © (11.08.05 19:37) [7]
> >begin...end
> То есть вторая процедура является просто ограничителем,
> по которй узнаем длинну кода первой?
Единственное(?) ограничение в том, чтобы оный символ не
экспортировался, иначе его адрес может быть невалиден.
--
Regards, LVT.
begin...end (2005-08-11 19:39:00) [18]> TStas © (11.08.05 19:37) [7]
Да.
begin...end (2005-08-11 19:37:00) [19]> Bios_ (11.08.05 15:18) [5]
Оно, конечно, пожалуйста, но в общем случае, как и было замечено в [6], это не будет работать. Поэтому в [4] и смайлик имеется.
TStas (2005-08-11 19:37:00) [20]>begin...end
То есть вторая процедура является просто ограничителем, по которй узнаем длинну кода первой?