2019-2020-2_20174322童硕_《网络对抗技术》_Exp1_PC平台逆向破解

  😎遇到的问题我都写进来了,目前实验流程写完了,我遇到的一些卡手的问题也写了,如果你第三部分做不出来,按ctrl+f搜索第三部分出现段错误原因 看看我遇到的问题会不会也是你面前的问题。如果你不会计算偏移地址,也可以在这里找到我的理解。本文8000余字,80张截图,学习内容加实验加编写博客8小时以上,阅读全文约30分钟

==>感想和问题写在最后了

端坐敲代码,不容易敲错,听歌写博客,写的更快。🤪

我做这个实验遇到很多问题,也百度解决很多问题,甚至成为kali九级安装师(创一次虚拟机升一级)。

所有代码指令,实验楼有详细教学,我附这么多博客只是正好搜到了

  

Exp1_PC平台逆向破解

20174322童硕

 

一、逆向及Bof基础实践说明

  1.1 实践目标

  本次实践的对象是一个名为pwn1的linux可执行文件。

  该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。

   

 

    该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

  1.2 三个实践内容如下:

  (1)手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。——>直接运行原本不可访问的代码片段

  (2)利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。——>强行修改程序执行流程,运行foo函数时调用getShell函数

  (3)注入一个自己制作的shellcode并运行这段shellcode。——>注入一个shell代码,让程序运行注入的代码,这里已经不运行程序原来有的getShell函数了

   1.3 基础知识(这里把基础两个字划掉是在说不基础吗哈哈哈)

   熟悉Linux基本操作

  能看懂常用指令,如管道(|),输入、输出重定向(>)等。

  理解Bof的原理。

  能看得懂汇编、机器指令、EIP、指令地址。

  会使用gdb,vi。(这是两个指令,用于编译文件的)

  当然,如果还不懂,通过这个过程能对以上概念有了更进一步的理解就更好了。

  1.4老师寄语:

   指令、参数 这些东西,我自己也记不住,都是用时现查的。所以一些具体的问题可以边做边查,但最重要的思路、想法不能乱。要时刻知道,我是在做什么?现在在查什么数据?改什么数据?要改成什么样?每步操作都要单独实践验证,再一步步累加为最终结果。操作成功不重要,照着敲入指令肯定会成功。重要的是理解思路。看指导理解思路,然后抛开指导自己做。碰到问题才能学到知识。具体的指令可以回到指导中查。  

   我很同意😊,卡手了,百度就完事了

 二、实验步骤

  2.1直接修改程序机器指令,改变程序执行流程

   📚知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具

   🚩学习目标:理解可执行文件与机器指令

   📈进阶:掌握ELF文件格式,掌握动态技术

 步骤0:下载目标文件pwn1。这里交代下,我把pwn1文件解压放到20174322tongshuo_exp1文件下,看我新建目录给你露一手。

pwn1文件下载链接:点我点我

      

    这样跳转目录的时候输入cd  2  然后按Tab键自动补全,也是很方便的,等到实验二的时候我就把这个目录名字改成z20174322…就不会重复。

   把pwn1文件从exp1文件复制一份到20174322tongshuo_exp1文件 

  

   看到20174322tongshuo_exp1文件 里有pwn1文件就好了

 步骤1:输入objdump -d pwn1 | more,反汇编20174322tongshuo_exp1文件 里的pwn1文件

  

   这里不能汇编的话看下pwn1文件权限是否不对,w =(写)r = (读) x=(可执行)修改权限代码:

  摘录自:修改文件权限

   小问题,接着说,反汇编后按回车一行一行显示,长按回车迅速滚屏,输入/getShell(大小写)可以从文件头向文件尾找到getShell 函数反汇编的代码。

  

    内存地址我看大家都是一样的,第一行55都是0804847d

   首位0省略,后面各个含义在老师视频里有详细解释,这里简单列下。

   

    摘录自:《汇编指令和机器码的对应表》

   

    对照汇编指令表,可以看到main函数第四行80484b5: (这条指令内存地址) e8(call)d7f f f f f f (8048491<foo>), 我现在分析下这里为什么是d7 ff ff ff ,只是看流程,可以直接跳下一步骤2

  🕵️‍♂️首先明确这是补码,这样符号可以作为数值一并进行加减法,化简计算机负数运算的复杂问题。这里考虑两个指针,简单化假设这计算机一次只走一条汇编指令,有ESP指示当前时刻要执行的指令(call 调用子函数指令);有EIP指示下一条汇编指令(mov 数据赋值给寄存器)

  ESP(Extended Stack Pointer)为扩展栈指针寄存器,是指针寄存器的一种,用于存放函数栈顶指针。与之对应的是EBP(Extended Base Pointer),扩展基址指针寄存器,也被称为帧指针寄存器,用于存放函数栈底指针。

  另外,ESP为栈指针,用于指向栈的栈顶(下一个压入栈的活动记录的顶部),而EBP为帧指针,指向当前活动记录的底部

