您的位置:首页 > 职场人生

程序员的自我修养: Windows下的动态链接

2010-03-08 13:01 302 查看
一 DLL

Windows下的DLL文件和exe文件实际上是一个概念,他们都是有PE格式的二进制文件,有些不同的是:PE文件头部中有个符号位表示该文件是EXE或是DLL.

每个进程有一份私有的数据副本, 由于在ELF文件中, 代码段是地址无关的, 所以可以在多个进程之间共享一份代码. 但是DLL的代码并不是地址无关的, 所以他只是在某种情况下可以被多个进程间共享.

1. DLL共享数据段与进程间通信

在win32下,可以采用DLL共享数据段的方法实现进程间通信.正常情况下,每个DLL的数据段在各个进程中都是独立的,每个进程都拥有自己的副本.但是windows允许将DLL的数据段设置成共享的,即任何进程都可以共享该DLL的同一份数据段.(可以将其分离出来放到另外一个数据段,然后将这个数据段设置成进程间可共享的.也就是说一个DLL中有两个数据段,一个进程间共享,另一个私有.)

但是也产生了一个安全漏洞, 这用利用DLL共享数据段来实现进程间通信的方法应该尽量避免.

2. lib文件, dll文件, obj文件, exp文件的联系

//Math.c
__declspec(dllexport) double add(double a, double b)
{
return a+b;
}

__declspec(dllexport) double sub(double a, double b)
{
return a-b;
}

__declspec(dllexport) double mul(double a, double b)
{
return a+b;
}


当使用MSVC的编译器cl进程编译时:

F:/ProgrammingSpace/TempForever/TempForever>cl /LDd Math.c
用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 15.00.21022.08 版
版权所有(C) Microsoft Corporation。保留所有权利。

Math.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:Math.dll
/dll
/implib:Math.lib
Math.obj
正在创建库 Math.lib 和对象 Math.exp


可见,总计生成了Math.obj, Math.exp, Math.dll, Math.lib四个文件.

当查看Math.lib文件的导出时,

F:/ProgrammingSpace/TempForever/TempForever>dumpbin /EXPORTS Math.lib
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file Math.lib

File Type: LIBRARY

Exports

ordinal    name

_add
_mul
_sub

Summary

BA .debug$S
14 .idata$2
14 .idata$3
4 .idata$4
4 .idata$5
A .idata$6


导出分别为: _add _sub _mul, 并且可知Math.lib中的段有:

BA .debug$S
14 .idata$2
14 .idata$3
4 .idata$4
4 .idata$5
A .idata$6


当查看Math.dll时,

F:/ProgrammingSpace/TempForever/TempForever>dumpbin /EXPORTS Math.dll
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file Math.dll

File Type: DLL

Section contains the following exports for Math.dll

00000000 characteristics
4B99E326 time date stamp Fri Mar 12 14:45:58 2010
0.00 version
1 ordinal base
3 number of functions
3 number of names

ordinal hint RVA      name

1    0 00001000 add
2    1 00001020 mul
3    2 00001010 sub

Summary

3000 .data
9000 .rdata
4000 .reloc
1F000 .text


可知, dll文件可以导出的函数有: add, sub, mul, 我们还可以看到他们的相对地址RVA.

Math.dll文件中的段有:

Summary

3000 .data
9000 .rdata
4000 .reloc
1F000 .text


//TestMath.c
#include <stdio.h>
__declspec(dllimport) double sub(double a, double b);

int main()
{
double ret = sub(3.0, 2.0);
printf("RET: %f/n", ret);
return 0;
}


使用cl /c TestMath.c 编译产生TestMath.obj文件.

当链接时,使用命令link TestMath.obj Math.lib产生TestMath.exe文件.

当查看TestMath.obj的.drectve段时,

F:/ProgrammingSpace/TempForever/TempForever>dumpbin /DIRECTIVES TestMath.obj
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file TestMath.obj

File Type: COFF OBJECT

Linker Directives
-----------------
/DEFAULTLIB:"LIBCMT"
/DEFAULTLIB:"OLDNAMES"

Summary

9 .data
8C .debug$S
2F .drectve
10 .rdata
46 .text


可见, 没有要求导出的函数(供链接时使用).

整个过程如下:

Math.lib------------------------------------

Math.c->Math.dll                                              |

Math.exp                                            |

|--->TestMath.exe

|

TestMath.c->TestMath.obj-------------------------|


