eBPF Talk: trampoline on x86【续】【汇编慎入】
文章目录
本系列是 x86 架构平台上 trampoline 的实现,从原理和实现上进行了详细的介绍。
- eBPF Talk: poke on x86【汇编慎入】
- eBPF Talk: perilogue on x86【汇编慎入】
- eBPF Talk: freplace on x86【汇编慎入】
- eBPF Talk: trampoline on x86【汇编慎入】
- eBPF Talk: trampoline on x86【续】【汇编慎入】
- eBPF Talk: trampoline stack on x86【汇编慎入】
书接上回,使用 fexit 的时候,为什么在 ret 前增加 add $0x8,%rsp 指令就能跳过执行原来的函数?
call
学习一下几条常用指令:
call %N: 相当于push %eip+mov %N, %eip。leave: 相当于mov %ebp, %esp+pop %ebp。ret: 相当于pop %eip。
push and pop

看下执行内核 inet_csk_complete_hashdance() 函数、和 attach 到上面的 fexit trampoline 时,寄存器和栈的变化。
0,因为 call inet_csk_complete_hashdance(),所以栈上存有一个旧的 %eip 值。
call %0xffffffff9eda55a0相当于push %eip+mov %0xffffffff9eda55a0, %eip。

1,call %0xffffffffc0431000。
call %0xffffffffc0431000相当于push %eip+mov %0xffffffffc0431000, %eip。
此时,栈上保存了两个连续的 %eip 值。

2,执行完 fexit trampoline 的 prologue 后。
push %rbpmov %rsp, %rbpsub $0x40, %rsp

3,执行 epilogue 里的 leave 后。
leave相当于mov %ebp, %esp+pop %ebp。

4,执行 epilogue 里的 add $0x8, %rbp 后。
add $0x8, %rbp
丢弃栈上保存的 %eip 值 0xffffffff9eda55a5,就不会继续执行原来的函数。

5,执行 epilogue 里的 ret 后。
ret相当于pop %eip。

总结
经过几张寄存器与栈状态变化的图片,便可知道在 leave 和 ret 之间增加 add $0x8,%rsp 指令就能跳过执行原来的函数。
学习汇编、机器指令时,画图分析寄存器和栈的变化,或者通过可视化工具将寄存器和栈的变化呈现出来,才是正确的学习方法。
文章作者 Leon Hwang
上次更新 2023-05-23