EIP:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。

摘录自:《EIP & EBP & ESP》

   一切准备就绪,开始走ESP,读e8发现是个call指令,CPU就会转而执行

EIP + d7ffffff( call后的偏移量 )

     地址上的代码。

 道理是这样的,但为什么是d7ffffff呢?这是咋算的?

     列个方程:

移项后得到:EIP - 目标子函数地址 = - d7ffffff;

    再看下刚才反汇编的结果,找到EIP 和目标函数 地址

    

    

       由图得到EIP foo地址,代入计算👇:

 

   嗨呀,这是(29)16呀,d7ffffff是啥? d7ffffff是( - 29)16的补码。

  (29)16 = (1 0010 1001)     补码:1 1101 0111  (第一位符号位,负数取补码符号位不变,逐位取反,末尾加1)

  32位计算机寻址也是32位二进制,所以前面补1 变成 ffffffd7

   八位二进制代表一字节,两位16进制代表一字节,但界面上表示的d7 ff ff ff 从左往右是按照低位字节到高位字节的顺序排列的

   所以call后面代码的计算方式就是

      EIP - 目标子函数地址 的差 加上负号后 再取补码

   

    明确这一点,就知道该改成啥了✔

    我们目的不要让它运行foo函数,我们要让他运行getShell函数,getshell才是我们的目标函数,如下

 

      带入数值计算

(080484ba)16   -(0804847d)16  =(3d)16   

      把我们的结论拿出来再看一眼

    

       先加负号 : (- 3d)16    ->( 1 0011 1101 )

       取补码:( 1 1100 0011 ) ->( ff ff ff c3 )16     前面加1填充为32位二进制

       然后显示在屏幕上是每字节一组,从低位字节到高位字节就是c3ff ff ff

          所以在文件中找到这一行,修改 d7ff ff ff  为 c3 ff ff ff  就可以实现调用getShell的目的了

 步骤2:使用vi编辑器修改文件

