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

本文介绍在Delphi中如何通过设置函数导出表的名称为空字符串来隐藏DLL中的函数名,同时提供了静态和动态调用隐藏函数的方法。隐藏函数名可以增加程序的安全性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用 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); stdcallexternal 'proDll.dll' index 1;
procedure ShowMessageB(hWnd: HWND); stdcallexternal '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(0or LoWord(1)));
      
if @ShowMessageA = nil then
        
raise Exception.Create('proDll.dll 中没有输出 ShowMessageA 函数');
      @ShowMessageB :
= GetProcAddress(hDllHandle, Pointer(HiWord(0or 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值