Delphi中编写无输出函数名的DLL文件

  • Post author:
  • Post category:其他
用 Delphi 用长了,总是发现,有些和 MS 不同的地方。例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用。一旦知道如何调用,可以给自己的应用程序提供很强的功能和很大的灵活性。但,这些函数通常又没有函数名(即使用 ExeScope 查看 DLL 文件的导出表也看不出函数意义),仅仅只有一个序号来表示。有时候我又自己想,为什么我在写程序的时候不能学学 MS 隐藏一些自己不希望公开的函数呢?

 其实用 Delphi 写 DLL 的时候,使用简单的技巧就可以实现隐藏函数名的效果。让我们来看看下面这个 DLL 源码:

library
 proDll;
 

uses

  Windows;
 

{
$R *.res
}

 

procedure
 ShowMessageA(hWnd: HWND); 
stdcall
;

begin

  MessageBox(hWnd, 


您调用的是 ShowMessageA 函数



DLL 函数信息

,
    MB_ICONINFORMATION);

end
;
 

procedure
 ShowMessageB(hWnd: HWND); 
stdcall
;

begin

  MessageBox(hWnd, 


您调用的是 ShowMessageB 函数



DLL 函数信息

,
    MB_ICONINFORMATION);

end
;
 

exports

  ShowMessageA index 

1
 name 

,
  ShowMessageB index 

2
 name 

;
 

begin


end
.

 

注意看 exports 部分,用 index 关键字指定输出函数的序号,后面紧跟一个 name 关键字指明输出函数名称。关键就在这里,name 后面是一个空字符串,这样就给函数生成了一个空字符串名。实际效果既是隐藏了输出函数的名称。是不是很容易呢?

 那么我们怎样调用这样的输出函数呢?由于没有了函数名,我们调用起来会显得和以前不一样。其实也不用担心,调用同样非常简单。我下面就静态调用和动态调用制作了两个工程,源码如下:

 静态调用例子:

unit
 Unit1;
 

interface

 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 

type

  TForm1 

=
 
class
(TForm)
    Button1: TButton;
    Button2: TButton;
    

procedure
 Button1Click(Sender: TObject);
    

procedure
 Button2Click(Sender: TObject);
  

private

    

{
 Private declarations 
}

  

public

    

{
 Public declarations 
}

  

end
;
 

var

  Form1: TForm1;
 

implementation

 

{
$R *.dfm
}

 

procedure
 ShowMessageA(hWnd: HWND); 
stdcall

external
 

proDll.dll

 index 
1
;

procedure
 ShowMessageB(hWnd: HWND); 
stdcall

external
 

proDll.dll

 index 
2
;
 

procedure
 TForm1.Button1Click(Sender: TObject);

begin

  ShowMessageA(Handle);

end
;
 

procedure
 TForm1.Button2Click(Sender: TObject);

begin

  ShowMessageB(Handle);

end
;
 

end
.

 

动态调用的例子:

unit
 Unit2;
 

interface

 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 

type

  TForm2 

=
 
class
(TForm)
    Button1: TButton;
    Button2: TButton;
    

procedure
 Button1Click(Sender: TObject);
    

procedure
 Button2Click(Sender: TObject);
  

private

    

{
 Private declarations 
}

  

public

    

{
 Public declarations 
}

  

end
;
 

var

  Form2: TForm2;
 

implementation

 

{
$R *.dfm
}

 

type

  TDllShowMessageFunc 

=
 
procedure
 (hWnd: HWND); 
stdcall
;
 

var

  hDllHandle: THandle;
  ShowMessageA, ShowMessageB: TDllShowMessageFunc;
 

procedure
 LoadFuncDll;

begin

  

if
 hDllHandle 
=
 
0
 
then

  

begin

    hDllHandle :

=
 LoadLibrary(

proDll.dll

);
    

if
 hDllHandle 
=
 
0
 
then

      

raise
 Exception.Create(

proDll.dll 加载失败

);
    

try

      

{

      lpProcName: the second argument of function GetProcAddress
        Points to a null-terminated string containing the function name,
        or specifies the function’s ordinal value. If this parameter is
        an ordinal value, it must be in the low-order word; the high-order
        word must be zero.
      

}

      @ShowMessageA :

=
 GetProcAddress(hDllHandle, Pointer(HiWord(
0

or
 LoWord(
1
)));
      

if
 @ShowMessageA 
=
 
nil
 
then

        

raise
 Exception.Create(

proDll.dll 中没有输出 ShowMessageA 函数

);
      @ShowMessageB :

=
 GetProcAddress(hDllHandle, Pointer(HiWord(
0

or
 LoWord(
2
)));
      

if
 @ShowMessageB 
=
 
nil
 
then

        

raise
 Exception.Create(

proDll.dll 中没有输出 ShowMessageB 函数

);
    

except

      FreeLibrary(hDllHandle);
      hDllHandle :

=
 
0
;
      

raise
;
    

end
;
  

end
;

end
;
 

procedure
 FreeFuncDll;

begin

  

if
 hDllHandle 
<>
 
0
 
then

  

begin

    FreeLibrary(hDllHandle);
    hDllHandle :

=
 
0
;
    @ShowMessageA :

=
 
nil
;
    @ShowMessageB :

=
 
nil
;
  

end
;

end
;
 

procedure
 TForm2.Button1Click(Sender: TObject);

begin

  

if
 @ShowMessageA 
=
 
nil
 
then
 LoadFuncDll;
  ShowMessageA(Handle);

end
;
 

procedure
 TForm2.Button2Click(Sender: TObject);

begin

  

if
 @ShowMessageB 
=
 
nil
 
then
 LoadFuncDll;
  ShowMessageB(Handle);

end
;
 

initialization

  

//
 
do
 nothing

finalization

  FreeFuncDll;

end
.

 

转载于:https://www.cnblogs.com/rogee/archive/2010/09/15/1827283.html