堆栈溢出
- 格式:doc
- 大小:430.00 KB
- 文档页数:68
堆栈溢出攻击的一般步骤
堆栈溢出攻击呀,这可是个有点“小坏”的技术手段呢。
那它第一步呢,就是要找到一个存在漏洞的程序。
就像在一群房子里找到那扇没锁好的门一样。
这个程序可能是因为编写的时候没有很好地考虑边界检查之类的问题,才会有这样的漏洞。
比如说一些老版本的软件,或者是开发过程中粗心大意的小应用。
接着呀,攻击者就要构造特殊的数据啦。
这个数据就像是一把特制的钥匙,专门为了打开这个漏洞程序的“坏锁”。
他们会精心设计数据的内容,让这个数据的长度超过程序原本为它准备的存储空间。
这就像是你本来只给一个小盒子准备了放5个糖果的空间,结果有人硬塞进来10个。
然后呢,这些构造好的数据就被输入到有漏洞的程序里啦。
这一输入可不得了,就像把那把特制钥匙插进了没锁好的门一样。
因为数据太长,超过了堆栈分配的空间,它就会开始“溢出”到其他的内存区域。
再之后呀,攻击者就可以利用这个溢出的情况,把恶意代码放到那些不该放的内存区域。
这个恶意代码就像是一个小坏蛋,偷偷潜入了程序的地盘。
它可能会做很多坏事呢,比如说获取系统的控制权,或者偷偷把用户的重要信息发送出去。
不过呢,堆栈溢出攻击这种事儿可不好,是破坏网络安全的行为。
现在的程序员们也越来越聪明啦,会做很多防范措施。
比如说加强边界检查,不让那些超长的数据随便进来,还有对堆栈的保护机制也越来越完善。
咱们可不能用这种手段做坏事,但是了解它的步骤也能让我们更好地防范这种攻击,保护好我们的电脑和数据呢。
堆栈溢出解决方法我折腾了好久堆栈溢出这事儿,总算找到点门道。
说实话堆栈溢出这事,我一开始也是瞎摸索。
我记得有一次写一个程序,它老是出现堆栈溢出的错误。
我当时就很懵,完全不知道从哪儿下手。
我最先想到的就是查看代码里那些函数调用,因为我觉得可能是函数调用太多了,就像你一层一层地盖房子,结果盖得太高,超过了地基能承受的范围。
我就仔仔细细检查每个函数内部的逻辑,看看有没有可能进入死循环的地方或者不必要的递归。
结果我发现还真有个函数里面有个隐藏的递归调用,在某些特定条件下它就不停地自己调用自己,就像一个人掉进了一个无限循环的陷阱里出不来,这肯定会把栈给撑爆啊。
我赶紧把这个递归条件修改好,以为万事大吉了。
但没想到这个办法并没有完全解决问题。
然后我又觉得是不是我的局部变量申请得太多了。
就好比你在一个小房间(函数栈帧)里面塞了太多东西,空间不够用了。
于是我又检查代码里那些大块头的局部变量,像一些很大的数组之类的。
我尝试把一些不必要在函数内部定义的变量挪到外面去,变成全局变量。
这就像把一些不常用的大件东西从拥挤的小房间搬到宽敞的仓库一样。
有时候还会遇到一种比较隐蔽的情况,就是在多线程编程的时候。
我试过好几个不同的线程同时频繁地调用同一个函数,每个线程都在自己的栈上进行操作,累积起来也很容易导致堆栈溢出。
我处理的方法就是给线程调用函数的频率设置了限制,不能让它们太疯狂地调用。
前几天又试了个新方法,就是增加栈的大小。
不过这就像你把房子的地基扩大一样,虽然有时候能解决问题,但这不是从根本上解决代码问题的好办法,只是一种临时的应急方案。
如果你的程序在不同环境运行,可能其他环境下你没有办法随意更改栈的大小。
我不确定我这些方法是不是能涵盖所有堆栈溢出的情况,但这些都是我真实遇到过并且通过这些方法解决了问题的经验。
如果有谁也遇到堆栈溢出的情况,可以先像我这样从函数调用、局部变量和多线程这几个方面去排查。
总之,一定要有耐心,因为这些问题有时候特别隐蔽,你得像个侦探一样,不放过任何一个可疑的代码片段。
如何解决Sybase数据库堆栈溢出导致的异常如何解决Sybase数据库堆栈溢出导致的异常(v 1.0)版本说明目录版本说明 (2)故障现象: (4)故障原因: (4)处理方法: (4)故障现象:SYBASE数据库异常退出,重新启动失败,访问不了数据库。
查看数据库日志,出现如下系统日志:00:00000:00000:2004/10/13 23:30:00.75 kernel Stack overflow detected: limit: 0xf8446ab0, sp: 0xf845275c 00:00000:00000:2004/10/13 23:30:00.75 kernel *** Stack guardword corrupted.00:00000:00000:2004/10/13 23:30:00.77 kernel pc: 0x006654d0 pcstkwalk+0x24(0xf8452688, 0x00000000, 0x0000270f, 0x00000002, 0xfffffff8)00:00000:00000:2004/10/13 23:30:00.78 kernel pc: 0x006653dc ucstkgentrace+0x194(0x00040004, 0x00000000, 0x00000000, 0xf8eff590, 0x00000000)00:00000:00000:2004/10/13 23:30:00.78 kernel pc: 0x00632300 ucbacktrace+0xa8(0xf8eff590, 0x00000001, 0x00040004, 0x00000008, 0xf845275c)故障原因:SYBASE数据库堆栈溢出,可能是某些很长的where子句、较长的选择列表、深层嵌套的存储过程在执行时导致原来配置的堆栈大小不够用导致,需要修改堆栈大小。
标题: 堆栈溢出系列讲座(1)本文以及以下同系列各文为ipxodi根据alphe one, Taeho Oh 的英文资料所译及整理,你可以任意复制和分发。
序言:通过堆栈溢出来获得root权限是目前使用的相当普遍的一项黑客技术。
事实上这是一个黑客在系统本地已经拥有了一个基本账号后的首选攻击方式。
他也被广泛应用于远程攻击。
通过对daemon进程的堆栈溢出来实现远程获得rootshell的技术,已经被很多实例实现。
在windows系统中,同样存在着堆栈溢出的问题。
而且,随着internet的普及,win系列平台上的internet服务程序越来越多,低水平的win程序就成为你系统上的致命伤。
因为它们同样会被远程堆栈溢出,而且,由于win系统使用者和管理者普遍缺乏安全防范的意识,一台win系统上的堆栈溢出,如果被恶意利用,将导致整个机器被敌人所控制。
进而,可能导致整个局域网落入敌人之手。
本系列讲座将系统的介绍堆栈溢出的机制,原理,应用,以及防范的措施。
希望通过我的讲座,大家可以了解和掌握这项技术。
而且,会自己去寻找堆栈溢出漏洞,以提高系统安全。
堆栈溢出系列讲座入门篇本讲的预备知识:首先你应该了解intel汇编语言,熟悉寄存器的组成和功能。
你必须有堆栈和存储分配方面的基础知识,有关这方面的计算机书籍很多,我将只是简单阐述原理,着重在应用。
其次,你应该了解linux,本讲中我们的例子将在linux上开发。
1:首先复习一下基础知识。
从物理上讲,堆栈是就是一段连续分配的内存空间。
在一个程序中,会声明各种变量。
静态全局变量是位于数据段并且在程序开始运行的时候被加载。
而程序的动态的局部变量则分配在堆栈里面。
从操作上来讲,堆栈是一个先入后出的队列。
他的生长方向与内存的生长方向正好相反。
我们规定内存的生长方向为向上,则栈的生长方向为向下。
压栈的操作push=ESP-4,出栈的操作是pop=ESP+4.换句话说,堆栈中老的值,其内存地址,反而比新的值要大。
win10系统检测出堆栈区溢出的解决方法Win10系统是微软公司推出的操作系统,目前在广大用户中使用非常广泛。
然而,对于某些用户来说,可能会遇到一些问题,例如堆栈区溢出的错误。
堆栈区溢出是指程序在使用堆栈空间时,超出了其预定大小,导致数据溢出到其他内存区域,从而可能导致系统崩溃或安全漏洞。
这篇文章将为您介绍一些解决堆栈区溢出错误的方法。
一、了解堆栈区溢出的原理要解决堆栈区溢出错误,首先需要了解其原理。
在计算机系统中,堆栈用于存储函数调用的参数、局部变量和其他临时数据。
堆栈的大小是有限的,根据系统和应用程序的不同而不同。
当函数调用过程中创建大量的局部变量或递归调用深度过大时,堆栈空间可能会超过其限制,导致堆栈区溢出错误。
二、检查程序的代码在解决堆栈区溢出错误时,第一步是检查相应的程序代码。
特别是需要关注的是局部变量和递归调用的情况。
可以通过增加堆栈空间的大小或优化代码逻辑来解决问题。
如果是在使用第三方库或框架时发生堆栈溢出错误,可以尝试更新到最新版本或联系厂商获取支持。
三、增加堆栈空间的大小如果经过代码优化后仍然无法解决堆栈区溢出错误,可以尝试增加堆栈空间的大小。
在Win10系统中,可以通过修改进程的启动参数来调整堆栈的大小。
具体步骤如下:1. 打开命令提示符:按下Win键+R,输入"cmd"并按下回车键。
2. 输入以下命令并按下回车键:`editbin /stack:<大小> <可执行文件路径>`。
其中,"<大小>"表示要设置的堆栈大小,以字节为单位;"<可执行文件路径>"表示要修改的可执行文件路径。
3. 保存并关闭命令提示符。
四、使用调试工具检测和解决堆栈区溢出错误如果以上方法仍然无法解决堆栈区溢出错误,可以使用调试工具来检测和解决问题。
Win10系统提供了一些强大的调试工具,例如WinDbg和Visual Studio。
通过堆栈溢出来获得root权限是目前使用的相当普遍的一项黑客技术。
事实上这是一个黑客在系统本地已经拥有了一个基本账号后的首选攻击方式。
他也被广泛应用于远程攻击。
通过对daemon进程的堆栈溢出来实现远程获得rootshell的技术,已经被很多实例实现。
在windows系统中,同样存在着堆栈溢出的问题。
而且,随着internet的普及,win系列平台上的internet服务程序越来越多,低水平的win程序就成为你系统上的致命伤。
因为它们同样会被远程堆栈溢出,而且,由于win系统使用者和管理者普遍缺乏安全防范的意识,一台win系统上的堆栈溢出,如果被恶意利用,将导致整个机器被敌人所控制。
进而,可能导致整个局域网落入敌人之手。
本系列讲座将系统的介绍堆栈溢出的机制,原理,应用,以及防范的措施。
希望通过我的讲座,大家可以了解和掌握这项技术。
而且,会自己去寻找堆栈溢出漏洞,以提高系统安全。
堆栈溢出系列讲座入门篇本讲的预备知识:首先你应该了解intel汇编语言,熟悉寄存器的组成和功能。
你必须有堆栈和存储分配方面的基础知识,有关这方面的计算机书籍很多,我将只是简单阐述原理,着重在应用。
其次,你应该了解linux,本讲中我们的例子将在linux上开发。
1:首先复习一下基础知识。
从物理上讲,堆栈是就是一段连续分配的内存空间。
在一个程序中,会声明各种变量。
静态全局变量是位于数据段并且在程序开始运行的时候被加载。
而程序的动态的局部变量则分配在堆栈里面。
从操作上来讲,堆栈是一个先入后出的队列。
他的生长方向与内存的生长方向正好相反。
我们规定内存的生长方向为向上,则栈的生长方向为向下。
压栈的操作push=ESP-4,出栈的操作是pop=ESP+4.换句话说,堆栈中老的值,其内存地址,反而比新的值要大。
请牢牢记住这一点,因为这是堆栈溢出的基本理论依据。
在一次函数调用中,堆栈中将被依次压入:参数,返回地址,EBP。
如果函数有局部变量,接下来,就在堆栈中开辟相应的空间以构造变量。
目录1案例描述 (1)2案例分析 (1)3解决过程 (2)4总结 (3)关键词:堆栈溢出,检测摘要:堆栈溢出对于我们软件开发人员来说,最严重的后果是破坏了内存中的指针,及其造成的一系列难查的bug。
对于这种情况,我们应该怎么办。
1 案例描述相信Linux程序员最讨厌的字符串是“Segmentation fault”,而Windows程序员最讨厌的是“C0000005”。
其实本质上是一样的,都是内存访问错误,且八成是错误的指针导致。
指针错误一般分两种,一种是空指针,一种是野指针。
对付空指针,我们不怕,因为即便出现了,偷懒的话,我们都可以不去定位原因,直接加上条件判断保护即可。
对于野指针,产生的原因有两种,一种是自身指针所指内存已销毁,这种好查,找到异常点和free的地方,比较一下就查到原因了。
另一种就是我今天所说的堆栈溢出造成的内存内容被篡改,假如这块内存中保存着程序指针,那么这些指针就“野”了。
堆栈溢出造成的野指针是很悲剧的,就算有dump工具,你也不知道是谁陷害了你的指针。
整个进程中的模块都有嫌疑,你不得不大海捞针似地去盯代码,眼神好的话兴许能揪出bug,运气不好的话可能几个星期都没有进展。
最近我就碰到了这种情况产生的bug。
是一个windows上的程序,跑若干钟头就会崩溃,且通过map文件显示异常出现在一个野指针处。
因为该指针不会在中途销毁创建,所以基本上断定是哪里堆栈溢出了。
在解决这个bug的过程中,我产生了一些对堆栈溢出的思考。
2 案例分析我想到3种有关堆栈溢出的方法:⏹编译器选项Gcc提供了一个编译选项,加入-fstack-protector-all即可实现对堆栈的保护。
但是实际上这个对于我们软件开发人员来说,一点用都没有。
Gcc的堆栈保护实质上是一种软件安全措施,为的是防止黑客恶意篡改函数栈调用黑客代码。
而作为软件开发人员,我们希望,程序崩掉没关系,重要的是我能检测出是哪里的堆栈溢出导致的,这个编译选项显然不起任何作用。
cad 堆栈溢出的原因及解决方式
近期有用户反馈在打开AutoCad 2007 的时候频繁出现卡死的情况,
并提示还提示0x00000FD 堆栈溢出,重启电脑和重装软件都无法解决。
针对
该问题小编整理了一些方法供大家参考。
1、排除了系统的问题就可能是软件的原因,但是我们重装之后,问题还是存在,那就不是软件的原因,那就可能是我们打开的文件问题,可是我们换了别的文件打开,还是有问题,那就排除了打开文件的因素;
2、剩下的问题就出在了打开CAD 的时候运行的文件的上面了。
大
家都知道在打开CAD 的时候,它会加载许多的预置文件,此次堆栈溢出的
问题就出现在这些文件上面,其中的某个文件将CAD 卡死了。
我们用CAD 的时候,经常打开图纸,有时候遇到图纸太大或者别的原因导致CAD 卡死,重新打开会发现CAD 崩溃,提示堆栈溢出的问题。
重
启电脑,重装软件都不能解决。
当然重装系统,再重装CAD 是肯定能解决的。
网友们也提出了多种解决问题的办法,但是作为亲身经历者,不少人看的是模棱两可,可能部分网友也是稀里糊涂的将问题解决。
下面就根据我的亲身经历,将这个问题的解决办法详细介绍一下。
CAD堆栈溢出如何处理
我们用CAD的时候,常常会遇到打开大图纸卡死的问题。
重启CAD 之后,发现系统警告说CAD堆栈溢出,常见的有0x00000FD堆栈溢出。
那么遇到这些问题的时候,我们该如何处理呢。
下面就是我的亲身经历解决办法
出现了堆栈溢出,基本排除是系统的问题。
如果软件不兼容,那么安装好软件之后,首次运行就会有提示。
重装了CAD,问题还是存在,说明不是软件本身的问题。
换了别的图纸打开,还是出现问题,说明不是打开的图纸的问题。
综合分析:应该是CAD运行的文件问题。
我们都知道,在打开CAD的时候,它自己会加载一些CAD内部的预置文件。
问题就出在这些预置文件里面。
下面给出参考的文件路径:
C:\Users\Administrator\AppData\Roaming\Autodesk\AutoCA D 2007\R17.0。
其中的Administrator,是默认用户名,用户要根据自己的实际用户名更改。
在其中的文件夹中找到Support文件夹。
问题就出现在这个文件夹的内容上。
为了快速的解决问题,我这里以360安全卫士自带的查到大文件的功能为例。
在最后一步中,找到Acaddoc.lsp的文件,问题就出在这个文件上,直接删掉就OK.
注意:不管你的CAD是装在哪个盘,查找的时候路径都是C盘。
其他版本的CAD溢出问题都可以用这个方法处理。
cad 堆栈溢出的原因及解决方式近期有用户反馈在打开AutoCad 2007 的时候频繁出现卡死的情况,并提示还提示0x00000FD 堆栈溢出,重启电脑和重装软件都无法解决。
针对该问题小编整理了一些方法供大家参考。
1、排除了系统的问题就可能是软件的原因,但是我们重装之后,问题还是存在,那就不是软件的原因,那就可能是我们打开的文件问题,可是我们换了别的文件打开,还是有问题,那就排除了打开文件的因素;2、剩下的问题就出在了打开CAD 的时候运行的文件的上面了。
大家都知道在打开CAD 的时候,它会加载许多的预置文件,此次堆栈溢出的问题就出现在这些文件上面,其中的某个文件将CAD 卡死了。
我们用CAD 的时候,经常打开图纸,有时候遇到图纸太大或者别的原因导致CAD 卡死,重新打开会发现CAD 崩溃,提示堆栈溢出的问题。
重启电脑,重装软件都不能解决。
当然重装系统,再重装CAD 是肯定能解决的。
网友们也提出了多种解决问题的办法,但是作为亲身经历者,不少人看的是模棱两可,可能部分网友也是稀里糊涂的将问题解决。
下面就根据我的亲身经历,将这个问题的解决办法详细介绍一下。
遇到上面出现的CAD 堆栈溢出问题的时候,基本可以排除系统,软件的原因。
因为是卡死之后,才出现的崩溃,之前一直可以正常使用,所以基本可以排除系统的原因。
即要是不兼容,在你安装好之后,首次运行不兼容的问题大都会暴露了。
大家都知道在打开CAD 的时候,它会加载许多的预置文件,此次堆栈溢出的问题就出现在这些文件上面。
其中的某个文件将CAD 卡死了。
这些预置文件大都是在C 盘的。
不管你的CAD 是否安装在C 盘,这些文件都是在C 盘的用户文件夹里面的。
具体请参看下图的路径,其他版本的CAD 路径大致相同。
图中打了马赛克的地方,是自己的用户名,一般默认是Administrator.参考路径C:\Users\Administrator\AppData\Roaming\Autodesk\AutoCAD 2007\R17.0在这些文件夹中的某个运行的文件有问题。
标题: 堆栈溢出系列讲座(1)本文以及以下同系列各文为ipxodi根据alphe one, Taeho Oh 的英文资料所译及整理,你可以任意复制和分发。
序言:通过堆栈溢出来获得root权限是目前使用的相当普遍的一项黑客技术。
事实上这是一个黑客在系统本地已经拥有了一个基本账号后的首选攻击方式。
他也被广泛应用于远程攻击。
通过对daemon进程的堆栈溢出来实现远程获得rootshell的技术,已经被很多实例实现。
在windows系统中,同样存在着堆栈溢出的问题。
而且,随着internet的普及,win系列平台上的internet服务程序越来越多,低水平的win程序就成为你系统上的致命伤。
因为它们同样会被远程堆栈溢出,而且,由于win系统使用者和管理者普遍缺乏安全防范的意识,一台win系统上的堆栈溢出,如果被恶意利用,将导致整个机器被敌人所控制。
进而,可能导致整个局域网落入敌人之手。
本系列讲座将系统的介绍堆栈溢出的机制,原理,应用,以及防范的措施。
希望通过我的讲座,大家可以了解和掌握这项技术。
而且,会自己去寻找堆栈溢出漏洞,以提高系统安全。
堆栈溢出系列讲座入门篇本讲的预备知识:首先你应该了解intel汇编语言,熟悉寄存器的组成和功能。
你必须有堆栈和存储分配方面的基础知识,有关这方面的计算机书籍很多,我将只是简单阐述原理,着重在应用。
其次,你应该了解linux,本讲中我们的例子将在linux上开发。
1:首先复习一下基础知识。
从物理上讲,堆栈是就是一段连续分配的内存空间。
在一个程序中,会声明各种变量。
静态全局变量是位于数据段并且在程序开始运行的时候被加载。
而程序的动态的局部变量则分配在堆栈里面。
从操作上来讲,堆栈是一个先入后出的队列。
他的生长方向与内存的生长方向正好相反。
我们规定内存的生长方向为向上,则栈的生长方向为向下。
压栈的操作push=ESP-4,出栈的操作是pop=ESP+4.换句话说,堆栈中老的值,其内存地址,反而比新的值要大。
请牢牢记住这一点,因为这是堆栈溢出的基本理论依据。
在一次函数调用中,堆栈中将被依次压入:参数,返回地址,EBP。
如果函数有局部变量,接下来,就在堆栈中开辟相应的空间以构造变量。
函数执行结束,这些局部变量的内容将被丢失。
但是不被清除。
在函数返回的时候,弹出EBP,恢复堆栈到函数调用的地址,弹出返回地址到EIP以继续执行程序。
在C语言程序中,参数的压栈顺序是反向的。
比如func(a,b,c)。
在参数入栈的时候,是:先压c,再压b,最后压a.在取参数的时候,由于栈的先入后出,先取栈顶的a,再取b,最后取c。
(PS:如果你看不懂上面这段概述,请你去看以看关于堆栈的书籍,一般的汇编语言书籍都会详细的讨论堆栈,必须弄懂它,你才能进行下面的学习)2:好了,继续,让我们来看一看什么是堆栈溢出。
2.1:运行时的堆栈分配堆栈溢出就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界。
结果覆盖了老的堆栈数据。
比如有下面一段程序:程序一:#include <stdio.h>int main ( ){char name[8];printf("Please type your name: ");gets(name);printf("Hello, %s!", name);return 0;}编译并且执行,我们输入ipxodi,就会输出Hello,ipxodi!。
程序运行中,堆栈是怎么操作的呢?在main函数开始运行的时候,堆栈里面将被依次放入返回地址,EBP。
我们用gcc -S 来获得汇编语言输出,可以看到main函数的开头部分对应如下语句:pushl %ebpmovl %esp,%ebpsubl $8,%esp首先他把EBP保存下来,,然后EBP等于现在的ESP,这样EBP就可以用来访问本函数的局部变量。
之后ESP减8,就是堆栈向上增长8个字节,用来存放name[]数组。
现在堆栈的布局如下:内存底部内存顶部name EBP ret<------ [ ][ ][ ]^;name堆栈顶部堆栈底部执行完gets(name)之后,堆栈如下:内存底部内存顶部name EBP ret<------ [ipxodi\0 ][ ][ ]^;name堆栈顶部堆栈底部最后,main返回,弹出ret里的地址,赋值给EIP,CPU继续执行EIP所指向的指令。
2.2:堆栈溢出好,看起来一切顺利。
我们再执行一次,输入ipxodiAAAAAAAAAAAAAAA,执行完gets(name)之后,堆栈如下:内存底部内存顶部name EBP ret<------ [ipxodiAA][AAAA][AAAA].......^;name堆栈顶部堆栈底部由于我们输入的name字符串太长,name数组容纳不下,只好向内存顶部继续写‘A’。
由于堆栈的生长方向与内存的生长方向相反,这些‘A’覆盖了堆栈的老的元素。
如图我们可以发现,EBP,ret都已经被‘A’覆盖了。
在main返回的时候,就会把‘ AAAA’的ASCII码:0x41414141作为返回地址,CPU会试图执行0x41414141处的指令,结果出现错误。
这就是一次堆栈溢出。
3:如何利用堆栈溢出我们已经制造了一次堆栈溢出。
其原理可以概括为:由于字符串处理函数(gets,strcpy等等)没有对数组越界加以监视和限制,我们利用字符数组写越界,覆盖堆栈中的老元素的值,就可以修改返回地址。
在上面的例子中,这导致CPU去访问一个不存在的指令,结果出错。
事实上,当堆栈溢出的时候,我们已经完全的控制了这个程序下一步的动作。
如果我们用一个实际存在指令地址来覆盖这个返回地址,CPU就会转而执行我们的指令。
在UINX系统中,我们的指令可以执行一个shell,这个shell将获得和被我们堆栈溢出的程序相同的权限。
如果这个程序是setuid的,那么我们就可以获得root shell。
下一讲将叙述如何书写一个shell code。
--※ 转载:·北大未名站·[FROM: 162.105.170.28]标题: 堆栈溢出系列讲座(2)堆栈溢出系列讲座如何书写一个shell code一:shellcode基本算法分析在程序中,执行一个shell的程序是这样写的:shellcode.c------------------------------------------------------------------------#include <stdio.h>void main() {char *name[2];name[0] = "/bin/sh";name[1] = NULL;execve(name[0], name, NULL);}------------------------------------------------------------------------execve函数将执行一个程序。
他需要程序的名字地址作为第一个参数。
一个内容为该程序的argv[i](argv[n-1]=0)的指针数组作为第二个参数,以及(char*) 0作为第三个参数。
我们来看以看execve的汇编代码:[nkl10]$ gcc -o shellcode -static shellcode.c[nkl10]$ gdb shellcode(gdb) disassemble __execveDump of assembler code for function __execve:0x80002bc <__execve>: pushl %ebp ;0x80002bd <__execve+1>: movl %esp,%ebp;上面是函数头。
0x80002bf <__execve+3>: pushl %ebx;保存ebx0x80002c0 <__execve+4>: movl $0xb,%eax;eax=0xb,eax指明第几号系统调用。
0x80002c5 <__execve+9>: movl 0x8(%ebp),%ebx;ebp+8是第一个参数"/bin/sh\0"0x80002c8 <__execve+12>: movl 0xc(%ebp),%ecx;ebp+12是第二个参数name数组的地址0x80002cb <__execve+15>: movl 0x10(%ebp),%edx;ebp+16是第三个参数空指针的地址。
;name[2-1]内容为NULL,用来存放返回值。
0x80002ce <__execve+18>: int $0x80;执行0xb号系统调用(execve)0x80002d0 <__execve+20>: movl %eax,%edx;下面是返回值的处理就没有用了。
0x80002d2 <__execve+22>: testl %edx,%edx0x80002d4 <__execve+24>: jnl 0x80002e6 <__execve+42>0x80002d6 <__execve+26>: negl %edx0x80002d8 <__execve+28>: pushl %edx0x80002d9 <__execve+29>: call 0x8001a34<__normal_errno_location>0x80002de <__execve+34>: popl %edx0x80002df <__execve+35>: movl %edx,(%eax)0x80002e1 <__execve+37>: movl $0xffffffff,%eax0x80002e6 <__execve+42>: popl %ebx0x80002e7 <__execve+43>: movl %ebp,%esp0x80002e9 <__execve+45>: popl %ebp0x80002ea <__execve+46>: ret0x80002eb <__execve+47>: nopEnd of assembler dump.经过以上的分析,可以得到如下的精简指令算法:movl $execve的系统调用号,%eaxmovl "bin/sh\0"的地址,%ebxmovl name数组的地址,%ecxmovl name[n-1]的地址,%edxint $0x80 ;执行系统调用(execve)当execve执行成功后,程序shellcode就会退出,/bin/sh将作为子进程继续执行。