首页
社区
课程
招聘
[原创]DVRF下Mips堆栈溢出ROP举一反三
发表于: 1天前 153

[原创]DVRF下Mips堆栈溢出ROP举一反三

1天前
153

MIPS 堆栈原理
栈是一种具有先进后出队列性质的数据结构。调用栈(Call Stack)是指存放某个程序正在运行的函数的信息的栈。调用栈由栈帧(Stack Frame)组成,每个栈帧对应一个未完成运行的函数。

非叶子函数调用过程
程序在跳转到非叶子函数以后,则非叶子函数会把调用它的函数的返回地址(也就是RA)RA寄存器)存入堆栈中,再将自己函数返回地址存入到RA寄存器)存入堆栈中,再将自己函数返回地址存入到RA,在函数返回时,非叶子函数会将栈中先前保存的返回地址取出保存到RAjrRA中,再执行 “jrRA中,再执行jrra”返回原函数。

叶子函数调用过程
程序在跳转到叶子函数中,过程比较简单,叶子函数不会改变寄存器RAjrRA的值,因为函数跳转到它,就不会再有跳转了,因此在函数返回时,直接 “jrRA的值,因为函数跳转到它,就不会再有跳转了,因此在函数返回时,直接jrra”返回原函数。

简单来说,*区分“叶子函数”和“非叶子函数”的关键在于:这个函数是否会调用其他函数。这一点直接决定了它们对待堆栈和返回地址寄存器($ra)的态度。
函数调用参数传递
在MIPS 体系的函数调用过程中,通过
aa0~a0 a3 *传递前四个参数,多余的通过栈传递。
栈空间缓冲区溢出

栈空间缓冲区是用于内存中存储数据的内存区域。缓冲区溢出就是大缓冲区数据向小缓冲区复制的过程中,由于没有检查小缓冲区的边界不严格,导致小缓冲区明显不足以接收整个大缓冲区的数据,超出的部分覆盖了与小缓冲区相邻的内存区中的其他数据而引发的内存问题。成功利用缓冲区溢出可能造成严重的后果,基本上可分为3 种情况,分别是拒绝服务、获得用户权限、获得系统权限。

以下是详细的原理和流程解析:
在 MIPS 中,堆栈用于存储函数调用过程中的临时数据、局部变量以及需要保存的寄存器值(如 ra,ra,ra,s0-$s7)。
生长方向:向下生长(从高地址向低地址)。
入栈 (Push):先减小栈指针 sp(subsp (subsp(subsp, ...),再存入数据 (sw)。
出栈 (Pop):先读取数据 (lw),再增加栈指针 sp(addsp (addsp(addsp, ...)。
核心寄存器:
$sp (Stack Pointer, r29):始终指向栈顶。
$ra (Return Address, r31):存储函数返回的地址(即调用该函数指令的下一条指令地址)。

叶子函数 (Leaf Function)
定义:一个函数内部不再调用任何其他函数。它是调用链的末端。
特点:
rara 很安全:因为它不调用别的函数,就没有指令会覆盖ra很安全:因为它不调用别的函数,就没有指令会覆盖ra 寄存器的值。
效率高:通常不需要把 $ra 压入堆栈(除非寄存器不够用,需要借用栈空间)。
2. 调用流程
由于不需要保护 $ra,叶子函数的流程非常简单:
调用者 (Caller):
准备参数 (aa0-a0a3)。
执行 jal LeafFunc(jal 会自动把返回地址写入 $ra)。
被调用者 (Callee - LeafFunc):
Prologue (序言):如果有局部变量,只需移动 spsp 开辟空间。不需要保存sp开辟空间。不需要保存ra。
Body (主体):执行计算。尽量只使用临时寄存器 (tt0-t0t9),这样就不用保存/恢复 $s 寄存器。
Epilogue (结语):如果动了 $sp,将其加回去。
返回:直接执行 jr $ra。

非叶子函数 (Non-Leaf Function)
定义:一个函数内部调用了其他函数(包括递归调用自己)。它是调用链中间的节点。

特点
rajalSubFuncjalra 极度危险:因为你要在函数里执行 jal SubFunc。jal 指令会无情地修改ra极度危险:因为你要在函数里执行jalSubFuncjal指令会无情地修改ra 的值。如果你不提前把旧的 raSubFuncra 存到栈里,当 SubFunc 返回后,你自己的ra存到栈里,当SubFunc返回后,你自己的ra 就丢了,你永远回不到调用你的地方了(死循环或崩溃)。
必须压栈:必须在函数开头把 $ra 保存到堆栈中。


[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回