mips的堆栈
MIPS的栈💣
栈增长方向:同x86,向低地址增长
没有EBP指针(但是有一个fp,见MIPS汇编这篇文章)
传参:前四个参数通过$a0~$a3传递,多出的参数放入栈空间
返回值:$RA寄存器
mips与x86函数调用区别
- 将$PC寄存器移到$RA寄存器
- 如果被调用的函数是如果是非叶函数(调用其他函数),将$RA存在栈;叶函数则不变
- 函数返回时,叶函数直接
jr $RA
,非叶函数先把返回地址存入$RA再跳转
《家用路由器0day漏洞挖掘》这本书上的图例:
主调函数干的事
演示
创建
more argument.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//more argument.c
#include <stdio.h>
int more_arg(int a,int b,int c,int d,int e)
{
char dst[100] = {0};
sprintf(dst,"%d%d%d%d%d\n",a,b,c,d,e);
}
void main()
{
int a1=1;
int a2=2;
int a3=3;
int a4=4;
int a5=5;
more_arg(a1,a2,a3,a4,a5);
return ;
}编译
1
mips-linux-gnu-gcc ./more\ argument.c -o more\ argument
ida打开
首先可以看到前四个参数存入了$a0~$a3
然后前面5个:
1
2li $v0, ?
sw $v0, 0x??+var_18($fp)是赋值操作,因此中间的
1
2lw $v0, 0x38+var_8($fp)
sw $v0, 0x38+var_28($sp)即为第五个参数的传递
被调函数干的事
被调用函数的开头干了以下几件事(仅针对非叶函数):
1 |
|
首先,抬高sp 0x40个字节(这里0x40是随便写的)。然后将ra放到sp + 0x38 + 4
,fp放到sp + 0x38 + 0
的位置,也就是被调函数的栈底为ra,然后是fp。最后将fp赋值为sp。
然后需要对参数进行处理,arg_0 到arg_C是主调函数预留出来的空间,需要被调函数再把$a0-$a3存入进去,然后arg_10本身主调函数就已经存好了第五个参数,不需要动。
最终主调和被调函数的栈长这样:
mips的堆栈
https://isolator-1.github.io/2022/12/23/mips汇编/mips堆栈/