能力值:
( LV2,RANK:10 )
2 楼
不懂的也帮忙顶一下哈
能力值:
( LV6,RANK:90 )
3 楼
据说导入表中表项IMAGE_IMPORT_BY_NAME中的Hint值是可选的,有的编译器把它设置为0。导入表中的Hint值并不可靠。
在dll链接处理中,系统先根据hint值来获得需导入函数的地址,如果失败了,会按函数名来搜索比对获取,哈,有代码为证
if (Hint < ExportDir->NumberOfNames)
{
ExName = RVA(BaseAddress, ExNames[Hint]);
if (strcmp(ExName, (PCHAR)SymbolName) == 0)
{
Ordinal = ExOrdinals[Hint];
Function = RVA(BaseAddress, ExFunctions[Ordinal]);
if (((ULONG)Function >= (ULONG)ExportDir) &&
((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
{
DPRINT("Forward: %s\n", (PCHAR)Function);
Function = LdrFixupForward((PCHAR)Function);
if (Function == NULL)
{
DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName);
}
return Function;
}
if (Function != NULL)
return Function;
}
}
/*
* Binary search
*/
minn = 0;
maxn = ExportDir->NumberOfNames - 1;
while (minn <= maxn)
{
LONG mid;
LONG res;
mid = (minn + maxn) / 2;
ExName = RVA(BaseAddress, ExNames[mid]);
res = strcmp(ExName, (PCHAR)SymbolName);
if (res == 0)
{
Ordinal = ExOrdinals[mid];
Function = RVA(BaseAddress, ExFunctions[Ordinal]);
if (((ULONG)Function >= (ULONG)ExportDir) &&
((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize))
{
DPRINT("Forward: %s\n", (PCHAR)Function);
Function = LdrFixupForward((PCHAR)Function);
if (Function == NULL)
{
DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName);
}
return Function;
}
if (Function != NULL)
return Function;
}
else if (minn == maxn)
{
DPRINT("LdrGetExportByName(): binary search failed\n");
break;
}
else if (res > 0)
{
maxn = mid - 1;
}
else
{
minn = mid + 1;
}
}
能力值:
( LV2,RANK:10 )
4 楼
看上面的代码,如果hint存在的话,会取hint(ID)的Name再比较,如果比较失败,会重新以Name再找吗?
能力值:
( LV2,RANK:10 )
5 楼
噢,看到,是有在while里遍历所有name查找,
只是奇怪用vs2003编译出来的exe,调用user32.dll和kernel32.dll里面的函数, 导入表里面的Hint(序号)竟然会是错的,
难道是我后来装了vs2008,更新了这两个dll,可microsoft不应该改变序号才对呀,不然程序起动会慢很多。....
能力值:
( LV2,RANK:10 )
6 楼
by the way:老兄这段代码从哪挖出来的?
能力值:
( LV6,RANK:90 )
7 楼
reactos 赚分不容易阿,
能力值:
( LV2,RANK:10 )
8 楼
让我们看看 IMAGE_EXPORT_DIRECTORY:
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base; // <==== 主意这个
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA from base of image
DWORD AddressOfNames; // RVA from base of image
DWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
在 User32.dll 里,Base = 1
stud_PE 把 EndDialog 的 ordinal (198) + Base (1) = 199!
能力值:
( LV2,RANK:10 )
9 楼
楼上的这个说得有道理,不过我举另一个例子,请解释是为何:
从随意一个exe里(vc6写的),用stud_pe查看它的导入表,
从kernel32.dll中导入一个函数如下:
0x002E "CloseHandle"
查kernel32.dll中导出表信息如下:
Base: 0x00000001
0x0032 0x00009B47 "CloseHandle"
按楼上朋友的加法: 0x002E + 1 (Base) 肯定不等于 0x0032
请问何解?
能力值:
( LV2,RANK:10 )
10 楼
就如3楼的大哥所说,系统先根据hint值来获得需导入函数的地址,如果失败了,会按函数名来搜索比对获取.
VC6是根据你所使用的 Microsoft Visual Studio\VC98\LIB\kERNEL32.LIB 来制定 CloseHandle 的 Hint. 如果你用一个 Hex Editor 来看 Kernel32.lib, 你会在 0x16230 找到:
00016230h: 2C AD 01 35 1C 00 00 00 1B 00 0C 00 5F 43 6C 6F ; ,-.5........_Clo
--------
00016240h: 73 65 48 61 6E 64 6C 65 40 34 00 4B 45 52 4E 45 ; seHandle@4.KERNE
00016250h: 4C 33 32 2E 64 6C 6C 00 4B 45 52 4E 45 4C 33 32 ; L32.dll.KERNEL32
00016260h: 2E 64 6C 6C 2F 20 20 20 38 38 39 33 30 32 33 31 ; .dll/ 88930231
00016270h: 36 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; 6
CloseHandle 的 Hint 是 1B.
如果你是用<Microsoft Platform SDK for Windows Server 2003 R2>\Lib\Kernel32.lib,
00019210h: BB 32 C2 41 1C 00 00 00 34 00 0C 00 5F 43 6C 6F ; »2ÂA....4..._Clo
-------
00019220h: 73 65 48 61 6E 64 6C 65 40 34 00 4B 45 52 4E 45 ; seHandle@4.KERNE
00019230h: 4C 33 32 2E 64 6C 6C 00 4B 45 52 4E 45 4C 33 32 ; L32.dll.KERNEL32
00019240h: 2E 64 6C 6C 2F 20 20 20 31 31 30 33 32 34 36 30 ; .dll/ 11032460
00019250h: 31 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; 11
CloseHandle 的 Hint 是 34.
系统里的 Kernel32.dll 不一定属于SDK 里的 Kernel32.lib!