3

プログラムから exe ファイルを動的にロードし、その動的にロードされた exe から SomeProcedure を実行しようとしています。これが、ロードされたexeで行っていることです-library.exe

interface    

procedure SomeProcedure; stdcall;

implementation    

procedure SomeProcedure;
begin
  ShowMessage('Ala has a cat');
end;

そして、これがlibrary.exeをロードし、そこからSomeProcedureを実行しようとする私のexeです。

type
  THandle = Integer;
  TProc = procedure();

var
  AHandle: THandle;
  Proc: TProc;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AHandle := LoadLibrary('library.exe');
  if AHandle <> 0 then begin
    @Proc := GetProcAddress(AHandle, 'SomeProcedure');
    if @Proc <> nil then 
      try    
        Proc;
      finally
        FreeLibrary(AHandle);
      end;
    end;
  end;
end;

残念ながら、それは機能していません。AHandle にはアドレスがありますが、GetProcAddress は常に nil を返します。私は何を間違っていますか?

4

3 に答える 3

6

私の知る限りでは、あなたが試みていることは不可能です。LoadLibrary を使用して .exe ファイルをロードし、エクスポートされた関数を呼び出すことはできません。プロセスにロードできる .exe ファイルは 1 つだけです。機能をライブラリ、COM サーバー、またはその他のソリューションに移動する必要があります。

Sertacが指摘しているように、ドキュメントはこれをカバーしています:

LoadLibrary を使用して、他の実行可能モジュールをロードすることもできます。たとえば、関数は .exe ファイルを指定して、FindResource または LoadResource で使用できるハンドルを取得できます。ただし、LoadLibrary を使用して .exe ファイルを実行しないでください。代わりに、CreateProcess 関数を使用してください。

実行可能ファイルのモジュール ハンドルで GetProcAddress を使用できます。ただし、たとえば GetModuleHandle(0) を呼び出して、モジュール ハンドルを取得する必要があります。

于 2013-08-14T06:24:36.720 に答える
1

デビッドがすでに指摘したように、それはほぼ不可能です。不可能ではありません。理解のために、理論的に CreateProcess を呼び出してから、その呼び出しとそれに続く呼び出しをフックすることができます。呼び出しの 1つにも ZwCreateSectionがあります。私はずっと前にそのようなことで遊んだことがありますが、理論的には可能です。CreateProcess は空のプロセス コンテキストを作成し、その後、他の Zw/Nt カーネル呼び出しで満たされます。呼び出しを知っていれば、コンテンツを提供できます。

しかし、それは理論であり、それでさえ OS へのハッキングです。David が指摘したように、正気で文書化された方法でそれを行うことは不可能です。ただし、実行できることは、exeをリソースとして一時ファイルに抽出して実行することです。その後、ファイルが終了するのを待ってから、ファイルを削除できます。それが唯一の方法です。RAMですべてを行うことはできません。

編集:

使える技の記事はこちら。しかし、それは醜いハックです:)

于 2013-08-14T07:18:10.073 に答える
-1

「Proc を呼び出している AV があります」 - TProc の定義で「stdcall」を定義するのを忘れています。

別の EXE からエクスポートされた関数の読み込み/実行を示す小さなサンプルを作成しました。

アプリケーション 1:

program Exe4Export;
uses
  Vcl.Forms,
  Unit3 in 'Unit3.pas' {Form3},
  ExportTypes in 'ExportTypes.pas';

{$R *.res}

function Test:integer; stdcall; export;
begin
  result := 7;
end;

exports
  Test;

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm3, Form3);
  Application.Run;
end.

アプリケーション 2:

type
  TExtProc = function: integer; stdcall;

procedure TForm3.FormCreate(Sender: TObject);
var
  h: HMODULE;
  p: TExtProc;
begin
  h := LoadLibrary('Exe4Export.exe');
  p := GetProcAddress(h, 'Test');
  if assigned(p) then
    caption := IntToStr(p);
  FreeLibrary(h);
end;

したがって、app2 は app1 を独自のアドレス空間にロードし (はい、DLL で可能です)、関数のアドレスを取得し、DLL の場合と同じ方法で呼び出します。

于 2013-08-13T21:04:01.770 に答える