Delphi中编写无输出函数名的DLL文件
2010-07-27 20:48
176 查看
用 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
.
的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用。一旦知道如何调用,可以给自己的应用程序提供很强的功能和很大的灵活
性。但,这些函数通常又没有函数名(即使用 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
.
相关文章推荐
- Delphi中编写无输出函数名的DLL文件(有点意思)(400多篇博客)
- Delphi中编写无输出函数名的DLL文件
- Delphi中编写无输出函数名的DLL文件
- 【C语言】编写函数实现:100-200素数的输出
- C语言:编写函数将一个整数的二进制位模式从左到右翻转后的值输出
- delphi编写函数,出现over flow
- 编写一个函数 找出double类型中最大数的下标 输出下标
- 编程:编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串
- 编写函数交换两个int型指针所指向的值,调用并检查该函数,输出交换后的值。
- 使用模板类编写通用的任意类型调试输出函数
- 黑马程序员 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串,但要保证汉字不被截取半个
- 如何在Delphi中调用.Net编写的DLL中的函数(Function)、过程(Procedure)
- 编写将给定字符串倒序输出的函数[Java笔试题]
- 编写一个函数 接受两个字符串参数 如果 第一个参数被第二个包含 则输出第一个参数的首字符(图)
- delphi 函数参数传递 默认参数(传值)、var(传址)、out(输出)、const(常数)四类
- 编写一个判断素数的函数,在主函数输入一个整数时,输出是否素数的信息。
- 编写一个截取字符串的函数,(网上流传的答案有的是错的)输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4
- 函数_习题:编写一个函数将任意一个整数逆序输出
- 第一周:项目1 使用switch结构编写函数根据月份输出对应的季节
- 编写一个函数,在页面上输出1~1000之间所有能同时被3,5,7整除的证书,并要求每行显示6个这样的数