您的位置:首页 > 其它

解析静态库(Lib)文件,提取出所有函数信息,组织成自定义格式文件

2018-01-28 15:15 337 查看
标准:《Microsoft可移植可执行文件和通用目标文件格式文件规范》,简称《PE COFF文件规范》

注意:这里的LIB指的是静态库,要和编写DLL所生成的lib区别开来

《PE COFF文件规范》 中称静态库格式为:

档案(库)文件格式,在WinNT.h中称Archive format.

《PE COFF文件规范》 中称另一种Lib为:

导入库格式-是描述由一个映像导出供其它映像使用的符号的库

具体思路:

1.解析静态库(Lib)文件,提取出其中的所有目标文件成员(obj)

2.解析各个目标文件成员(obj),提取出其中的函数信息(函数名,函数数据,函数数据大小)

3.把提取出的函数信息,组织成自定义文件格式(flb)

函数库(.flb)文件格式: 签名-函数头表-函数名称段-函数数据段

一.解析静态库(Lib)文件,提取出其中的所有目标文件成员(obj)

1.静态库(Lib)文件结构

档案(库)文件(.lib)结构非常简单,就是签名+很多个成员,详细参见《PE COFF文件规范》第7节,或者看这里:http://dev.csdn.net/htmls/21/21543.html

签名,WinNT.h是这么定义的:

成员,是由头部和成员内容组成;WinNT.h是这么定义头部的:

三个特别成员:第一链接器成员,第二链接器成员,长名称成员;(签名后面紧跟着的,就是这三个特别成员)

对于两个链接器成员,WinNT.h是这么定义它们头部的Name域的:

对于长名称成员,WinNT.h是这么定义它们头部的Name域的:

目标文件成员(重点),三个特别成员之后直到文件结束,都是由这种目标文件成员组成。解析lib文件的本质就是解析它们,对于它们的头部Name域,有两种形式:

1.“名称/”

2.“/n” 当名称大小大于Name域的16个字节的话,就会存在长名称成员中;而n(十进制)就给出其名称位于长名称成员中的偏移

目标文件成员的内容,就是标准的目标文件(COFF格式)。

2.定位目标文件成员

解析lib文件的本质就是解析它们,它们是标准的目标文件格式,所有的函数信息都这里面;定位它们,是CLibParser这个类的工作。具体工作分为两步:

1.定位第一个目标文件成员。

2.遍历所有目标文件成员。

具体代码:

1.定位第一个目标文件成员

2.遍历所有目标文件成员:

二.解析各个目标文件成员(obj),提取出其中的函数信息(函数名,函数数据,函数数据大小)

1.目标文件(.obj)结构:

文件头(IMAGE_FILE_HEADER)

节表(IMAGE_SECTION_HEADER)

。。。

节数据

。。。

重定位表(IMAGE_RELOCATION),几乎每个节都有一张重定位表

符号表(IMAGE_SYMBOL),目标文件的中心,所有工作都围绕这张表展开

字符串表,一些符号的名称太长(超过8个字节),其名称就会存在这里

2.解析目标文件(obj)

目标文件的核心是符号表,整个解析工作就是围绕它展开。CObjParser负责解析目标文件(.obj)

具体步骤:

1.定位符号表,过滤出其中的函数符号

2.根据函数符号获得函数名称,输出到.nam中间文件,并记录下相应的偏移和大小

3.根据函数符号获得函数数据,输出到.dat中间文件,并记录下相应的偏移和大小

4.根据函数符号对重定位信息进行标志,在以后检测的时候,会跳过这些信息

1.定位符号表,过滤出其中的函数符号

《PE COFF文件规范》中对函数符号式这么描述的:存储类别为EXTERNAL(2)、Type 域的值为(0x20)以及SectionNumber 域的值大于0,表明它是一个函数

具体方法:

2根据函数符号获得函数名称,输出到.nam中间文件,并记录下相应的偏移和大小

3.根据函数符号获得函数数据,输出到.dat中间文件,并记录下相应的偏移和大小

这就是我上面提到的那个问题,函数数据的size确定问题,我现在的方法是:直接断定pSymbol所在节从pSymbol->Value偏移处开始到节结束都是pSymbol所对应的函数数据,但如果一个节中包含多个函数数据,这种方法就有问题了,现在的一些测试还没遇到问题。但这种方法显然不严谨,《PE COFF文件规范》里提到一种:

“5.5.1 辅助符号表记录格式之一:函数定义”;里面可以拿到size;

但悲剧的是每个函数符号后面一张辅助符号表都没有,所以这种方法流产了

我到现在也找不到好方法,望有牛人提点!

下面是具体方法:

4.根据函数符号对重定位信息进行标志,在以后检测的时候,会跳过这些信息

关于重定位信息,我是这么理解的,比如在一个函数数据里有这样一条命令

Call 0x0040124a,而obj里此数据可能是这样的Call 0x00000000,要到链接的时候,根据重定位信息再进行修订

所以我直接用0x00000000标志这里是重定位信息,以后检测的时候,直接跳过这些重定位信息,不比较。

三.自定义文件格式函数库文件(.flb)

自动义函数库文件(.flb)结构非常简单:

签名:

函数头表:

函数名称段,里面存的是所有函数名,是一张以null结尾的字符串表

函数数据段,里面存的是所有函数的二进制数据

组织函数库文件

1.定义一个全局的函数头表,在解析每个函数符号的时候,记录相应的偏移和大小

2.将所有的函数名写入一个.nam中间文件

3.将所有的函数数据写入一个.dat中间文件

4.最后修订好偏移,按照顺序将 函数头表,.nam文件内容,.dat文件内容,写入最终的flb文件中去

至此,所有解析工作完成,剩下的就是测试flb文件是否正确!

57
收藏





最新回复 (52)

1
2






1
某某 2010-6-28
18:26
3 楼

一.解析.flb文件

1.加载.flb文件

2.检测签名

3.定位函数头表

4.检测函数,只要遍历函数头表就可以了

这样就可以使用flb文件了

二.拿到函数数据

要想测试flb文件,你还得拿到函数数据,我使用的是PVDasm,下面说一下我的方法:

1. 解析PE文件,获得代码段

2. 使用反汇编引擎,PVDasm,监控Call指令(只做0xe8),获得函数数据

3. 加载相应的flb文件,检测每个获得函数数据,是否属于此flb文件中的函数

我已经把各个版本的C语言静态库都搞成相应的flb文件了,我写了几个test,(附件里都有)并和ida做过比较,占时还没发现问题,但那个函数数据size的问题,就像锅里的一坨S,请大家帮帮忙!

最后再提一下我的问题,希望有前辈指点一下!

函数数据的size确定问题,我现在的方法是:直接断定一个节中只有一个函数数据!

《PE COFF文件规范》里提到一种:

“5.5.1 辅助符号表记录格式之一:函数定义”;里面可以拿到size;

但悲剧的是每个函数符号后面一张辅助符号表都没有,所以这种方法流产了

我到现在也找不到好方法,望有牛人提点!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: