admin 管理员组

文章数量: 887021


2024年2月7日发(作者:system是什么意思中文)

1198 2010,31(6) ・信息安全技术・ 计算机工程与设计ComputerEngineeirng andDesign 基于堆栈的Windows Shellcode编写方法研究 迟 强, 罗 红, 乔向东 (空军工程大学电讯工程学院,陕西西安710077) 摘 要:为更好地理解与防范缓冲区溢出攻击,对Windows平台下Shellcode的编写、提取技术及验证方法进行了研究。从概 念出发,理清了Shellcode与Exploit的区别,分析了Shellcode的工作原理,介绍了利用Shellcode所需的3个步骤。在实验的基 础上,总结了Shellcode的编写方法及提取技术,最后给出了验证Shellcode有效性的方法。 关键词:缓冲区溢出;Shellcode;Windows;堆栈;反汇编 中图法分类号:TP309 文献标识码:A 文章编号:1000—7024(2010)06.1198.04 Method research of writing Windows Shellcode based on stack CHI Qiang,LUO Hong, QIAO Xiang—dong (College of Telecommunication Engineering,Air Force Engineering University,Xi’an 7 1 0077,China) Abstract:To understand and prevent buffer overflow exploit better,the method ofwriting and validating Shellcode is researched.Firstly, the difference between Shellcode and Exploit is analyzed after introducing the concept.Secondly,the principle of Shellcode and he tthree steps ofexploiting Shellcode re iallustrated.Thirdly,based on many experiments,several methods ofwriting nd aextracting Shell- code are summarized.Finally,a few measures ofvalidating Shellcode are presented. Key words:buffer overflow;Shellco‘le:Windows;stack;disassemble 0引 言 基于堆栈的缓冲区溢出攻击依然是威胁网络安全的重要 STACKFORFUNANDPROFIT))中首次提出的,他把向进程中 植入的一段用于获得shell的代码称为“SheUcode”。后来,这 一概念被继续延用扩充,有了更广义的内涵:泛指在缓冲区溢 出攻击中被用于植入进程中的代码。通过精心设计SheUcode, 手段,溢出发生后,攻击者通常会向目标主机的进程内植入实 现特定功能的代码(Shellcode),并使其执行,对安全系统构成 了极大威胁。而缓冲区溢出漏洞的利用,实质上就是使计算 可以实现许多操作,如弹出消息框、添加用户、上传木马、格式 化硬盘等。 机的进程跳入我们编写的Shellcode中去执行,分析研究Shel— lcode对于更好的认识与防范缓冲区溢出攻击有重要意义,如 文献[1.2】中介绍了通过对Shellcode进行检测来防范缓冲区溢 与之相关的,还有一个概念—— 【pl0it。研究Shellcode, 有必要弄清两者的关系。Exploit可被译为“破解”或“利用”, 是指利用漏洞将代码植入的过程,包括定位并覆盖函数返回 出攻击的方法。Shellcode通常用汇编语言编写并需将其转换 成二进制机器码,其内容和长度又经常受到很多苛刻限制,开 地址,获取进程控制权,把EIP传递给Shellcode使其执行,而 不管Shellcode究竟如何实现弹出消息框或是添加新用户等操 作。这就像导弹(Exploit)与弹头(Shellcode)的关系,导弹可以 发和调试难度较大,目前大多数攻击采用的SheUcode代码都 是来自于Internet,如通用漏洞测试平台Metasploit就提供了一 些常用的Shellcode(如用于绑定端口反向连接、新建用户等)。 除了直接使用前人写好的Shellcode外,有时我们还需自己动 实现打击一个特定目标,而导弹上携带的弹头却可以是各种 功效的0 。因此Exploit往往是针对特定漏洞的,而Shellcode有 一定的通用性。 手编写或将其进一步改进成更高质量的符合自己需求的Shel— lcode,这就需要对Shellcode的编写技术进行研究,本文针对 Windows平台下Shellcode的编写提取方法进行了研究,并给 出了Shellcode的验证方法。 2 Shellcode的原理 编写Shellcode的目的,是为了让目标程序偏离预期方式, 按编写者的意图运行。Shellcode以一组十六进制的字符串数 1 Shelleode概述 Shellcode是1996年AlephOne在其论文((SMASHINGTHE 组表示,实质上对应着计算机能够直接执行的机器代码。计 算机在执行指令时,都只是执行当前指令指针(EIP)指向的指 令。当前指令执行后,EIP自动加1,指向下一条指令。若有 收稿日期:2009.04—14;修订日期:2009.06.19。 作者简介:迟强(1984--),男,山东莱州人,硕士研究生,研究方向为网络安全与信息对抗; 罗红(1963--),男,陕西西安人,博士,副教 授,研究方向为网络与信息安全; 乔向东(1970一),男,陕西佳县人,博士,副教授,研究方向为信息融合与信息安全。E—mail:cq7216@163.tom 

迟强,罗红,乔向东:基于堆栈的Windows Shellcode编写方法研究 JMP、CALL、RET一类的指令,EIP会被强行改变成指定的地 2010,31(6) 1199 作系统下使用系统中断调用不同,在Windows平台下函数的 调用首先需要把函数所在的动态链接库load进去,然后用堆 栈传递参数,最后CALL该函数的地址即可。 例如,为实现弹出一个消息框,需要调用这个函数: MessageBoxA(NULL,”hello,CQ”,”he11o,CQ”,NULL) 址,从而完成流程的跳转。编写Shellcode,是想用Shellcode的 数据把内存中原有的部分数据覆盖掉,之后设法使计算机的 指令指针EIP指向Shellcode在内存中的开始位置,就可以执 行Shellcode,实现想要的功能 。 总结来说,编写一个Shellcode并使用之成功Exploit需要 3个步骤: 编写此函数调用的汇编代码需要3个步骤。 :①装载动态 链接库user32.dll。MessageBoxA是动态链接库user32.du的导 (1)定位程序溢出点,确定函数返回点的精确位置; (2)编写一段可实现特殊目的的Shellcode代码; 出函数。大多数有图形化操作界面的程序都已经加载了这个 库;②在调用前需向栈中按从右至左的顺序压.) ̄MessageBoxA 的4个参数;③调用MessageBoxA这个函数的入口地址。 (3)覆盖返回点地址,通过某些特定方式,引导指令指针 EIP传递给Shellcode使其执行。 程序溢出点的定位和返回点的覆盖都属于Exploit的过程, 这里不作过多研究,本文主要研究Shellcode编写的相关技术。 3 SheHcode编写的关键技术 3.1 SheHeode的编写方法 Shellcode是计算机可以直接执行的机器码,编写时要非 常严谨,即使是一些细微的差错,也会导致整个Shellcode的罢 工。下面主要讨论两种Shellcode编写的方法: 3.1.1高级语言反汇编提取法 这种方法的思路是:先用高级语言编写所需的实现特定 功能的Shellcode程序,然后用编译器(如Vc.r+6.O)编译、调试 并反汇编这个程序(如图1所示),从中整理出汇编代码对应的 机器码(opcode),尽量减小它的体积并使它可注入(生成的代码 不包含NULL字符),最后得到Shellcode。 图1程序的反汇编调试 采用这种方法经常会遇到一个问题,由高级语言直接反 汇编得到的Shellcode往往会含有NULL(LxO0),由于在字符数 组中,NULL是用来终止字符串的,所以将来把Shellcode复制 到缓冲区的时候会导致异常。 为解决这个问题,就需要把NULL转为non-nullopcode“’, 通常用其它具有相同功能的指令替换那些产生NULL的指令 (如可用xor ebx,ebx来代替mov ebx,O);也可直接在Shellcode 的编写过程中使用不生成NULL的指令加上NULL,由此便产 生了下面一种编写Shellcode的方法。 3.1.2低级语言汇编提取法 这种方法的思路是:在用高级语言写完程序之后,不经过 编译器的编译与反汇编,直接根据函数调用的过程人工编写 相应的汇编代码,最后再提取出机器码。这种方法虽然看似 稍显复杂,但可以很好的避免出现NULL,因此,在实际编写中 大都采用这种方法。 Shellcode的执行过程就是函数调用的过程。与Linux操 为了使示例更简洁,实验时己手动加载了user32.dl1。Mes— sageBoxA函数的入口地址可以通过user32.du在系统中加载 的基址和MessageBoxA在库中的偏移相加得到。具体可用 VC++6.0自带的工具“Depends”加载任一有图形界面的程 序获得。 如图2所示,user32.dll的基地址为0x77D10000,Message- BoxA的偏移地址为0x000407EA,两者相加就得到了Message— BoxA在内存中的入口地址0x77D507EA。 图2计算MessageBoxA函数的入口地址 下面就可以根据函数调用的过程人工编写相应的汇编代 码了。首先参数入栈,先将EBX清零,作为字符串的截断符, 然后将“hello,CQ”字符串逆序压入栈中,第2和第3个参数重 复压入指向这个字符串的指针,表示消息框的文本和标题都 显示为“hello,CQ”,第1个和第4个参数都设置为NULL,最后 再CALL函数地址。写出汇编代码如下: XOR EBX,EBX ;将EBX清零作为截断符 PUSH EBX ;避免“PUSH 0”中的NULL PUSH 0x5 1432C6F PUSH 0x6C6C6548:压入“hello,CQ”字符串 MOV EAX,ESP :在EAX中存放字符串指针 PUSH EBX PUSH EAX PUSH EAX PUSH EBX :4个参数从右至左入栈 M0V EAX.Ox77D507EA CALL EAX ;调用MessageBoxA 将其十六进制机器码提取出来即可得到Shellcode:“Lx33\ xDB\x53\x68\x6F\x2CLx43\x5 1Lx68\x48\x65\x6C\)【6C\x8B\xC4\ x53 50\】【50\)【53 B8\xEA\)【07\xD5\】【77LxFF ̄xD0”。 3.2 SheUeode的提取方法 在编写Shellcode的过程中都用到了提取机器码,其具体实 施也有下面3种方法: 3.2.1编译器调试提取法 这种方法是将汇编代码在编译器(如Vc++6.0)中用asm _