Math.lib中并不真正包含Math.c的代码和数据,他用来描述Math.dll的导出符号,他包含了TestMath.obj链接Math.dll时所需要的导入符号以及一部分"桩"代码(胶水代码),以便于将程序与DLL粘在一起. Math.lib又叫"导入库".

Math.exp是链接器在创建DLL时的临时存放导出表的文件.

3.模块定义文件.def

__stdcall调用规范也是大多数windows下的编程语言所支持的通用调用规范, 那么作为一个能过广泛使用的DLL最好采用__stdcall的函数规范.而MSVC默认采用__cdecl调用规范,否则他就会使用符号修饰,经过修饰的符号不便于维护和使用,于是采用.def文件对导出符号进行重命名就是一个很好的方案. windows中的WINAPI实际上就是__stdcall, 所以DLL也是采用了导出函数重名名的方法.

关于导出符号, math.c文件修改如下:

__declspec(dllexport) double __stdcall add(double a, double b)
{
return a+b;
}

__declspec(dllexport) double __stdcall sub(double a, double b)
{
return a-b;
}

__declspec(dllexport) double __cdecl mul(double a, double b)
{
return a+b;
}

double __cdecl div(double a, double b)
{
return a/b;
}


结果如下:

F:/ProgrammingSpace/TempForever/TempForever/new>dumpbin /exports math.dll
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file math.dll

File Type: DLL

Section contains the following exports for Math.dll

00000000 characteristics
4B99FE0D time date stamp Fri Mar 12 16:40:45 2010
0.00 version
1 ordinal base
3 number of functions
3 number of names

ordinal hint RVA      name

1    0 00001000 _add@16
3    1 00001010 _sub@16
2    2 00001020 mul

Summary

3000 .data
9000 .rdata
4000 .reloc
1F000 .text


add sub经过名字修饰,mul不变.

当我们用如下的def文件时:

LIBRARY Math
EXPORTS
add = _add@16
sub = _sub@16
mul
div


结果如下:

F:/ProgrammingSpace/TempForever/TempForever/new>dumpbin /exports math.dll
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file math.dll

File Type: DLL

Section contains the following exports for Math.dll

00000000 characteristics
4B99FF08 time date stamp Fri Mar 12 16:44:56 2010
0.00 version
1 ordinal base
6 number of functions
6 number of names

ordinal hint RVA      name

1    0 00001000 _add@16
4    1 00001010 _sub@16
5    2 00001000 add
2    3 00001030 div
3    4 00001020 mul
6    5 00001010 sub

Summary

2000 .data
2000 .rdata
1000 .reloc
A000 .text


4. 导出重定向

EXPROTS

HeapAlloc = NTDLL.RtlAllocHeap

实现机制: 正常情况下,导出表的地址数组中包含的是函数RVA, 但是如果这RVA指向的位置位于导出表中,那么表示这个符号被重定向了.被重定向了的RVA并不代表该函数的地址,而是指向一个ASCII的字符串,这个字符串在导出表中,它是符号重定向后的DLL文件名和符号名.

二 导入导出表

1. 导出表

PE头文件有一个叫DataDirectory的结构数组, 这个数组共有16个元素, 每个元素中保存的是一个地址和一个长度. 其中第一个元素就是导出表的结构的地址和长度. 导出表是一个IMAGE_EXPORT_DIRECTORY的结构体. 他被定义在WINNT.h中:

IMAGE_DATA_DIRECTORY DataDirectory IMAGE_NUMBEROF_DIRECTORY_ENTRIES];


IMAGE_DATA_DIRECTORY结构如下:

typedef struct _IMAGE_DATA_DIRECTORY {  DWORD VirtualAddress;  DWORD Size;
} IMAGE_DATA_DIRECTORY,  *PIMAGE_DATA_DIRECTORY;


映证了"每个元素中保存的是一个地址和一个长度"的说法.那么就可以说明, 其中第一个元素就是导出表的结构的地址和长度.

导出表的结构如下:

typedef struct _IMAGE_EXPORT_DIRECTORY{
DWORD Characteristics;
DOWRD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctons; //导出地址表(EAT,Export Address Table)
//存放的是各个导出函数的RVA(相对虚拟地址, Relative Virtual Address)

DWORD AddressOfNames;    //符号名表(Name Table)
//函数名表,它保存的是导出的函数名字,其中的所有的函数名是按照ASCII顺序
//排序的,以便于动态连接器在查找函数名字时可以速度更快

DWORD AddressOrdinals;   //名字序号表(Name-Orinal Table)
}IMAGE_EXPORT_DIRECTORY;
//上面三个表的关系是:
//符号名表顺序排列, 名字序号表记录他的序号, 以寻找它在导出地址表中的索引

