其实用 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 .
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 .
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 .
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 .