1200 2010,3 1(6) 计算机工程与设计Computer Engineering and Design 这个方法具体实施起来也有几种不同的方式: {)嵌入,编译,按F10调试,调出和汇编代码对应的机器码记 录即可。为了记录方便,也可以在汇编内存中直接拷贝,方法 4.1函数指针调用法 是用VC嵌入汇编并按F10进入调试状态后,调出内存窗口, 输入eip,内存窗口就会显示从eip开始的数据,就是我们想要 的Shellcode代码,如图3所示。 图3 内存中提取机器码 3.2.2可执行文件提取法 另一种提取Shellcode的方法就是可执行文件提取法,将 汇编程序调试成功后,会生成exe可执行文件,将其用Ollydbg 来加载,找到相应的机器码即可,如图4所示。 图4用Ollydbg来提取机器码 3.2.3 C语言直接提取法 除了上面两种方法外,还有一种C语言直接提取法,这个 思路最早是由yuange提出,并由hume进一步优化的。它的思 路是Shellcode由汇编和C语言混合编写。汇编部分主要完成 动态定位函数地址,而C语言部分是完成程序的功能流程。 整个程序的本质,就是让编译器为我们生成二进制代码,然后 在运行时编码、打印输出 。 需要注意的是,上面编写出的Shellcode有一个缺点,就是 通用性不好。由于不同版本的操作系统,其动态链接库的加 载基址、导出函数的地址都可能不同,使用手工查出的函数地 址很可能会在其它计算机上失效,因此需要研究编写可以跨 平台使用的通用Shellcode的技术。解决Shellcode的通用性本 质上就是要解决函数地址的通用性,因此在实际使用中的 Shellcode需要动态地获得自身所需的API函数地址。Win32 平台下Shellcode最常使用的方法,就是通过从进程控制块中 找到动态链接库的导出表,并搜索所需的API地址,然后逐一 调用。 。关于通用Shellc0de的开发研究,在文献[3】中有详 细例解。 4验证SheHcode的方法 当我们花费半天功夫编写出一个Shellcode,如何确定它 们是否正确有效?如何进行测试与调试?这就有必要研究 Shellcode的验证方法。 通常有两种方法:第1种实际测试法,就是在实际的溢出 程序中,使用提取出来的Shellcode进行测试。第2种Shellcode 直接执行法,是把Shellcode数组当成一个函数来执行。其中 方法二比较方便易行,下面重点介绍此方法。 打开Vc++6.0,新建一个工程和C++源文件,然后把Shell- code拷贝下来作为一个十六进制的字符串数组,最后在main 中添加下面一个语句即可。 ((void(幸)(void))&Shellcode)(); 这个语句把Shellcode转换成一个参数为空、返回值为空 的函数指针,并调用它。执行这一句就相当于执行Shellcode 数组里的数据。 我们可以用这段程序运行写好的或搜集到的Shellcode, 并调试之。若不能满足需求,也可以在调试的基础上稍作修 改,为它增加其它功能。 举例完整代码如下: unsigned char ShellCode[】= ”\xFC\X68\x6ALx0ALx38Lx1E\)【68\】【63 89 Dl\)【4F 68\)【32、 x74\x91Lx0C” ”\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\ xBB\)【33\x32Lx53” ”\x68\x75Lx73\x65\】【72\】【54\x33\xD2\)【64\x8B\】【5A\】【30\x8B\ x4B\】【0CLx8B” ”\x49\xlC\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0AXx38\ x1E\)【75\x05\】【95” ”\xFFLx57XxF8\】【95\)【60Lx8BLx45\)【3C\x8Bkx4CLx05Lx78Lx03\ xCDLx8B、】【59” ”\】【20\)【03LxDD\x33XxFFLx47 8BLx34LxBBXx03LxF5kx99\)【0F\ xBE\x06\)【3A” ” C4\x74\x08\xCl\xCA\x07\x03\xD0\x46\xEB\xFl\x3Bt x54kx24Lx1C 75” ”\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8BXx59\ x1C O3\)【DD\)【O3” ”\x2C\xBB\x95\x5F\xAB\】【57\x6l\x3D\x6A\xOA\】【38kx1 E\ x75kxA9Lx33 江)B” ”\x53\】【68\x6F ̄x2CLx43\)【5 1Lx68\)【48 65\)【6CLx6C 8B\】【C4\ x53\)【50\)【50” ” 53\)【FF\)【57 FC 53\)【FF\)【57\】【F8”: intmain 0 { ((void(*)(void))&ShellCode)O; return 0; ) 结果如图5所示。 4.2返回函数调用法 我们也可以使用这样一段简单的代码对Shellcode进行验 证调试: char sheUcode[]=”LxFCLx68Lx6ALx0ALx38LxlELx68…..”; //欲调试的十六进制机器码 voidmain 0 { asm 一{lea eax,shellcode//将shellcode的起始地址传递给寄存器 

