Delphi DLL注入和共享变量

时间:2012-07-20 05:53:50

标签: dll delphi-7 code-injection delphi

我使用BTMemoryModule将DLL注入进程。 主/父进程可以调用函数/过程,但另一种方式呢? dll可以从Main / Parent进程读取/获取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;

3 个答案:

答案 0 :(得分:4)

首先,这似乎不是通常所谓的注射。这只是一个简单的模块加载,虽然来自内存而不是文件。

关于DLL如何从EXE导入函数,请以与从EXE导入DLL时完全相同的方式执行此操作。

  1. 使用exports列出EXE导出的函数。
  2. 通过调用GetModuleHandle(nil)获取EXE的模块句柄。
  3. 将该模块句柄传递给GetProcAddress以导入函数。
  4. 与更常见的EXE链接到DLL模式的唯一区别是您使用GetModuleHandle而不是LoadLibrary。那是因为EXE必须已经加载,所以你可以简单地询问它的模块句柄,而不是要求加载模块。

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

答案 1 :(得分:2)

如果Child模块(您的DLL)知道父应用程序的数据结构和功能,则可以这样做。这些数据和功能必须在父方面提供。

答案 2 :(得分:0)

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


DLL端:

  1. 在DLL中添加 Init 过程
  2. 导出它。
  3. 根据需要添加所需的类型/ var声明
  4. 代码段:

    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;
    

    Nota Bene:

    我也使用BTMemory进行了测试,但它确实有效。