dynamic加载exe文件

我试图从我的程序dynamic加载一个EXE文件,并从该dynamic加载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总是返回零。 我究竟做错了什么?

Solutions Collecting From Web of "dynamic加载exe文件"

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

正如Sertac所指出的那样, 文档包含了这个内容:

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

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

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

但这是理论,甚至是入侵操作系统。 正如David所指出的那样,不可能以一种理智而有据可查的方式来做到这一点。 你可以做的是将exe作为资源解压到一个临时文件并执行它。 然后您可以等待它结束,之后删除文件。 这是做到这一点的唯一方法。 要做到这一切在RAM是不行的。

编辑:

这是一篇关于可以使用的技术的文章。 但它是一个丑陋的黑客:)

“现在我有一个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一样。