迟强,罗红,乔向东:基于堆栈的Windows Shellcode编写方法研究 2010,3 1(6) 1201 call eax//直接用call语句调用shellcode } 总而言之,方法2就是把Shellcode数组当成一个函数,设 法调用它,使它可以直接执行。 5结束语 编写Shellcode不仅仅要考虑其实现的功能,还要考虑跨 平台、健壮性、稳定性、通用性等各方面因素。因此,要编写一 图5 Shellcode的验证方法1 段高质量的Shellcodc,还需用到~些高级的编写技术,比如编 push eax //将eax中的值入栈 码技术、“瘦身”技术等,通过对Shellcode进行编码,可以有效 避免截断、使其符合目标程序对字符的规范要求,还可以突破 ret}) 首先将Shellcode的起始地址传递给寄存器eax,然后将 IDS的探测;短小精悍的Shellcode可以应用在更小的内存空 间中,适应多种多样的缓冲区组织策略,具有更强的通用性。 eax中的值push入栈,最后ret指令会将push进去的Shellcode 在栈中的起始地址弹给EIP,让处理器跳转到栈区去执行Shell— 这些技术的研究将是以后工作的重点。 code,示例如图6所示。 参考文献: [1] 何乔,吴廖丹,张天刚.基于shellcode检测的缓冲区溢出攻击防 御技术研究[J].计算机应用,2007,27(5):1045—1049. 【2】 陈悦,薛质,王轶骏.针对Shellcode变形规避的NIDS检测技术 [J].信息安全与通信保密,2007,23(1):99—103. [3] 王清.0day安全:软件漏洞分析技术[M].北京:电子工业出版社, 2008:72—79. [4】 Arhat.Shellcoder’s handbook:Discovering and exploiting secu— rity holes[EB/OL].http://download.csdn.net/down/7046—04/ hhincq,2007. 图6 Shellcode的验证方法2 [5] 王炜,方勇.Q版缓冲区溢出教程[EB/0L].http://down—load. 4.3地址直接调用法 csdn.net/source/802477.2008. 根据函数调用原理,也可以直接call函数的地址去执行 【6】 SKAPE.Understanding Windows shellcode[EB/OL].http:// Shellcode,这里当然是把Shellcode当成一个函数来看。具体 www.hiek.org/code/skape/papers/win32-shellcode.pdf,2003. 代码如下: [7] 谭文,邵坚磊.从汇编语言到Windows内核编程[M].北京:电子 asm 工业出版社,2008. { 【8】 许治坤,王伟,郭添森,等.网络渗透技术[M】.北京:电子工业出版 lea eax,shellcode 社.2005. (上接第1 197页) 参考文献: 蒋卓明,许榕生.基于内容审计的千兆网络监控系统的设计[J]. 计算机应用研究,2008,25(4):1114.1116. [1] 中国互联网络信息中心.2008年7月第21次中国互联网络发 JohnsonK.InternetE.mail协议开发指南【M].北京:机械工业出 展状况统计报告[Z]. 版社,2000:124—128. [2] 陈明建.电子邮件协议还原及分析系统的设计与实现【J].计算 陈明建.高速网络数据的存储及内容监控【D].福州大学,2006. 机应用与研究,2006,20(12):265.270. 李庚.入侵检测中一种新的多模式匹配算法[J】_计算机应用研 [3] 张诚,郝东白.基于正则表达式的WebMail监控与审计[J】.计算 究,2008,25(8):2474—2476. 机工程与设计,2008,29(13):3277—3282. Yang Dong—Hong,Xu Ke,Cui Yong.An improved Wu—Manber [4】 王佰玲,方滨兴,云晓春.零拷贝报文捕获平台的研究与实现[J]. multiple patterns matching algorithm[J].Journal of Tsinghua 计算机学报,2005,28(1):462-466. University Science and Technology,2006,46(4):5552—5558. [5] 李旭芳.网络信息审计系统中数据采集的研究与实现[J]_计算 孙钦东,管晓宏.网络信息内容审计研究的现状及趋势[J].计算 机工程与设计,2007,28(3):550—552. 机研究与发展,2009,46(8):1241.1250. 


本文标签: 编写 方法 研究 函数 地址