动态加载exe文件

时间:2013-08-13 20:27:26

标签: windows delphi dll delphi-7

我正在尝试从我的程序动态加载exe文件,并从动态加载的exe运行SomeProcedure。这是我在加载的exe中执行的操作 - library.exe

interface    

procedure SomeProcedure; stdcall;

implementation    

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

这是我的exe加载的library.exe并尝试从中运行SomeProcedure。

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。我做错了什么?

3 个答案:

答案 0 :(得分:6)

据我所知,你所尝试的是不可能的。您不能使用LoadLibrary加载.exe文件,然后调用其导出的函数。您只能将一个.exe文件加载到进程中。您需要将功能移动到库,COM服务器或其他解决方案中。

正如Sertac指出的那样,documentation确实涵盖了这一点:

  

LoadLibrary也可用于加载其他可执行模块。例如,该函数可以指定.exe文件   获取可在FindResource或LoadResource中使用的句柄。但是,不要使用LoadLibrary来运行.exe文件。而是使用CreateProcess函数。

您可以将GetProcAddress与可执行文件的模块句柄一起使用。但是,您必须通过调用GetModuleHandle(0)来获取模块句柄。

答案 1 :(得分:1)

大卫已经指出这几乎是不可能的。我不会说不是不可能。只是为了理解你可以从理论上调用CreateProcess,然后挂钩它的调用和后面的调用。其中一个电话也是ZwCreateSection。很久以前我玩过这样的东西,理论上可以做到这一点。 CreateProcess创建一个空的进程上下文,然后用其他Zw / Nt kernell调用填充。知道你可以提供内容的电话。

但那是理论,甚至是黑客入侵操作系统。正如大卫所指出的那样,不可能以理智和记录的方式做到这一点。您可以做什么hovewer将exe作为资源提取到临时文件并执行它。然后,您可以等待它结束,然后删除该文件。这是唯一的方法。要在RAM中完成所有操作是不行的。

编辑:

以下是可以使用technique的文章。但它是一个丑陋的黑客:)

答案 2 :(得分:-1)

“现在我有一个AV来调用Proc” - 你忘了在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相同的方式调用它。