首页
社区
课程
招聘
[旧帖] 关于PE结构中导入表dll的序号,与dll文件中的序号对应不上... 0.00雪花
发表于: 2010-3-28 16:00 5570

[旧帖] 关于PE结构中导入表dll的序号,与dll文件中的序号对应不上... 0.00雪花

2010-3-28 16:00
5570
1。我写了一个MFC exe程序,用Peditor查看导入表:
从User32.dll中导入:
Hint           name
00C6        EndDialog

00C6h---->198
我再用stud_PE查看User32.dll时,发现序号不对:
  EndDialog rva: 000159C9 ord: 199

请问是为何?
同样查看其它函数,有些差别更大...

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 194
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不懂的也帮忙顶一下哈
2010-3-28 17:04
0
雪    币: 75
活跃值: (638)
能力值: ( 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;
          }
     }
2010-3-28 17:18
0
雪    币: 194
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
看上面的代码,如果hint存在的话,会取hint(ID)的Name再比较,如果比较失败,会重新以Name再找吗?
2010-3-28 17:33
0
雪    币: 194
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
噢,看到,是有在while里遍历所有name查找,

只是奇怪用vs2003编译出来的exe,调用user32.dll和kernel32.dll里面的函数, 导入表里面的Hint(序号)竟然会是错的,
难道是我后来装了vs2008,更新了这两个dll,可microsoft不应该改变序号才对呀,不然程序起动会慢很多。....
2010-3-28 17:36
0
雪    币: 194
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
by the way:老兄这段代码从哪挖出来的?
2010-3-28 17:37
0
雪    币: 75
活跃值: (638)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
7
reactos 赚分不容易阿,
2010-3-28 22:43
0
雪    币: 594
活跃值: (16)
能力值: ( 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!
2010-3-29 10:45
0
雪    币: 194
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
楼上的这个说得有道理,不过我举另一个例子,请解释是为何:
从随意一个exe里(vc6写的),用stud_pe查看它的导入表,
从kernel32.dll中导入一个函数如下:
    0x002E       "CloseHandle"

查kernel32.dll中导出表信息如下:
Base:                   0x00000001
  0x0032  0x00009B47 "CloseHandle"
按楼上朋友的加法: 0x002E + 1 (Base) 肯定不等于 0x0032

请问何解?
2010-3-30 22:46
0
雪    币: 594
活跃值: (16)
能力值: ( 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!
2010-3-31 08:40
0
游客
登录 | 注册 方可回帖
返回
//