//RVA(相对虚拟地址,Relative Virtual Address):
//它是相对于PE文件的装载基地址(Base Address)的一个偏移地址

/**********************************************************/


对于链接器来说, 它在链接输出DLL时需要知道哪些函数和变量是要被导出的.
因为对于PE文件来说,默认全局函数和变量是不导出的.

指定要导出的符号的一种方法是: 使用MSVC的__declspec(dllexport)拓展,它
实际上是通过目标文件的编译器指示来实现的
(对于math.obj来说, 它在.drectve段保存了四个/EXPORT参数, 用于传递给
链接器,告知链接器导出相应的函数).

F:/ProgrammingSpace/TempForever/TempForever>dumpbin /DIRECTIVES math.obj
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file math.obj

File Type: COFF OBJECT

Linker Directives
-----------------
/DEFAULTLIB:"LIBCMTD"
/DEFAULTLIB:"OLDNAMES"
/EXPORT:_add
/EXPORT:_sub
/EXPORT:_mul

Summary

88 .debug$S
57 .drectve
2B .text


5. 导入表

当PE文件加载时, windows加载器的其中一个任务就是将所有需要导入的函数地址确定并且将导入表中的元素调到正确的地址, 以实现动态链接.

在PE文件中, 导入表是一个IMAGE_IMPORT_DESCRIPTOR的结构体数组, 每一个这个结构对应一个被导入的DLL.

typedef struct {
DWORD OrginalFistThunk;
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DOWRD FirstThunk;    //指向一个导入地址数组IAT(Import Address Table)
}IMAGE_IMPORT_DESCRIPTOR;


FirstThunk指向一个导入地址数组IAT.

在动态链接器刚完成映射,还没有开始重定位和符号解析的时候, IAT中的元素表示相对应的导入符号的序号或符号名;

当windows的动态链接器在完成该模块的链接时,元素值会被动态链接器改写成符号的真正地址.

那么怎么判断导入地址数组的元素是导入符号的序号还是名字?

如果最高位是1, 低31位就是导入符号的序号值;

如果是0, 低31位就指向一个叫IMAGE_IMPORT_BY_NAME的RVA, IMAGE_IMPORT_BY_NAME由一个WORD和一个字符串组成.那个WORD就表示Hint,即导入符号最有可能的序号值, 后面的字符串是一个符号名. 当使用符号名导入时, 动态链接器先使用Hint值去定位该符号在目标导入表中的位置, 如果是就命中; 否则就按照正常的二分查表进行符号查表.

IMAGE_IMPORT_DESCRIPTOR的OrginalFistThunk指向一个数组叫做导入名称表INT(Import Name Table).

延迟载入(Delayed Load):

当延迟载入的API第一次被调用时, 由链接器添加的特殊的桩代码就会启动, 这个桩代码负责对DLL的装载工作. 然后这个桩代码通过GetProcAddress来找被掉用API的地址.

6. 导入函数的调用

在PE模块中, 需要调用一个导入函数时, 就是使用一个间接调用指令:

CALL DWORD PTR [0x0040D11C]

0x0040D11C对应于IAT中的某一项, 也就是0x0040D11C开始取4个字节作为目标地址.

我们可以看到,0x0040D11C是做个目标地址的地址的常数被写入在指令中的. 可以说, PE DLL的代码段并不是地址无关的.所以要使用重定基地址的方法.

对于编译器来说, 他无法判断一个函数是本模块内部的, 还是从外部导入的.因为对于普通模块内部函数调用来说, 编译器产生的指令是这样的:

CALL XXXXXXXX

XXXXXXXX是模块内部的函数地址.

MSVC引入 __declspec(dllexport)属性, 一段一个函数有被声明为 __declspec(dllexport), 那么编译器就知道它是外部导入的, 以便产生相对应的指令形式.

三 DLL的优化技术

1. 重定基地址(Rebasing)

对DLL文件的基地址进行装载时重定位.

从上面的分析中我们可以注意到DLL文件有一个段叫.reloc.存放的是重定位信息. 我们同样可以从DataDirectory数组里面得到重定位信息.

F:/ProgrammingSpace/TempForever/TempForever/new>dumpbin /relocations math.dll > new.txt
//部分内容
Microsoft (R) COFF/PE Dumper Version
Dump of file math.dll
File Type: DLL

