草庐IT

memcpy函数实现缓冲区溢出漏洞

hhhhhxian 2023-03-28 原文

本次实验需要用到的环境和工具要是需要的可以留言评论,我就不一一介绍了,估计也没啥人看。主要是太多了,我不想打字。

学习这个漏洞我们要去学习漏洞的理论知识。

在汇编程序的执行过程中,如果需要调用某个函数一般是call函数地址,而call这条指令在执行的时候会把函数返回地址(执行完函数后要执行的下一条指令的地址)压栈,然后在栈中的伸展方向是从高地址向低地址延申的。这里可能不是很好理解,我画个图hhhh,比如我在执行call指令时压栈的返回地址的在栈中的序号是10000,然后我调用函数的变量也需要压榨,我申请的一个空间为10的数组,所以我就会申请9990到10000这10个格子用来放参数,然后在存参数的过程中其实栈指针是从低地址移向高地址,第一个参数存9990,第二个存9991,,,但是如果我们的申请的空间是10但是实际上有20个参数的话,参数还是会继续往栈中存,就会覆盖原本存函数返回地址的数据。

 

当执行完memcpy函数以后,就是那个栈平衡,就会把栈中的调用函数入栈的数都出栈,直到把存返回地址的位置出栈到EBP,EBP的地址是当前指令的地址,EIP的地址是下一条指令的地址。

那我们想想,如果我们把恶意代码作为参数传到栈中,然后想办法让函数返回以后再跳回栈中执行栈中的恶意代码,那不就能实现栈溢出了吗?

所以问题就在于,1.如果我们存的数据造成了栈溢出,那么数据是从哪里开始溢出的(覆盖返回地址的数据)?2.如何让已经返回的主程序EIP再回到栈中执行我们存进去的恶意代码?

 先展示一下实验的包含溢出漏洞代码程序:

 

 可以看出我们在主函数中调用并overflow函数,并传了参数shellcode进去,在overflow函数里面,有调用memcpy函数,这个函数是复制字符串到数组中,申请的数组长度为10,但是我们传的参数shellcode是大于数组的空间的。

实验思路:先找到程序运行时memcpy函数返回地址在栈中的位置被shellcode的哪一部分覆盖了,然后修改shellcode覆盖返回地址的部分为jmp esp(回到栈中)的字节码(汇编的字节码),在shellcode中jmp esp后改为我们要执行的恶意代码的字节码,就能实现溢出。也许这里讲的很抽象,但是通过调试跟踪就会明白,下面我们来记录一下调试的过程。

调试用vc++6.0调试,因为能看到堆栈变化过程,还能看到反汇编的代码,和字节码,以前觉得好难,现在觉得好强大hhhhh。

打个断点,让鼠标停在打断点那行代码上,点那个小手,然后出现一个红色的圆点,就是断点:

 

 然后点击框起来的地方,就能调试并停在断点出,如果没有编译的话,编译器会提醒你编译,照做就行。

 

运行停在断点处后,点我圈起来的三个图标,从左到右依次是,显示寄存器,显示内存情况(后面可以搜索看栈的内容),显示反汇编代码

 

 

 然后点下一步,圈出来的是步过和步入,我一般喜欢步过,不明白去别的可以百度一下。

 

 可以看到call memcpy和把返回地址出栈到ebp然后ret,返回执行。

 

当执行到pop ebp前一句时,栈的内容,此时是把esp的地址的内容出栈到ebp中,此时看到内容为46474849,机器读是49484746(这里涉及大端小端存储,不作解释,自行百度)。

 

 然后再往下执行的时候,就会报错,因为把46474849出栈到ebp中,机器下一条就会去找这个地址去执行下一条代码,可是这个地址是没有代码的就会报错。

 

 所以,前面思路的第一个问题我们已经解决了,shellcode的内容从46开始就会覆盖返回地址,现在我们解决第二个问题,使下一条指令的地址回到栈中。这个时候我们可以利用动态链接库中的jmp esp,我们这个时候用一个工具去找。就双击Findjmpesp.exe,显示的全都是,我们选第一个。

 

 然后把这个地址写到shellcode中46474849的位置,然后代替它入栈,细心的同学就发现刚刚出栈的时候怎么是49484746,所以我们写地址到shellcode中的时候也要倒着写,就是da24e477.

 再重新编译调试一次,是不是出栈以后执行的指令就变成了,jmp esp。

 

 再下一步看看回到栈中以后,执行啥代码。虽然后面机器解释为push,pop啥的,但是它那个字节码其实是我们存到栈里面的,49以后的数字50,51.....

 

 

 

 所以第三步就是我们把我们要执行的恶意代码的字节码写进来,就会继续执行我们要的操作。如何搞出字节码呢,就是编译器的工作了,我们先把恶意代码的C语言程序写出来,这里我用的是老师给的。

展示一下我的程序,这个程序是汇编代码,它内容是调用一个弹窗函数,然后再调用一个退出程序的函数,这个程序并不是我写的,我们查找并填入两个函数的绝对内存地址:

 

 如何找到函数的绝对内存地址:

MessageBox A在user32.dll中的相对地址为3D8DE,user32.dll的基址为77e10000,程序运行的时候,函数的地址就是base+相对地址。所以我们把这两个数加起来77e4d8de。

00

 

 另一个函数,自己算哈:

 

 然后我们编译运行一下createshellcode.程序看看是什么样的。

 

 然后我们把这个函数asm的部分(弹窗并退出程序)的字节码写到overflow.c函数的shellcode的jmp esp的后面。反汇编可以查看字节码。要把asm部分所有的字节码都抄过去,我知道这个工作量很大,或许网上有脚本hhhh,但是我是手抄

 

 然后回到overflow.c,然后我们编译执行一下。

 

执行的结果是这样子的,也许细心的同学会发现我的两个弹窗的字不是一样的,因为前面的弹窗的字被我改过的,这个弹窗的字符我用的是原本的字节码。成功实现了栈溢出~~~

 

 

 本次实验学习介绍就到这里啦!

有关memcpy函数实现缓冲区溢出漏洞的更多相关文章

  1. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  2. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  5. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  6. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. Tomcat AJP 文件包含漏洞(CVE-2020-1938) - 2

    目录1.漏洞简介2、AJP13协议介绍Tomcat主要有两大功能:3.Tomcat远程文件包含漏洞分析4.漏洞复现 5、漏洞分析6.RCE实现的原理1.漏洞简介2020年2月20日,公开CNVD的漏洞公告中发现ApacheTomcat文件包含漏洞(CVE-2020-1938)。ApacheTomcat是Apache开源组织开发的用于处理HTTP服务的项目。ApacheTomcat服务器中被发现存在文件包含漏洞,攻击者可利用该漏洞读取或包含Tomcat上所有webapp目录下的任意文件。该漏洞是一个单独的文件包含漏洞,依赖于Tomcat的AJP(定向包协议)。AJP自身存在一定缺陷,导致存在可控

  9. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  10. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

随机推荐