20242405 2026-2027-1 《网络与系统攻防技术》实验1实验报告

20242405 2026-2027-1 《网络与系统攻防技术》实验1实验报告

1. 基础知识\

在本次实验中,可执行文件pwn1遵循Linux下的ELF格式,其结构包含ELF头、程序头表、节头表以及.text(代码)、.data(已初始化数据)、.bss(未初始化数据)等核心节区;程序运行时的栈帧结构由EBP(栈底指针)、ESP(栈顶指针)和EIP(指令指针,指向下一条待执行指令)协同维护,函数通过push
ebp、mov
ebp,esp建立新帧并用leave和ret恢复;由于x86架构采用小端序存储,数据的低位字节存放在低地址、高位字节存放在高地址;call指令(机器码e8)的操作数采用相对寻址,计算公式为"目标地址
= 下一条指令地址 + 偏移量",偏移量以补码形式小端序存储。

2.实验内容\

(1)手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。

  • (2)利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
  • (3)注入一个自己制作的shellcode并运行这段shellcode。\

3.实验过程

  • 任务一:

  • 首先反汇编查看地址

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 1.png图片
1{width="5.764583333333333in"
    height="3.4493055555555556in"}

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 2.png图片
2{width="5.739583333333333in"
    height="2.8333333333333335in"}

截图显示,getShell 函数的起始地址:0804847d,main 函数中调用 foo
的指令地址:80484b5,call 指令的机器码:e8 d7 ff ff ff,call
指令的下一条指令地址(即执行时 EIP 的值):80484ba。

call 指令的计算公式:偏移量 = 目标地址 - 下一条指令的地址

目标地址(getShell)= 0x0804847d

下一条指令地址 = 0x080484ba

计算:0x0804847d - 0x080484ba = -0x3d

结论:将原机器猫(e8 d7 ff ff ff)中的d7改为c3

进入vi进行更改:

C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 3.png图片
3{width="5.375in"
height="4.308333333333334in"}

  • 反汇编查看:

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 4.png图片
4{width="5.416666666666667in"
    height="4.25in"}

  • 运行结果:

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 5.png图片
5{width="5.466666666666667in"
    height="0.875in"}

  • 成功的进入了shell

  • 任务二

  • 首先GDB 调试确定偏移量

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 6.png图片
6{width="5.395833333333333in"
    height="4.4375in"}

  • 截图显示,第 29~32 个字符覆盖了保存的 EBP,第 33~36
    个字符覆盖了函数的返回地址(EIP)。所以缓冲区填充需要 32个字节(28字节
    buf + 4字节 EBP),第 33~36 个字节就是要覆盖的返回地址位置。

  • 构造payload,并进行注入攻击。

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 7.png图片
7{width="5.333333333333333in"
    height="2.5in"}

  • 成功拿到了shell。

  • 任务三

  • 首先关闭防御机制,为pwn1设置堆栈可执行,并关闭ASLR

  • 再构造初始攻击载荷

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 8.png图片
8{width="5.7659722222222225in"
    height="1.9236111111111112in"}

  • 在一个终端进行攻击,另一个终端寻找地址

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 9.png图片
9{width="5.141666666666667in"
    height="0.6083333333333333in"}

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 10.png图片
10

  • 找到ret指令的地址,并设置断点

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 11.png图片
11{width="5.7659722222222225in"
    height="1.1416666666666666in"}

  • 找到了Shellcode 在内存中的真实起始地址是 0xffffd350。

  • 生成最终的payload并进行攻击

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 12.png图片
12{width="4.733333333333333in"
    height="1.0583333333333333in"}

  • C:/Users/syl/Desktop/新建文件夹/新建 DOCX 文档/图片 13.png图片
13{width="4.716666666666667in"
    height="1.8583333333333334in"}

  • 成功拿到了shell\

4.问题及解决方案\

- 问题1:在任务二中,最初使用"32字节填充 +
4字节返回地址"构造Payload,导致程序反复报错崩溃。

  • - 问题1解决方案:调整Payload结构为"28字节A填充 + 4字节有效EBP地址 +
    6个ret指令地址+ getShell地址"。保留有效EBP避免了 leave
    阶段崩溃,且通过多个 ret
    指令弹栈消耗掉多余字节,解决16字节栈对齐问题,最终成功获取Shell。
    - 问题2:注入攻击成功后,终端光标卡住闪烁,但并未如预期般弹出 # 或
    $ 提示符,让人误以为攻击失败。
    - 问题2解决方案:实验通过管道 (cat input; cat) | ./pwn1
    将Payload输入程序。Shell启动后,其标准输入是一个非交互式的管道,因此它默认不显示命令提示符。但此时Shell已经成功获取,不需要等待提示符。直接在卡住的光标处盲打输入命令(如
    whoami、ls)并回车,Shell能够正常执行命令并回显结果,以此验证攻击成功。

  • - 问题3:在任务三第一次构造Payload时,采用了"nop + shellcode +
    retaddr"的布局,程序在Shellcode执行过程中崩溃。
    - 问题3解决方案:更改Payload布局为"anything + retaddr + nops +
    shellcode"(RNS模式),即将Shellcode放置在返回地址之后的高地址区域,使栈顶向上增长时不再与代码区重叠。重新注入后成功获取Shell。
    - 问题4:为了调试Shellcode地址,在另一终端运行 (cat inputshellcode;
    cat) | ./pwn1,但执行 ps -ef | grep pwn1
    却找不到该进程,导致无法用GDB attach调试。
    - 问题4解决方案:该调试Payload末尾包含了 \x0a(回车符),导致 gets
    函数读取后程序不再阻塞等待输入,直接执行到 ret
    指令并跳转到占位地址,程序瞬间发生段错误(Segmentation
    fault)并退出,因此 ps 查不到进程。 因此重新生成一个去掉 \x0a
    的调试Payload(如 inputshellcode_debug)。运行后 gets
    会因等待输入而阻塞,程序保持挂起状态,此时再使用 ps
    即可成功找到进程号,并顺利在GDB中进行 attach 和内存地址定位。\

5.学习感悟、思考等\

(1)AI的辅助十分强大,几乎所有问题都可以通过询问Ai得到解决

  • (2)每一步都需要进行验证,否则很可能出现命令没有运行成功,接下来的实验出现问题。
posted @ 2026-10-11 18:50  gchhghfgt  阅读(3)  评论(0)    收藏  举报