可参考:《Kali Linux的vi编辑器/vim编辑器使用方法》

   输入vi pwn1 后按回车,如下

     

     

   这看不了,按esc 可输入  :!xxd   变换显示进制模式,输入/e8 d7ff ff (空格是必要的) 会找到相应位置。那会不会有重复的代码段呢?这个d7就是我们要找的d7吗?(操作不会可以看看链接。使用vi编辑器修改文件

《Kali Linux的vi编辑器/vim编辑器使用方法》

   

   其实重复的话就要看上下文,找到正确的位置,这里看e8前面89e5 83e4 fe

     

    按 “  i   ”进入插入模式,使用退格、鼠标等修改d7为c3

     

    改好了,(要先输入 :%!xxd - r  转格式变回原来的乱七八糟的形式再退出!,先看我接下来就是先掉坑里再出来)输入:wq 保存并退出,更多操作,请看《Kali Linux的vi编辑器/vim编辑器使用方法》https://www.52host.cn/blog/kali-linux-vi-editor/

     

    真的改好了吗?再输一下vi pwn1看一下

     

      

    乱码?别急 esc 输入:%!xxd ,转进制,输入/e8 c3 看看有没有

             

   我有了,输入:wq 退出 ,或者:!q不保存直接退出

  这里一定要先转格式变成原格式    然 后   再退出

  否则往后做会卡手,文件会因为是十六进制编码无法编译,就像下图

    

   如果你知道了要先转格式,再退出,你为你的人生节省了15分钟,现在站起来活动一下吧,朋友圈有更新了。

   如果你不幸直接退出,那就得输一下vi pwn1打开文件  输入 :%!xxd - r  

    

                    

    

    和谐的一幕,输入:wq 保存退出

     

    步骤3:输入objdump -d pwn1 | more 反汇编

     

     

    输入 /getShell 找到getShell文件 (应该大小写敏感,注意下)

    

   看下修改有没有成功,它会变成<getshell> 附上之前的比较下,这样更感性🙌

     

   步骤4: 接下来输入./pwn1 执行       

    

    我怀疑是老师留一手,要不就是我……算了,做题,用ls -l查看文件权限,左边- rw - - - - - - - 没有一个x,代表没有用户可以执行,含义详细想了解看博客吧。

可参考:《linux文件的权限位代表的含义》

  另外实验楼也讲的很清楚,我也能给你说的“很清楚”

  修改权限代码:chmod a +x pwn1  chmod是修改权限,a是(all)指对所有用户,+x代表增加“操作执行”的权限

    

   这样三个x所有用户都可以执行

  详细修改权限指令看博客《linux修改文件权限》

   改完权限,输入./pwn1 可用shell指令了,输入ls -l 可以显示当前目录里所有文件详细信息

       

   第一小部分完成了

<=================================分==割==线=====================================>

2.2通过构造输入参数,造成BOF攻击,改变程序执行流

  📚知识要求:堆栈结构,返回地址 学习目标:理解攻击缓冲区的结果,掌握返回地址的获取 进阶:掌握ELF文件格式,掌握动态技术

  🚩实验目的:反汇编,了解程序的基本功能,函数功能第一部分差不多说清楚了,再聊聊地址以外的。

    🙇‍♂️EBP和ESP是一个函数的栈底和栈顶,在子函数EBP上方是主函数的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp(把esp栈顶地址给ebp,这样栈底和栈顶一样了,就丢掉栈内数值,然后 pop ebp (出栈,栈指针在子函数退出后,就指向主函数的栈顶), 然后ret 结束符,子函数就结束了

    ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。

    

   Foo函数功能是用户输入什么东西,它就返回在屏幕上显示生么东西❔

  0x1c就是预申请的栈空间,转成十进制,大小是28 字节。用来保存用户输入的,如果允许栈输入越界,用户输入就会覆盖到下一条指令的数据区,就是下一行的call指令,0x08084a8这行call调用子函数的指令,原本是输出字符串的,地址变成getShell的地址,就可以攻击的目的。

这里题回答下

  主函数main中的ebp 地址是080484af,在子函数foo里把它压入栈,作为子函数运行完后返回的地址

     

  第0步:首先是重新再用一个pwn1文件,我取名为pwn1_for_exp2

  到pwn1文件目录,启动gdb编译模式,以便看到寄存器是什么数值,找到我们应该输些什么东西覆盖返回地址:

  第1步:输入gdb pwn1_for_exp2 编译,输入  r ,运行(run)程序。

    

  

我首先验证下堆栈溢出,前面说了预留28个字节,输入了32字节(程序是char型变量,一个数字一个字节),所以后面四个字节是溢出的,我想看看它会覆盖到哪里,输入8个1 8个2  8个3 12345678,运行后输入 info r 查看运行信息。

    

    我看到ebp,栈底指针的值已经变成了0x38373635,发现了规律32位可以覆盖到自己的ebp,再多四个字节,36位就可以覆盖到返回地址。解释下为什么,纯原创绘图

 

   再多输几个数试一试,输入   r  ,再跑一次,程序问要不要重新来? 输 y 当然了

    输入 8个1 8个2  8个3 8个4 12345678,运行后输入 info r 查看运行信息。

     

这里eip已经是0x34333231,去掉3就发现是4321,为什么我们坚信5678四个数可以覆盖到返回地址呢?,因为foo函数这个get函数不读到回车绝不停,允许堆栈越界的话,他就一直覆盖下去。而返回地址就与ebp相邻,一定可以的。     

     找下getShell地址:0x0804847d

    

    看顺序会是按字节倒序,由于16进制两位一个字节

  

  这些准备好我们就开始输入了,这里使用perl指令先把这么长的命令变成一个文件,然后用文件在pwn1执行时注入

  输入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input

  这段指令就成为了文件input

  x0a是代表回车,不加这个的话,注入数据后按下回车就能执行

  可以使用16进制查看指令xxd查看input文件的内容是否如预期。

  输入xxd input 我看了下我的和老师网站一样,没问题

  然后输入 (cat input; cat) | ./pwn1_for_esp2  (我的pwn1文件叫 pwn1_for_esp2 )将input的输入esp2 ,通过管道符“|”,作为pwn1的输入。

     

 

  输入ls -l 发现确实可以响应指令,列出所有文件

  第二部分也做完啦

《==================分======割=====线==========================》

 

2.3注入Shellcode并执行

 

   2.3.1 准备一段Shellcode

 

   shellcode就是一段机器指令(code)

  通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。

   在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令

 📚最基本的shellcode的编写可参考许同学的文章Shellcode入门,写得非常之清楚详实。以下实践即使用该文章中生成的shellcode。如下:

 

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\

 

 2.3.2准备工作

   修改些设置。这部分的解释请看第5小节Bof攻击防御技术.

 

步骤1:输入apt-get install execstack安装栈的相关文件,这里要读一下界面返回,看看你装的kali能不能联网下载更新安装,我就是没安装成功,用爱瞎做了一下午,如果安装成功就跳到下一步,步骤 2

   我安装不成功的界面是这样的

    

   它提示我无法连接网站,如果你情况和我不一样,就再百度kali联网更新,找找博客试试,但尽量不要看到就拿起做,我就是看到就改,kali安装等级又升了一级

    用鼠标打开 etc/apt/sources.list文件,添加更新网址,全部复制就好了,可以把原来的所有注释都删了,没事的,这步我大概重复了2次。

     

 

#官方源

deb http://http.kali.org/kali kali-rolling main non-free contrib

deb-src http://http.kali.org/kali kali-rolling main non-free contrib

 #阿里云

deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib

deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib

 #清华大学

deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non- free

deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free

 摘录自:《Kali Linux网络配置,更新升级,软件包安装,浏览器插件》

   然后输入apt-get install execstack安装栈的相关文件,下面这样有下载提示啥的就应该没问题了。

    

 步骤2:输入execstack -s pwn1设置堆栈可行,这里的pwn1文件目录一定要对奥,如果你也把pwn1文件放到目录里,一定要加上目录信息,或者先转移到文件目录

    

    接着输入execstack -q pwn1查询pwn1文件的堆栈是否可执行他会返回x pwn1文件名

    

   输入more /proc/sys/kernel/randomize_va_space查看地址随机化信息

     

    它的返回值是2

    输入echo "0" > /proc/sys/kernel/randomize_va_space停用它,然后再输入more /proc/sys/kernel/randomize_va_space查询下信息

    

    返回数值为0就对了。

   栈和 mmap 映射区域并不是从一个固定地址开始,并且每次的值都不一样,这是程序在启动时随机改变这些值的设置,使得使用缓冲区溢出进行攻击更加困难。当然也可以让程序的栈和 mmap 映射区域从一个固定位置开始,只需要设置全局变量 randomize_v a_space 值为 0 ,这个变量默认值为 1 。用户可以通过设置 /proc/sys/kernel/randomize_va_space 来停用该特性

摘录自:《linux进程内存布局--randomize_va_space》

 2.3.3一切做的都对吗?

  准备工作做完了,整理下思路,如果只是做的话往后看步骤3就好了。前两次,覆盖调用子函数返回地址,让它跳转到文件中的getShell函数实现攻击目的,但总不可能攻击目标正好有个getShell函数就摆在那让我们攻击,第三部分,我们要自己注入getShell函数,就是自己输一段代码,再利用栈越界覆盖foo函数里call的地址。实现调用我们注入代码的目的。

  这段代码是这样的:

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\

关于更多Shellcode的知识,请参考《Shellcode基础》

接下来构造要注入的payload。不能直接输这两行,没用的,要武装起来。

  Linux下有两种基本构造攻击buf的方法:

  Retaddr + nop + shellcode      VS       Nop + shellcode + retaddr

       

 

老师说:因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。

简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

  哦怎么理解?掏出我之前的学习学习成果

                

    简简单单,这里采用第一种方式,数组用32个“A”占位同时把ebp也占掉,因为允许栈溢出,retaddr可以占掉图中返回主函数的地址,让他指向shellcode执行shellcode

 步骤3:这里我做了好久,重复好几次,截图已经不是第一次做的,只是数不一样,还是原来的配方

  输入  perl -e 'print "A" x 32;print "\x50\xd3\xff\xff\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x00\xd3\xff\xff\x00"' > input_shellcode  

构造输入流文件, \x50\xd3\xff\xff是retaddr,这几位是跳转到shellcode用的,我看大家都不一定相同,后面详细解释

    

   输入xxd input_shellcode, 可以查看文件,校对一下,这里太容易输错了。

步骤4:打开两个终端窗口,左边输入(cat input_shellcode;cat) | ./pwn1 注入然后这个挂着不动,换到第二个端口查看这个任务进程,我这里就是6900,就这四个数左上角这个,就这个,不用别的。这个进程每次运行都不一样的

    

   输入gdb打开编译器,输入attach 6900 编译这个进程,上图很全了

步骤5:在编译调试界面输入disassemble foo设置断点,暂停在foo函数

    

   然后在调试界面输入break *0x080484ae 代表着在上图ret的地方加书签断点,程序运行到这里会暂停。这个*0x080484ae所有人都一样,不一样的应该就是初始设置没弄好,重新设置下,可以试着在pwn1文件的目录下设置

     

   设置完断点回车结束这个指令,弹出新的一行“(gdb)”,然后不要动,换窗口了,

     

 

 

 

   在左边注入代码这个窗口按一下回车,

    

 

 

 

  然后在调试界面输入c 代表continue继续运行,输入info r esp查看它的地址

     

 

 

 

   0xffffd350就是上图0x90909090的地址,怎么做?是在右框找到0x90909090的地方,算出它的地址,把地址写在注入代码

(/x90/x90/x90 …/x0b/xcd/x80/x90/x30/xd3/xff/xff/x00)的最前面就行了,像我这里的0xffffd350就是

    (0xffffd34c) 16 + (4)16 算出来的。(已修正)

    

 

 

 

我就写在最前面,那个perl指令就变成下图

    

  你可以试试(0xffffd34c) 16 + (5或者6)16,只要地址是9090,或者0xc031…的地方应该都没问题 

  这样再输入(cat input_shellcode;cat) | ./pwn1就运行成功了,这里文件夹名我是变了的,但是意思就是pwn1不加任何修改的原文件,做到这里如果做不出来原因有很多的,不要放弃,慢慢来。

    

   我注入代码结尾的x60/xd3/xff/xff是按老师的打上去的,其实我看这个不重要,我换了几个也可以运行成功。后面有遇到的很多问题,很多想法,我都写在下面,如果你做不出可以看看。

 

3.1实验感想和总结

   本次实验实现了PC平台逆向破解,使用三种方式攻击主机,达到执行恶意代码,创建一个可用shell的目的,三种方法都在允许堆栈越界的情况下运行成功的,第三部分还关闭了堆栈随机化,条件更加苛刻。

  “栈和 mmap 映射区域并不是从一个固定地址开始,并且每次的值都不一样,这是程序在启动时随机改变这些值的设置,使得使用缓冲区溢出进行攻击更加困难。当然也可以让程序的栈和 mmap 映射区域从一个固定位置开始,只需要设置全局变量 randomize_v a_space 值为 0 ,这个变量默认值为 1 。用户可以通过设置 /proc/sys/kernel/randomize_va_space 来停用该特性。”

摘录自linux进程内存布局--randomize_va_space》

      

                 堆栈地址和mmap地址随机化(图一)                学习成果(图二)

   图上这里箭头往上和往下,初始位置是可变的,所以准备工作设置关闭它的随机化。使得我们第一次“运行、找进程号、找到0x90909090的地址,然后关闭这个进程,去修改注入代码指令的子函数返回地址为/x50/xd3/xff/xff、再次运行的时候,0x90909090的地址还是 0xffffd350,攻击成功”不关地址随机化的话它一定会变到其他地址,因为计算机一直再运行指令一直在动。

  我觉得我得出的学习成果(图二)非常棒,它解释了为什么在关闭堆栈保护的情况下,输入32字节可以覆盖掉数组的28字节空间和ebp的4字节空间,它也解释了为什么输入 36 字节的话会将子函数返回地址覆盖,使得子函数运行时会转到其他函数,还表现出数据在栈中从高位向低位保存数值。

  另外的收获就是,在判断nop+shellcode+retadder 还是retadder+nop+shellcode的时候,gdb编译模式下,我是查到gbd操作指令,使用info frame 看到了eip存储的地址

       

 

          使用info frame指令(图三)          无数的段错误,图中还没真正做出来(图四)

 

  发现了eip(下一条指令地址)就是我所期待的地址(图三),所以我觉得应该使用第二种组合方式,retadder才能刚好覆盖到返回地址。,做第三部分的时候我遇到了无数段错误

 

第三部分出现段错误原因:(从小问题到大问题排序)

1.注入命令 perl -e 'print "A" x32 …漏打、多打、错打、多斜杠、斜杠打反。下图五。点我直达

2.准备工作的设置没弄好,注意最好在pwn1文件同级目录下进行安装和关闭地址随机化的操作,我是第一次在主目录里做这些设置,然后总是段错误,我对比了失败的和成功的截图信息,0x50d3ffff我早就算出了,其它的也完全一样,我感觉第三部分做不出来,可能是这个原。点我直达

3.注入命令生成的文件名和管道注入的文件名不一致,即 perl -e 'print "A" x32 …x1\x00 " '> input ; 但是下一条语句(cat input_shellcode ; cat ) ./pwn1 。黄色标出的地方得一样才对,文件名可以改,但是要明确哪个文件是啥,别输错了。还有时我们改了pwn1文件的名字,在注入时也不能输错了。

4.覆盖地址算错了,这个可以在当前网页按ctrl + f 打开搜索栏,输入  一切做的都对吗? 查看我学的计算方式

5.其实结尾的0x00d3ffff不是一定的,这里我试了几个数,如果你在因为这个纠结,就不用担心啦,我试了0x60d3ffff,0x0000ffff,0x50d3ffff,0x90d3ffff 都是可以的,图六图七

                错误截图(图五)                      结尾的d3ffff不是一定的(图六)

 

         结尾的d3ffff不是一定的(图七)

3.1.2什么是漏洞?漏洞有什么危害? 

漏洞是指程序中缺少的判断条件和指令代码,导致程序不能稳定运行,在实验中利用没有栈边界保护的漏洞使得肆意修改函数调用的地址,使得系统运行恶意代码,系安全和系统内的文件安全受到威胁。

 

 

3.2回答老师的问题

  3.2.1.第三部分的,申请了28字节,返回地址080484af

  3.2.2.NOP, JNE, JE, JMP, CMP汇编指令的机器码?

    NOP - 90 空指令,一个时钟周期什么都不做

    JNE - 75 有条件的转移指令

    JE - 74 有条件的转移指令

    JMP无条件跳转

      JMP short - e8 段内直接短跳转

      JMP near - e9 段内直接近转移

      JMP word - ff 段内间接转移

      JMP far - ea 段间直接转移(远)

    CMP - 39 比较大小,cmp a,b 用a减一下b,看结果正负得出大小,但是不记录结果在其他寄存器里

  3.2.3掌握反汇编与十六进制编程器 (0.5分) objdump命令和:%!xxd指令,实验中也顺利完成啦

        3.2.4能正确修改机器指令改变程序执行流程(0.5分)实验全部成功啦

        3.2.5能正确构造payload进行bof攻击(0.5分)第三部分构造成功啦

 

4.1如果遇到的一些问题想知道为什么

  第一个问题,我在想为什么看esp?不是应该找ebp地址,然后ebp相邻的才是函数返回地址。

    

 

  这里说esp是最老的,另一种说法现在断点运行完子函数已经结束了,接下来释放空间是把esp等于栈底指针ebp这样计算机有其他指令清理被占用的空间。如下图

     

  可以看出esp等于ebp了,栈顶等于栈底,就可以清空栈了,就是这样式的,因为预申请28字节,ebp占四字节,填充的32个“A”就把这两个占掉了,接下来的数字就是子函数返回地址

    

   要把蓝框框里的变成909090909090的空间地址,这样会自动滑到shellcode代码/x31/xc0/x50/x68……这里运行,所以909090被称作降落区(nop)

    

  

   

   开头这个\x50\xd3\xff\xff是覆盖了子函数的返回地址,(我这是这个数,大家可能都不一样的)使得子函数跳转到后面的0x9090909

的地址,执行上面的909090,其实可以再往后一点,到0xc0319090,甚至c031的位置都可以,

这里可以算一下,注意这个存储的顺序,四个字节为一组,每组内字节倒叙,记得我画的那个列表格,数据是按字节从高位往低位填的。

      

     所以按道理0xffffd356也是可以的,我试一下。

    

  这里是可以的,当然我是 x50/起始的,这点大家可能不一样,一定记得

    第二个问题,payload的另一种构造方法有什么问题?为什么不行

  程序预申请28个字节保存数组,允许栈溢出

 

posted on 2020-03-04 16:17  20174322童硕  阅读(388)  评论(0编辑  收藏  举报

返回顶部