0

我使用 BTMemoryModule 将 DLL 注入进程。主/父进程可以调用函数/过程,但其他方式呢?dll 可以从主/父进程读取/获取 var 或调用函数吗?

谢谢您的帮助。

编辑:DLL

library mydll; // DLL obviously...
uses windows;

procedure Test
begin
 // I need a string/integer/pointer from ParentProcess
end

exports
Test;

begin
 // I need a string/integer/pointer from ParentProcess. (if possible). 
end.

程序:

program myprogram
uses
...
var
 M : PBTMemoryModule;
begin
 BTMemoryLoadLibary (pointer, pointerlength);
 @myMaintest    := BTMemoryGetProcAddress(M, 'Test');
 ...
end;
4

3 回答 3

4

首先,这似乎不是通常所说的注射。这只是一个普通的模块加载,尽管来自内存而不是文件。

至于DLL如何从EXE中导入函数,和EXE从DLL中导入时完全一样。

  1. 用于exports列出 EXE 导出的函数。
  2. 通过调用获取EXE的模块句柄GetModuleHandle(nil)
  3. 将该模块句柄传递GetProcAddress给导入函数。

与更常见的 EXE 链接到 DLL 模式的唯一区别是您使用GetModuleHandle而不是LoadLibrary. 那是因为 EXE 必须已经加载,所以您可以简单地询问它的模块句柄,而不是要求加载模块。

我会评论说,以这种方式做事是很不寻常的。通常,EXE 会调用 DLL 并传递 DLL 所需的任何信息。该信息可能包括允许 DLL 查询其主机 EXE 的回调函数、接口等。

于 2012-07-20T08:04:21.867 回答
2

如果子模块(您的 DLL)知道父应用程序的数据结构和功能,这是可能的。这些数据和功能必须在父方可用。

于 2012-07-20T06:07:09.020 回答
0

这是为了将我的评论进一步扩展到大卫的回答:


DLL端:

  1. 在 DLL 中添加Init程序
  2. 导出它。
  3. 根据需要添加所需的类型/变量声明

片段代码:

library TheDLL;

...

var
  OwnerAPP: HMODULE; // To be initialized by a call of the exported procedure Init from the EXE

...

type
  TTestCallfromExe = procedure(f_Text: PAnsiChar); stdcall;

var
  OwnerAPP: LongInt;
  l_TestCallfromExe: TTestCallfromExe;

procedure Init(Owner: HMODULE);
begin
  OwnerAPP := Owner;
end;

...

exports
  Init, // This is it and the others exports follow
  ...

TestCallfromExe的调用与通常调用任何 Dll 的导出函数/过程一样。只要OwnerAPP正确初始化,就可以根据 OP 的要求在 Dll 导出函数的主体中进行调用。


EXE端:

根据需要导出每个过程/函数(从 DLL 调用),当然您应该实现它们中的每一个。

program TheEXE;

uses
  ...
  MyExportImplementation; // Refence to implementatio unit

...

exports
  TestCallfromExe, // This is it
  ...

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

示例实现细节:

unit MyExportImplementation;

interface

...

procedure TestCallfromExe(f_Text: PAnsiChar); stdcall;

implementation

...

procedure TestCallfromExe(f_Text: PAnsiChar); stdcall;
begin
  MessageBoxA(0, f_Text, 'Exe Dialog Ansi (stdcall)', 0);
end;

...

end.

把它们放在一起:

这是基于 DemoDLL(来自 BTMemory)示例,例如在TheEXE.dpr项目的 MainForm 单元中实现:

procedure TForm1.BtnCAllClick(Sender: TObject);
var
  l_Init: procedure(Owner: HMODULE);
begin
  m_DllHandle := LoadLibrary('TheDLL.dll');
  try
    if m_DllHandle = 0 then
      Abort;

    @l_Init := GetProcAddress(m_DllHandle, 'Init');  // <<<
    if @l_Init = nil then
      Abort;

    // Fetch the remainding exported function(s)/procedure(s) adresses

    l_Init(HInstance); // <<<  Hand EXE's HInstance over to the DLL

    // Call exported function(s)/procedure(s) accordingly
  except
    Showmessage('An error occured while loading the dll');
  end;

  if m_DllHandle <> 0 then
    FreeLibrary(m_DllHandle)
end;

注意事项:

我也用 BTMemory 对其进行了测试,它可以工作。

于 2012-07-20T11:32:58.913 回答