C++程序经常大量地使用STL,这可以使得代码更加简洁和高效。对于反编译器来说,必须能有效地识别这些STL.否则一段使用STL的简单代码能被反编译成一大段代码,代码的膨胀率急剧上升。
IDA Pro的反编译插件hex_rays在有符号信息的是很好可以识别出STL,但没有符号信息的时候,则无法识别。STL的识别跟C语言库函数的识别不一样。C语言库函数是以二进制代码的方式包含在调用者的函数中。该二进制代码是不变的。因此,对C语言库函数的识别只需要解析相应的库文件,然后进行机器码匹配就能识别。技术难度低。
而没有符号信息的STL识别,难度非常大,主要体现在三方面。
1. C++ STL是一个编译时库,直接以源代码而非二进制代码的方式,将模板类或者模板函数提供给编译器及逆行类似宏的预编译。不同的编译器以及不同的编译选项组合都能产生不同的机器码。
2. 不同的C++STL版本对同个模板函数的具体实现不一样。因此在相同编译器和优化选项组合下编译出来的机器码也不一样。当前的C++STL版本主要有HP STL, SGI STL, STLport等等。
3. C++ STL是模板类和模板函数的集合。每个模板可以接收不同类型的参数。不同的参数类型,在相同编译器和相同的编译选项组合下可以编译出来的机器码也不一样。
也就是说,C++STL在不同的编译器、不同的优化选项组合,不同版本的STL和不同的参数类型下,所产生的机器码是不一样的。因此靠简单的机器码是无法识别出来的。
本文采用公有签名的方法进行机器码的匹配。所谓公有签名指的是提取同个模板函数在不同参数类型下所生成的机器码的共有部分,并以此为签名,进行机器码匹配。与被识别函数的机器码进行比对,若公有签名的信息全部包含在这个函数的机器码中,则认为该函数是这个共有签名对应的STL信息。
使用以上方法生成的公有签名可以识别大部分C++STL,但有一定的签名冲突率。下图是一个签名有冲突的C++STL模板类函数。
签名冲突解决方法。扩展签名格式,由公有机器码和被调用函数的签名,组合起来,能大大降低签名冲突率,如下图所示:
结束。