黑客免杀攻防


黑客免杀攻防 任晓珲 著 文前.indd 1 2013-9-16 10:05:25 图书在版编目(CIP)数据 黑客免杀攻防 / 任晓珲著 . —北京:机械工业出版社,2013.10 ISBN 978-7-111-44042-0 Ⅰ. 黑… Ⅱ. 任… Ⅲ. 计算机网络 – 安全技术 Ⅳ. TP393.08 中国版本图书馆 CIP 数据核字(2013)第 218041 号 版权所有 • 侵权必究 封底无防伪标均为盗版 本书法律顾问 北京市展达律师事务所 国内首部关于黑客免杀技术的专著,旨在为反病毒工程师剖析各种恶意软件和应对各种安全威胁提 供全面指导。不仅从攻击者(黑客)的视角全方位揭示了黑客免杀技术的常用方法、常用技术和思想原 理,还从防御者(反病毒工程师)的视角深入讲解了遏制免杀技术的具体方法策略。从纯技术的角度讲, 本书不仅详细讲解了免杀技术的各种细节和方法,还详细讲解了 PE 文件、逆向工程、C++ 壳的编写、 免杀壳的打造、脱壳、Rootkit 等安全技术的细节。 全书共 20 章,分为三大部分 :基础篇(第 1~6 章)详细介绍了黑客免杀技术的初级技巧,包括查 找(修改)特征码、常见特征码绕过技巧、壳在免杀中的应用、花指令和其他免杀基础知识;高级篇(第 7~16 章)深入讲解了 PE 文件、逆向工程、C++ 壳的编写、免杀壳的打造、脱壳、Rootkit 等常用安全技 术的原理和细节,以及黑客免杀技术是如何应用它们的,为反病毒工程师应对各种恶意软件提供了原理 性指导;扩展篇(第 17~20 章)为遏制黑客免杀技术提供了思路和具体的方案。 机械工业出版社(北京市西城区百万庄大街 22 号  邮政编码 100037) 责任编辑:孙海亮 印刷 2013 年 9 月第 1 版第 1 次印刷 186mm×240 mm • 29.25 印张 标准书号:ISBN 978-7-111-44042-0 定  价:89.00 元 凡购本书,如有缺页、倒页、脱页,由本社发行部调换 客服热线:(010)88378991 88361066 投稿热线:(010)88379604 购书热线:(010)68326294 88379649 68995259 读者信箱:hzjsj@hzbook.com 文前.indd 2 2013-9-16 10:05:25 前  言 为什么要写这本书 计算机安全领域最初且规模最大的博弈莫过于病毒与反病毒的博弈,这也是计算机安全 领域的硝烟燃起之处。然而,我们当中的有些人可能并不知晓黑客免杀技术现今已经成为反 病毒领域中的主要破坏力量,而究其原因,也许是由此技术带来的大规模病毒木马泛滥与黑 客免杀技术本身的隐蔽性所导致的。 但是很幸运,您手中的这本书就是迄今为止第一本详细介绍免杀技术的图书,您和我都 应为此而感到庆幸。 2008 年 2 月,我应邀与《黑客 X 档案》杂志的主编一起策划了《黑客免杀入门》的 编写工作。《黑客免杀入门》就是本书的雏形,那真的是一个很好的开始。当时还在上大一 的我为了使这本书能够快速上市,几乎牺牲了所有课余时间。在经过半年的艰苦写作之后, 《黑客免杀入门》终于在 2008 年 10 月正式上市,并在半年内创下了 5000 册销量的佳绩。 但是由于种种原因,使得我对自己的第一本书并不满意,因为要考虑到初学者的接受力 与知识储备,因此并未将黑客免杀技术的真正意义体现在那本书里,再加之免杀技术在第一 本书发行后的几年里发生了很大变化,因此使我有了编写第二本书的动力。 如何阅读本书 本书详细描述了 Windows 系统下黑客免杀的所有技术细节,讲解了为什么病毒、木马在 经过免杀处理后就会被反病毒软件误认为是正常的程序。除此之外,本书还详细讲述了黑客 文前.indd 3 2013-9-16 10:05:26 IV 与反病毒工程师都应该掌握的基础知识,包括 PE 文件结构、软件逆向工程、壳的原理及编 写思路、Rootkit 等等。在最后,笔者总结了一些遏制免杀技术的方法以及应对策略,相信对 于很多反病毒工程师来讲都会有所启发。 本书共分为基础篇、高级篇与扩展篇三大部分,分别面向的是零基础读者、高级读者与 反病毒工程师,要完全掌握这三部分,所需的基础知识如下: 基础篇 其中所有内容几乎都未过深涉及任何计算机语言,因此只要能熟练操作 Windows 系统,并对硬件有基本的常识性认识,即可顺利阅读这部分内容,除此之外不再需 要读者有任何基础。 高级篇 要求读者对于 C/C++、汇编语言有基本的了解,并且要有一定的 Windows 程 序开发经验,除此之外也需要读者对操作系统的结构有所了解。 扩展篇 要求读者熟悉黑客免杀的技术细节,并初步掌握 PE 文件结构、软件逆向工程、 壳的原理及编写思路、Rootkit 等高端技术。 本书的主要内容 基础篇 包括第 1 章~第 6 章,这部分由第 1 章“变脸”开篇,以类比的形式将黑客免 杀技术的特点向大家娓娓道来,随后通过对免杀基础知识的介绍,可以迅速让初级读者彻底 明白何为黑客免杀技术。 待初级读者理解了何为免杀技术后,随后的几个章节则以比较简单易懂的语言向大家描 述与黑客免杀技术密切相关的一些技术,例如特征码、花指令、壳等等。 高级篇 包括第 7 章~第 16 章,这部分所讲的内容都是黑客们得以展开较高层面免杀 操作的技术基础,同时也是反病毒工程师与大部分软件安全行业从业者必备的技术基础。 本篇详细地阐述了 Windows 下的 PE 文件结构,并着重讲解了软件逆向工程的技术原理 与分析思路。除此之外,第 11 章还在纯 C++ 语言的角度描述了一个壳的编写,这在国内来 说尚属首次。在本篇的最后,还详细介绍了部分 Rootkit 技术的实现原理与当前黑客免杀技 术的最前沿思想。 扩展篇 包括第 17 章~第 20 章,这部分主要针对当下的免杀技巧及黑客常用的免杀手 法提出了一些反制措施,分别对反特征码定位、遏制 Rootkit 展开了讨论,并在最后对时下 的反病毒产品简略地给出了一些改进建议。 这正是那酝酿三年的 2.0 版 现在您拿在手里的这本书是以《黑客免杀入门》的部分内容为基础,加入大量新鲜内容 后重新组织、编排的一个全新版本,这本书真正考虑到了免杀技术的广度与深度,采用了知 识层次分离编写的方式,以求照顾到高中低各层次的绝大多数读者。 文前.indd 4 2013-9-16 10:05:26 V 深广结合,高低分离 本书的全部内容分为三个部分,其中每个部分都相对独立、互成体系,分别面对不同层 次的读者。对于基础知识的讲解主要集中在前两部分,第一部分只对相关知识进行了解性讲 解,其难度以满足阅读第一部分内容所需的知识储备为标准。第二部分对免杀的所有技术细 节进行了细致深入的讲解,可看作是第一部分的延伸与拓展。 分解难点,注重延续 第一部分的阅读基础大致定位在非专业人士的层次上。因此为了照顾这部分读者的后续 学习能力,对每个重点、难点都进行了相应的拆分讲解,并以第二部分的部分内容作为扩展 阅读资源,使得初级读者的技术飞跃成为可能。 增新改旧,重排章节 本书新增了大量的技术描述,例如 PE 文件结构、壳的编写技术、Rootkit 技术等,同时 删除了第一版中关于突破主动防御的章节并重新整理编写。除此之外,对于其他章节也进行 了大量的重写与更新,这些更新使得第一版保留下来的内容不超过 10%。 本书的读者 第一篇对应的为初级层次的读者,如果你已经有了一定的基础,且对黑客免杀技术有了 一定的了解,可跳过本部分。适合阅读本部分的读者如下: 黑客技术爱好者 ❑ 信息安全专业的学生 ❑ 想了解黑客免杀技术的初学者 ❑ 第二篇对应的为中级层次的读者,如果你已经对 PE 文件、软件逆向、壳的编写、 Rootkit 有了较为深入的了解,可跳过本部分。适合阅读本部分的读者如下: 软件安全爱好者 ❑ 想系统学习 PE 文件结构的人 ❑ 需要快速掌握软件逆向技术的相关工作人员 ❑ 想用 C++ 写壳的技术狂人,或仅想写一个壳的爱好者 ❑ 对于 Rootkit 感兴趣的人 ❑ 第三篇对应的为高级层次的读者,此部分内容并没有具体的技术细节,着重讲解了相关 技术的核心思想,适合具备一定基础的人阅读: 反病毒工程师 ❑ 免杀技术爱好者 ❑ 勘误和支持 本书从创意到落实写作,再到最终完成,整整度过了三年的时间,其中有足足两年的时 文前.indd 5 2013-9-16 10:05:26 VI 间是用于本书的写作,这是我用人生最精彩的一段时间撰写的一本书,因此也期望这本书能 同样精彩。 但是,事实总是残酷的,由于本人的水平有限,而且感觉两年的时间还是太少了,书中 难免还会有一些不足。记得俄罗斯的“斯坦尼斯拉夫斯基”用了一生的时间才写出了《演员 的自我修养》这本书,这是没有认真写书经历的人难以体会的。 我是一个不愿妥协的人,在撰写本书之初就是如此,但是很不幸的是我还是一次次地被 残酷的事实打败。在我与之对抗了两年之后,才感觉这本书可以拿出来见人了,我承认它离 完美还有相当长的一段距离。 这本 40 余万字的图书是我目前为止做过的最大的一个“工程”,我承诺会在精力允许的 前提下,在本书出版之前不放弃任何一次修正本书错误的机会,但是我知道它最终还是会带 着若干错误与读者们见面,请原谅我无法修复这些错误,这有可能是我的精力问题,也有可 能是我的能力问题。但是,我非常期望能收到您的来信,指导我修正本书中的错误,为这本 书走向完美“添砖加瓦”。 为此,我在黑客反病毒论坛中建立了一个专门的分区来处理本书中的所有问题,包括读 者反馈、勘误列表与本书的相关资源下载,本书的交流专区 :http://book.hackav.com/。本书 相关资源还可到华章官网下载,华章的官网:http://www.hzbook.com/。 除此之外,您还可以通过邮件与我取得联系,我的邮箱 :0x0026@gmail.com、a1pass@ 163.com。 特别致谢 首先请允许我借此机会感谢我的父母在事业上、写作上以及生活上对我的支持与关爱, 我因拥有你们的爱而变得更加坚强与勇敢,我的所有荣耀都属于你们。 其次,尽管只有我的名字被印在了本书的封面上,但是您手中的这本 40 余万字的书显 然不是一个人的工作成果,本书的顺利出版得益于众多朋友的鼎力相助。在此,我要感谢那 些在我写作的过程中为我提供过帮助的人。 钱林松 感谢您将我引荐给杨福川,这使得我有了完成自己写作梦想的机会。 薛亮亮 我的创业伙伴,没有你的理解与担当就不可能有这本书的面世。 黄 瀚 为本书提供了大量一手资料,感谢你一直以来对于本书的关注与支持。 段 刚 段老师预读了本书的部分章节,并对本书的定位提出了很多特别好的建议。 李常坤 审阅了本书的第 11 章和第 12 章,并提出了宝贵建议。 卢超超 在本书的定位方面及前期的策划时发挥了重要作用,并在初期提出了宝贵建议。 彭燕青 对第 14 章和第 15 章的编写提供了宝贵的技术方面的建议。 许晓明 审阅了本书的第 7 章和第 9 章,并修改了一些技术上的错误。 吴 彬 在写作初期向我详细阐述了反病毒工程师的各个工作流程。 全珠荣 为本书提出了不错的建议,感谢你在写作上对我的帮助。 文前.indd 6 2013-9-16 10:05:26 VII 杨福川 首席策划,感谢您在整本书的写作期间所做的大量协调工作。 孙海亮 我的编辑,感谢您对本书的审校工作,您的敏锐思维能力让我很欣赏。 杨绣国 我的编辑,十分细心地审阅了本书的大部分章节,感谢您对此做出的工作。 白 宇 我的编辑,帮我熟悉了整套图书出版的流程,感谢您的帮助。 最后,感谢北京蓝森科技有限公司的所有同事,这本书的顺利出版离不开你们的理解 与支持,是你们在我写作的过程中为我承担了大部分的工作。另外,感谢黑客反病毒组织 (www.hackav.com)中对本书提出过宝贵意见的所有网友,是你们的投票保证了本书内容安 排的合理性。 任晓珲 于北京 文前.indd 7 2013-9-16 10:05:26 目  录 前言 基础篇 初级免杀技术 第 1 章 变脸 ························································································································· 2 1.1 为何变脸 ················································································································ 2 1.2 何为变脸 ················································································································ 3 1.3 免杀的发展史 ········································································································ 3 1.4 免杀技术的简单原理 ···························································································· 4 1.5 免杀与其他技术的区别 ························································································· 5 1.5.1 免杀不是 Rootkit 技术 ··············································································· 5 1.5.2 免杀不是加密解密技术 ············································································· 5 1.6 小结 ························································································································ 6 第 2 章 免杀基础知识 ········································································································· 7 2.1 如何开始免杀 ········································································································ 7 2.2 反病毒软件原理与反病毒技术介绍 ····································································· 8 2.2.1 反病毒软件的工作原理 ············································································· 8 文前.indd 8 2013-9-16 10:05:26 IX 2.2.2 基于文件扫描的反病毒技术······································································ 9 2.2.3 基于内存扫描的反病毒技术···································································· 12 2.2.4 基于行为监控的反病毒技术···································································· 12 2.2.5 基于新兴技术的反病毒技术···································································· 12 2.2.6 反病毒技术前沿 ······················································································· 14 2.2.7 反病毒技术展望 ······················································································· 14 2.3 了解 PE 文件 ······································································································· 15 2.3.1 什么是 PE 文件 ························································································ 15 2.3.2 PE 文件的结构 ························································································· 16 2.4 免杀原理 ·············································································································· 17 2.4.1 文件免杀原理 ··························································································· 17 2.4.2 内存免杀原理 ··························································································· 20 2.4.3 行为免杀原理 ··························································································· 21 2.5 工具脱壳技巧 ······································································································ 21 2.5.1 壳的分类 ··································································································· 22 2.5.2 免杀与脱壳是什么关系 ··········································································· 23 2.5.3 使用专用脱壳工具脱壳 ··········································································· 24 2.5.4 使用通用脱壳工具脱壳 ··········································································· 25 2.6 小结 ······················································································································ 26 第 3 章 免杀与特征码 ······································································································· 27 3.1 特征码免杀技术 ·································································································· 27 3.1.1 理想状态下的免杀 ··················································································· 27 3.1.2 由脚本木马免杀理解特征码···································································· 28 3.2 特征码定位原理 ·································································································· 29 3.2.1 特征码逐块填充定位原理 ······································································· 29 3.2.2 特征码逐块暴露定位原理 ······································································· 31 3.2.3 特征码混合定位原理 ··············································································· 34 3.3 脚本木马定位特征码 ·························································································· 35 3.4 MyCCL 查找文件特征码 ···················································································· 39 3.4.1 MyCCL 的典型应用 ················································································· 39 3.4.2 针对 MyCCL 的一点思考 ········································································ 41 3.5 MyCCL 查找内存特征码 ···················································································· 43 3.6 特征码修改方法 ·································································································· 44 3.6.1 简单的特征码修改 ··················································································· 44 文前.indd 9 2013-9-16 10:05:26 X 3.6.2 特征码修改进阶 ······················································································· 45 3.7 小结 ······················································································································ 50 第 4 章 其他免杀技术 ······································································································· 51 4.1 修改入口点免杀 ·································································································· 51 4.2 使用 VMProtect 加密 ·························································································· 54 4.3 Overlay 附加数据的处理及应用 ········································································· 54 4.4 驱动程序免杀修改技巧 ······················································································· 55 4.4.1 驱动程序的常见免杀方法 ······································································· 55 4.4.2 驱动程序的手工免杀思路 ······································································· 56 4.5 补丁在免杀中的应用 ·························································································· 57 4.6 PE 文件进阶介绍 ································································································· 59 4.6.1 PE 文件格式 ····························································································· 60 4.6.2 虚拟内存的简单介绍 ··············································································· 62 4.6.3 PE 文件的内存映射 ················································································· 63 4.7 网页木马的免杀 ·································································································· 66 4.7.1 脚本木马免杀 ··························································································· 66 4.7.2 网页挂马的免杀 ······················································································· 77 4.8 小结 ······················································································································ 78 第 5 章 花指令与免杀 ······································································································· 80 5.1 什么是花指令 ······································································································ 80 5.2 脚本木马的花指令应用 ······················································································· 81 5.3 花指令的根基—汇编语言 ··············································································· 83 5.3.1 认识汇编 ··································································································· 83 5.3.2 通过反汇编添加任意功能 ······································································· 85 5.4 花指令入门 ·········································································································· 88 5.5 花指令在免杀领域的应用 ··················································································· 91 5.5.1 花指令的应用技巧 ··················································································· 91 5.5.2 花指令的修改技巧简介 ··········································································· 91 5.5.3 空白区域寻找与加空白区段···································································· 92 5.6 花指令的高级应用 ······························································································ 94 5.6.1 花指令的提取与快速应用 ······································································· 94 5.6.2 SEH 异常的应用 ······················································································ 96 5.7 小结 ······················································································································ 97 文前.indd 10 2013-9-16 10:05:26 XI 第 6 章 壳在免杀中的应用 ······························································································ 98 6.1 壳的基础知识 ······································································································ 98 6.2 壳在免杀领域的应用 ·························································································· 99 6.2.1 加壳的免杀原理 ····················································································· 100 6.2.2 FreeRes 多重加壳 ··················································································· 100 6.3 壳的修改技巧 ···································································································· 101 6.3.1 壳的初级修改 ························································································· 101 6.3.2 制作通用补丁 ························································································· 102 6.4 小结 ···················································································································· 107 高级篇 免杀技术进阶 第 7 章 PE 文件格式详解 ·······························································································110 7.1 MS-DOS 头 ·········································································································111 7.1.1 重要字段 ··································································································112 7.1.2 其他字段 ··································································································112 7.2 PE 文件头 ···········································································································113 7.2.1 Signature 字段 ·························································································113 7.2.2 IMAGE_FILE_HEADER 结构 ································································113 7.2.3 IMAGE_OPTIONAL_HEADER 结构(x86/x64) ··································115 7.2.4 数据目录表 ······························································································118 7.3 区段表 ·················································································································119 7.3.1 IMAGE_SECTION_HEADER 结构 ·······················································119 7.3.2 区段名功能约定 ····················································································· 121 7.3.3 区段对齐详解 ························································································· 122 7.3.4 地址转换 ································································································· 123 7.4 导出表 ················································································································ 123 7.4.1 IMAGE_EXPORT_DIRECTORY 结构 ·················································· 123 7.4.2 识别导出表 ····························································································· 124 7.5 导入表 ················································································································ 127 7.5.1 IMAGE_IMPORT_DESCRIPTOR 结构 ················································ 128 7.5.2 识别导入表 ····························································································· 130 7.6 资源 ···················································································································· 132 7.6.1 资源结构 ································································································· 132 7.6.2 识别资源 ································································································· 135 文前.indd 11 2013-9-16 10:05:27 XII 7.7 异常 ···················································································································· 137 7.8 安全 ···················································································································· 139 7.8.1 安全目录结构 ························································································· 139 7.8.2 识别安全结构 ························································································· 140 7.9 基址重定位 ········································································································ 141 7.9.1 基址重定位表结构 ················································································· 141 7.9.2 识别基址重定位表 ················································································· 143 7.10 调试 ·················································································································· 146 7.11 特殊结构数据(版权) ····················································································· 147 7.12 全局指针 ·········································································································· 147 7.13 TLS ·················································································································· 148 7.13.1 TLS 的回调函数 ··················································································· 149 7.13.2 TLS 的结构(x86/x64) ········································································ 151 7.13.3 识别 TLS ······························································································ 152 7.14 载入配置(x86/x64) ······················································································· 153 7.15 绑定导入表 ······································································································ 155 7.15.1 绑定导入表结构 ··················································································· 155 7.15.2 识别绑定导入表 ··················································································· 156 7.16 导入地址表 ······································································································ 157 7.17 延迟加载表 ······································································································ 157 7.17.1 延迟加载表结构 ··················································································· 158 7.17.2 识别延迟加载表 ··················································································· 159 7.18 COM 描述符 ···································································································· 159 7.19 小结 ·················································································································· 159 第 8 章 PE 文件知识在免杀中的应用 ·········································································· 161 8.1 PE 文件与免杀思路 ··························································································· 161 8.1.1 移动 PE 文件头位置免杀 ······································································· 161 8.1.2 导入表移动免杀 ····················································································· 163 8.1.3 导出表移动免杀 ····················································································· 165 8.2 PE 文件与反启发式扫描 ··················································································· 165 8.2.1 最后一个区段为代码段 ········································································· 165 8.2.2 可疑的区段头部属性 ············································································· 166 8.2.3 可疑的 PE 选项头的有效尺寸值 ··························································· 166 8.2.4 可疑的代码节名称 ················································································· 166 文前.indd 12 2013-9-16 10:05:27 XIII 8.2.5 多个 PE 头部 ·························································································· 166 8.2.6 导入表项存在可疑导入 ········································································· 167 8.3 一个稍显复杂的例子—隐藏导入表 ····························································· 167 8.3.1 操作原理与先决条件 ············································································· 167 8.3.2 修改 PE 文件 ·························································································· 168 8.3.3 构造我们的反汇编代码 ········································································· 168 8.4 小结 ···················································································································· 169 第 9 章 软件逆向工程 ····································································································· 170 9.1 准备工作 ············································································································ 170 9.1.1 要准备的工具及基础知识 ····································································· 171 9.1.2 程序是从哪里开始运行的 ····································································· 171 9.2 一个简单的小例子 ···························································································· 177 9.3 函数识别初探 ···································································································· 179 9.4 if-else 分支 ········································································································· 185 9.4.1 以常量为判断条件的简单 if-else 分支 ·················································· 185 9.4.2 以变量为判断条件的简单 if-else 分支 ·················································· 186 9.4.3 以常量为判断条件的复杂 if-else 分支 ·················································· 188 9.4.4 以变量为判断条件的复杂 if-else 分支 ·················································· 189 9.4.5 识别三目运算符 ····················································································· 190 9.5 循环分支 ············································································································ 194 9.5.1 do-while 循环 ························································································· 194 9.5.2 while 循环 ······························································································· 196 9.5.3 for 循环 ··································································································· 199 9.5.4 循环体的语句外提优化 ········································································· 202 9.6 switch-case 分支 ································································································ 203 9.6.1 简单 switch-case 分支识别技巧 ····························································· 203 9.6.2 复杂分支的 switch-case 识别 ································································· 208 9.6.3 switch-case 分支结构与稀疏矩阵 ·························································· 210 9.6.4 switch-case 分支结构与平衡二叉树 ······················································ 215 9.7 加法与减法的识别与优化原理 ········································································· 220 9.7.1 加法的识别与优化 ················································································· 221 9.7.2 减法的识别与优化 ················································································· 223 9.8 乘法与除法的识别与优化原理 ········································································· 224 9.8.1 乘法的位移优化 ····················································································· 224 文前.indd 13 2013-9-16 10:05:27 XIV 9.8.2 乘法的 lea 指令优化 ·············································································· 225 9.8.3 除法与倒数相乘 ····················································································· 228 9.8.4 倒数相乘与定点运算的配合·································································· 229 9.8.5 除法运算的识别与优化 ········································································· 230 9.8.6 取模运算的识别与优化 ········································································· 236 9.9 指针与数组 ········································································································ 238 9.9.1 指针与数组的渊源 ················································································· 238 9.9.2 数组的不同表达方式 ············································································· 242 9.10 数组、结构体与对象 ······················································································ 243 9.10.1 数组与结构体 ······················································································· 243 9.10.2 结构体与类 ··························································································· 245 9.11 变量作用域的识别 ·························································································· 245 9.12 识别构造与析构函数 ······················································································ 247 9.12.1 快速识别出类 ······················································································· 248 9.12.2 识别构造函数 ······················································································· 252 9.12.3 识别析构函数 ······················································································· 253 9.13 虚函数与纯虚函数的识别 ··············································································· 254 9.13.1 识别简单的虚函数 ··············································································· 254 9.13.2 识别较复杂的虚函数 ··········································································· 260 9.14  正确识别类的继承关系 ·················································································· 275 9.15 最后一役 ·········································································································· 290 9.15.1 MFC 逆向初探 ····················································································· 291 9.15.2 分析 BypassUAC.exe ··········································································· 292 9.16 小结 ·················································································································· 301 第 10 章 源码级免杀 ······································································································ 302 10.1 怎样定位产生特征的源代码 ··········································································· 302 10.1.1 定位文件特征 ······················································································· 302 10.1.2 定位行为特征 ······················································································· 304 10.2 基于源码的特征修改 ······················································································ 304 10.2.1 变换编译器与编译选项 ······································································· 304 10.2.2 添加垃圾代码 ······················································································· 305 10.2.3 语法变换 ······························································································· 306 10.2.4 添加汇编花指令 ··················································································· 306 10.3 小结 ·················································································································· 307 文前.indd 14 2013-9-16 10:05:27 XV 第 11 章 详解 C++ 壳的编写 ························································································· 308 11.1 了解壳的运行流程 ·························································································· 308 11.2 设计一个纯 C++ 编写的壳 ·············································································· 309 11.2.1 用 C++ 编写的壳应该是什么样的 ······················································· 310 11.2.2 编写过程中会遇到的问题 ···································································· 310 11.3 用 C++ 写一个简单的壳 ···················································································311 11.3.1 配置工程 ······························································································· 312 11.3.2 编写 Stub 部分 ······················································································ 314 11.3.3 编写加壳部分 ······················································································· 318 11.3.4 编写界面部分 ······················································································· 325 11.4 设计一个由 C++ 编写的专业壳 ······································································ 326 11.4.1 为问题找到答案 ··················································································· 326 11.4.2 设计专业壳的框架 ··············································································· 329 11.4.3 如何设计 Stub 部分 ·············································································· 330 11.4.4 如何设计加壳部分 ··············································································· 331 11.4.5 需要注意的细节问题 ··········································································· 334 11.5 怎样调试由 C++ 编写的 Stub 部分 ································································· 334 11.6 小结 ·················································································································· 335 第 12 章 黑客是怎样打造免杀壳的 ·············································································· 336 12.1 免杀壳与加密壳的异同 ··················································································· 336 12.2 导入表加密 ······································································································ 337 12.3 代码混淆与代码乱序 ······················································································ 337 12.4 附加驱动 ·········································································································· 338 12.5 小结 ·················································································································· 339 第 13 章 脱壳技术 ·········································································································· 340 13.1 寻找 OEP ········································································································· 340 13.1.1 利用内存断点 ······················································································· 340 13.1.2 利用堆栈平衡 ······················································································· 342 13.1.3 利用编译语言特点 ··············································································· 343 13.1.4 利用跨区段跳转 ··················································································· 345 13.2 转储内存映像 ·································································································· 346 13.3 重建导入表 ······································································································ 346 文前.indd 15 2013-9-16 10:05:28 XVI 13.3.1 导入表重建原理 ··················································································· 347 13.3.2 使用 ImportREC 重建导入表 ······························································· 347 13.4 小结 ·················································································································· 348 第 14 章 Rootkit 基础 ····································································································· 349 14.1 构建一个 Rootkit 基础环境 ············································································· 349 14.1.1 构建开发环境 ······················································································· 349 14.1.2 构建基于 Visual Studio 2012 的调试环境 ··········································· 350 14.1.3 构建基于 WinDbg 的调试环境 ···························································· 354 14.1.4 将 Rootkit 加载到系统 ········································································· 356 14.1.5 创建一个简单的驱动并调试 ································································ 357 14.2 何为 Ring0 层 ·································································································· 360 14.3 关键表 ·············································································································· 361 14.4 内存分页 ·········································································································· 362 14.4.1 地址转译 ······························································································· 363 14.4.2 内存访问检查 ······················································································· 367 14.4.3 Windows 对重要表的保护 ··································································· 368 14.5 内存描述符表 ·································································································· 369 14.6 中断描述符表(IDT) ······················································································ 369 14.7 系统服务调度表 ······························································································ 371 14.8 控制寄存器 ······································································································ 371 14.8.1 利用 CR0 禁用内存保护机制 ······························································ 371 14.8.2 其他控制寄存器 ··················································································· 372 14.9 小结 ·················································································································· 372 第 15 章 Rootkit 在免杀中的应用 ················································································ 373 15.1 用户模式 Rootkit ····························································································· 373 15.1.1 DLL 远程注入技巧 ·············································································· 373 15.1.2 内联钩子 ······························································································· 375 15.1.3 导入地址表钩子 ··················································································· 375 15.1.4 一个保护文件不被删除的例子 ···························································· 376 15.2 内核编程基础 ·································································································· 377 15.2.1 内核编程环境与用户层编程环境的异同 ············································ 377 15.2.2 如何选择 Windows 驱动开发模型······················································· 378 15.2.3 驱动设备与请求处理 ··········································································· 378 文前.indd 16 2013-9-16 10:05:28 XVII 15.2.4 内核编程中的数据类型 ······································································· 386 15.2.5 函数调用 ······························································································· 387 15.2.6 Windows 内核编程的特点 ··································································· 389 15.3 内核模式 Rootkit ····························································································· 390 15.3.1 SYSENTER 钩子 ·················································································· 390 15.3.2 SSDT 钩子 ···························································································· 394 15.3.3 内联钩子 ······························································································· 399 15.3.4 IRP 钩子 ······························································································· 401 15.3.5 LADDR 钩子 ························································································ 406 15.3.6 IDT 钩子 ································································································411 15.3.7 IOAPIC 钩子 ························································································ 413 15.4 小结 ·················································································································· 417 第 16 章 免杀技术前沿 ·································································································· 418 16.1 免杀技术的发展趋势 ······················································································ 418 16.2 免杀前沿之突破主动防御 ··············································································· 419 16.2.1 “移花接木”之屏幕截图突破主动防御 ·············································· 419 16.2.2 “暗渡陈仓”之利用可信进程突破主动防御 ······································ 419 16.2.3 “釜底抽薪”之利用系统进程突破主动防御 ······································ 420 16.2.4 “顺手牵羊”之利用逻辑漏洞突破主动防御 ······································ 420 16.2.5 “浑水摸鱼”之利用变形复制突破主动防御 ······································ 420 16.2.6 “金蝉脱壳”之利用异同逃逸虚拟机 ·················································· 420 16.2.7 “借尸还魂”之利用替换文件突破主动防御 ······································ 421 16.2.8 “借刀杀人”之利用调试接口突破主动防御 ······································ 421 16.3 黑客免杀技术的展望 ······················································································ 421 16.4 小结 ·················································································································· 422 扩展篇 遏制免杀技术初探 第 17 章 浅谈部分免杀技巧的遏制 ·············································································· 424 17.1 盯紧 PE 文件 ··································································································· 424 17.2 盯紧程序行为 ·································································································· 425 17.3 小结 ·················································································································· 425 文前.indd 17 2013-9-16 10:05:28 XVIII 第 18 章 反特征码定位 ·································································································· 426 18.1 释放干扰码 ······································································································ 426 18.2 定位行为的判定 ······························································································ 426 18.3 设定“靶特征码” ···························································································· 427 18.4 小结 ·················································································································· 427 第 19 章 遏制免杀与 Anti Rootkit ················································································ 428 19.1 适当的监控 ······································································································ 428 19.2 基本检测逻辑 ·································································································· 428 19.3 Rootkit 检测方法初探 ····················································································· 429 19.4 小结 ·················································································································· 430 第 20 章 浅谈反病毒产品的改进 ·················································································· 431 20.1 云查杀与本地查杀紧密结合 ··········································································· 431 20.2 注重感染型病毒木马的清除工作 ··································································· 431 20.3 精进启发式扫描解决效率问题 ······································································· 432 20.4 小结 ·················································································································· 432 附录 A 80x86 汇编基础知识 ························································································· 433 文前.indd 18 2013-9-16 10:05:28 基础篇 初级免杀技术 简介: 此部分详细讲解了黑客免杀技术的初级技巧,包括查找(修改)特征码、常见特征码绕 过技巧、壳的简单利用,以及一些相关基础知识。 如果您从未了解过免杀技术,或自认为对于免杀的了解还不够充分,那么建议您通读这 部分内容。 需要前置知识: 熟悉 Windows 操作系统。 ❑ 理解计算机的基本概念,例如什么是 CPU、内存、硬盘等。 ❑ 章节预览: 第 1 章 变脸 第 2 章 免杀基础知识 第 3 章 免杀与特征码 第 4 章 其他免杀技术 第 5 章 花指令与免杀 第 6 章 壳在免杀中的应用 正文.indd 1 2013-9-16 10:06:54 第 1 章 变  脸 由尼古拉斯·凯奇主演的电影《变脸》想必大家并不陌生。通过整形手术,尼古拉 斯·凯奇扮演的警探变身为歹徒,打入匪徒内部,而那名被假冒的歹徒也使用同样的手段混 入了警署,扰乱了这名不幸警探的生活。就这样,原本十恶不赦的歹徒披着警探的“外衣” 肆意满足着自己的窥探欲,并取得了重要的信息。 1.1 为何变脸 我们都不会承认自己是窥探狂,但是我想绝大部分人都不会否认自己偶尔会有窥探他人 的想法,虽然在现实生活中并不容易做到。然而,在计算机领域中实施同样的行为则显然会 容易许多。 比如,众人皆知的后门与木马就是为了窥探并获取他人计算机中的信息而诞生的。但 是,病毒与木马永远无法得到受害者的喜爱与杀毒软件的怜悯,在大多数情况下,它们会被 无情地斩杀!当然我相信本书的读者也都希望如此。 不过这可不是攻击者所希望看到的结果,他们希望自己的木马能顺利绕过杀毒软件与防 火墙,在受害者的计算机中长期隐藏下去,并能在必要的时候向攻击者提供有用的信息。 然而事实上并没有多少木马或后门能达到这个目的,例如各位读者都熟悉的灰鸽子木 马,很显然它现在可以被任何杀毒软件发现并查杀,不过我们是否从此以后就不用再担心灰 鸽子木马了呢?对于这个问题,攻击者们用他们制造的成百上千个灰鸽子木马变种给出了清 晰的答复。 很显然,我们的威胁依然存在! 只要免杀技术在世界上存在一天,那么后门木马就不会消亡 ;免杀技术一日不消亡,木 马病毒的变种就会源源不断地出现。 不知各位读者想过没有,攻击者们是怎样制造出那么多的变种的呢?他们使用的是什么 技术?有没有什么应对方案? 这就要求我们以攻击者的角度来进行研究,这样才能更好地探求到答案。本章就以攻击 者的视角开篇,为这 3 个问题找到满意的答案。 正文.indd 2 2013-9-16 10:06:54 第 1 章 变  脸   3 1.2 何为变脸 上一节我们用变脸形象地解释了免杀技术。不知各位读者此时是否了解了何为免杀? 在国内,黑客免杀技术应该是这几年才浮出水面的,也就是说国内的免杀技术发展至 今也不过六七年。对于一个技术的发展来说,特别是对于黑客这个边缘群体里的边缘技术来 说,几年的发展时间是比较短的。 因此给一个还未成体系的技术下定义显然是比较困难的,然而我们又需要这样一个定 义,以便于对它有更清晰的了解。 很明显,免杀,也就是反病毒(Anti Virus)、反间谍(Anti Spyware)的对立面,英文为 Anti Anti- Virus(Virus AV)或 by Pass AV。逐字翻译即为“反 – 反病毒”,我们可以翻译为 “反杀毒技术”。单从汉语“免杀”的字面意思来理解,可以将其看作是一种能使病毒或木马 免于被杀毒软件查杀的技术。 笔者认为免杀技术属于信息安全领域中“病毒 / 木马技术”里的一个分支,它随着杀毒 软件的出现而诞生,并且一定是出现在杀毒软件之后的。 由此看来,免杀技术其实就是一种反杀毒技术。它除了使病毒木马免于被查杀外,还可 以扩增病毒木马的功能,改变病毒木马的行为,甚至添加 Rootkit、Anti Rootkit 代码。 然而即便如此,免杀技术也并非就是十恶不赦的,它并不总是被恶意攻击者所使用,也 有用于“正途”的时候。例如,在软件保护所用的加密产品(比如壳)中,有一些会被杀毒 软件误认为是木马或病毒;一些安全领域中使用的部分安全检测产品,也会被杀毒软件误杀。 这时就需要使用免杀技术来应对这些不稳定因素。所以说,免杀仅仅是一项技术而已,它最 终导致什么后果完全取决于使用它的人,就像冶炼、火药、核能与远程监控技术一样。 1.3 免杀的发展史 关于世界免杀技术的历史情况现在并无从考证,但从国内情况来讲它的起步可以说是非 常晚的。以下是笔者在创作《黑客免杀入门》一书时调查后总结的一份列表,出版后被百度 百科引用(但是引用内容在后期被植入了广告,请各位读者注意甄别)。 1989 年:第一款杀毒软件 Mcafee 诞生,标志着反病毒与反查杀时代的到来。 ❑ 1997 年 :国内出现了第一个可以自动变异的千面人病毒(Polymorphic/Mutation ❑ Virus)。自动变异就是病毒针对杀毒软件的免杀方法之一,但是与现在免杀手法的定 义有出入。 2002 年 7 月 31 日 :国内第一个真正意义上的变种病毒“中国黑客 II”出现,它不但 ❑ 具有新的特征,还实现了“中国黑客”第一代所未实现的功能。可见这个变种也是病 毒编写者自己制造的。 2004 年 :在黑客圈子内部,免杀技术在这一年首次公开提出,由于当时还没有 CLL ❑ 等专用免杀工具,所以一般都使用 WinHEX 逐字节更改技术。 正文.indd 3 2013-9-16 10:06:54 4   基础篇 初级免杀技术 2005 年 1 月:大名鼎鼎的免杀工具 CCL 的软件作者 tankaiha 在杂志上发表了一篇文章, ❑ 推广了 CCL 工具,从此国内黑客界才有了第一个专门用于免杀的工具。 2005 年的 2 ~ 7 月:通过各方面有意或无意的宣传,黑客爱好者们逐渐重视免杀技术, ❑ 在一些黑客站点的木马专栏下,开始有越来越多的人讨论此技术,这也为以后木马免 杀技术的火暴埋下根基。 2005 年 8 月 :第一个可查的关于免杀的教学录像诞生,为大量黑客爱好者提供了一 ❑ 个有效的参考资料,成功地对免杀技术进行了第一次科普。 2005 年 9 月:免杀技术开始被越来越多的黑客技术爱好者知晓。 ❑ 由上面的信息可见,国内在 1997 年出现了第一个可以自动变异的千面人病毒,虽然自 动变异也可以看作是针对杀毒软件的一种免杀方法,但是由于它与现在定义的免杀手法有出 入,因此如果将国内免杀技术的起源定于 1997 年会显得比较牵强。 2002 年 7 月 31 日,国内第一个真正意义上的变种病毒“中国黑客 II”的出现或可称为 免杀技术的起源,因此我们暂且将国内免杀技术起源定在 2002 年 7 月。 从国内免杀技术的发展过程来看,一直到 2005 年 9 月免杀技术才正式进入公众的视野。 但是从国外的发展来看,20 世纪 80 年代就已经出现了使用 Rootkit 反扫描技术的病毒,不 过这属于一个源码级应用的例子。而国内的病毒或木马是什么时候开始使用 Rootkit 的呢? 2003 年还是 2003 年以后的某个日子?要知道国内各大论坛普遍出现系统内核利用的文章应 该是从 2007 年~ 2008 年才开始的。 由此我们就不难发现,国内某些领域的落后可能是以年为单位计算的。但是我相信免杀 技术或许是一个特例。当然,这仍需要我们共同的努力! 1.4 免杀技术的简单原理 在笔者最初接触免杀技术,使用 MyCCL 定位特征码的时候就有很多疑问,例如“特征 码究竟是什么”、“特征码是怎么被定位出来的”,以及“除此之外就没有其他的了吗”…… 当然,后来我终于明白了这些看似简单的问题,并且很高兴能在这里分享出来。 下面我们就先从一句话开始谈起,“免杀就是定位特征码”这句话相信一些读者可能听 说过。不过笔者撰写本书的基本目标之一,就是想让读者知道这句话是错误的。 然而,我们不得不承认免杀确实是从特征码开始的。原因很简单,因为杀毒软件也是从 这里开始的,所以我们先要明白“特征码”是什么。 所谓的“特征码”其实是从反病毒领域引进的一个词,意指相应病毒或木马所特有的一 段二进制码。我们都知道,其实病毒与木马就是一个特殊的应用程序,鉴于其特殊性,它 的文件结构与相应的二进制指令肯定是要与正常程序(比如正常的 PE 文件格式)是有所 不同的。 当反病毒公司的相关技术人员得到一个病毒样本时,他最重要的任务之一就是找出这个 病毒的“特征码”。 正文.indd 4 2013-9-16 10:06:54 第 1 章 变  脸   5 但是“特征码”究竟是从哪里来的呢?或者说相关技术人员是依靠什么找到特征码的 呢?我们知道,一个正常的应用程序是不可能包含格式化所有硬盘的指令的,但是假如某个 病毒包含这段“个性十足”的指令,那么我们将其对应的二进制码定位为特征码简直是再准 确不过了。 事实上我们不容易碰到这种具有鲜明个性的病毒,但在给病毒定位特征码时所应用的原 理是大同小异的。 不过,现实世界中的杀毒软件所用的特征码是异常复杂的,一般都是由数段特征片段加 上一定的逻辑判断机制组合而成的。 相比较而言,破坏这种复杂的特征码显然要简单许多,我们只需要有计划地向病毒或木 马文件中分批填入无用的垃圾信息即可。如果被垃圾信息覆盖后文件不再会被杀毒软件所查 杀,那么我们就可以判定覆盖区域内一定存在特征码片段。不管这种覆盖是否包括了全部特 征码,只要是杀毒软件不再查杀,那么目的就达到了。 当然,如果仔细思考一下,其实这里还有很多问题没有解决,例如填入垃圾信息后的木 马是否仍可以运行、我们在填入时所用的算法是什么样的,等等。 对于这些比较复杂的问题,在本书后面会有专门的章节介绍,此处提出这些问题会使大 家在阅读本书时更有针对性。 1.5 免杀与其他技术的区别 正如前面所讲的,免杀是一门新兴技术,同时也是一门涉猎很广的技术,因此笔者觉得 很有必要阐明它与其他相关技术的不同之处,以免读者产生混淆,或造成概念不清。 1.5.1 免杀不是 Rootkit 技术 诚然,免杀与 Rootkit 有许多相同之处,例如它们的最终目的都是隐藏自己不被其他程 序发现。但是我们不能因此就说免杀就是 Rootkit 技术。 我们从单词 Rootkit 中的 kit 就不难发现,其实 Rootkit 的本质是指一组非常直接的工具, 但是免杀只是使用这组工具的方法之一。 现在的免杀主要分为 3 种,其中的一种便是行为免杀,也就是通过控制病毒木马的行为 来达到躲过杀毒软件主动防御检测的目的。而这种行为免杀所用到的处理技术之一就是通过 Anti Rookit 来使反病毒程序的 Rootkit 失效,从而不能有效地监测系统,达到一劳永逸的目 的。当然,我们还可以通过对病毒或木马的调整来被动地达到行为免杀的效果。 因此我们可以看到,Rootkit 并不能代表免杀技术,它只是构成高级免杀技巧的组成部分。 1.5.2 免杀不是加密解密技术 有很多人认为免杀其实就是破解技术的一个分支,例如对于程序的修改、脱壳加壳、对 程序的加密解密等,这些都是免杀与加密解密的相同之处。 正文.indd 5 2013-9-16 10:06:54 6   基础篇 初级免杀技术 但是就两种技术所导致的行为来讲,它们主要存在以下不同: 加密解密技术是针对某一个程序展开研究,而免杀技术在任何时候都是针对两个程序 ❑ 展开研究。 加密解密技术是以某一程序为媒介所产生的技术对抗(例如程序保护者与破解者), ❑ 免杀技术则是通过某一个程序对另外一个程序所产生的技术对抗(例如免杀的木马与 杀毒软件)。 除此之外,加密解密技术大多是在没有源代码的情况下进行的(称为无源工作环境), 而源码级免杀则是指通过直接修改源代码的方式达到免杀目的,它是一种有源工作环境下的 技术。 1.6 小结 免杀技术从诞生之初的修改源代码与特征码,到现在的利用 Anti Rootkit 躲过主动防御, 期间走过的路并不平坦,有许多无名的技术爱好者为我们后续的学习打下了基础。 对于免杀技术,现在最重要的就是建立起其独有的知识体系,使其成为一个真正的技术 领域,当然这也是笔者撰写本书的愿望之一。 在未来的几年中,免杀技术势必会随着杀毒软件的进步而发展,而杀毒软件的发展则取 决于新型病毒与木马的前沿走向。 因此从病毒与木马的角度上来讲,随着技术的发展,其发展路线必然会产生分化,一类 更加注重其功能性,例如加入人工智能、云计算等相关技术思想 ;另一类则逐渐脱离系统, 向硬件靠拢,例如将后门安装在 BIOS 或某处固件中,甚至是处理器的微代码中。 这两种发展路线的共同点就是小型化、精确化,因此也更加难以掌控。我们可以更容易 地想到,一个存在于 BIOS 或固件中的恶意程序,其体积不可能动辄几百 KB,因此它所包 含的二义性(可改动)的字节肯定不会太多。 并且,由于人类受到这个好奇本能的影响,窥探他人的愿望以及对陌生领域的求知欲会 促使病毒木马与反病毒产品持续抗争,这种抗争将一直随着技术的发展而延续下去。在这场 脑力角逐中总会有无数新人摸索着参与进来,黑客免杀技术作为他们接触病毒与木马领域的 敲门砖,必然会在技术的发展与历史的潮流中总会占有一席之地。 正文.indd 6 2013-9-16 10:06:54 第 2 章 免杀基础知识 这一章主要介绍有关免杀的基础知识,从了解反病毒软件开始到特征码定位原理,通俗 的语言加上简单的比喻让你轻松成为反病毒软件的“内行人士”!在你了解了反病毒软件的 大体原理与工作方式之后,也会看到反病毒软件的不足之处。 都说好的开始代表着成功的一半,这一章的目的就是要带领读者从免杀的基础知识开始 了解免杀技术的概况与框架,从而使得尚未入门的读者能以本章为跳板进入神秘的免杀技术 殿堂。 2.1 如何开始免杀 在我们接触一个新的技术领域时,第一个问题往往都是问“如何开始”,这看似再简单 不过了,却往往是初学者很难逾越的一道关卡。 那么,黑客们究竟是如何开始免杀的呢? 首先,从事免杀工作的黑客们都有自己的需求,或者纯粹为了挑战,或者为了某种渗透 需求,不管黑客们的目的是什么,他们必须先做一个需求分析,例如打算针对哪种反病毒软 件、为一个何种类型的恶意程序做免杀。 其次,就是根据需求收集相应的信息,例如这款反病毒软件强度如何,有何弱点,使用 了什么独特的反病毒技术,要怎样才能突破它,等等。 除了这些,还要对这个恶意程序做一定的评估,例如它是用什么语言编写的?它的二进 制代码是否已经被混淆或加密过了?使用它的人数是否很多? 最后,根据收集的信息制订计划,从修改特征码开始,直到能完全躲过这款反病毒软件 的所有监控。就这样,一次免杀完成了。 了解了上面的整体流程,相信读者已经对免杀有了一个初步的理解。下面,让我们再整 理一下上述信息: 目标反病毒软件强度如何? ❑ 目标反病毒软件有何弱点? ❑ 目标反病毒软件使用了什么独特的反病毒技术? ❑ 要怎样才能突破它? ❑ 待处理的恶意程序是用什么语言编写的? ❑ 待处理的恶意程序的二进制代码是否已经被混淆或加密过了? ❑ 正文.indd 7 2013-9-16 10:06:54 8   基础篇 初级免杀技术 待处理的恶意程序的使用人群是否广泛? ❑ 从免杀需要收集的信息来看,首先要了解的是反病毒软件,其次才是恶意程序。由此我 们可以推断出,如果黑客们想要比较全面透彻地收集反病毒软件的信息,那么势必要对反病 毒软件有一定的研究才行。 2.2 反病毒软件原理与反病毒技术介绍 首先,反病毒软件仅仅是一个普通的软件,它之所以具有看似神奇的反病毒功能,不 过是因为它被赋予了这种使命而已。一个反病毒软件的构造的复杂程度要远远高于木马或病 毒,而且鉴于木马和病毒现在的发展趋势是越来越深入系统底层(Ring0 层),反病毒软件也 在不断地向系统底层靠近。例如现在的“主动防御”技术,就是应用系统底层的技巧。 小知识 什么是“系统底层”,什么又是 Ring0 ? 关于系统底层,我们先来举一个简单的例子,如果有人想控制你的计算机,既可以通过 软件也可以通过硬件,但如果你想要对这种控制进行防御,则需要安装另一种可以防范它的 软件,或从硬件上做文章(比如给计算机加锁)。其中,软件是计算机中相对高层的,而硬 件是底层的,也就是说,越靠近底层拥有的权力就越大。 从计算机原理来说,计算机中有一个用于控制 CPU 完成各项功能的命令系统,它叫做 “指令系统”,指令系统将指令分为特权指令与普通指令。对于一些危险的指令(即绝大部分 特权指令),只允许操作系统及其相关模块使用,而普通的应用程序只能使用那些不会造成 灾难的指令(即普通指令)。Intel 的 CPU 将特权级别分为 4 层,它们分别是 Ring0、Ring1、 Ring2 与 Ring3。Ring0 为底层,也就是所谓的“内核层”,它也是操作系统的底层;Ring3 为 最高层,也就是用户层。目前 Windows 只使用其中的两个级别(这样既能实现安全的访问控 制,又能降低系统的设计成本与复杂程度),它们是 Ring0 和 Ring3 层,Ring0 只供操作系统 使用,而 Ring3 谁都能用。但是使用一定的方法我们还是可以通过编写程序来“操控”Ring0 层的指令。 2.2.1 反病毒软件的工作原理 反病毒软件一般由扫描器、病毒库与虚拟机组成,并由主程序将它们整合为一体,如图 2-1 所示 。 一般情况下,扫描器用于查杀病毒,它也是反病毒软件的核心。一个反病毒软件的效果 好坏直接取决于扫描器的技术与算法是否先进。而且反病毒软件的不同功能往往对应着不同 的扫描器,也就是说,大多数反病毒软件都是由多个扫描器组成的。 病毒库中存储着病毒所具有的独一无二的特征字符,我们称之为“特征码”。而病毒库  反病毒软件本身并没有一个绝对固定的结构,但是我们可以将反病毒软件的结构抽象地归纳出来。 正文.indd 8 2013-9-16 10:06:55 第 2 章 免杀基础知识   9 存储特征码的存储形式则取决于扫描器采用哪种扫描技术。特征码可能存在于任何文件中, 例如 EXE 文件、RMVB 文件、JPG 文件,甚至是 txt 文件中 ,所以它们也都有可能被查杀。 图 2-1 反病毒软件的程序结构 而虚拟机则是最近引入的概念,它可以使病毒在一个由反病毒软件构建的虚拟环境中执 行,这样就与现实的 CPU、硬盘等物理设备完全隔离了,从而可以更加深入地检测文件的安 全性。2 2.2.2 基于文件扫描的反病毒技术 基于文件扫描的反病毒技术可以分为“第一代扫描技术”、“第二代扫描技术”与“算法 扫描”3 种,对于黑客来说,只有对每一种扫描技术了如指掌,才能成为高手!不过,对于 反病毒技术的初学者来说了解一下就可以了。 这一节将介绍以上 3 种方法,对其详细的技术原理感兴趣的读者可以自己研究 。 1. 第一代扫描技术 第一代扫描技术可以用“在文件中检索病毒特征序列”这句话来高度概括,由于目前大 部分计算机书籍对病毒检测都停留在相当浅的层次上,所以通常都会用这句话来概述相关技 术。其实第一代扫描技术直到现在也仍然被各大反病毒软件厂商使用着,其主要分为“字符 串扫描技术”与“通配符扫描技术”两种。 (1)字符串扫描技术 可以将此技术中的字符串理解为一段有意义或无意义的字符,例如“黑客免杀技术”、 “OK”、“Windows XP”与“ww11 好好 22”等都是一段字符串。所以说此技术是检测计算机 病毒最早的也是最简单的办法。   部分病毒会将自身分解成若干份保存到看似不相干的文件中,因此即便是JPG图片等数据型文件也可能保 存有病毒的片段。   感兴趣的读者可以参考Peter Szor著的《计算机病毒防范艺术》(The Art of Computer Virus Research and Defense) 正文.indd 9 2013-9-16 10:06:55 10   基础篇 初级免杀技术 字符串扫描技术一般使用从病毒中提取出来的具有特征的一段字符来检测病毒,当然这 些字符在一般程序中是不太可能出现的。例如一个隐藏执行格式化所有硬盘的命令是不可能 出现在普通程序里的,如果某个应用程序包含了相应的特征字符,那么它就应该是病毒了。由 此可见字符串扫描技术的原理还是比较简单的,但它却是反病毒软件扫描技术的思想发端。 (2)通配符扫描技术 此技术中的通配符可以理解为具有一定意义的符号,例如 DOS 命令里的“*”号就是代 表任意长度、任意字符的通配符,而且通配符在不同的领域中也可能会代表不同的意思。 由于字符串扫描技术有执行速度慢与特征码长度限制等问题,所以它正在逐渐退出历 史舞台,而通配符扫描技术取而代之,因为它以同样简单的原理与技术实现了更为强大的功 能,所以现在反病毒软件中简单的扫描器常常支持通配符。扫描器中的通配符一般用于跳过 某些字节或字节范围,而现在大多数的扫描器已经支持正则表达式了。 下面我们通过一个例子来讲解通配符扫描技术的原理。例如我们的病毒库中有以下一段 特征码: ...... 020E 07BB ??02 %3 56C9 ...... 可以将其解释为: 尝试匹配 02,如果找到则继续,否则返回假。 ❑ 尝试上一匹配目标后匹配 0E,如果找到则继续,否则返回假。 ❑ 尝试上一匹配目标后匹配 07,如果找到则继续,否则返回假。 ❑ 尝试上一匹配目标后匹配 BB,如果找到则继续,否则返回假。 ❑ ?? 表示忽略此字节。 ❑ 尝试上一匹配目标后匹配 02,如果找到则继续,否则返回假。 ❑ %3 表示在接下来的 3 个位置(字节)中尝试匹配 56,如果找到则继续,否则返回假。 ❑ 尝试上一匹配目标后匹配 C9,如果找到则继续,否则返回假。 ❑ 这种扫描技术通常支持半字节匹配,这样可以更精确地匹配特征码。一些早期的加密病 毒用这种方法都能比较容易地检测出来。 (3)其他扫描技术 除了上面介绍的两种扫描技术外,还有一些其他的扫描技术,由于它们与免杀的关系不 大,在这里只做一个简单的介绍,有兴趣的读者可以自己研究。 不匹配字节数扫描技术 :这是为 IBM Antivirous 软件开发的一种技术,它允许字符串 ❑ 中有 N 个字节为任意值。 通用检测法扫描技术:用一个简单的字符串来搜索某类病毒的部分或全部已知变种。 ❑ 散列扫描技术 :散列是一个常见的术语,这里指可以对特征码的首字节或第一个 16 ❑ 位或 32 位字节进行计算,从而允许字符串后面的字节包含通配符。 书签检测法:这是一种保证病毒检测与清除过程更加准确的方法。 ❑ 首尾扫描检测法:通过只扫描文件头部和尾部而加快病毒检测速度的复杂方法。 ❑ 正文.indd 10 2013-9-16 10:06:55 第 2 章 免杀基础知识   11 入口点和固定点扫描:可以进一步提升防毒扫描工具检测速度的一种方法。 ❑ 文件名扫描法 :这是国内某著名安全软件所使用的扫描方法,其原理是根据文件名及 ❑ 文件所在路径粗略地判断此文件是否是病毒的。 2. 第二代扫描技术 第二代扫描技术的代表为“近似精确识别法”与“精确识别法”,除此之外还有“智能 扫描法”与“骨架扫描法”。从名字可以看出,第二代扫描技术对检测精度给予了充分的重 视,因误杀而导致严重的后果是绝大部分反病毒软件厂商都不愿看到的,因此检测精度逐渐 提高也在情理之中。 (1)智能扫描法 这种方法是在大量变异病毒出现之后提出的。智能扫描法会忽略检测文件中像 NOP 这 种无意义的指令。而对于文本格式的脚本病毒或宏病毒,则可以替换掉多余的格式字符,例 如空格、换行符或制表符等。由于这一切替换动作往往是在扫描缓冲区中执行的,从而大大 提高了扫描器的检测能力。 小知识 “缓冲区”其实就是一块内存空间,应用程序运行前都需要加载到内存中,而缓冲 区就是系统向运行的程序分配的一块动态的空间。它存在的主要目的就是为了节省内存的开 销,加快程序的运行速度。其实硬盘甚至光驱也是有缓冲区的,只不过从严格意义上来讲它 们还是有一定差别的,有兴趣的读者可以自己了解一下。 (2)近似精确识别法 近似精确识别法包含了若干种方法,在这里不可能一一介绍。下面介绍的两种方法是比 较具有代表性的扫描技术。 多套特征码 ❑ :该方法采用两个或更多个字符串集来检测每个病毒,如果扫描器检测到 其中一个特征符合,那么就会警告发现变种,但并不会执行下一步操作(例如清除病 毒体或删除文件)。如果多个特征码全部符合,则报警发现病毒,并执行下一步操作。 校验和 ❑ :对于校验和,也许有些读者会想到文件校验和对比的方法,不过这个方法的 思路是让每一个无毒的文件生成一个校验和,等待下次扫描时再进行简单的校验和对 比。如果校验和有所变化,再做进一步的扫描,否则就说明这个文件没有被感染,这 样有利于提升扫描器的效率。但是严格地说,这并不算是扫描技术。除此之外,某些 安全产品还对病毒文件采取了分块校验的方式以提高准确性。 将校验和扫描技术利用得最为到位的就是比较出名的卡巴斯基了,它的第二代扫描器就 采用了密码校验和技术,从而基本淘汰了搜索字符串技术。 关于校验和,其实是一个复杂的概念,简单地说就是通过对病毒中的某一段代码进行计算, 从而得出一个值(例如 123XY4),它与 MD5 文件校验有些相似。当然这样说不完全正确。 (3)骨架扫描法 此方法由卡巴斯基(Kaspersky)公司发明,在检测宏病毒时特别有用。它既不用特征码 正文.indd 11 2013-9-16 10:06:55 12   基础篇 初级免杀技术 也不用校验和,而是通过逐行解析宏语句,并将所有非必要字符丢弃,只剩下代码的骨架, 通过对代码骨架的分析,从而提高对变种病毒的检测能力。 (4)精确识别法 精确识别法是现今能够保证扫描器精确识别病毒变种的唯一方法,常与第一代扫描技术 结合使用。精确识别法也是利用校验和技术,只不过应用得更广、更复杂。它甚至能通过对 整个病毒进行校验和计算来生成特征图。 2.2.3 基于内存扫描的反病毒技术 内存扫描反病毒技术是一种原理复杂的扫描技术,例如如何使一个病毒失去活性,如何 对付只读型内核内存等系统底层知识。但是作为免杀爱好者,我们现阶段完全没必要知道这 些,现在我们只需要知道内存反病毒的思想与概念即可。 内存扫描器一般与实时监控型扫描器协作,从理论上来讲,反病毒软件的文件扫描组 件能识别的病毒,内存扫描器也能识别。但是不能从而武断地认为它们用的就是同一套特征 码,相信大家在后面的学习中会深切地体会到这点。就算对一个木马文件免杀成功,如果不 对其做内存免杀,大多数在运行中的木马文件仍然会被反病毒软件杀掉。 但是为什么会出现这样的情况?这是因为程序在运行后会将自身释放到内存中,释放后 的文件结构与未执行的文件相比有较大的差异。而且作为病毒来讲,被加载到内存就证明它要 开始执行一些动作了,在病毒或木马初始化运行环境的时候,会让更多的可疑点暴露出来。 因此为了提高效率与准确性,反病毒软件厂商一般会为内存扫描组件单独定义一套新的 特征码。 2.2.4 基于行为监控的反病毒技术 基于行为监控的反病毒技术一般需要与虚拟机、主动防御等技术配合工作。其原理是, 主要针对病毒木马行为进行分析比对,如果某些程序在执行后会进行一些非正规的、可疑的 操作,那么即便这是一个新生病毒,也会被拥有这种技术的反病毒产品拦截。 所谓的“行为”,就是指一个应用程序运行后的操作,对于一个程序来说,如果其在按 照某种顺序执行某一系列的操作,我们就将其称为“行为特征”。 以一个典型的木马程序为例,它可能执行的操作步骤如下: 1)释放一些文件到系统关键目录中; 2)修改系统设置使这些新释放的文件可以自启动; 3)删除自身。 如果我们遇到一个执行以上操作的程序,那么它十有八九就是木马了。 2.2.5 基于新兴技术的反病毒技术 随着信息时代的正式来临,IT 行业的各种技术也是日新月异,而位于计算机领域浪潮最 前沿的反病毒行业自然也不甘落后。从智能查杀、计算机体检,到新兴时髦的云查杀,反病 正文.indd 12 2013-9-16 10:06:56 第 2 章 免杀基础知识   13 毒技术始终在吸引着广大网民的眼球。 1. 云查杀 云计算自从诞生以来便备受关注,云查杀当然也不例外。 而对于黑客们来说,云查杀也是最具有挑战性的,这主要取决于云查杀的特点以及跟随 其衍生出来的技术。如果用一句话来概括云查杀,那么这句话就是“可信继承,群策群力”。 在理解这句话之前我们需要先了解云查杀及其特点。首先,云查杀的基本思路就是以服 务器为脑,以所有用户的机器为触角,从而使得服务器可以随时知道每个用户的情况,如果 其中某一个用户与其他用户对比发生了异常,那么服务器就会发出指令,让发生异常的机器检 查出问题所在,并将问题反馈给服务器,从而在这个问题干扰到其他用户之前将其扼杀掉。 我们上面提到的“其他用户”就是云查杀整个信任机制的基石。举例来说,如果大多数 机器上都运行过 QQ.EXE,那么当一个新加入的机器也试图运行 QQ.EXE 时,服务器就认为 这是正常的,否则服务器就会发出相应指令让用户的机器去阻止其运行。 (1)可信继承 当然,整个云的信任机制是非常复杂的结构,其中包含用户参与的信任评价体系、反病 毒专业人员参与的样本分析信任体系、服务端自动判断信任体系,以及基于数字签名的认证 信任体系等。 在这其中,顶端的信任体系是由数字签名、样本分析构成的,这些顶端的信任体系在用 户的机器上表现出来的形式就是“根可信进程”。所谓的“根可信进程”就是指可信进程链 条的顶端,凡是由可信进程开启的新进程都被认为是可信的。 我们举个例子,假如进程 A 是具有数字签名的根可信进程,那么它在被用户直接执行时 就不会触发反病毒软件的任何操作 ,而且由 A 进程创建的新进程也会成为可信进程。如果 进程 B 是一个非可信进程,那么它在被用户执行时就会受到严密的监控,如果它在执行期间 有什么敏感操作,其样本马上就会被提交给服务器处理。3 由此一来,这个基于云的信任网络就会越来越庞大,其收集的信息也将越来越多。 (2)群策群力 我们都知道云计算的特点就在于其具有分布性,而病毒木马的感染恰恰也具有分布性这 一特点。这样一来,病毒木马感染的速度越快、感染的面积越广,其被云查杀捕获到的可能 性就越大。 只要其中某一台计算机上发现新病毒,那么它马上就会被提交到服务端,在服务端快速 更新后,所有在云中的计算机就都获得了对这种病毒的免疫力。 2. 双引擎查杀 / 多引擎查杀 “双引擎查杀”正如其字面意思一样,即同时运用两个反病毒引擎扫描病毒,其扫描的 准确度会比单一反病毒引擎有所提高。 一般情况下,具有多个反病毒引擎的产品都会让用户选择扫描模式,例如是启用某一个  这里只是为尽量简洁明了地阐述云查杀的信任体系。 正文.indd 13 2013-9-16 10:06:56 14   基础篇 初级免杀技术 引擎,还是启动所有引擎。因此黑客们在针对这种反病毒产品进行免杀时往往会在操作思路 上将其分割为若干个反病毒产品,然后再一一攻破。 2.2.6 反病毒技术前沿 目前反病毒技术应用得比较广泛的是“主动防御”与“云查杀”这两项,而这两项技 术中最为强大的环节就在于“虚拟机扫描技术”。所以这里介绍一下“虚拟机扫描技术”与 “文件流查杀”思想的“鼻祖”—“代码仿真技术”。 代码仿真(Code Emulation)技术是一种极强大的病毒检测技术,这种技术很好地实现 了一个程序运行所需要的基本虚拟环境。它的原理是通过一个虚拟机环境来仿真 CPU 和内 存管理系统,从而模拟代码执行过程。 当反病毒软件决定将某个程序放到虚拟机中运行时,首先要将可执行文件的内容读取到 内存缓冲区中,然后由仿真器中一个庞大的 switch() 语句对各个指令操作码进行逐一分析, 最后执行。 小知识 switch() 是一个多数计算机语言都会涉及的语句,它的作用就是使程序按照需求执 行若干个备选方案中的某一个项或其中数项,在这里可以理解为 :虚拟机要把程序的每一句 指令操作码都逐一分析完毕后才去执行。 由此可见,代码仿真技术是十分消耗系统资源的,同样的一个应用程序,如果在虚拟机 中运行,其执行速度将会降低到原来的几百分之一!但是面对目前个人计算机执行速度的飞 跃,纵然降低到原来的几百分之一,也还是可以让我们轻松接受的,所以这种奢侈的查杀技 术才得以推广。 文件流查杀与这种技术相比差异还是比较大的,它虽不需要模拟一个虚拟环境来运行 病毒,但是它需要让病毒被人为地主动运行,当病毒运行时它会分析病毒释放到内存中的代 码,直到病毒本来的代码被完全还原后才进行查杀,因此这种扫描算法虽不需要耗费大量的 系统资源,但是却十分被动! 2.2.7 反病毒技术展望 4 未来计算机会朝着智能化的方向发展,计算机病毒实现智能化也是迟早的事,因此下一 代反病毒软件也在朝着这个方向发展。 现在已经有人尝试了用神经网络来检测计算机病毒,业内的专家们称为“基于神经网络的 启发式分析”。神经网络也是人工智能领域的一个分支,因此这个话题还是很令人激动的。研 究者已经成功地用经过训练的神经网络检测出了复杂的 EPO 病毒。这种复杂的技术将来可能 会与启发式分析及云查杀合为一体,从而产生出高识别率、小特征库且低误报的扫描器。 但是神经网络也有一个致命的缺点,它需要数量巨大的样本病毒供其分析学习,而且就  有关于反病毒行业更多新技术的介绍与讨论请关注本书的“扩展篇 遏制免杀技术初探”。 正文.indd 14 2013-9-16 10:06:56 第 2 章 免杀基础知识   15 现阶段来看,能力的提高也不是很明显。但这仍不能掩盖它的优点,病毒越多,它的查杀效 果就越令人满意。 由此可见,神经网络的启发式分析是否能得到用户的认可并长期存在于市场中,还得看 它最终“学习效率”的高低。 小知识 EPO(Entry-Point Obscuring)也称“入口点模糊”技术,这种技术出现的唯一目的 就是与反病毒软件做对抗,利用这种技术编写的病毒具有极强的反探测、反查杀及反删除能 力,我们会在第 4 章介绍这种技术。 2.3 了解 PE 文件 可执行文件结构是操作系统的根基之一,Windows 系统下的若干种文件,例如 *.exe、 *.dll、*.sys、*.ocx 等都遵守 PE 文件结构的约定。 本节将帮助读者对 PE 文件建立一个最基础的概念性框架,如果你对 PE 文件有的了解, 可以略过本节直接阅读 4.6 节“PE 文件进阶介绍”。 2.3.1 什么是 PE 文件 鉴于技术的时效性,本书所讨论的内容均是 32 位操作系统中的内容。因为 PE 文件是在 32 位操作系统中诞生的,且与 64 位系统中的可执行文件格式基本相同。而被淘汰的 16 位操 作系统下的文件格式称为 NE,即 New Executable(新执行体),对于 NE 文件格式我们不再 做任何讨论。 在 Windows 系统中,凡是可以直接以二进制形式被系统加载执行的文件都是 PE 文件, 这一点可能会使部分读者困惑。PE 文件不像 DOC 等文件一样只有一个后缀,这个特性并不是 其所独有的,例如我们非常熟悉的 JPEG 图像文件格式,其后缀就有 *.jpg、*.jpeg 与 *.jfif 等。 因此,PE 文件其实就是一种文件格式,只不过这个文件格式是与我们息息相关的,无 论是对于黑客还是对于反病毒工作者来说,透彻地了解 PE 文件格式都是非常重要的基本功。 PE 文件中的 PE 就是 Portable Executable(可移植的执行体)的简写,它是 32 位的 Windows(简称 Win32)环境自身所带的可执行文件格式。“可移植的执行体”意味着此文 件格式是跨 Win32 平台的,也就是说,即使 Windows 运行在非 Intel 的 CPU 上,任何 Win32 平台的 PE 装载器都能识别和使用该文件格式,所以所有 Win32 下的可执行文件也都必须使 用 PE 文件格式。 小知识 什么是 Win32 环境? Win32 环境就是指 Windows 操作系统下的 32 位运行环境,例如大家常用的 Windows 2000、Windows XP 等都是 Win32 环境,而 Windows 3.x 则是 16 位的 Windows 环境,也就 是 16 位操作系统。 正文.indd 15 2013-9-16 10:06:56 16   基础篇 初级免杀技术 2.3.2 PE 文件的结构 PE 文件总的来说是由 DOS 文件头、DOS 加载模块、PE 文件头、区段表与区段 5 部分 构成的,但是作为 Windows 下的一个文件格式,弄两个与 DOS 相关的结构干什么呢?其实 如果程序在纯 Windows 环境下运行,则 DOS(即 MS-DOS,此为简称)文件头与 DOS 加载 模块是根本用不上的,PE 加载器会根据 DOS 文件头中的最后一个标志跳过 DOS 加载模块, 直接转到 PE 文件头上。加上两个与 DOS 相关的结构完全是为了兼容性问题。 如图 2-2 所示就是以十六进制方式显示的 PE 文件的基本结构。 图 2-2 PE 文件的基本结构 通过图 2-2 可以发现,整个程序就是以 DOS 文件头的 MZ 标志位开始的,接下来就是 DOS 加载模块的标志性字符串 This program cannot be run in DOS mode,这两个几乎就是恒 定不变的,差不多每个 Windows 程序的前面都是这样一些信息。 下面有一个以字母 PE 为开头的文件块,这就是我们前面一直在讨论的 PE 文件头了。 PE 文件头的标准大小为 224 字节,由图 2-2 可见,里面有一个画了横线标记的问号与左面的 十六进制信息 E0 相对应,这便是 PE 文件头体积的描述标记,十六进制的 E0 等于十进制的 224,由此也不难看出 PE 文件头的大小为 224 个字节 。5 再往下就是以 .text、.data 与 .rsrc 组成的区段表了,区段表也称节表,它的作用就相当   这里“PE文件头的大小为224字节”的描述并不严谨,读者可以先忽略这个问题,我们在本书的后续介绍 中会详细探讨。 正文.indd 16 2013-9-16 10:06:56 第 2 章 免杀基础知识   17 于一本书中的目录,你想看哪一章哪一节,只要按着目录标注的页数去找就可以了,PE 文件 的区段表也起着同样的作用,只不过它又附加了一些很有用的属性,例如读写权限与区段大 小等,它的任务就是使 PE 加载器能准确快速地加载相应的区段。 通过区段名称我们可以大体猜出来这个区段里包含了些什么信息,在整个程序中能起到 什么作用等。因为 PE 文件里的区段名称都是有相应的约定的,但是如果被人为地修改了就 没有任何意义了。 由此可见,PE 文件是一种结构组成十分科学的文件格式,这也对我们快速认识它有一 定的帮助,只要你记住 PE 文件的这 5 个构成部分,你就可以向别人说,我了解 PE 文件! 一个简简单单的应用程序后面存在着这么多有趣的知识,但是这些知识仅仅是 PE 文件 中的一小部分而已。由于 PE 文件涉及的知识面很广,本书将在高级篇的第 7 章中详细讨论 PE 文件格式,考虑到初学者的知识水平,这一节暂时就介绍到这里。本节意在让大家对 PE 文件有一个大体的了解,认识 PE 文件中这些至关重要的内容,以便对 PE 文件产生一种最起 码的熟悉感。随着本书的逐渐深入,会在后面的章节中详细介绍 PE 文件的构成。 2.4 免杀原理 免杀的最基本思想就是破坏特征,这个特征有可能是特征码,有可能是行为特征,只要 破坏了病毒与木马所固有的特征,并保证其原有功能没有改变,一次免杀就能完成了。 但是黑客们究竟是怎样破坏特征的呢?本节就对黑客使用的各种免杀技术的原理进行 曝光。 小知识 什么是特征码? 在本章开篇时我们多次提到了“特征码”这个名词,并且举了一个生动的小例子,但并 没有对特征码进行更为深入的介绍。其实特征码就是反病毒软件用于判断文件是否带病毒的 一段独一无二的代码,这些特征码在不同的反病毒软件的病毒库中不尽相同。 随着反病毒软件的发展,特征码也逐渐细化为很多不同的分支,其中差距最大的就是文 件特征码与内存特征码。由 2.2 节的反病毒软件原理可知,即便是文件反病毒,也分为若干 种方法,而且方法不同,必然会使每种方法下所涉及的特征码存在细微的不同。 但是总体来说,特征码就是一种只在病毒或木马文件内才有的独一无二的特征,它或 是一段字符,或是在特定位置调用的一个函数。总之,如果某个文件具有这个特征码,那反 病毒软件就会认为它是病毒。反过来,如果将这些特征码从病毒、木马的文件中抹去或破坏 掉,那么反病毒软件就认为这是一个正常文件了。 2.4.1 文件免杀原理 黑客们研究木马免杀的最终目标就是在保证原文件功能正常的前提下,通过一定的更 改,使得原本会被查杀的文件免于被杀。 正文.indd 17 2013-9-16 10:06:57 18   基础篇 初级免杀技术 要达到不再被杀的目的方法有很多种,其中最直接的方法就是让反病毒软件停止工作, 或使病毒木马“变”为一个正常的文件。 然而如何使一个病毒或木马变成一个正常文件,对于黑客们来说其实是一个比较棘手 的问题,不过只要学会了一种免杀原理,其他的免杀方案也就触类旁通了。为了便于大家理 解,我们将这些免杀方案分别进行讲解。 1. 改特征码免杀原理 所谓的特征码,我们可以将其理解为反病毒软件的黑名单。黑客们显然无法将木马从反 病毒软件的黑名单中删除,所以他们要让病毒改头换面!例如原来黑名单中有“灰鸽子”这 么一款木马,黑客们将其改头换面后不叫灰鸽子了,比如叫“白鸽子”!当然,这只是一个 例子,现实中仅仅依靠改名是骗不了反病毒软件的。 就目前的反病毒技术来讲,更改特征码从而达到免杀的效果事实上包含着两种思想。 一种思想是改特征码,这也是免杀的最初方法。例如一个文件在某一个地址内有“灰鸽 子上线成功!”这么一句话,表明它就是木马,只要将相应地址内的那句话改成别的就可以 了,如果是无关痛痒的,直接将其删掉也未尝不可,如图 2-3 所示。 图 2-3 通过修改特征字符串免杀 第二种是针对目前推出的校验和查杀技术提出的免杀思想,它的原理虽然仍是特征码, 但是已经脱离纯粹意义上特征码的概念,不过万变不离其宗。其实校验和也是根据病毒文件 中与众不同的区块计算出来的,如果一个文件某个特定区域的校验和符合病毒库中的特征, 那么反病毒软件就会报警。所以如果想阻止反病毒软件报警,只要对病毒的特定区域进行一 定的更改,就会使这一区域的校验和改变,从而达到欺骗反病毒软件的目的,如图 2-4 所示。 这就是在定位特征码时,有时候定位了两次却得出不同结果的原因所在。 2. 花指令免杀原理 花指令其实就是一段毫无意义的指令,也可以称之为垃圾指令。花指令是否存在对程序 的执行结果没有影响,所以它存在的唯一目的就是阻止反汇编程序,或对反汇编设置障碍。 正文.indd 18 2013-9-16 10:06:57 第 2 章 免杀基础知识   19 图 2-4 通过修改区域内部分代码来免杀 然而这种障碍对于反病毒软件来说同样也是致命的,如果黑客们的花指令添加得足够高 明,就可以使木马很轻松地逃脱查杀! 但是,为什么它会影响反病毒软件的判断呢?通过前面的学习大家都已经知道,大多数 反病毒软件是靠特征码来判断文件是否有毒的,而为了提高精度,现在的特征码都是在一定 偏移量限制之内的,否则会对反病毒软件的效率产生严重的影响!而在黑客们为一个程序添 加一段花指令之后,程序的部分偏移会受到影响,如果反病毒软件不能识别这段花指令,那 么它检测特征码的偏移量会整体位移一段位置,自然也就无法正常检测木马了。 当然,这也仅仅是针对第一代扫描技术的方法,不过即便是反病毒软件采用虚拟机分 析、校验和扫描或启发式分析,花指令同样会起到一定的作用,针对每种检测方法的不同, 花指令所起到的作用亦不相同。它最根本的思想就是扰乱程序运行顺序,并为破解者(反病 毒人员)设下陷阱。而如果花指令可以成功保护软件真正代码不被轻易反汇编,那么对于反 病毒软件来说,它所检测的自然也就不是木马文件中真正的内容了。 3. 加壳免杀原理 说起软件加壳,零基础的读者们也许还不知道它是什么。简单地说,软件加壳其实也可 以称为软件加密(或软件压缩),只是加密(或压缩)的方式与目的不一样罢了。 一般的加密是为了防止陌生人随意访问我们的数据。但是加壳就不一样了,它的目的是 减少被加壳应用程序的体积,或避免让程序遭到不法分子的破坏与利用,例如最常见的共享 软件,如果不对软件加以保护,那么这个软件就会很轻易地被破解,也就没有人去向软件的 作者购买注册码了。 既然加壳后的软件还能正常运行,那么这些壳究竟将软件的哪些部分加密了呢?其实, 我们可以从“加壳”这个词语本身着手,为什么不叫加密、防盗或其他的名称,而偏偏称其 为加壳呢? 我们可以将未加壳的软件想象成美味的食物,太多的人想要得到它,想借此大饱口福! 于是食物的主人就将其保存了起来,放到一个只有他能打开的硬壳里,这样就可以避免其他 人打它的主意。而当自己的客人到来时,他可以很轻松地打开这个硬壳,供客人品尝…… 正文.indd 19 2013-9-16 10:06:57 20   基础篇 初级免杀技术 上面所说壳就是我们加的保护,它并不会破坏里面的程序,当我们运行这个加壳的程序 时,系统首先会运行程序的“壳”,然后由壳将加密的程序逐步还原到内存中,最后运行程 序。这样一来,在我们看来,似乎加壳之后的程序并没有什么变化,然而它却达到了加密的 目的,这就是壳的作用。 现在,我们再回头看看反病毒软件,如果说加壳之后的文件我们都无法将其还原,那么 反病毒软件自然也就“看”不懂了。加密后的文件结构已经产生了天翻地覆的变化,原有的 特征码早已不知去处,反病毒软件自然也就会认为它是一个正常的文件了。 当然,鉴于目前所讲的深度,这些都只是停留在程序未执行前提下的理论,在文件执行 后,那就是另一番风景了,我们在第 6 章会详细地探讨这些问题。 由以上 3 种方法可知,基于文件的免杀基本上就是破坏原有程序的特征,无论是直接修 改特征码还是加上一段花指令,抑或是将其加壳,其最后的目的只有一个,那就是打乱或加 密可执行文件内部的数据。 2.4.2 内存免杀原理 自从文件免杀的方法在黑客圈子内部流传开后,反病毒公司将这场博弈升级到了另一个 层次—内存中。 内存在计算机安全领域中向来就是兵家必争之地,从信息截取、软件破解,到内核 Hook、修改内核,再到缓冲区溢出等,其主要战场都在内存中,由此可见内存是一个多么复 杂而又变幻莫测的地方。 之所以说内存复杂,是因为一般情况下内存是数据进入 CPU 之前的最后一个可控的物 理存储设备。在这里,数据往往都已经被处理成可以直接被 CPU 执行的形式了,像我们上 一小节讲的加壳免杀原理在这里也许就会失效了。 我们知道,CPU 不可能是为某一款加壳软件而特别设计的,因此某个软件被加壳后的可 执行代码 CPU 是读不懂的。这就要求在执行外壳代码时,要先将原软件解密,并放到内存 里,然后再通知 CPU 执行。 如果是这样,那么从理论上来讲任何被加密的可执行数据在被 CPU 执行前,肯定是会 被解密的,否则 CPU 就无法执行。也正是利用这个特点,反病毒公司便在这里设了一个关 卡,这就使得大部分运用原有文件免杀技巧处理过的病毒木马纷纷被杀。 其实,与上面这个原因相比较,反病毒公司选择扫描内存更多是从战略角度出发的。 因为将要被执行的程序肯定比未执行程序的威胁更大。即便是再厉害的病毒木马,只要 能保证它不被执行,它在用户的计算机中最多也就算是一个垃圾文件,就不会对用户及网络 构成任何威胁。 但是黑客们又是如何对抗内存查杀的呢?其实套路与文件查杀一样,因为杀毒软件的内 存扫描原理与硬盘上的文件扫描原理都是一样的,都是通过特征码比对的,只不过为了制造 迷惑性,大多数反病毒公司的内存扫描与文件扫描采用的不是同一套特征码,这就导致了一 个病毒木马同时拥有两套特征码,必须要将它们全部破坏掉才能躲过反病毒软件的查杀。 正文.indd 20 2013-9-16 10:06:57 第 2 章 免杀基础知识   21 因此,除了加壳外,黑客们对抗反病毒软件的基本思路没变。而对于加壳,只要加一个 会混淆程序原有代码的“猛”壳,其实还是能躲过杀毒软件的查杀的。 2.4.3 行为免杀原理 当文件查杀与内存查杀都相继失效后,反病毒厂商便提出了行为查杀的概念,从最早的 “文件防火墙”发展到后来的“主动防御”,再到现在的部分“云查杀”,其实都应用了行为 查杀技术。 而对于行为查杀,黑客们会怎样破解呢?我们都知道一个应用程序之所以被称为病毒或 者木马,就是因为它们执行后的行为与普通软件不一样。 因此从 2007 年行为查杀相继被大多数反病毒公司运用成熟后,黑客免杀技术这个领域 的门槛也就一下提高到了顶层。 反病毒公司将这场博弈彻底提高到了软件领域最深入的一层—系统底层,这就使得 黑客们需要掌握的各种高精尖知识爆炸式增长,这一举动将大批的黑客技术的初学者挡在 了门外。 然而由于初期的行为查杀刚刚兴起,很多反病毒产品的主动防御模块把关不严,应用的 技术也并不先进,从而导致了一大批内核级病毒木马的出现。而随着技术的逐渐升温,攻防 双方的技术最后变得势均力敌,反病毒公司得益于计算机领域先入为主的定律,使得黑客们 从这时开始陷入被动。 因此黑客免杀技术发展到现在,已经出现了向渗透入侵等领域靠拢的趋势,黑客们将能 躲过主动防御的方法称为 0Day,并且越来越多的木马选择使用本地缓冲区溢出等攻击手法 来突破主动防御。 但是反病毒爱好者们也不能因此麻痹大意,黑客领域中的任何技术从来都是靠思路与技 术这两条腿走路的,免杀技术也不例外。黑客技术的初学者仍然想出了非常多的方法,有效 地突破了现在的主动防御与云查杀。 鉴于这些思路的时效性,笔者就不在这里详细讲解了,这些技巧用一句话概括就是“条 条大路通罗马”,Windows 的强大之处就在于为我们提供了达到同一目的的多种不同的方法。 2.5 工具脱壳技巧 在真正开始学习免杀技术之前还是需要掌握一定的脱壳技巧的,因为很多木马都是加 过壳的,而且这些加壳后的木马已经被反病毒公司提取了特征,所以如果黑客们不能将其脱 壳,也就无法进行有效的免杀。这里假设读者“对于手工脱壳的相关内容理解起来还有一定 的难度”,所以首先为大家讲解一下工具脱壳的技巧。虽说是工具脱壳,但是完全可以顺利 脱掉一大部分常用壳。 正文.indd 21 2013-9-16 10:06:57 22   基础篇 初级免杀技术 2.5.1 壳的分类 所谓的“壳”就是一种对软件进行保护的加密程序,我们在上一节中已对它做了基本的 介绍。这一节将主要探讨壳的种类及其特点。 1. 压缩壳 压缩壳的主要目的是压缩应用程序的体积,例如最稳定的 UPX 可以将一般的应用程序 压缩到原体积的 30% 左右。 压缩壳并不会对被加壳程序本身做任何修改,而是直至将其换成一种更加节省空间的存 储方式,其目的大致类似于我们经常使用的 RAR 或 ZIP。经过压缩壳处理过的程序在真正被 CPU 执行前是会自动解压缩(解密)的。 2. 加密壳 加密壳的主要目的是保护原程序不被破解,一般情况下,经过加密壳处理的应用程序体 积会增加,但也有部分加密壳结合了压缩壳的特性,会在加密完成后再进行压缩。 而且一般情况下,加密壳会对原程序进行一定的修改,例如代码乱序、代码混淆等,因 此经过加密壳处理的程序即便是提交给 CPU 去执行,原程序的代码也还是发生了改变。 小知识 什么是“代码乱序”与“代码混淆”? 所谓的代码乱序,就是将本来线性执行的代码分成若干份后颠倒存储位置,再通过跳转 指令将其按照正确的顺序连接起来。这样对于 CPU 来说其执行的程序逻辑没变,只是多了 几条跳转指令而已,但是这段代码在硬盘上或内存中的组织排列方式却发生了很大的变化。 而代码混淆的本质其实就是将一条指令扩展为若干条指令,例如原本是一个计算“1+1” 的代码,但是混淆后就变成了“1+10–9+0–0+1–1”了,虽然最后的结果一样,但是程序本身 的代码甚至部分逻辑都发生了变化。 3. 虚拟机保护壳 虚拟机保护壳是近几年在软件安全领域内流行起来的一种非常强悍的加密保护方案。它 的关键技术就在于实现了一个软件版的 CPU,被加密的可执行代码已经不再遵守 Intel 制定 的 OPCode 标准了,而是执行由虚拟机作者本身制定的非公开的、动态的 CPU 指令编码解码 标准,我们通常称之为 TextCode。 虚拟机保护壳会将被保护程序的可执行代码重新编码为自己的软件 CPU 可以识别的格 式,并进行存储、加载及模拟执行。因此在任何时候,原程序代码对外界来说都将是一个彻 底的黑盒,任何人都很难破解。 由于 CPU 指令本身的复杂性(OPCode 的解析需要通过 3 张复杂的表相对照才能顺利进 行),因此被虚拟机加密过的可执行代码在业内至今仍没有人可以完全攻破。而更为强悍的 是,现今的虚拟机软件 CPU 的编码格式已经是随机生成的了。 正文.indd 22 2013-9-16 10:06:57 第 2 章 免杀基础知识   23 小知识 什么是虚拟机,什么是 OPCode ? 这里的虚拟机主要指的是软件虚拟机,由于它是用软件虚拟出来的,因此在虚拟机中的 任何操作均无法对真正的机器(宿主机)产生任何不可控的影响。而虚拟机按照应用领域的 不同分为如下几种类型。 模拟虚拟机 :它是一个模拟真实计算机运行环境的软件,我们可以像操作真实机器一 ❑ 样为这个虚拟的机器安装操作系统和应用软件,甚至在其中运行病毒木马做测试。这 种软件的典型代表为 VMware。 反病毒虚拟机 :这种虚拟机一般都是在杀毒软件中以一个引擎的方式存在的,其本身 ❑ 可以为应用程序顺利运行提供一个必要的环境,以捕获此应用程序的行为。 软件保护虚拟机 :这种虚拟机的主要目的是加密应用程序,其本身只负责简单的指令 ❑ 解码及堆栈模拟工作,然后将解码后的操作分配给软件 CPU 的不同分支去处理,直到 被加密软件需要与系统发生交互时,才将准备好的请求及堆栈环境提交给系统执行。 而 OPCode 则是一个稍微复杂些的概念。 我们首先要知道一件事,即我们所写的程序在没经过编译或解析时是无法执行的,例如 用 C 语言写一个“nNumA =1+2;”语句,这显然是不会被 CPU 直接执行的。要让 CPU 执行 这行代码,就需要经历一个编译的过程。 在编译器扫描完这行 C 语言代码后,有可能会生成以下汇编代码: ... push eax mov eax,0x1 add eax,0x2 mov [ebx+4],eax pop eax ... 严谨一点说,这些汇编代码都应该被称为“助记符(Mnemonic)”,然后再由汇编器生 成如下由 0 和 1 组成的机器码: 十六进制:50 B8 01 00 00 00 83 C0 02 89 45 04 58 二进制: 1010 0001 0111 0000 0000 0010 0000 0000 0000 0000 0000 0001 0000 0111 1000 000 这些可以直接被 CPU 执行的机器码才是我们前面所说的 OPCode。 由以上 3 种壳我们可以发现,其实所谓的“壳”就是包裹在被保护的应用程序外面的一 段代码,这段代码的使命是保证里面被加密的应用程序能够按照其原有的逻辑顺利执行。 2.5.2 免杀与脱壳是什么关系 我们都知道黑客们通过加壳的方式来躲过杀毒软件的查杀,那么脱壳(与加壳相反的过 程被称为脱壳)与免杀又是什么关系呢? 黑客们想要使用的某种恶意软件有可能已经被其他人做过类似的加密处理了,然而这个 正文.indd 23 2013-9-16 10:06:58 24   基础篇 初级免杀技术 被加密的版本又恰好被杀毒软件捕获到了,所以如果黑客们想要再次处理这个恶意软件,就 要先去掉那层无用的保护,因此这也是免杀技术泛滥的一种表现。 另外,如果读者是反病毒爱好者的话,那么掌握脱壳技巧也是与病毒木马对抗的基本功。 2.5.3 使用专用脱壳工具脱壳 针对不同的壳,网上有很多专用的脱壳工具,它们常常可以将某个壳的所有版本完全脱 掉,脱壳的效率与可靠性往往也是最高的。 这里我们先将一个程序加一层 UPX 的壳,双击运行 UPX 后单击“打开”按钮选择要加 壳的程序,如图 2-5 所示。打开后程序会自动跳到“压缩”选项卡下,单击选项卡下的“→” 按钮即可成功加壳,如图 2-6 所示。 图 2-5 选择要加壳的程序 图 2-6 单击“→”按钮加壳 加壳完毕后运行 PEID。PEID 是一款用来查看文件信息的强大工具,用它可查看文件 的加壳状态,如果想要用其加载某个程序,像如图 2-7 所示的那样将文件拖拽到 PEID 的界 面上即可打开该文件。打开文件后发现信息栏里显示 UPX 0.89.6 - 1.02 / 1.05 - 1.24 (Delphi) stub -> Markus & Laszlo 这段信息,如图 2-8 所示。 以上信息的大致意思是这个文件被 UPX 加壳了,壳的版本可能是 0.89.6 - 1.02 或 1.05 - 1.24。其他的信息暂且不用去管,只需要记住开始部分是文件的状态,包括加壳种类或编写 语言等信息,如果显示的是编写语言信息,则说明该程序没有被加壳。但是值得大家注意的 是,现在通过一定的处理已经可以使加壳文件欺骗 PEID 了。 为了便于大家以后的操作,下面举了几个实例为大家快速上手 PEID 做一个参考。 显示信息:Borland C++ 1999 解 释:文件采用 Borland C++ 编写,版本为 1999,文件未加壳。 ---------------------------------- 显示信息:ASPack 2.12 -> Alexey Solodovnikov 解 释:文件已被 ASPack 加壳,壳的版本为 2.12 ---------------------------------- 显示信息:Microsoft Visual C++ 6.0 正文.indd 24 2013-9-16 10:06:58 第 2 章 免杀基础知识   25 解 释:文件采用 Microsoft Visual C++ 编写,版本为 6.0,文件未加壳。 图 2-7 打开文件 图 2-8 分析后显示的信息 通过上面的例子我们可以发现,凡是被加壳的文件信息中都有一个“->”符号,它代表 后面的内容为这个壳的扩展信息。 下面就开始为这个文件脱壳。虽然针对 UPX 有一款名 为 Anti-UPX-Srambler 的脱壳软件,但是就目前的情况来看, 它已经不能脱掉 UPX 的壳了,因为较新版本的 UPX 本身就 带有脱壳功能,所以这款脱壳软件也就停止了更新了。我们 打开一个较新的 UPX 后加载那个已加壳的文件,发现 UPX 会自动打开相应对话框,并且其下的“解压”选项卡已经默 认选中,如图 2-9 所示。我们只需单击“执行”按钮即可成 功地将程序脱壳。 2.5.4 使用通用脱壳工具脱壳 既然叫做通用脱壳工具,肯定是能脱很多壳的,在这些工具里比较成熟的就要数 Quick Unpack 了,它不但可以脱去已知的大部分壳,还可以脱去一些经过加密的或变异的未知壳。 但是这里首先为大家展示一下怎样使用 PEID 脱壳,因为我们平多用 PEID 查壳,所 以如果可以直接用 PEID 来脱壳将是一件比较方便的事,而且 PEID 的脱壳效果也不错。我 们先用 PEID 打开一个已加壳的文件,如图 2-10 所示。单击“=>”按钮,依次选择“插 件”→“PEID 通用脱壳器”,在弹出的对话框中单击“->”按钮自动寻找入口点,然后单击 “脱壳(U)”按钮即可成功脱壳,如图 2-11 所示。脱壳过程中可能会提示是否使用 ImpREC 重建输入表,单击“是”按钮即可。 但是有时候单击“->”按钮后会运行原程序,并且 PEID 无法将其自动关闭,这时只需 手动关闭即可。如果使用 PEID 无法脱壳或脱壳后的程序不可用,就要看看 PEID 是否能正 确读出壳的信息了,如果能正确读出,我们可以使用超级巡警发布的基于虚拟机的万用脱壳 工具 VMUnpacker。VMUnpacker 的特点就是只要它能正确识别壳的信息,一般情况下都可 以完美脱壳。如果 PEID 无法正确读出壳的信息,那就要试试 Quick Unpack 了。但是 Quick Unpack 也有不好的地方,因为它的使用需要一定的技巧,并且有注意事项。另外在 Windows 图 2-9 单击“执行”按钮脱壳 正文.indd 25 2013-9-16 10:06:58 26   基础篇 初级免杀技术 XP 系统下如果使用 Quick Unpack 脱壳失败,也容易引起系统崩溃。 图 2-10 打开 PEID 的插件菜单 图 2-11 PEID 的通用脱壳插件 对于 Quick Unpack 的使用的方法,读者可以自己摸索,这里为了节省篇幅就不进一步讲 解了。 2.6 小结 到此,这一章就完全结束了。在这一章中我们介绍了许多看似简单,实则非常重要的知 识点,这些知识是笔者花费很多精力总结出来的。如果读者不能透彻地理解这些知识点,可 能对后面章节的理解有一定影响。 除此之外,这一章最大的特点就是始终以“选择”贯穿其中,针对有很多知识点都向读 者提出了“选择学习”的建议。但这并不代表这些内容真的很难懂,其实随着我们对计算机 研究的逐渐深入,就会知道“从数学角度上看,人们本无法理解事物,而只能去习惯它们” 这句话的真正含义。一开始就谋求真正的理解是一种愚蠢的做法,谁也不可能不经过学习就 能真正理解什么,而理解后的知识总结也因人而异。所以我们应该先试着去记住它、总结 它,再去应用它,最后才是理解它。希望这句话对您有用,也希望这句话能促使您再次阅读 本章中您认为值得反复琢磨的地方。 正文.indd 26 2013-9-16 10:06:58 第 3 章 免杀与特征码 如果说黑客技术的精髓在于 ShellCode,那么免杀技术的精髓就在于特征码免杀。病毒与 木马之所以能逃出反病毒软件的监控,很大一部分原因就是因为有特征码免杀技术的存在。 本章的任务就是带领大家进入这个颇具魅力的技术领域,我们将从简单的脚本木马免杀 开始介绍,引导大家逐步认识特征码、特征码免杀,进而了解如何修改特征码。其中对每一 步的讲解都力求细致,以便于读者能透彻了解特征码免杀技术,从而研究出自己独特的反特 征码免杀的方法,进而为以后防御病毒和木马的入侵打下坚实基础。 3.1 特征码免杀技术 上一章为各位读者大致介绍了一下特征码免杀技术的基本原理,但是并未阐述黑客的具 体操作过程。 本节将为各位读者介绍一下黑客是如何进行特征码免杀的。 3.1.1 理想状态下的免杀 首先,我们要知道黑客在从事病毒木马的免杀活动时是存在着非常多的变数的,也正是 那些变数不利于我们直观地了解特征码免杀这一技术行为。为了方便大家理解,下面会以一 个理想环境下的脚本木马为例,讲述黑客是怎样对其进行处理的 。6 这里以一款比较常见的脚本上传木马为例,用分割法对其进行免杀操作。所谓的分割 法,就是指将一个文件分为数份,然后再用反病毒软件查杀,如果发现其中某一份有病毒, 则说明这部分含有特征码,然后我们再将检测到病毒的这一份分割为数份,如此往复,直到 定位出我们认为长度合适的特征码为止,其操作流程图如图 3-1 所示。 我们先将文件按图 3-2 那样分为两份。 然后用反病毒软件查杀,发现“默认木马 .asp”与“2-0-0.asp”被查杀了,如图 3-3 所 示。这就说明文件“2-0-0.asp”里含有特征码,下面我们再将“2-0-0.asp”分为两份,继续 进行查杀,如果发现哪个文件有病毒就再次将其分割,直到将文件分割到足够小,方便我们 更改特征码为止。这里假设我们定位出了特征码在“<% err.clear %>”里,那么只需将其字 母大小写进行替换就可以了,例如替换为“<% ErR.clEaR %>”即可免杀。   这里提出的一些思想与技巧在脚本木马免杀方面也许并不通用,但是它有利于各位读者对免杀的进一步 认识。 正文.indd 27 2013-9-16 10:06:58 28   基础篇 初级免杀技术 图 3-1 用分割法发现特征码的过程 图 3-2 将脚本木马分成上下两份 图 3-3 发现 2-0-0.asp 中包含特征码 3.1.2 由脚本木马免杀理解特征码 到这里,不知道各位读者是否对脚本的特征码免杀有了更加直观的了解。上面通过分割 文件进而逐渐缩小范围的方式讲解了特征码的查找方式,以及特征码的存在形态。但是,如 果大家跟着前面所讲的内容逐步操作,那么很可能会陷入一个尴尬的循环中,因为只要将文 件分割到 3 份以上时,反病毒软件将不再能检测到病毒,可是如果将它们组合到一起再检测 时却仍然会查出病毒。 这是因为某些反病毒软件的扫描器采用的是密码校验和技术,密码校验和技术指的是 将一段病毒文件代码计算出特定的值,然后与病毒库的值进行比对,如果匹配到特征码则有 正文.indd 28 2013-9-16 10:06:59 第 3 章 免杀与特征码   29 毒,反之则无毒。但我们在分割文件时肯定会破坏它,因为原本在一起的代码让我们给分成 了若干份,密码校验和自然也就不同了,所以就不会检测出病毒,但是一旦我们将其组合起 来,又恢复了其原貌,因此会继续报毒。 在实际操作中,最多可以将文件分为两份,如果整个文件为 30 行代码,经检测是文件 的上半部分报毒,那么也就是说此反病毒引擎获取校验和的代码在前 15 行。而且如果再将 这 15 行代码分开后会发现不能被检测出病毒,那么我们就可以将目标盯在这 15 行代码上。 因为某些反病毒软件在密码校验和扫描算法上对字母大小写并不十分敏感,因此如果仅 靠更改大小写来免杀,不免有些没“技术含量”了。 下面为大家简单介绍一下黑客的脚本木马花指令免杀方法。花指令本是软件安全领域早 期的一种代码保护技术,后面的章节会有详细的介绍。脚本木马的花指令免杀操作起来特别 简单,只需在如图 3-4 所示的第 13 行代码的下面添加一句“<%response.write ""%>”代码即 可。现在再用杀毒软件查杀后发现已经躲过了检测。 图 3-4 为脚本木马添加花指令免杀 值得注意的是,某种扫描技术可能是某个反病毒厂商发明的,但这并不代表此技术就是 某厂商所独有的,比如一些反病毒软件,在查杀例子中的这个木马时与本例中的密码校验和 技术的表现是完全一致的。所以我们要更加注重现象,万不可钻牛角尖,认为某种反病毒技 术就一定是属于某款反病毒产品的。 3.2 特征码定位原理 相信通过上一节的学习,各位读者对特征码已经有了比较深层次的理解,为了使大家能 够更好地理解特征码免杀,这一节我们将讲解黑客们在定位特征码时使用的一些典型逻辑与 技术。同时会以目前几款特征码定位器的工作原理作为引导,帮助读者更加透彻地了解特征 码定位的原理,从而可对付在反病毒时碰到的一些突发问题。 3.2.1 特征码逐块填充定位原理 逐块填充定位的方法在国内首先出现在 CCL 上,CCL 是国内首款演示研究性的特征码 定位工具,也是一款原理简单的单一特征码定位器。 鉴于我们现在还没讲到特征码定位器的使用技巧,所以这里只讲原理,不涉及操作,具 体操作会在后面介绍。待了解了特征码定位器的使用技巧后,如果再回头来反复咀嚼这一节 正文.indd 29 2013-9-16 10:06:59 30   基础篇 初级免杀技术 所讲的内容,相信对免杀的理解也会更进一步。 为了更加直观地介绍各个特征码定位器的原理,我制作了一个极其简单的例子程序,如 图 3-5 所示。当然这个程序是不能运行的,只是为了演示所用。这个程序中的“1111……” 代表的是有数据的地方,其中的“AA”就是我们假定的特征码。 图 3-5 理想状态下的例子“程序” 当我们用 CCL 定位特征码时,它会从区段头部开始填充“00”数据,因为“00”往往 都表示“此处为空”,所以如果将某一段数据替换为“00”,也就相当于删除了这段数据。为 了让演示效果更加明显,这里将整个文件作为一个区段来定位。现在来看看 CCL 生成的第 一个无后缀文件 OUT_00000000_00000010,如图 3-6 所示。不难发现,第一行已经被无意义 的“00”给填充了,我们假设的特征码“AA”现在已经不存在了,很显然这个文件是不会 被反病毒软件查杀的。 图 3-6 被 CCL 填充后的效果 下面再看看生成的第二个文件 OUT_00000010_00000010,如图 3-7 所示。 图 3-7 CCL 生成的第二个文件 我们发现由于填充的部位变成了第 2 行,所以特征码“AA”这时又暴露出来,因此这 个文件肯定会被反病毒软件查杀。再来看第三个文件 OUT_00000020_00000010,如图 3-8 所示。 图 3-8 CCL 生成的第三个文件 很显然,这次是文件的第 3 行被“00”填充了,这个文件依然包含特征码。到了现 在,我们可以猜得出来,第四个文件肯定是第 4 行被填充了,而且由于没有覆盖住特征码 “AA”,因此它同样会被杀,如图 3-9 所示。 正文.indd 30 2013-9-16 10:06:59 第 3 章 免杀与特征码   31 图 3-9 CCL 生成的第四个文件 在这次操作中 CCL 总共生成了 4 个文件,其中 3 个被杀,经过简单的推理可以确定, 是第一个文件覆盖掉了特征码,又因为第一个文件中的第一行数据被“00”填充了,进而可 以很自然地推断出—特征码就在第一行。 但是这个特征码的范围是不是有些大呢?其实在真正操作的时候,如果我们想得到比较 小的特征码范围,可以将 CCL 一次填充“00”的字节数减少,例如由默认的 16 字节减少到 4 字节。为了便于大家的理解,我做了一张比较形象的 CCL 特征码定位示意图,如图 3-10 所示。通过这张图可以更加透彻地理解 CCL 特征码定位原理了。 图 3-10 CCL 特征码定位示意图 3.2.2 特征码逐块暴露定位原理 所谓的逐块暴露其实就是一个与逐块填充相反的过程,MyCCL 是现在应用最广泛的一 款特征码定位器,也是一款采用逐块暴露定位原理的特征码定位软件,它因反病毒软件采用 复合特征码定位而诞生。所谓的复合特征码,就是一个病毒定义了一套以上的特征码,只有 改掉所有的特征码后才不会被查杀。 为了便于演示 MyCCL 的复合定位方法,这里准备了如图 3-11 所示的示例程序,其中的 “AA”、“CC”为两个特征码,如果这两个特征码有一个存在,反病毒软件就会报毒。现在我 们看看 MyCCL 究竟是怎样工作的吧。 图 3-11 一个用于实验的多特征码程序 正文.indd 31 2013-9-16 10:06:59 32   基础篇 初级免杀技术 将 MyCCL 文件的分块个数设置为 3,MyCCL 会将“例子 .exe”按照其特有的填充方 式生成 3 个文件,并用“00”填充不同的位置。第一次分为如图 3-12 所示的 3 个文件。由 图 3-12 可知,第一个文件暴露出了 1/3 的数据,剩下的被“00”填充了,第二个文件暴露了 2/3 的数据,而第三个文件则全部暴露了。根据 MyCCL 生成文件的规律可知,它生成第一 批文件采用的是由头到尾的暴露方式。但是在图中可发现,这 3 个文件或多或少都含有特征 码,那怎么办呢?继续往下看,当反病毒软件将这 3 个文件全部删除后,用 MyCCL 生成了 第二批文件。 图 3-12 MyCCL 生成的第一批文件 当然,第二批生成的文件仍然是 3 个,如图 3-13 所示。 图 3-13 MyCCL 生成的第二批文件 这次 MyCCL 采用的方式有些特别,它首先默认上次生成的第一个文件中有特征码,也 就是说 MyCCL 先默认第一个文件暴露的那块数据中含有特征码,所以这次它生成的 3 个文 件都不含有这一块数据,而是直接从第二块数据开始暴露。 这 3 个文件生成完毕后,在使用反病毒软件查杀时只有暴露了第三块数据的文件被删掉 了,由此 MyCCL 就很容易地判断出在第三个文件中包含特征码。在用反病毒软件将第三个 文件查杀之后,再用 MyCCL 生成第 3 批文件,如图 3-14 所示。 在图 3-14 中,我们发现特征码已经被完全覆盖了,由此 MyCCL 得出了如图 3-15 所示 的结果。 正文.indd 32 2013-9-16 10:06:59 第 3 章 免杀与特征码   33 图 3-14 MyCCL 生成的第三批文件 也许各位读者看到这里会有些迷糊,为什么 MyCCL 最后一次生成的文件中,其中两个是一样的呢?其实很简 单,用一句话概括就是“由上到下逐渐暴露,遇到特征码 以后则始终将其覆盖,直到覆盖掉所有特征码”。因为在生 成第二批文件时 MyCCL 已经知道第三个文件中包含有特 征码了,但是遵循“遇到特征码以后则始终将其覆盖”的 原则,所以本该暴露的第三块数据并没暴露,于是就造成 了两个文件内容一致的奇怪现象。 为了便于大家理解,我制作了一张 MyCCL 特征码定位原理示意图,如图 3-16 所示。通 过这张示意图可以帮助你更清楚地了解 MyCCL 的特征码定位原理。 图 3-16 特征码逐块暴露定位原理 图 3-15 MyCCL 生成的 特征码分布报告 正文.indd 33 2013-9-16 10:07:00 34   基础篇 初级免杀技术 3.2.3 特征码混合定位原理 特征码的混合定位一般是应用二分法或逐块暴露法定位出含有特征码的较小区域,然后 再采用逐位测试法探测出特征码的具体位置及长度。 应用特征码混合定位原理比较成熟的工具是 MultiCCL 定位工具,它的具体思路是先使 用二分法定位出特征码的粗略位置,再用逐位测试法探测出特征码的具体位置与长度。 由于上面在介绍脚本木马免杀技术时已经介绍过二分法,因此这节主要探索逐位测试法 的定位原理。 首先假设我们拥有如图 3-17 所示的测试数据块。 再假设这个数据块已经被特征码定位软件(简称“定位软件”)用粗略定位的方式确定 里面含有特征码。而由图 3-17 可知,这个数据块含有 4 组特征码,这其实应该是一个比较罕 见的情况。 一般情况下定位软件会从头部开始逐位后退,直到后退到如图 3-18 所示的位置时,反 病毒软件才报毒。 图 3-17 含有特征码的测试数据块 图 3-18 第一段特征码暴露出来 这时定位软件已经知道第一段特征码的末尾在哪里了,随后定位软件会逐位向前移动测 试,如图 3-19 所示。 在图 3-19 所示的这组文件中,进行到最后一步时反病毒软件才会报毒,这时定位工具 确定了这一段特征码的头部位置。到此为止定位软件已经精确地定位出了特征码的开始与末 尾偏移,于是将此特征码填充掉,然后开始对第二个特征码进行定位,如图 3-20 所示。 图 3-19 逐位向前移动测试 图 3-20 开始定位第二段特征码 正文.indd 34 2013-9-16 10:07:00 第 3 章 免杀与特征码   35 定位软件按照此逻辑如此往复后,最终会生成一个如图 3-21 所示的文件。至此所有的 特征码都被精确定位完毕。 3.3 脚本木马定位特征码 为了让大家更直观地了解特征码定位技巧,笔者以脚本木马的 特征码定位为例进行讲解,因为它相对更容易理解。俗话说“磨刀 不误砍柴工”,下面先为大家介绍一下 MyCCL 特征码定位器这个工具,相信会对大家日后 的深入研究与自学有帮助。打开 MyCCL 程序后的界面如图 3-22 所示。为了便于理解,我将 MyCCL 分为“参数区”与“控制区”来进行讲解。 参数区 控制区 图 3-22 MyCCL 的主界面 (1)参数区 参数区各个参数及其说明如下。 文件路径:将进行特征码定位的木马文件的路径(必填项)。 ❑ 目录路径 :存放 MyCCL 即将生成的特征码样本的目录,默认是与木马同文件夹下的 ❑ OUTPUT 目录(必填项)。 分块个数:生成特征码样本的数量,数量越多,定位结果越精确(必填项)。 ❑ 单位长度:填充无效字节的单位长度,例如填 120,就是每次填充 120 个无效字节。 ❑ 填充:填充数据设定,默认为“00”,也可以是其他十六进制信息。 ❑ 开始位置:第一个特征码样本将会从此处指定的位置开始填充。 ❑ 分段长度:填充字符的总长度。 ❑ 结束位置:最后一个特征码样本填充到此处指定位置便结束了。 ❑ 图 3-21 最终生成的文件 正文.indd 35 2013-9-16 10:07:00 36   基础篇 初级免杀技术 “正向”按钮:选择填充方向,例如“正向”就是从文件头部开始暴露。 ❑ 复合定位:超过一处特征码时便需要选择此定位方法,推荐选择此方法。 ❑ 单一定位:单一特征码定位。 ❑ (2)控制区 控制区各个按钮及其说明如下。 “文件”按钮:用来选择要进行免杀的木马文件。 ❑ “目录”按钮:用来选择生成特征码样本文件的目录,默认即可,无需选择。 ❑ “特征区间”按钮:用来展开存放已定位出来特征码的信息栏。 ❑ “< 生成 >”按钮:用来执行特征码定位样本生成的命令。 ❑ “二次处理”按钮:单击“< 生成 >”按钮,并删除带毒样本后,用来二次精确定位。 ❑ 关于 MyCCL 就先介绍到这里,由于 MyCCL 存在后缀名 Bug 问题,所以不能生成带有 后缀名的文件,但是现在的大多数反病毒软件都已经不查杀无后缀的脚本木马了,所以需要 用一款工具来辅助完成任务。 现在就用海阳顶端脚本木马(简称“海阳木马”)做一个针对某反病毒软件的免杀案例。 打开 MyCCL 后选择海阳木马,分块个数填写为 100,如图 3-23 所示。有的读者可能会问 了,为什么这个 MyCCL 变样了呢?其实这是一款改造过的 MyCCL,它比原先的版本更加 稳定,而且也没有了背景音乐,并且它对程序的一些资源与区段进行了删减,所以其体积也 减小了 20%,更利于各位读者研究与试验。 单击“< 生成 >”按钮后,运行文件名批量更改工具 Bulk Rename Utility,打开特征码样 本文件夹 OUTPUT,依次单击菜单栏的“动作”→“全选”,如图 3-24 所示。 图 3-23 MyCCL 安静稳定版 图 3-24 依次单击菜单栏的“动作”→“全选” 然后在“添加”框架内的“后缀名”里填入 .asp,如图 3-25 所示。最后单击右下角的 “重命名”按钮即可。 正文.indd 36 2013-9-16 10:07:01 第 3 章 免杀与特征码   37 图 3-25 在“添加”框架内的“后缀名”里填入 .asp 现在找到特征码样本文件夹 OUTPUT,并进行查杀,查出了 8 个带毒文件。删除报毒样 本后,还需将文件名更改回来,这样才能被 MyCCL 正确识别,否则将会定位出错误的结果。 再返回到 MyCCL 界面,单击“二次处理”按钮,并用前面的方法将文件重命名之后再 次查杀。如此反复,最后得到的结果如图 3-26 所示。 图 3-26 最后结果 应该怎样理解 MyCCL 提供的以下报告呢?下面我就带领大家一点点来了解。 正文.indd 37 2013-9-16 10:07:01 38   基础篇 初级免杀技术 ------------------------------------------------ >> 复合特征码定位结果 << 文件名 :E:\ 免杀实验 \2006P.asp ------------------------------------------------ 特征码 物理地址 / 物理长度 如下 : [ 特征 ] 00000000_00000468 特征码分布示意图 : [MMM----------------------------------------------------] [-------------------------------------------------------] [-------------------------------------------------------] [-------------------------------------------------------] [-------------------------------------------------------] 其实 MyCCL 提供的报告已经比较详尽了,需要重点关注的就是“[ 特征 ] 00000000_ 00000468”这段报告信息。正如上面所标示的,从偏移地址为 0x00000000 的地方开始,其 后面 0x00000468 偏移量的数据内含有特征码。 零基础的读者也许还不明白偏移地址是什么意思,这里先简单为大家介绍一下。就 拿 0x000000A0 这个偏移地址来说,如果想知道它指定的偏移地址是什么数据的话,先用 WinHex 等十六进制查看工具打开这个文件,然后在这个工具中看看“日光海岸 .mp3”这个 文件的 0x000000A0 处是什么信息。 首先打开 WinHex 十六进制编辑工具,按【Ctrl+O】快捷键打开文件对话框,选择“日 光海岸 .mp3”,在 Offset 栏下的第 11 行就是我们的目的地,如图 3-27 所示。这个位置的内 容是一个十六进制数据 D3。 图 3-27 文件“日光海岸 .mp3”偏移 0x000000A0 处的十六进制信息 知道怎样寻找偏移地址后,那么找到刚才定位出来的特征码“[ 特征 ] 00000000_ 00000468”也就容易了。但是在这之前需要注意的是,MyCCL 生成的报告有个缺陷,虽然 前面的地址信息是十六进制的,但是后面的长度信息却是十进制的,所以在使用前要将其 转换一下才行。 由此我们找到了特征码所在的位置,也就是如图 3-28 所示的地方。当然,一般情况下 是不会出现这么长的特征码的,这里是为了便于各位读者理解,所以举了一个比较特殊的 例子。 正文.indd 38 2013-9-16 10:07:02 第 3 章 免杀与特征码   39 图 3-28 特征码的开始与结尾偏移 3.4 MyCCL 查找文件特征码 通过上一节的学习,相信大家对 MyCCL 的操作已经有了一个整体的了解。从这一节开 始,我们将会接触到黑客实战级的免杀操作。 3.4.1 MyCCL 的典型应用 NBSI 是国内 SQL 注入工具的代表作品之一,今天我们就用 MyCCL 定位一下 NBSI 的卡巴斯基特征码,为大家演示一下黑客是怎样制作免杀的,以及黑客在免杀中会思考什 么问题。 首先找到一个无壳版的 NBSI,运行 MyCCL 后选择 NBSI,并在“分块个数”中填写 20。有的读者或许有些疑问,这里的分块个数为什么设为 20,是以什么为依据的呢?其实设 置分块个数不外乎就涉及两个问题,一个是时间问题,另一个是成功率问题。 从时间上来讲,分块个数越多,定位的特征码就越精确,就拿 NBSI 来讲,如果第一次 生成 330 895 个特征码样本的话,甚至不用“复合定位”进行二次处理就可以定位出精度为 1 个字节的特征码。但是这 33 万个文件没有 1 个小时恐怕是处理不完的。 因此,第一次完全可以少生成一些,例如先定位出 500 字节的特征码,由于文件的绝大 部分区域不含有特征码,所以在二次复合定位时完全可以把那些不含特征码的区域忽略掉, 这样一来就可以在极小的区域内查找特征码了。如果就像上面所说的,第一次定位出 500 字 正文.indd 39 2013-9-16 10:07:02 40   基础篇 初级免杀技术 节精度的特征码,那么进行第二次符合定位时,只需生成 250 个特征码样本即可完成特征码 的查找工作。这样一来总共生成的文件不超过 2000 个,效率一下提高了 200 多倍。 当然,究竟生成多少个样本还是要靠个人把握的。就我个人来讲,我一般第一次会先生 成 20 个样本,第二次则以精度优先,在生成样本个数不超过 500 的前提下,将精度控制在 50 字节以内。如果将精度控制在 50 字节以内会超过 500 个样本,我便会考虑降低一些精度 了。总之我的原则就是将样本个数控制在 500 个以内,而精度则控制在 50 字节以内,这样, 针对大多数体积在 100KB~1000KB 的木马文件来说,定位的效率会比较高。至于成功率问 题,后面会单独探讨。 现在回到免杀现场,在设置完生成个数后,单击“< 生成 >”按钮生成样本文件。用卡 巴斯基反病毒软件扫描后删除所有带毒的文件,然后单击“二次处理”按钮,再用卡巴扫描。 如果这一次并没有发现病毒,再次单击“二次处理”按钮,将会出来如图 3-29 所示的结果。 通过结果可以看出 NBSI 中只存在一处特征码。但由于这是第一次定位,所以特征码精 度有些吓人,竟然是 8141 个字节!这肯定要进行复合定位了,单击“特征区间”按钮后弹 出一个名为“填充 / 特征码 区间设定”的界面,如图 3-30 所示。 图 3-29 定位 NBSI 的卡巴斯基特征码结果 图 3-30 “填充 / 特征码 区间设定”界面 不要被它的名字给唬住了,其实它就是一个记录特征码的 地方,只不过加了一些针对特征码进行二次处理的功能而已。 由图 3-30 不难发现,刚刚定位出来的特征码就在那里。接下来 右键单击这段特征码,由于特征码的精度仍然有些大,所以在 弹出的菜单里选择“复合定位此处特征码”,然后在“单位长度”里填写 80,也就是说这次 定位出来的特征码精度为 80 字节,如图 3-31 所示。 然后重复上面的步骤,单击“< 生成 >” →用反病毒软件扫描并删除→单击“二次处 理” →用反病毒软件扫描并删除→单击“二次处理”…… 图 3-31 填写单位长度 正文.indd 40 2013-9-16 10:07:02 第 3 章 免杀与特征码   41 需要注意的是,由于生成的文件个数较多,在单击“< 生成 >”按钮后会出现计算机假 死状态,不过等待一段时间即可生成完毕。 经过几次重复操作后,最终得到的特征码为 00003AFB_0000005C。 3.4.2 针对 MyCCL 的一点思考 上一节中我们提到分块个数除了会影响到特征码查找时间以外,还会涉及成功率问题,也 许有过免杀经验的读者会对此疑问重重,但是相信你看完以下两个问题后就不会有困惑了。 为什么有时候定位的特征码不尽相同?除了和反病毒软件所采用的部分技术有关之 ❑ 外,还有没有其他原因? 为什么定位特征码时,总是精度比较低,或者经常会出现一些奇怪的问题? ❑ 相信这两个问题会令一些读者沉思一下。可以确定的是,上面的问题必然是有原因的, 不可能是随机出现的问题,而既然有原因,那么肯定就有办法 找到原因。 要想找到相关的原因,我们还要从 MyCCL 的工作原理说 起。举一个比较极端的例子,假设有如图 3-32 所示的一个文件。 它的特征码“AA”正好位于文件的正中央,当我们将“分 块个数”设为 2 时,就会出现如图 3-33 所示的流程。 图 3-33 分块个数为 2 由图 3-33 可知,文件被填充到一半时正好会破坏掉了特征码,此后无论怎样被填充都 不会将特征码暴露出来了,所以 MyCCL 得出了“文件一与文件二掩盖了特征码,特征码在 24~48 字节之间”这个结论,也就是将半个文件都定位成特征码了。而当用这个结论来进行 二次“复合定位特征码”时,却永远也找不到带毒文件,因为这处特征码在定位时已经被一 分为二了。所以说此时用 MyCCL 定位的最高精度就是这一半文件的大小了。 而将文件数设为 3 时,则会出现如图 3-34 所示的流程,可见受其特征码位置的影响, 定位出来的精度为 1/3 的文件长度,而后即便使用了粗略的复合定位法,特征码的长度仍然 是整个文件的 1/6。可以发现,文件数设为 3 时生成的文件个数虽然只比设为 2 时多了 1 个, 但是在这种特殊情况下,特征码的精度却提高了 3 倍!那么如果将生成样本数设为 6 个呢? 图 3-32 一个比较极端的例子 正文.indd 41 2013-9-16 10:07:03 42   基础篇 初级免杀技术 经过计算,特征码的精度与分为 3 个相比,其精度提高了 2 倍。 图 3-34 分块个数设为 3 因此,分块个数对特征码的定位是有很大影响的,但是如何才能让 MyCCL 按照黑客所 期望的方式工作呢?这似乎并没有难倒他们。 通过上面的例子不难发现,初次所设置的样本文件生成个数越多,定位出来的结果自 然也就越精确,而且生成样本的个数与特征码的精度是成正比的。但是随着生成样本数的增 多,它对特征码精度的影响就会逐渐减小,所以在必要的时候选择一个比较适中的生成个数 才是明智之举。 通过上面的讲解,也许大家已经明白了生成个数对特征码定位成功率的影响,但是也 许还会有读者问 :这仅仅是一个比较特殊的例子而已,恐怕在实际操作中很难碰到这类情况 吧?请读者们注意,上面用的是基于特征码扫描的普通反病毒引擎做的实验,如果在基于卡 巴斯基的密码校验和扫描方式下做这个实验的话,鉴于密码校验和的特征码体积之大,原理 之特殊,碰到这种情况的概率就会成倍增长。 除此之外,MyCCL 的“填充”项也是不容忽视的,虽然大多数用默认的“00”即可, 但是现在已经有反病毒软件可以识别这种填充方式了,遇到特征偏移量位置全部被“00”填 充的情况时,反病毒软件就会自动释放出伪特征码,导致黑客在定位最后一处特征码时受 阻,从而会使整个免杀工作以失败告终。 所以黑客早已不再用简单的 0x00 来覆盖特征码了,如果我们在实验中碰到了类似情况, 正文.indd 42 2013-9-16 10:07:03 第 3 章 免杀与特征码   43 完全可以将填充字符改为其他字符,例如 0x11、0x22、0xAA 等。 而且从概率方面来讲,一个文件存在的空区段或空白处往往占整个文件体积的 10% 左 右,也就是说“00”字节在文件中出现的概率大约为 10%,而其他十六进制的那 15 个字符 出现的概率仅为 6.6%。那么特征码必然也会受影响,也就是说出现特征码数据为“00”的概 率是比较大的,如果此时再用填“00”的方式来定位这种特征码,那是无论如何也定位不出 来的! 一个简简单单的 MyCCL 的填充个数就引发出了这么多的问题,如果大家在以后的学习 中勤于思考,一定会想出应对特征码定位的就方法。 通过本节的学习,相信您在掌握 MyCCL 的文件特征码定位技巧之余,也学到了其他的 东西,比如利用本节所讲解的知识,就可以澄清目前免杀领域内的一些模糊问题与错误的思 路。但是即便如此,单就 MyCCL 来讲,还是有一些问题等待大家去探索的,例如分块个数 的奇偶数问题等。 3.5 MyCCL 查找内存特征码 如果想定位内存特征码,则需要注意两个问题,一个是断网,另一个就是一定要先做好 文件的免杀,这样才能精确地找到所需要的内存特征码,否则定位结果将会非常不可信。 现在我们已经有了一个做好文件免杀的木马服务端 Server.exe,用 MyCCL 打开后单击 “内存复合特征码定位前勾选此处,否则勿选!”复选框,如图 3-35 所示。 图 3-35 勾选复选框 然后单击“< 生成 >”按钮生成样本文件,最后用鼠标右键单击“目录路径”处,调出 “用 TK.Loader 打开目录”菜单并单击即可,如图 3-36 所示。 随后便进入如图 3-37 所示的“内存辅助定位器 TK.Loader”界面,单击“全部载入”按 钮后即可进行内存查毒了。 杀完毒之后,剩下的操作就与进行文件免杀一样了。内存定位的唯一不同之处就在于需 要用 TK.Loader 将样本加载到内存中,再就是反病毒软件在查杀病毒时要选择内存扫描。需 要注意的是,有时反病毒软件并不能顺利地删除所有的木马文件,如果出现这种情况,到目 录里手工删除即可,不过在执行手工删除前,要先退出 TK.Loader。 正文.indd 43 2013-9-16 10:07:03 44   基础篇 初级免杀技术 图 3-36 调出“用 TK.Loader 打开目录”菜单 图 3-37 “内存辅助定位器 TK.Loader”界面 3.6 特征码修改方法 通过前面的学习,相信各位对黑客是怎样查找特征码的已经比较了解了,但是单单查找 出特征码并不能达到其想要免杀目的,如果想让文件免杀,又使文件正常运行,就要用到特 征码修改技巧了。 这里先提示一下,各位读者在进行特征码修改实验时,并不需要拿个真正的木马来做, 完全可以随便挑选一个体积比较小的软件来实验。下面就由浅入深地给大家讲解特征码的修 改方法。 3.6.1 简单的特征码修改 先说明一下,这里所讲的方法只适用于文件特征码,对于内存特征码的修改方法,将在 下一节中介绍。既然是简单的特征码修改,那么就从简单的大小写替换方法开始讲起,大家 理解起来会比较容易。 1. 大小写替换修改 所谓的大小写替换方法就是将原有的大写或小写字母更改为相反的状态,例如特征码为 code,那么不管是将其改为 CODE 还是 Code 或是 coDe,都可以达到免杀的目的。7 这种方法适用于所有特征区域出现字符的状况,如图 3-38 中所选定的区域就是一处特 征码,我们可以发现这处特征码的每个字符之间都有个“.”,也就是“00”隔开,因此可以 推断这属于 Unicode 类型 。不过字符串的类型并不影响我们更改特征码,之所以介绍一下 相关知识是为了让大家掌握更多的基础知识。   采用这种说法仅为了便于读者理解,其本身并不严谨。相对比ASCII来说,采用Unicode编码的数据都是双 字节的,因此在遇到英文字符或英文标点符号及数字时高位就会空出来,而空出来的0x00就是正文中所说 的“.”了。 正文.indd 44 2013-9-16 10:07:04 第 3 章 免杀与特征码   45 图 3-38 查找到的特征码 由图 3-37 可知,特征码其实就是“Explor”这段字符,因此只需要对其进行简单的大小 写替换就可以了。 但是为什么在将字母大小写更改之后就会使反病毒软件“失效”呢?这实际上是基于 Windows 系统与反病毒软件的一个不同特性的,Windows 系统在很多情况下对大小写并不敏 感,但是反病毒软件则不同,它们大多数是根据字符的编码来判定病毒特征的,而大写字母 与小写字母的编码是不同的,因此修改后的程序虽然对于反病毒软件来说已经完全变了,但 在 Windows 系统下仍然可以正常运行。 那是不是碰到字母就采用大小写替换方法即可放心使用呢?事实上并非如此,个别的情 况下还是不能使用的(例如系统的 API 函数),我们在以后的章节中会向大家介绍。 2. 用“00”字节填充 前面在讲解特征码查找原理时说过,在汇编里“00”表示空的意思,如果将某一个代 码在十六进制下用“00”替换的话,那么就相当于删除了这段代码,所以在程序运行时就会 存在出现一些问题的概率,如果想要尽量避免出现这些问题,那么就应该尽量少地使用“00” 来填充,或者在操作时灵活运用。例如如果用这个字节填充失败,就应该换一个字节试试,如 果所有的字节都不行,那么就在定位特征码时将精度调低一些,这样选择的余地就会更大。 3. 加 1 减 1 法 加 1 减 1 法所利用的就是十六进制值相近的部分汇编指令,其所代表的意思往往也大体相 同,例如十六进制的 0x74、0x75 分别代表汇编指令中的 JE 与 JNE,虽然它们所代表的含义相反, 但都是具有跳转功能的指令。需要提醒各位读者的是,本节里讨论的都是坊间流传的一些真实的 修改方法,这些方法看起来似乎根本不符合某些基本原理,但是在某些情况下确实很管用。 知晓这些方法有利于我们在以后的反病毒工作中更加从容地处理一些看似不不合理的 事件。 3.6.2 特征码修改进阶 这一部分将介绍以反汇编的方式修改特征码的方法,这里介绍的方法对文件特征码和内 存特征码均有一定的作用。8 以反汇编的方式修改特征码时,首先将得出的十六进制偏移量地址改为内存偏移地址 , 听起来似乎很模糊,其实操作起来却非常简单。   正确的说法应该是“将文件偏移地址转换为虚拟偏移地址”,之所以用白话方式描述,是考虑了部分读者 的基础。 正文.indd 45 2013-9-16 10:07:04 46   基础篇 初级免杀技术 使用 OC 偏移量转换器即可将偏移地址转换为内存地址,转换后便得出了如图 3-39 所示 的结果。其中,0x0100FAEE 即为转换之后的内存地址。在本节下面将要提到的所有特征码 修改方法中都要先进行这一步操作,此内容在后面的章 节中将不再重复了。 1. 空白区域跳转法 这种方法应该是修改特征码工作中最常用的一种方 法了。当然,也应该是最好用的一种方法。但是对于入 门不久的读者来讲,也许在操作时会遇到一些小麻烦, 这里所说的“小麻烦”指的是这种方法操作起来比较麻 烦,由于刚入门的读者可能之前没怎么使用过这类工 具,所以很可能在操作时会粗心大意,造成修改失败。 假设我们找到一处特征码“0000EEEE _00000004”,用 OC 转换之后得到内存地址 “0x0100FAEE”,现在用 Ollydbg 打开实验文件,如图 3-40 所示。 图 3-40 Ollydbg 主界面 1) 按 快 捷 键 Ctrl+G 调 出“ 跟 随 表 达 式 ” 对 话 框, 并 输 入 转 换 出 来 的 内 存 地 址 “0x0100FAEE”,然后用鼠标单击地址“0x0100FAEE”处的汇编指令,按快捷键 Ctrl+C 复 制,并保存在记事本中,如图 3-41 所示。 图 3-41 保存一段汇编指令 2)找到如图 3-42 所示的一处空白区域,并记住其中的任意一个地址,这里选择的是 图 3-39 将偏移地址转换为内存地址 (虚拟偏移地址) 正文.indd 46 2013-9-16 10:07:04 第 3 章 免杀与特征码   47 “0x0101865E”这个地址。 图 3-42 找到空白区域 3)返回“0x0100FAEE”处,右键单击这句指令,在弹出的对话框中依次选择“二进 制”→“用 NOP 填充”,如图 3-43 所示。然后再以同样的方式将地址“0x0100FAF0”与 “0x0100FAF2”的内容也用 NOP 填充(在操作之前将位于这两个地址后面的汇编指令保存在 记事本里)。 图 3-43 用 Nop 填充 4)选中刚刚 NOP 的语句,在“0x0100FAEE”行单击右键,在弹出的如图 3-44 所示的 菜单中选择“汇编”,然后写入指令 jmp 0x 0101865E,无条件跳转到刚才找到的那个空白地 址处。 图 3-44 汇编此处 5)记下“0x0100FAEE”下面的地址“0x0100FAF3”,再到“0x0101865E”这个刚才找 到的空白地址处右键单击,并在弹出的菜单中选择“汇编”,同时写入前面记录在记事本的 3 条指令,如图 3-45 所示。我想大家应该发现了,图 3-45 中的不就是刚才 NOP 掉的那个语句 吗(参见图 3-43)?正是如此,但是我们为什么要这样做呢?这个问题先放一放,将这次修 改完成之后再说。 6)将“0x0101865E”下面那条空指令汇编为 jmp 0100FAF3。最后在这个窗口的任意区 域单击右键,依次选择“复制到可执行文件” →“所有修改”,如图 3-46 所示。在弹出的对 话框中单击“全部复制”按钮,然后在新界面中单击右键,并选择“保存文件”即可。 正文.indd 47 2013-9-16 10:07:05 48   基础篇 初级免杀技术 图 3-45 在“0x0101865E”汇编入程序入口点处被 NOP 掉的 3 条指令 图 3-46 复制到可执行文件 到这里已经修改完毕了,为了使得各位读者能更加清晰地了解这种修改方法,下面介绍 一下关于“空白区域跳转法”的一点补充知识。 看了上面的操作,不知道大家是否会有这样的疑问 :这样跳来跳去的究竟是要达到什么 目的呢?其实这是利用杀毒软件特征码查杀的弊端所创建的一种修改方法。我们知道,特征 码的定位是有一个偏移量地址的,而这样更改之后在原来那个偏移地址里的内容就变成了跳 转指令,原来的指令则被移动到了另外一个位置,所以杀毒软件自然也就不报毒了。而且由 于那两个跳转的存在,所以整个程序仍然是连贯的,整体修改思路如图 3-47 所示。对此还不 太明白的朋友可以根据这幅插图进一步理解一下。 图 3-47“空白区域跳转法”的修改逻辑 正文.indd 48 2013-9-16 10:07:05 第 3 章 免杀与特征码   49 也许大家在看完这幅图之后还会产生新的疑问,对于这些问题我们在后面的章节将会涉 及,这里就不介绍了。 另外还有一种叫做“nop 位移法”的修改方式,使用它要有一个比较苛刻的条件,就是 特征码附近(不超过 10 行)必须要有 0x00 区域。如果符合条件,操作方法就是将整段代码 位移到下面,具体位移几行全凭 0x00 区域的大小限制与个人爱好。由于前面空出来的都用 NOP 填充,因此称为“nop 位移法”。但是这种方法的实用性不好,还存在诸多弊端,所以 这里只给大家做一个简单的介绍,了解一下即可,不推荐大家使用。 2. 上下互换 其实上下互换与上面介绍的方法操作步骤基本上是一样的。我们仍然以特征码 “0000EEEE_00000004”为例讲解。通过前面实验,我们已经知道将其转换为内存地址后为 “0x0100FAEE”,用 Ollydbg 打开实验文件,然后按快捷键 Ctrl+G 调出“跟随表达式”对话 框,并进入地址“0x0100FAEE”,选择将要互相替换的两端指令。然后按快捷键 Ctrl+C 复 制,并将其保存在记事本中。回到 Ollydbg 后在那两段代码上面单击右键,在弹出的菜单中 依次选择“二进制”→“用 00 填充”,如图 3-48 所示。 图 3-48 用 NOP 填充 接下来将刚刚记录在记事本里的指令上下调换一下,并按 上面讲的方式依次汇编回去,如图 3-49 所示。 最后按照上面的步骤(右击→“复制到可执行文件” →“所 有修改”→“全部复制”→“保存文件”)将其保存。 这种方法利用的就是汇编对指令上下调换不是很敏感的这一特点来达到免杀目的的,因 为上下调换指令之后,虽然大部分程序仍然能正常运行,但是作为特征码的十六进制信息已 经互相调换了,那么依靠特征码查杀病毒的反病毒软件也就无能为力了。 3. 等值替换法 等值替换属于涉及知识层次比较深的一种修改特征码的方法,它的原理就是利用汇编语 言中相近或有可能达到同一结果的指令,来替换原来被定义为特征码的指令。 很显然,这会涉及很多汇编语言方面的知识,但是读者很可能可能并没有掌握多少汇编 知识,所以这里只给出几个比较常用的例子,更深层的利用要等大家自身的汇编功底提高以 后,自然而然就会总结出更多的方法了。以我个人的经验来说,比较适合初学者的等值替换 图 3-49 将上下互换后的 指令汇编回去 正文.indd 49 2013-9-16 10:07:05 50   基础篇 初级免杀技术 法主要用到以下几个指令 :9 Push 与 pop 互换 例如:遇到 Push XXXXX 可以改为 pop XXXXX Je 与 jnz 互换 例如:遇到 Je XXXXX 可以改为 jnz XXXXX Add 与 sub 互换 例如:遇到 add xxx,5 可以改为 sub xxx,-5 上面 3 条指令的应用方法非常简单,就是一个替换的问题。我们重点讲解一下“Add 与 sub 互换”。Add 与 sub 在汇编里分别是加与减的意思,例如 add xxx,5 就是将“xxx”加上 5 的意思,很显然,sub xxx,-5 则是将“xxx”减去 -5 的意思。但是我们仔细地想一想,加 5 与 减去 -5 在结果上有何不同呢?很显然它们取得的结果是一样的啊!既然取得的结果一样,自 然也就不会对程序的运行产生影响了,因此就可以利用这个原理来将这两个指令调换着使 用。但是需要注意的是,这里加减运算所应用的都是十六进制数据。 而其他的指令互换仅仅考虑到了指令长度问题,并不是严格意义上的等价互换。 3.7 小结 这一章主要目的在于带领各位读者熟悉免杀的思路,其中 3.4 节介绍的内容主要是带领 各位读者熟悉黑客的免杀工作环境,给读者带来一些其他启示。 但是鉴于本章对于读者层次的定位,3.4 节讲述的一些内容并不太准确,或者是有歧义 的,这么做只为了让读者更加容易地对黑客免杀技术有一个整体的理解。请大家记住,只会 使用工具而不知道原理是永远都做不了免杀的。   我提供的这些可以互换的指令,除了Add与Sub的互换方案外,其他的只考虑了指令长度,并没有考虑指令 本身的含义,因此使用这些替换方法并不能保证成功。 正文.indd 50 2013-9-16 10:07:05
还剩68页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

xmyth

贡献于2015-09-22

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf