三大架构比较
1.函数调用机制
关键寄存器比较:
| x86-64 | mips32 | arm32 | |
|---|---|---|---|
| 传参寄存器 | rdi,rsi,rdx,rcx、r8、r9 | $a0 到 $a3 | r0 到 r3 |
| 栈顶栈底 | rbp,rsp | $fp,$sp | r7,sp |
| 保存返回地址 | 无,保存在栈上 | $ra | lr(r14) |
| 指令指针 | rip | $pc | pc(r15) |
跳转函数指令比较:
| x86-64 | mips32 | arm32 | |
|---|---|---|---|
| 跳转指令 | call fun; | jal fun; | bl fun; |
| 特点 | 将下一条指令的地址压入栈中 | 将下一条指令的地址存入ra | 将下一条指令的地址存入lr |
但是,由于mips分支延迟效应,遇到jl,jalr,程序会优先执行后面代码再执行跳转指令:会先执行addiu,再执行jr跳转
1 | jr $ra |
函数内部指令比较:
x86-64:
fun:
push rbp ; 保存旧的基址指针
mov rbp, rsp ; 设置新的基址指针
sub rsp, 16 ; 为局部变量分配空间
; 函数体(执行计算等)
...
leave ; 恢复基址指针
ret ; 返回
mips32:
foo:
addi $sp, $sp, -12 # 栈上分配12字节空间
sw $ra, 4($sp) # 返回地址保存到$sp+4位置
sw $fp, 0($sp) # $fp保存到$sp
move $fp, $sp # 设置新的基址指针
addi $sp, $sp, -16 # 为局部变量分配空间
高地址
+----------------------+
0x7ffffff0: | 调用者的栈帧 |
+----------------------+
0x7fffffe8: | (预留) |
0x7fffffe4: | $ra = 0x80001234 |
0x7fffffe0: | $fp = 0x7fffff00 | <- $fp
0x7fffffd0: | 局部变量 (16B) | <- $sp
+----------------------+
低地址
# 函数体(执行计算等)
...
move $sp, $fp # 恢复栈指针
lw $fp, 0($sp) # 恢复旧的基址指针
lw $ra, 4($sp) # 恢复返回地址
addi $sp, $sp, 8 # 释放栈空间
jr $ra # 返回
arm32:
foo:
sub sp, sp, #8 ; 为保存旧的基址指针分配空间
str lr, [sp, #4] ; 保存返回地址
str r7, [sp] ; 保存旧的基址指针
mov r7, sp ; 设置新的基址指针
sub sp, sp, #16 ; 为局部变量分配空间
; 函数体(执行计算等)
...
add sp, sp, #16 ; 释放局部变量空间
ldr r7, [sp] ; 恢复旧的基址指针
ldr lr, [sp, #4] ; 恢复返回地址
add sp, sp, #8 ; 释放栈空间
bx lr ; 返回
执行返回地址内容时,要注意此时sp的位置,一般来说,sp此时已经来到了返回地址在栈上位置的上方
2.栈溢出利用
算溢出长度
| x86-64 | mips32 | arm32 |
|---|---|---|
| 找buf和ebp的偏移 | 找buf和$ra寄存器的偏移(确切地说是$ra压入栈中的位置) | 找buf和lr寄存器的偏移(同mips) |
ret2system的常用gadget
system(“/bin/sh”)
| x86-64 | mips32 | arm32 | |
|---|---|---|---|
| pop_rdi_ret | addiu a0,sp,0x10; lw t9,sp;jalr t9; | pop{r0,pc} | |
| ROPgadget –binary pwn –only “pop | 一般用ida插件mipsrop | 常用ropper工具 |
其他
arm架构:
pop{r0,pc}:将sp+0地址给r0,sp+4给pc;
若找不到,可以用 pop_r3_pc 和 mov_r0_sp;blx_r3这两条gadget实现跳转 ,如图:
把system的地址放在r3寄存器,后续直接跳转到r3寄存器,并且,跳转之前直接可以给r0传参
mips架构:
一个函数开头中(对比上文提到的函数内部指令比较),经常这样把寄存器内容保存到栈上,除了ra,fp以外,还有s0-s7等寄存器
在函数结尾,又会把栈上内容取回到原来的寄存器中,如果覆盖到ra,这是我们完成劫持返回地址的原理,同时如果覆盖s0到s7,那就相当于控制了s0-s7
s0-s7能提前控制的话,那么就可以使用这样的gadget,比如
在s0处布置一个system即可

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明来源 hfddh666's Blog!