在我们以下的讨论中,你需要去准备一些东西,首先去下载一个开发环境识别工具,比如 PEID ,或者是FI也可以。
然后你需要下载一个反汇编工具,SoftICE\OllDbg\W32dsm,只要其中一个就可以了,我就以W32dsm为例吧。
然后你需要一个VC++6.0来编译《躲弹高手》,我们还会用到VC的其他功能。
现在开始。
一个执行程序在编译后,不同的编译器的处理都不同,而且他们都会留下自己特有的信息。
总 的来说,区别较大的地方在程序的入口,现在我们来看看一个典型MFC工程编译后的执行入口是个什么模样,我们以茂叶的程序为例,我们先用VC编译这个游 戏,注意,不要用静态编译方式,因为超过100K论坛是不允许上传的,所以我用的是共享方式编译的,如果你能理解今天的讨论话题,你可以自己用静态编译方式去做一个。
然后用W32dsm打开yzm3.exe,在208行有我们感兴趣的信息:
+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object .text **************
Program Entry Point = 00401F1C (yzm3.exe File Offset:00004F1C)
这里告诉我们程序入口在00401F1C地址处,我们去看看:
//******************** Program Entry Point ********
:00401F1C 55 push ebp
:00401F1D 8BEC mov ebp, esp
:00401F1F 6AFF push FFFFFFFF
:00401F21 6840374000 push 00403740
看,这就是VC6.0的入口代码。
这个就是 PEID 这类的程序分析的重要依据。
现在我们开始来欺骗它。
先用16进制编辑器打开yzm3.exe,我喜欢用VC6,尽管我知道很多工具的16进制编辑功能比VC强大。(大家不要骂我老土,而应该去容忍我,而且在后面的讨论中,大家要把容忍我作为自己的习惯。^o^)
用VC打开yzm3.exe,注意打开方式是二进制。
然后我们找个大片全0的地方,这样地方是程序的多余空间,最好找个地址容易记住的。就2200处吧,然后我们在这里敲入机器代码 E9 17 FD FF FF。
然后 0 00 00 00 00 00 20 00 00 60
这是什么意思呢?大家都知道,一个程序在内存中的结构按作用分有四个段区,分别是数据区、代码区、堆区和栈区,数据区用户存放全局变量,代码区用来存放程序的代码,堆区用来动态内存分配(就是new出来的东西啦),栈区用来存放局部变量。
而这些信息都会预先存放在可执行的文件里,也是按照分区分片的管理方式,把各类信息分门别类地存放起来。
但是,系统并不能预先知道你的数据在程序运行的过程中会会起到什么作用,所以他不能按照数据区、代码区、堆区和栈区这样的区分方式。
对于系统来说,你的数据只有:可读、可写、可执行、可共享访问...等属性,系统不会过问你的数据用来做什么。
所以,我们的代码的属性默认就是可读可执行的,而全局变量数据的属性默认就是可读可写的。
在程序被装载的时候,系统会先按照这些属性把内存开出来,然后把你的数据填写到相应的地方去。
这个分区有个学名,叫做“节区”(Section)。
所有不同属性的节区信息都会被统一管理,这些信息都存放在节表(Sections Table)里。
而我们刚才看到的那些数据就是在节表里的一条记录,这些记录都像数组一样的连续存储的。
其中,2E 74 65 78 74 00 00 00 是节名称,名叫".text",这个节里面存放的就是程序的代码段,节名不超过8字节。
接下来的 E2 11 00 00 是有效数据的长度,
接下来的 00 10 00 00 是节区在内存里的偏移地址,
接下来的 00 20 00 00 是这个节区在文件中的size,
接下来的 00 10 00 00 是节区在执行文件中的偏移地址,
接下来的三个 00 00 00 00 是在obj文件里使用的,还有记录行号供调试使用,
最后的 20 00 00 60 就是节的属性了,这里的属性表示可读、可执行,是代码段啦。
根据有效数据的长度和节区在执行文件中的偏移地址,我们可以计算出有效的代码在执行文件里的范围,起始地址在1000处,末尾地址在 起始地址 + 有效数据的长度 = 21E2。
现在我们的问题就浮出水面了,我伪造的入口在2200处,也写了代码,但是在节表的记录的信息代码范围不超过21E2,虽然操作系统不处理这个溢出问题,但是PEID发现了这个矛盾,从而就报告出了 Not a valid PE file。
那么我们可以开始解决问题了,我决定,把有效数据的长度修改成节区的size。也就是说,整个节区里的数据都是有效的,任何个人和团体都不得以任何形式挪用我们的空间。
定位到文件地址1E8处,将 E2 11 00 00 修改为 00 20 00 00,保存。这样整个节区里的数据都是有效的了。
运行看看,OK,一切正常。用PEID看看,他报告“tElock V0.99-1.0”。呵呵,终于搞错了吧。
用FI看看,他倒圆滑,报告说这是个 Win GUI 程序....
接下来我们的目标升级了,我要把这个程序伪造成为Delphi,和所有的识别软件开个玩笑。
手敲酸了,休息,我把伪造成为 Borland Delphi 3.0 的 yzm3.exe 程序先放出来,有兴趣的朋友可以先去研究研究。
预知后事如何,请听下回分解。
伪造成为 Borland Delphi 3.0 的 yzm3.exe
我们更改程序入口,修正节区长度后,PEID和FI两个开发环境识别软件纷纷落马,PEiD说是tElock V0.99-1.0(壳),而Fi说这是个 Win GUI 程序, 这个....说了和没说一样。
现在我们有目的有方向地去欺骗识别软件,我们的目标是让PEiD等软件将茂叶同志的VC程序识别成 Borland Delphi 3.0。
现在的识别软件去判断一个应用程序的开发环境主要依据3个地方:
1, 代码入口
2, 可执行文件(PE)结构中的链接器版本
BYTE MajorLinkerVersion BYTE MinorLinkerVersion 3, 特征码, 对于Delphi, 把特征码定位在CODE节里, 这里是Delphi的支持库代码。不同的Delphi版本,对应的特征码不同。
我们先来看看典型的 Delphi 程序入口的样子,以某个游戏程序为例。^_^ (责任编辑:科锐软件教育机构) |