BASE RELOCATIONS #4
1000 RVA,       90 SizeOfBlock
3C  HIGHLOW            10001E4B
41  HIGHLOW            1000D008
47  HIGHLOW            1000D00C
4B  HIGHLOW            10001532
51  HIGHLOW            1000D010
55  HIGHLOW            100014E6
5B  HIGHLOW            1000D014
5F  HIGHLOW            1000151F
65  HIGHLOW            1000D018
69  HIGHLOW            10001488
6E  HIGHLOW            1000D01C
74  HIGHLOW            1000D020
78  HIGHLOW            10001DC3
7E  HIGHLOW            1000D024
82  HIGHLOW            100014A4
88  HIGHLOW            1000D028
8C  HIGHLOW            10001406
92  HIGHLOW            1000D02C
96  HIGHLOW            10001393
AF  HIGHLOW            1000DF84
F6  HIGHLOW            1000B004
FB  HIGHLOW            1000EB34
105  HIGHLOW            1000DF8C
139  HIGHLOW            1000DF88
151  HIGHLOW            1000DF88
159  HIGHLOW            1000DF88
15F  HIGHLOW            1000DFDC
1A5  HIGHLOW            1000D030
1AB  HIGHLOW            1000DFA4
1C6  HIGHLOW            1000B000
1F6  HIGHLOW            1000C340
212  HIGHLOW            1000DF88
22A  HIGHLOW            1000B12C
27D  HIGHLOW            1000B12C
2AA  HIGHLOW            1000B12C
336  HIGHLOW            1000D6A8
33E  HIGHLOW            1000D5C4
353  HIGHLOW            1000D4C8
35E  HIGHLOW            1000D5C4
620  HIGHLOW            1000B130
685  HIGHLOW            1000E13C
6BD  HIGHLOW            1000D830
C17  HIGHLOW            1000D830
CD2  HIGHLOW            1000D830
E76  HIGHLOW            1000D008
EC4  HIGHLOW            1000B140
ECD  HIGHLOW            1000B138
EF9  HIGHLOW            1000B164
EFF  HIGHLOW            1000B00C
F08  HIGHLOW            1000B148
F0F  HIGHLOW            1000B008
F29  HIGHLOW            1000D034
F2F  HIGHLOW            1000B014
F3A  HIGHLOW            1000D030
F46  HIGHLOW            1000D034
F5B  HIGHLOW            1000B180
F62  HIGHLOW            1000B010
F76  HIGHLOW            1000B170
F7D  HIGHLOW            1000B008
FA4  HIGHLOW            1000D034
FAA  HIGHLOW            1000B014
FB5  HIGHLOW            1000D030
FC1  HIGHLOW            1000D034
FD6  HIGHLOW            1000B180
FDD  HIGHLOW            1000B010
FF1  HIGHLOW            1000B19C
FF8  HIGHLOW            1000B008
0  ABS
2000 RVA,      160 SizeOfBlock
10  HIGHLOW            1000B018
1C  HIGHLOW            1000D034
22  HIGHLOW            1000B014
2E  HIGHLOW            1000DFA0
3D  HIGHLOW            1000D034
43  HIGHLOW            1000B01C
4C  HIGHLOW            1000D030
58  HIGHLOW            1000DFA8
66  HIGHLOW            1000D030
6C  HIGHLOW            1000D034
78  HIGHLOW            1000B020
7E  HIGHLOW            1000D034
8B  HIGHLOW            1000C360
95  HIGHLOW            1000B180
9C  HIGHLOW            1000B010
B4  HIGHLOW            1000B200
C3  HIGHLOW            1000B170
CA  HIGHLOW            1000B008
D7  HIGHLOW            1000B19C
FA  HIGHLOW            1000D0A0
10F  HIGHLOW            1000B024
135  HIGHLOW            1000D6A8
175  HIGHLOW            1000B02C
17B  HIGHLOW            1000D030
1A5  HIGHLOW            1000D030
1AB  HIGHLOW            1000DFA4
1C7  HIGHLOW            1000B000
1DF  HIGHLOW            1000B028
205  HIGHLOW            1000C388
27F  HIGHLOW            1000B200
2A2  HIGHLOW            1000B030
2AC  HIGHLOW            1000D0A0
2E4  HIGHLOW            1000D6A8
2EC  HIGHLOW            1000D5D0
338  HIGHLOW            1000D030
348  HIGHLOW            1000D034
34E  HIGHLOW            1000B014
35A  HIGHLOW            1000D030
360  HIGHLOW            1000D034
370  HIGHLOW            1000D030
376  HIGHLOW            1000DFA4
38B  HIGHLOW            1000D034
399  HIGHLOW            1000B01C
3A4  HIGHLOW            1000B180
3AB  HIGHLOW            1000B010
3C6  HIGHLOW            1000B008
3CB  HIGHLOW            1000B1CC
3D3  HIGHLOW            1000B1C0
3D9  HIGHLOW            1000DF9C
3E0  HIGHLOW            1000B1B4
3E6  HIGHLOW            1000DFA0
3ED  HIGHLOW            1000B1AC
3F3  HIGHLOW            1000DFA4
3FB  HIGHLOW            1000DF9C
402  HIGHLOW            1000B01C
407  HIGHLOW            1000DFA8
40F  HIGHLOW            1000DFA0
418  HIGHLOW            1000DFA4
424  HIGHLOW            1000B014
429  HIGHLOW            1000DFA0
42E  HIGHLOW            1000B020
434  HIGHLOW            1000DF9C
438  HIGHLOW            1000200E
43E  HIGHLOW            1000DFA4
443  HIGHLOW            1000DFA8
449  HIGHLOW            1000B018
44E  HIGHLOW            1000D034
45D  HIGHLOW            1000DFA0
473  HIGHLOW            1000DF9C
47E  HIGHLOW            1000DFA0
483  HIGHLOW            1000DF9C
48E  HIGHLOW            1000DFA4
493  HIGHLOW            1000DFA0
49E  HIGHLOW            1000DFA8
4A3  HIGHLOW            1000DFA4
4B0  HIGHLOW            1000DFA8
4BE  HIGHLOW            10002202
4C4  HIGHLOW            1000DF9C
4D1  HIGHLOW            1000D030
4F1  HIGHLOW            1000D030
4F7  HIGHLOW            1000DFA4
513  HIGHLOW            1000B000
52F  HIGHLOW            1000C3B0
541  HIGHLOW            1000EA04
590  HIGHLOW            1000E0F4
596  HIGHLOW            1000B034
5A7  HIGHLOW            1000B02C
5D4  HIGHLOW            1000DFAC
5DD  HIGHLOW            1000B038
5E9  HIGHLOW            1000DFAC
620  HIGHLOW            1000DFAC
629  HIGHLOW            1000B038
635  HIGHLOW            1000DFAC
66E  HIGHLOW            1000DFAC
677  HIGHLOW            1000B038
683  HIGHLOW            1000DFAC
6A7  HIGHLOW            1000B038
6B0  HIGHLOW            1000B010
6DD  HIGHLOW            1000D038
6F8  HIGHLOW            1000B1E8
6FE  HIGHLOW            1000B010
707  HIGHLOW            1000B1D8
70E  HIGHLOW            1000B008
730  HIGHLOW            1000B03C
78F  HIGHLOW            1000B120
797  HIGHLOW            1000B120
7AA  HIGHLOW            1000B120
7B5  HIGHLOW            1000B108
7BA  HIGHLOW            1000B0F8
7CA  HIGHLOW            100030DE
7D4  HIGHLOW            1000B0F0
7DB  HIGHLOW            1000B0F4
7E6  HIGHLOW            1000EB30
7EF  HIGHLOW            1000EB30
805  HIGHLOW            1000EB30
810  HIGHLOW            1000C3D0
82A  HIGHLOW            1000DFE0
836  HIGHLOW            1000DFDC
83E  HIGHLOW            1000DFD8
84E  HIGHLOW            1000EB28
863  HIGHLOW            1000EB24
8A3  HIGHLOW            1000EB28
8B0  HIGHLOW            1000EB24
8DA  HIGHLOW            1000B110
8DF  HIGHLOW            1000B10C
8EA  HIGHLOW            1000B118
8EF  HIGHLOW            1000B114
90D  HIGHLOW            1000DFE0
999  HIGHLOW            10002939
9A6  HIGHLOW            1000D038
9AF  HIGHLOW            1000C3F0
9C3  HIGHLOW            1000B04C
9E4  HIGHLOW            1000EA20
9EA  HIGHLOW            1000EA08
A1C  HIGHLOW            1000EA20
A73  HIGHLOW            1000EA20
A7B  HIGHLOW            1000EA08
ABB  HIGHLOW            1000EA08
AC5  HIGHLOW            1000EA08
AED  HIGHLOW            1000B048
B06  HIGHLOW            1000EA20
B47  HIGHLOW            1000EA20
B77  HIGHLOW            1000B044
B89  HIGHLOW            1000B048
BDB  HIGHLOW            1000EA08
BE1  HIGHLOW            1000B040
C05  HIGHLOW            1000EA20
C23  HIGHLOW            1000B050
C45  HIGHLOW            1000EB20
C50  HIGHLOW            1000EB2C
C5F  HIGHLOW            1000DF8C
C97  HIGHLOW            1000DFC0
CA1  HIGHLOW            1000DF8C
CF1  HIGHLOW            1000DF8C
CFC  HIGHLOW            1000DF8C
D06  HIGHLOW            1000EB20
D17  HIGHLOW            1000DFC0
D22  HIGHLOW            1000DFC0
ED5  HIGHLOW            1000EB2C
EE6  HIGHLOW            1000DFE8
EEE  HIGHLOW            1000E0EC
EF4  HIGHLOW            1000B054
EF9  HIGHLOW            1000EB34
EFF  HIGHLOW            1000DFD0
F6B  HIGHLOW            1000DFB4
F71  HIGHLOW            1000DFB8
F87  HIGHLOW            1000E0F0
F92  HIGHLOW            1000B068
FA9  HIGHLOW            1000E0F0
FB5  HIGHLOW            1000B02C
FC2  HIGHLOW            1000E0F0
FC9  HIGHLOW            1000E0F0
3000 RVA,       D4 SizeOfBlock
0  HIGHLOW            1000B064
4F  HIGHLOW            1000B060
62  HIGHLOW            1000B05C
94  HIGHLOW            1000B058


