前言
所有保护模式索引链接:保护模式笔记一 保护模式介绍
在先前的保护模式笔记六 代码跨段跳转中学习了远跳转:JUMP FAR指令
但如果想要实现跨段的调用就需要学习长调用:CALL FAR指令
短调用
短调用指令格式
CALL 立即数/寄存器/内存
指令类型 |
指令例子 |
对应硬编码 |
CALL 立即数 |
call 52610610 |
E8 F4560A52 |
CALL 寄存器 |
call eax |
FFD0 |
CALL 内存 |
call dword ptr ds:[0x52610610] |
FF15 10066152 |
短调用堆栈变化
关于短调用,其实在先前的逆向基础笔记七 堆栈图(重点)中,就已经分析过短调用堆栈的变化(不了解的可以回顾)
这里再简单地过一遍:
用OD随便打开一个程序
记录下此时的堆栈情况
相对ESP地址 |
堆栈地址 |
内容 |
ESP-8 |
0012FFBC |
00000009 |
ESP-4 |
0012FFC0 |
0012FFF8 |
ESP |
0012FFC4 |
7C817077 |
ESP+4 |
0012FFC8 |
005BFF80 |
ESP+8 |
0012FFCC |
0012B750 |
按F7单步步入CALL
此时的堆栈情况为
相对ESP地址 |
堆栈地址 |
内容 |
ESP-8 |
0012FFBC |
00000009 |
ESP |
0012FFC0 |
0056AF17 |
ESP+4 |
0012FFC4 |
7C817077 |
ESP+8 |
0012FFC8 |
005BFF80 |
ESP+C |
0012FFCC |
0012B750 |
对比前后的堆栈情况变化,可以发现:
短调用影响了ESP和EIP两个寄存器,并且会将返回地址压入到堆栈中
短调用通过RET指令返回,这里也不再赘述
长调用
长调用指令格式
CALL FAR CS:EIP(EIP是废弃的)
形如:CALL FAR 002B:00610610
CALL指令要调用的地址是由CS段选择子查GDT表得到的调用门 段描述符得来的,后面的EIP不发挥作用
长调用可以分为两种:跨段不提权和跨段提权
长调用通过RETF指令返回
跨段不提权
所谓的跨段不提权就是指要跳转段和当前段的特权级别相同
和短调用不同,长调用会先将CS压入堆栈,然后再将返回地址压入堆栈
跨段不提权的长调用影响了ESP EIP CS 三个寄存器,并且会将CS和返回地址压入到堆栈中
下面给出堆栈变化图:
跨段提权
与跨段不提权相对,所谓的跨段提权就是指要跳转段和当前段的特权级别不同
跨段提权的长调用 涉及到了权限的变化,一旦涉及到了权限的变化,堆栈也将随之切换,因此相比跨段不提权,还会影响SS寄存器
跨段提权的长调用影响了ESP EIP CS SS 四个寄存器,并且会将SS、ESP、CS和返回地址压入到堆栈中
为什么要压入SS和ESP?
因为当跨段提权时,堆栈会发生切换,压入SS和ESP是为了在调用结束后将堆栈恢复成原来的(切换前)的堆栈
堆栈切换的来源是什么?
堆栈切换的来源是TSS段,这个留作之后再深入
下面给出由RING3切换到RING0的跨段提权堆栈变化图
总结
跨段调用时,一旦有权限切换,就会切换堆栈
CS的权限一旦改变,SS的权限也要随着改变,CS与SS的特权级别必须一致(INTEL定义的规则)
JMP FAR 只能跳转到同级代码段,但CALL FAR可以通过调用门进行提权(提升CPL的权限)
由于长调用还涉及到调用门和TSS,于是此次笔记没有具体分析长调用的实例,留作之后补充
|