为解决易语言程序被杀毒软件误报而进行的一些不成熟的研究
作者:庄晓立 (liigo),2010/7/5
本文首发地址:http://blog.csdn.net/liigo/archive/2010/07/04/5712547.aspx
转载请注明出处:http://blog.csdn.net/liigo
易语言5.0静态编译版本发布以来,仍然有一些杀毒软件误报易语言编译的程序为病毒或木马。趁这两天周末时间,我(liigo)按照自己的一个简单到幼稚的思路,做了一些不成熟也尚未形成结论的研究。这个思路是:先用MyCCL定位特征码,然后看这个(这些)特征码位于EXE/PE文件的什么位置,如果是位于代码段(.text)中的可执行指令的话,再进一步查找这段指令来自于哪一个编译单元中的哪一个函数,最后再视情况进行相应的技术性处理,直至达到从根本上解除误报的目的。即使没有达到最终目的,如果能够大概总结出杀毒软件误报易语言程序的理由,也是不小的收获。
因为不了解、不成熟,研究需要有一些前提条件,先做如下假设:
1、多数知名杀毒软件是以特征码为主要查杀手段,修改文件特定偏移处的某段数据可以解除误报。
2、链接器(linker)生成的EXE/DLL文件中的可执行代码,全部来自外部的编译单元(.obj, .lib)。
分析易语言的静态编译链接过程,链接器使用的所有编译单元,分为以下三大部分:1、易语言编译器生成的OBJ文件(这是易语言程序的主体代码)和RES文件;2、易语言支持库的静态库(LIB文件);3、链接器自带的其它静态库(LIB文件),如C/C++基础库、MFC基础库、操作系统核心DLL的导入库(kernel32.lib, user32.lib)等。其中前两部分由易语言提供,其余由链接器生产商(如Visual Studio的生产商微软/MicroSoft)提供。
根据前面的第2条假设,以及编译链接过程的分析,得出以下推论:易语言静态编译生成的EXE/DLL文件,其中的任意一段可执行代码(X86指令集合),“必然”来自以上提到的链接器所使用的编译单元的三个部分之一。只要此推论成立,就可以追踪特征码的来源(详见下文),源于编译器则修改编译器,源于哪支持库则修改之,源于链接器自带的其它静态库则采用其它非常规手段处理。注意我在推论中使用了带引号的“必然”这个词,用“必然”是因为“依据理论推导理应如此”,加上引号则表示怀疑和否定,因为,我(liigo)暂时无法证实这个推论,更杯具的是,本文的后续进程甚至还一定程度上否定了这个推论,令我始料不及,以至无法继续深入研究。
下面顺序说说整个(应该是半个)研究流程吧。目标程序是一个使用易语言5.11正式版静态编译的空白窗口程序(EXE)(不写任何代码);杀毒软件先后使用了360和江民(升级到最新版本和最新病毒库),对目标程序都有误报。
首先是用 MyCCL 软件定位特征码,这个网上有很多教程,就不细说了,上图:
找到特征码后,看看它是在PE文件(EXE/DLL)的什么位置。
我先针对360杀毒软件找到一处特征码,位于文件偏移0x01FC处2个字节(值为 0x00,0x10),发现竟然位于PE标准代码段(.text)的段头中,再精确点就是IMAGE_SECTION_HEADER.PointerToRawData(DWORD)数据的一部分,天,这个也能做特征码(代码段数据头文件偏移为0x1000非常之普遍),先不管,随便改一个值,通过了360杀毒软件检测,不再误报了。可是这个360的特征码不是代码段中的可执行代码,无法追踪其来源。换一个江民杀毒软件,其中一个特征码定位到文件偏移0x052DEE处的24个字节(手工修改开头任意字节值均可解除误报),010 Editor中显示如下:
OllyDbg中看到的反汇编指令如下:
下面追踪特征码来源,本次研究的重头戏。
根据本文前面的推论,代码段中的特征码,应该来源于链接器所使用的某个.obj或.lib文件中。都是哪些文件呢,前面都已经分成三大块一一指出了。我用易语言编写了一个特征码扫描程序,去所有这些LIB和OBJ文件中逐一扫描特征码,如果找到则记录其所在LIB/OBJ文件及文件偏移,以便进一步追踪来源(定位到其所属函数)。由于特征码里面的可执行代码中可能存在需要重定位的地址或相对地址(如前面特征码中文件偏移0x052DFE处E8字节后面的四个字节),不一定与LIB/OBJ中的代码完全一致,扫描程序中已经对此做了过滤处理,以确保精确追踪定位特征码。哎,找到一个,在LIB文件GLAUX.lib中:
后来证实GLAUX.lib并未参与链接,因为把我它删除或重命名也能链接成功。除此之外,我的扫描程序没有在其它所有可能的LIB/OBJ文件中找到“确认在EXE代码段出现过的”这段特征码!所以结果是令人遗憾的。我至今依然疑惑,这段代码源于何处?难道是链接器(linker)自己生成的(优化整合代码)?还是我扫描时漏掉了某些LIB/OBJ文件(核心库以外的支持库LIB文件因确认未用没包括在内,链接器调用外部程序(CVTRES.EXE)从RES文件生成的OBJ文件因无可执行代码没包括在内)?扫描程序自身的BUG?虽然无法排除这种可能性,但可能性应该很小,因为有过仔细测试。这段特征码中有一个函数调用,去扫描那个函数体的头部代码段,也没有追踪到其来源LIB/OBJ。奇怪,怎么会这样?怎么会是这个结果?为什么?……
2010/7/8 02:30 续:
失误,失误,上次的失误,搜索时竟然漏掉了MFC的静态库!哈哈,这次补上之后终于找到了“罪魁祸首”,NAFXCW.LIB(同时发现同样包含相同特征码的LIB还有MFCS42.lib和UAFXCW.lib,已确认未参与链接):
我(liigo)会继续这项工作,按原计划下一步将找到这段特征代码来自NAFXCW.lib中的哪一个函数。敬请期待。
2010/7/11 0:05 续:
下面附上搜索定位特征码的核心源代码,使用易语言编写:
遍历所有LIB文件(主要是链接器的lib目录和易语言的static_lib目录),读取文件内容,并循环调用以上函数即可,非常之简单,代码就不贴了。
2010/7/12 续:
全文完。后续研究请看下一篇:在静态库LIB/OBJ文件中搜索定位病毒特征码所属函数,C/C++源码。