这样就导致如果一个DLL被多个进程共享, 且该DLL被这些进程装载到不同的位置, 那么每个进程都需要有一份单独的DLL代码段的副本.

2. 导入函数绑定

还可以将DLL导出函数的地址保存到模块的导入表中,就可以省去每次启动时符号解析的过程.这叫导入函数绑定.

用一种检验机制来知道是否DLL导出函数地址发生变化, 即链接器把DLL的时间戳和校验和保存到被绑定的PE文件的导入表中. 运行时,核对版本是否相同.

F:/ProgrammingSpace/TempForever/TempForever/new>dumpbin /imports c:/windows/note
pad.exe
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file c:/windows/notepad.exe

File Type: EXECUTABLE IMAGE

Section contains the following imports:

comdlg32.dll
10012C4 Import Address Table
1007990 Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

76344906      F PageSetupDlgW
763385CE      6 FindTextW
76349D84     12 PrintDlgExW
7633C3E1      3 ChooseFontW
76322306      8 GetFileTitleW
76337B9D      A GetOpenFileNameW
76338602     15 ReplaceTextW
76330036      4 CommDlgExtendedError
76337C2B      C GetSaveFileNameW

SHELL32.dll
1001174 Import Address Table
1007840 Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

7D647C18     1F DragFinish
7D5E18CE     23 DragQueryFileW
7D5FB1A9     1E DragAcceptFiles
7D632E6F    103 ShellAboutW

