编辑:
2013-12-13
接下来,让我们先暂停一下对恶意软件的恐惧,进入GPU的世界。GPU通用计算最近几年来飞速发展,当GPU本身可编程性和灵活性大大提高后,很多人开始着手探索如何利用GPU架构进行大规模的并行计算,毕竟GPU拥有系统中最为强劲的浮点计算能力,仅仅作为3D计算显然相当可惜。但GPU通用计算需要专用API才能在GPU上完美运行。一般的图形APIMDlrectX和OpenGL等,都不能很好地进行通用计算。
对传统GPU来说,无论是GPU本身设计还是调用方式都尽可能为GPU需要执行的图形计算优化。因此你如果想利用GPU庞大的计算资源,那些需要计算的数据和变量,必须映射为图形学对象,算法处理必须被表述为像素和顶点处理的形式,假装是在进行图形计算一样。这种“假装”的形式让程序员感到很束缚。因为传统GPU缺乏方便的数据类型,基本的计算函数,以及一个一般化的内存访问模型,使得它对于习惯于工作在传统编程环境下的程序员们来说没有多少吸引力。
进入DirectX 10时代后,NVIDIA提出了CUDAfCompute UnifiedDevice Architecture)这样一个相当富有创造力的通用运算API架构。有了这个API之后,程序员就不需要在自己的大脑中“映射”各种数据,APl作为沟通桥粱已经承担了数据转换、程序编译等任务。这样一来,GPU就能很好地发挥计算效能。与此同时,AMD也提供了对应自家GPU产品的通用计算方法,被称为Stream。
CUDA由一个C语言的极小扩展集和一个运行库组成,这个运行库提供的函数能够控制GPU,以及设备专有函数和相应的数据。从相对宏观的角度看,一个CUDA程序由两部分组成,一个运行在CPU上,另一个称之为“kernel”,是运行于GPU上的并行化部分。不过GPU上的kernel是不能独立运行的,它只能依赖于CPU上的父进程调用,因此,它不能被作为一个独立的程序直接初始化。
CUDA中的kernel在运行时被划分为多个线程来执行,这些线程被组织成多个线程块,然后交由GPU的CUDA Core--也就是常说的流处理器来执行。在GeForceGPU中,每个处理单元会包含8个SIMD流处理器组。这8个SIMD流处理器组会根据一个线程调度器的调配,令多个线程块尽可能高效率、最大化地运作,保障整个GPU的运行效率。
除了编程执行外,CUDA还提供了用于在主机和GPU问进行数据交换的函数,所有的I/O动作都通过PCI-E总线进行。不仅如此,存储器操作还可以通过DMA进行,这样就可以大幅度提高CPU和GPU工作的并行程度。在内存一致性方面,主机的分页锁定内存中的一个块可以被映射到GPU的地址空间里,使得在CPU上运行的普通程序和GPU上运行的kernel能够直接访问相同的数据。
总的来说,无论是CUDA还是Stream,都是尽可能利用GPU'性能的API。恶意软件要运行得有效率,就绕不开这两个API。下面就让我们来看看恶意软件是如何在GPU上捣鬼的。
上文说过,运行于GPU上的kernel必须依赖CPU上的父进程。恶意软件也是如此,那些能利用GPU超强性能的恶意软件往往包含两个部分--GPU部分和CPU部分。说得更细致一些,那就是恶意软件在执行时,会裁入GPU端的设备代码,分配CPU和GPU都可以访问到的一块内存区域,先初始化数据,然后调度GPU代码开始执行。当然,和所有利用GPU的程序一样,恶意软件可以在GPU和CPU之前来回转换,或者单独让GPU运行或者只让CPU运行,也可以同时在GPU和GPU并行执行。
当然,恶意软件编写者不仅仅看中了GPU的计算能力,他们还需要更自由、不被监视的执行空间。恰好,在GPU这里,恶意软件可以与CUDA库静态链接,成为一个独立的可执行程序,这样一来,恶意软件就不需要在被感染的系统中安装额外软件。更令人难以接受的是,目前GPU端的代码执行,以及CPU和GPU之间的通讯,都不需要管理员特权。这意味着,恶意软件可以在任何用户权限下成功运行——它不需要任何权限,也没人监控它。这就令恶意软件隐蔽性更高、更容易被运行起来。
束手无策?恶意软件如何利用GPU资源
前文已经描述了恶意软件感染系统的方式,并且说明了它利用GPU进行并行加速的可能性。接下来,研究人员将通过实例来模拟这个过程。在模拟中使用的原型代码不仅仅证明了恶意软件利用GPU的可行性,而且已经确信对现有的分析检测系统构成了不容忽视的挑战。
研究人员选择使用NVIDIACUDA来部署源代码,当然攻击者可以很容易地使用其他GPU代码版本,甚至还能在不同GPU之间进行转换。目前攻击者只要掌握了CUDA和Stream,就能基本上掌握100%的GPU恶意软件攻击范围。还有更令人恐惧的——OpenCL是一个跨平台的GPGPU框架,致力于提供统一的API,如果它得到广泛引用,那么就连插入不同版本的代码也完全没有必要,只要平台支持OpenCL,就可能被恶意软件利用你电脑中的GPU加速运行。
1.自脱壳GPU加速
前文已经简单介绍了恶意软件的加壳技术。当然,飞机上放炸弹的例子只是用于破坏性的炸弹。在软件这里,经过多层加壳伪装后的代码,需要脱壳解秘,才能变成真正的恶意代码危害系统。
一般情况下,恶意软件设计有自脱壳程序,这个程序在运行时会首先解包被隐藏的代码,然后将控制权移交给已在主机内存中变形为真实代码的恶意软件。当然,一种恶意软件可能不止使用一种加壳程序,使用不同的变换方法或者改变解包程序的代码,攻击者可以容易地制造同一个恶意软件的全新变种,还能有效地躲避检测程序。
目前传统恶意软件的自脱壳算法都不特别复杂,因为要考虑到CPU的计算能力,一旦显著拖累系统,恶意软件不但容易被察觉,还给自己的运行带来了不利影响。但利用GPU强大的并行计算能力后,恶意软件的作者能够利用极其复杂的加密算法给恶意软件加壳,这些复杂的加密算法最终将被GPU大规模并行架构快速而有效地处理。
这种高强度的加壳、脱壳操作,为现有的恶意软件分析检测系统制造了不容忽视的障碍。许多反恶意软件中用于检测自动脱壳的部分有先天缺陷,没办法应对基于GPU的自解包恶意软件。比如常用的PolyUnpack,在脱壳时依赖单步执行和动态反汇编,但这种技术在GPU上的动态和静态分析还很不成熟,当然也没有获得恶意软件分析系统的支持。另外一些反恶意软件的脱壳系统,比如Renovo,依赖于在虚拟机中监控恶意软件的执行过程,但显而易见的是,目前的虚拟机还仅仅只能做到虚拟图形设备而已,只能执行简单的3D计算,根本不能执行GPU通用计算任务,也没有这方面的功能。这样一来,利用虚拟机监控恶意软件的脱壳也将成为泡影。
当然,还有一些检测软件脱壳的技术比如omniUnDack,这种技术理论上可能会对恶意软件在GPU中的操作起到一定的检测作用,但实际上它在应用中还是和虚拟机联合部署的,也就是说,实际应用中也不能检测到GPU中的脱壳运行情况。
2.运行时多态技术
不过,前一页研究人员的演示可能并不能让人信服,有人肯定会说,无论加壳脱壳的设备是CPU还是GPU、无论壳算法多么复杂,最终都将恶意代码直接存放在主机内存中。这样一来只要反恶意软件扫描系统内容,就能很轻松地发现恶意软件执行意图并给予相应防御措施。
实际上这种情况只能代表部分恶意软件的运行方法。正像本文开头解释“运行时多态”技术时说的那样,恶意软件在运行时,往往不会暴露自己的全部代码,它可能重新加壳,或者只是按需分配、重复加壳脱壳那些当前需要的代码。不仅如此,恶意软件开发人员还会控制解码部分的粒度,也就是每次解码的数最,这个数量越小,在内存中暴露真实代码的区域就越小,被侦测的可能性也就越低,也越难以被发现和防御。这种代码分割算法给反恶意软件带来了明显的困扰。
在加入了GPU后,这些重复脱壳加壳的算法,都使用GPu执行,并且整个需要脱壳和加壳的部分代码也全部存在GPUAc。CPU的职责仅是在每个部分的代码执行前和执行后,将控制权交还给GPu上的调度代码,去做按需的解密变换和加密变换。也就是说,在执行期间,控制权在CPU和GPU之间不断地转换。同样,GPU和CPU也拥有一个可以同时访问的内存区域用于保持数据一致性和及时刷新。
不仅如此,在这种技术中,解密密匙被保存在较为保密的、无法从CPU端访问的CUDA设备存储器当中,更有甚者,在每个部分执行后的重加密过程中,还可以使用随机生成的不同密匙,这导致了恶意软件能够在存储器中以不可预测的方式不断地发生变异。而这些解密方法和变异都是不能被检测或者预测到的,将直接导致目前依赖抽取密钥和相应加密解密区域等方法的反恶意软件运行失败。当然从理论上来说,虽然原始代码的完整抽取仍然是可能被分析人员做到的,但是如果考虑现有的反调试技术,这种有GPu从旁协助的运行时多态会使得整个逆向工程分析过程变得异常地漫长和艰难。
未来更危险?GPU上恶意软件的发展方向
标签:计算机理论
精品学习网(51edu.com)在建设过程中引用了互联网上的一些信息资源并对有明确来源的信息注明了出处,版权归原作者及原网站所有,如果您对本站信息资源版权的归属问题存有异议,请您致信qinquan#51edu.com(将#换成@),我们会立即做出答复并及时解决。如果您认为本站有侵犯您权益的行为,请通知我们,我们一定根据实际情况及时处理。