![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Слхранение функции [D5]
MaD © (2002-05-25 16:02:00)Подскажите пожалуйста. Как мне записать функцию в файл??? Как загружать функцию из файла и выполнять её??? Я записываю в файл через адрес функции, но не могу получить её длину.
ION T (2002-05-27 22:10:00) [1]В общем попробовал я написать простенький пример:
unit MainFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btnWrite: TButton;
btnLoadExec: TButton;
procedure btnWriteClick(Sender: TObject);
procedure btnLoadExecClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function FuncToWrite(Tst: boolean; CallbackAddr: pointer): boolean;
type _Callback= procedure (Value: boolean);
begin
_Callback(CallBackAddr)(tst);
{asm
mov al, tst;
call CallBackAddr;
end;}
if Tst then
begin
Result:= true
end else
Result:= false;
end;
procedure Callback(Value: boolean);
begin
Form1.Caption:= booltostr(value, true);
end;
function WriteFunc(FileName: string; FuncAddr: pointer; FuncLen: integer): integer;
var f: file;
begin
AssignFile(f, FileName);
rewrite(f, 1);
BlockWrite(f, FuncAddr^, FuncLen, Result);
CloseFile(f);
end;
function LoadFunc(FileName: string; var Buffer; Offset: integer= 0): boolean;
var f: file;
begin
Result:= false;
AssignFile(f, FileName);
{$I-}
reset(f, 1);
{$I+}
if IOResult= 0 then
begin
Seek(f, Offset);
BlockRead(f, Buffer, FileSize(f));
Result:= true;
end;
CloseFile(f);
end;
procedure TForm1.btnWriteClick(Sender: TObject);
begin
btnWrite.Caption:= inttostr(
WriteFunc("Func2Write.bin", @FuncToWrite, integer(@Callback)- integer(@FuncToWrite)));
end;
procedure TForm1.btnLoadExecClick(Sender: TObject);
type _FunctionToWrite= procedure (Tst: boolean; CallbackAddr: pointer);
var StackFunc: array[0..1023] of byte;
// StackFuncPtr, CallbackPtr: pointer;
begin
FillChar(StackFunc, 1024, $c3); //just in case:))
if LoadFunc("Func2Write.bin", StackFunc) then
begin
_FunctionToWrite(@StackFunc)(true, @Callback);
{ StackFuncPtr:= @StackFunc;
CallbackPtr:= @Callback;
asm
mov al, true; //Setting first parameter to whatever (boolean)
mov edx, CallbackPtr; //Second one pointing to callback()
call StackFuncPtr;
end;}
end;
end;
end.
Конечно для проверки серийника использовать можно (если ещё и зашифровать), но для чего-то ещё вряд-ли.......
y-soft (2002-05-27 21:12:00) [2]>Юрий Зотов © (27.05.02 16:07)
Именно такие ограничения я и имел в виду :)
А вообще, вопрос интересен скорее теоретически, т.к. практически всегда можно обойтись легальными DLL, да и нынешние мощные скриптовые языки при производительности современных компьютеров вполне подойдут
Romkin (2002-05-27 16:40:00) [3]Может быть, не стоит мудрить, а просто воспользоваться, к примеру MS Scripting? Готовый интерпретатор JScript/VBScript
Юрий Зотов (2002-05-27 16:07:00) [4]> MaD (25.05.02 21:40)
Это вряд ли... :о)
> Vaddya (26.05.02 20:14)
И даже без "наверное". Код спокойно сохраняется, читается обратно и даже выполняется - проверено.
> y-soft © (27.05.02 10:14)
Конечно, в общем случае не будет, разве что случайно. Например, не будут работать вызовы других функций. Но способ есть - чтобы ссылки работали, надо писать загружаемую функцию в виде перемещаемого кода и передавать ей базовый адрес.
y-soft (2002-05-27 10:14:00) [5]>Vaddya (26.05.02 20:14)
Ваш подход скорее всего не будет работать, если в функции есть какие-либо внешние ссылки на адресное пространство вызывающего процесса
Vaddya (2002-05-26 20:14:00) [6]Функции WriteFile в качестве второго параметра задается указатель на данные, записываемые в файл, а третьего - размер этих данных. Если написать указатель на функцию и ее размер, то наверное можно будет сохранить ее в файл.
SPeller (2002-05-26 18:34:00) [7]2 MaD (25.05.02 21:40)
размер такой же как и sizeof(@A) и равен 4 байта.
А как ты хотел? Измеряется в этом случае указательна функцию, который 32-х разрядный, и равен соответственно 4-ём быйтам.
y-soft (2002-05-26 17:48:00) [8]>MaD
http://www.programme.ru/index.phtml?arch/032001/index.htm
При творческом подходе можно использовать исполняемый код, созданный и иными способами
MaD (2002-05-25 21:40:00) [9]Если Integer(B)-Integer(A), то фактически размер такой же как и sizeof(@A) и равен 4байта.
А где взять журнал???
Юрий Зотов (2002-05-25 17:30:00) [10]Все очень просто. Компилятор Delphi строит машинный код в порядке объявления функций, поэтому после такого объявления
procedure A(...);
begin
...
end;
procedure B(...);
begin
...
end;
длина кода процедуры A будет равна Integer(B) - Integer(A). Но чтобы выполнить ее код, подгруженный извне, его сначала нужно будет поместить в сегмент стека.
См. статью Криса Касперски в журнале "Программист", №3 за 2001 год - там и об этом и еще о многом.
ION T (2002-05-25 17:00:00) [11]А по моему он хочет откомпилированный код сохранить в файл и потом подгружать его прямо в память и выполнять.....теоретически это возможно, но надо ещё стек сохранять, регистры,....ну в общем, удачи;))
rhf (2002-05-25 16:04:00) [12]ты не про DLL?