WINSPOOL.DRV
10012B4 Import Address Table
1007980 Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

72F7643C     78 GetPrinterDriverW
72F74D40     1B ClosePrinter
72F75091     7E OpenPrinterW

COMCTL32.dll
1001020 Import Address Table
10076EC Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

7718D270      8 CreateStatusWindowW

msvcrt.dll
10012EC Import Address Table
10079B8 Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

4CFB2DAE     4E _XcptFilter
4CFB9E9A     F6 _exit
4CFB9ECE     C5 _c_exit
4CFCAECF    317 time
4CFCAB69    2D4 localtime
4CFB9EB6     C8 _cexit
4CF9D036    2C6 iswctype
4CFB5C94     ED _except_handler3
4CF9CE77    274 _wtol
4CFC802F    32F wcsncmp
4CFBFB0C    1E4 _snwprintf
4CFB9E7E    290 exit
4CFE17AC     A8 _acmdln
4CF9EEEB     6D __getmainargs
4CFB9D67    13B _initterm
4CFCD695     9A __setusermatherr
4CFE23D8     B6 _adjust_fdiv
4CF9F1A4     80 __p__commode
4CF9F1DB     85 __p__fmode
4CFB537C     98 __set_app_type
4CFCEE4F     D6 _controlfp
4CFC806B    330 wcsncpy

ADVAPI32.dll
1001000 Import Address Table
10076CC Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

