用 Delphi 用长了,总是发现,有些和 MS 不同的地方。例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用。一旦知道如何调用,可以给自己的应用程序提供很强的功能和很大的灵活性。但,这些函数通常又没有函数名(即使用 ExeScope 查看 DLL 文件的导出表也看不出函数意义),仅仅只有一个序号来表示。有时候我又自己想,为什么我在写程序的时候不能学学 MS 隐藏一些自己不希望公开的函数呢?
其实用 Delphi 写 DLL 的时候,使用简单的技巧就可以实现隐藏函数名的效果。让我们来看看下面这个 DLL 源码:
其实用 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
.
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
.
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
.
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