- 注册时间
- 2011-3-10
- 最后登录
- 1970-1-1
该用户从未签到
|
开篇首先骂人,至今为止不能用 "遍历PE输出表" 在搜索引擎上获取任何一篇有价值的文章,一个很简单的输出表被看雪那本书讲得晦涩难懂,第三版 --P286页对输出表的分析文章写得非常差劲,真不知道审稿的人干啥去了。
optional头的最后一个域是一个数组列表,该数组大小为16,元素为IMAGE_DATA_DIRECTORY,至于以后平台是否会增加,说不清楚,但是FileHeader中明确给出了该数组的大小。
该数组表的第一个元素就是指向输出表的。而输出表的定义如下:
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;
前面就不管了,直接看重要的,该结构体说明了 总共输出项目总数[NumberOfFunctions],带名称的为NumberOfNames,由于某些个别变态函数会以序号的形式输出,所以这2个值可能不等。 接下来是指向函数入口的指针,指向名称的指针,指向序号的指针。
这里有3个对应关系,看雪书上讲得有点晕。 描述一个PE文件的输出函数需要3个变量
函数入口,函数名称,函数序号。
如果你想偷懒一次性把这个表取完,那你程序多半要崩溃,至少目前从网上找到的代码都崩溃了,手上几个现成的Delphi代码几乎读不懂,很久没碰Delphi,生疏了许多。。
numberoffunctions 告诉了我们总共有多少个函数,这时候我们可以一次性获取所有函数的入口RVA,接着numberofnames 告诉了我们有多少个被命名输出,
第一次获取的函数名,一定是第一个序号所指定的函数名称。
比如
proc_rva 表
80505450 805a5614 805f1adc 805f5312 805f1b0e
nam_etable
abcdef hhhhhhh zxzzzzzzzz
ord_table
0100 0200 0400
这时候的对应关系如下:
abcdef===>0001===>805a5614
hhhhh===>0002===>805f1adc
zxzzzzz===>0004===>805f1b0e
一句话,先读取函数入口,再读取名称,而名称的填充,则根据ordianl中的索引来查找。
红书这页讲的很晕人,尤其是winhex开10进制,举例时候的数据太特殊,过于简单。
这个问题确实比较气愤,记得大概在今年6月的时候,准备写一个PE explorer,兴致勃勃的完成了框架的
描述以及初步代码,当测试核心模块的时候,不得不因为对输出表的研究不够深入而彻底放弃,今通宵达旦,总算圆满解决掉输出表的问题。
PE文件中比较复杂的 一个是引入表,一个输出表,最复杂的则属资源描述表。
|
|