77DA6FEF    1EF RegQueryValueExW
77DA6C17    1CA RegCloseKey
77DCBA25    1D0 RegCreateKeyW
77DCBD05    139 IsTextUnicode
77DA7AAB    1EE RegQueryValueExA
77DA7842    1E4 RegOpenKeyExA
77DAD757    1FC RegSetValueExW

KERNEL32.dll
100108C Import Address Table
1007758 Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

7C8097B8    13E GetCurrentThreadId
7C80932E    1D4 GetTickCount
7C80A4B7    294 QueryPerformanceCounter
7C80A864    16A GetLocalTime
7C809FA0    1D8 GetUserDefaultLCID
7C83378D    140 GetDateFormatW
7C833FEB    1D6 GetTimeFormatW
7C80FFA9    1F8 GlobalLock
7C80FF12    1FF GlobalUnlock
7C810CFD    15A GetFileInformationByHandle
7C809420     51 CreateFileMappingW
7C8017E9    1C0 GetSystemTimeAsFileTime
7C801E1A    34A TerminateProcess
7C80DE85    13B GetCurrentProcess
7C8449FD    336 SetUnhandledExceptionFilter
7C801D7B    244 LoadLibraryA
7C80B731    176 GetModuleHandleA
7C801EF2    1AE GetStartupInfoA
7C80FCBF    1F4 GlobalFree
7C8115F2    16C GetLocaleInfoW
7C8099BF    24E LocalFree
7C809A1D    24A LocalAlloc
7C809A99    3B8 lstrlenW
7C832EC9    254 LocalUnlock
7C80A3EE     38 CompareStringW
7C832E35    250 LocalLock
7C87A656     EA FoldStringW
7C809BD7     31 CloseHandle
7C80BAF4    3B2 lstrcpyW
7C801812    2A6 ReadFile
7C8107F0     52 CreateFileW
7C80AA26    3AF lstrcmpiW
7C8099B0    13C GetCurrentProcessId
7C80AE30    198 GetProcAddress
7C817013    10A GetCommandLineW
7C810FC2    3A9 lstrcatW
7C80EE67     CC FindClose
7C80EF71     D3 FindFirstFileW
7C80B7DC    159 GetFileAttributesW
7C80AA5C    3AC lstrcmpW
7C809856    266 MulDiv
7C80BA7F    3B5 lstrcpynW
7C8325D4    253 LocalSize
7C92FE01    168 GetLastError
7C810E17    38F WriteFile
7C92FE10    316 SetLastError
7C80A164    382 WideCharToMultiByte
7C830917    251 LocalReAlloc
7C834BA7     EC FormatMessageW
7C813100    1DA GetUserDefaultUILanguage
7C83205E    300 SetEndOfFile
7C831F4B     82 DeleteFileW
7C8099A5     F6 GetACP
7C80BA04    35E UnmapViewOfFile
7C809C88    267 MultiByteToWideChar
7C80B995    25A MapViewOfFile
7C863E6A    35B UnhandledExceptionFilter

GDI32.dll
1001028 Import Address Table
10076F4 Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

77F0DC19     98 EndPage
77F24A05      0 AbortDoc
77F0DEA9     96 EndDoc
77EF6E5F     8C DeleteDC
77F0F456    249 StartPage
77EF7F9D    1B6 GetTextExtentPoint32W
77EFBE28     2F CreateDCW
77F24B25    211 SetAbortProc
77EFA5BB    1BC GetTextFaceW
77EF7EAC    250 TextOutW
77F25695    247 StartDocW
77F1FB22     CE EnumFontsW
77EF61C1    1A6 GetStockObject
77EF83B3    198 GetObjectW
77EF5A69    16C GetDeviceCaps
77EF938F     3D CreateFontIndirectW
77EF6BFA     8F DeleteObject
77EF7DB9    1BE GetTextMetricsW
77EF5EDB    217 SetBkMode
77EFD4B7    1CC LPtoDP
77F03A05    243 SetWindowExtEx
77F03AAE    23F SetViewportExtEx
77EF9410    22C SetMapMode
77EF5B70    20F SelectObject

USER32.dll
1001188 Import Address Table
1007854 Import Name Table
FFFFFFFF time date stamp
FFFFFFFF Index of first forwarder reference

