强对抗环境下的安全编程(一)

发表于2015-06-24
评论1 625浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏程序行业精英群

711501594

 

技术微分享:强对抗环境下的安全编程(一)

——危险的C++对象数据结构 (1)

 

 

              软件安全的对抗从未停歇,技术发展也在对抗中被不断促进,如今压缩壳和非虚拟加密壳已经比较少见,而虚拟机保护的技术已经被广泛使用,无论是外挂木马还是对应它们的防御方案,都加上了各种虚拟机壳,如VMP, CV和我们的TVMP.

 

              尽管如此,我们的防御方案程序仍然无法避免被外挂和木马攻击,而各种对防御方案程序的篡改中,比较隐蔽的就是运行期数据篡改,甚至是短时长运行期数据篡改。原因很简单,运行期数据不方便像代码和只读数据一样进行检验,即使进行运行期的检验,既然攻击者已经定位到了数据的位置,那么显然,检验的操作也很容易被定位到,通过短时长运行期数据篡改,就可以实现篡改方案同时,并且绕过检查程序的巡逻。

 

              但是被虚拟机壳加密后的程序代码,看起来混乱一片,而运行期数据很多都是运行时分配出来的,每次的地址并不固定,我们的敌人是如何定位到运行期关键数据的呢?这里面发挥关键作用的就是绝大部分虚拟机保护软件的致命缺陷——以代码块或常量块为单位实施保护,却并没有对C++对象数据结构进行保护

 

              作为技术微分享系列短文的第一篇,这里先进行一个攻击演示,让我们一起拨开虚拟机保护软件的迷雾。

 

              作为示例,在这里我编写了一个很简单的C++程序,并用某被广泛采用的虚拟机保护软件对所有C++类成员函数以及主函数进行虚拟机保护。

 

 

 

 

              现在,我们的身份变成了一个攻击者,我们的任务就是找到程序中的一个C++对象,并定位到它所有的成员变量和成员函数起始地址,以便掌握篡改的位置和时机。

 

当我们运行程序,发现打印出了四行文字,理所当然,我们先定位到了程序调用的API wprintf_s并对它设置断点。

              运行到断点后,返回用户内存区间,看,一片混乱。

 

0001.bmp

             

              常规的分析手段是行不通的,那么我们观察这个程序的PE文件的节的结构。

 

 

              节名被马赛克覆盖的节是容纳虚拟机引擎的虚拟机码的节(下文简称为.v节)如果细心观察程序代码,会发现在.text节,有一些跨节跳转,直接从.text跳往.v节。

 

0002.bmp

 

0003.bmp

 

              尝试在这里设置断点,其实并没有代码调用到这里,为什么会有这样的跳转呢?这是由于虚拟机保护软件为了保证一些程序在按照被虚拟机加密前的地址进行调用时,仍然能正常调用这些函数,或者是保证,通过C++虚函数表解析出来的地址调用某个虚函数时,能够正常调用而这样做的。但是,这却是一个非常严重的脆弱点,第一,这些指令很明显,从.text节直接跳往.v节,第二,它们指示了虚拟机加密前函数原始地址和虚拟机加密后函数入口地址的对应关系。

 

              攻击者在这时就可以开始兴奋了,看上面第一个函数,它的原始地址是0x00401110, 它跳往的虚拟机加密函数入口地址为0x0040ADA4, 我们在这个地址设置断点,然后运行程序,程序在这个地址中断了下来。

 

0004.bmp

 

              注意开头时提到绝大多数虚拟机保护软件的致命缺陷,这里是确确实实的一个C++对象成员函数的入口,程序运行到这里时,ecx中的地址,正是这个C++对象的基址。

 

0005.bmp

 

看,从地址0x003970D0开始,虚函数表地址,在构造函数中分别被赋值为1,2,3,4的4个成员变量,被清晰展现。

 

0006.bmp

 

              然后我们再到虚函数表看看。

 

0007.bmp

 

              各个虚函数的地址也尽收眼底,我们看0x00401150和0x00401170这两个虚函数。

 

0008.bmp

 

0009.bmp

 

              根据跨节跳转的特性,我们也很轻松找到了它们对应的虚拟机加密后函数入口地址。

 

0010.bmp

 

              这里,也许你更理解为什么这个跨节跳转会存在,比如对于这个对象,直接从虚函数表中解析出来调用的虚函数,就要以来0x00401150和0x00401170地址处的跳转,而这仅仅是跨节跳转存在的原因之一。

 

              至此,作为攻击者,我们的任务已经完成了,这个C++对象的所有成员变量和虚函数表,以及成员函数、虚函数的原始地址和虚拟机加密后函数入口地址,已经全部清晰。

找跨节跳转,找对象基址,整个这个过程都是可以通过工具自动化完成的,而危险的是,这样的工具也许就在我们的敌人的电脑上运行着……

其实,即使是没有跨节跳转,除非一个对象的所有成员函数都被虚拟机加密(事实上为了效率很少这么做),也是可以很容易找到对象基址的。

 

              危险的C++对象数据结构,它暴露了被虚拟机保护软件加密后程序的各个C++对象的成员变量,以及它们的成员函数,甚至是对象之间继承关系的几乎所有信息。清晰了一个复杂程序的这些,也就清晰了一个复杂程序的结构和流程,分析起来的难度就会大大降低,如果在结合同样是虚拟机保护软件关键脆弱点之一的API调用行为暴露,那么……

 

              技术微分享的第一篇到此告一段落,关于如何对虚拟机保护软件的这些关键脆弱点进行增强和保护,我们再继续讨论。

 

[END]

5 / 5

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

游戏学院公众号二维码
腾讯游戏学院
微信公众号

提供更专业的游戏知识学习平台