77D2908E     FF GetClientRect
77D29930    24D SetCursor
77D1869D    22A ReleaseDC
77D186C7    10C GetDC
77D247AB     9F DialogBoxParamW
77D27822    243 SetActiveWindow
77D29BF6    122 GetKeyboardLayout
77D28D20     8F DefWindowProcW
77D2B19C     99 DestroyWindow
77D31F7B    1DB MessageBeep
77D2AF56    292 ShowWindow
77D29823    117 GetForegroundWindow
77D297FF    1A6 IsIconic
77D303C7    173 GetWindowPlacement
77D190D2     37 CharUpperW
77D19E36    1C9 LoadStringW
77D2EE76    1B4 LoadAcceleratorsW
77D2B222    15C GetSystemMenu
77D1AF7F    218 RegisterClassExW
77D27B97    1BE LoadImageW
77D19D69    1BA LoadCursorW
77D1DE46    282 SetWindowPlacement
77D2D0A3     61 CreateWindowExW
77D2D1D2    10E GetDesktopWindow
77D298C8    116 GetFocus
77D2E8BC    1BC LoadIconW
77D2960E    287 SetWindowTextW
77D2CA5A    201 PostQuitMessage
77D1AF34    228 RegisterWindowMessageW
77D2AEAB    2BB UpdateWindow
77D2F750    26F SetScrollPos
77D2B24C     29 CharLowerW
77D1929B    1FE PeekMessageW
77D29849     C4 EnableWindow
77D2B415     BE DrawTextExW
77D1EA3B     56 CreateDialogParamW
77D2A5CD    17A GetWindowTextW
77D18F9C    15D GetSystemMetrics
77D2B29E    1E9 MoveWindow
77D28FD5    193 InvalidateRect
77D61BD4    2D3 WinHelpW
77D2AF1B    110 GetDlgCtrlID
77D2201F     3C ChildWindowFromPoint
77D297A0    231 ScreenToClient
77D2974E    10B GetCursorPos
77D273CC    237 SendDlgItemMessageW
77D2929A    240 SendMessageW
77D2B1B0     2C CharNextW
77D31ABD     39 CheckMenuItem
77D30265     42 CloseClipboard
77D2F166    19F IsClipboardFormatAvailable
77D30277    1F3 OpenClipboard
77D1F967    137 GetMenuState
77D2D2C4     C2 EnableMenuItem
77D2D896    159 GetSubMenu
77D314BA    12C GetMenu
77D66534    1E3 MessageBoxW
77D2C2BB    281 SetWindowLongW
77D188A6    16F GetWindowLongW
77D2436E    111 GetDlgItem
77D2B112    256 SetFocus
77D2736C    254 SetDlgItemTextW
77D1A9B6    2D9 wsprintfW
77D24305    114 GetDlgItemTextW
77D24A4E     C6 EndDialog
77D2910F    145 GetParent
77D318AC    2AC UnhookWinEvent
77D18A01     A2 DispatchMessageW
77D18BF6    2AA TranslateMessage
77D1941E    2A8 TranslateAcceleratorW
77D27424    1A2 IsDialogMessageW
77D18CCB    200 PostMessageW
77D191C6    13E GetMessageW
77D317F7    27E SetWinEventHook

Header contains the following bound import information:
Bound to comdlg32.dll [4802BDA2] Mon Apr 14 10:12:50 2008
Bound to SHELL32.dll [4802BDB6] Mon Apr 14 10:13:10 2008
Bound to WINSPOOL.DRV [4802BDCA] Mon Apr 14 10:13:30 2008
Bound to COMCTL32.dll [4802BD6C] Mon Apr 14 10:11:56 2008
Bound to msvcrt.dll [4802BD6C] Mon Apr 14 10:11:56 2008
Bound to ADVAPI32.dll [4802BD89] Mon Apr 14 10:12:25 2008
Bound to KERNEL32.dll [4802BDC6] Mon Apr 14 10:13:26 2008
Contained forwarders bound to NTDLL.DLL [4802BDC5] Mon Apr 14 10:13:25 200
8
Bound to GDI32.dll [4802BD81] Mon Apr 14 10:12:17 2008
Bound to USER32.dll [4802BDBD] Mon Apr 14 10:13:17 2008

Summary

2000 .data
8000 .rsrc
8000 .text


可以看到绑定的信息.

四 DLL HELL

windows缺乏一种很有效的DLL版本控制机制.

解决方法:

1. 静态链接

2. 防止DLL覆盖(DLL Stomping)

3. 防止DLL冲突(放到应用程序的文件夹中)

4. .NET下DLL HELL的解决方案

用一个叫Manifest的清单文件描述程序集.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: