Windows保护模式学习笔记(三)—— 长调用/短调用/调用门

  • 要点回顾
  • 长调用与短调用
    • 一、短调用
    • 二、长调用(跨段不提权)
    • 三、长调用(跨段并提权)
      • 长调用执行时:
      • 执行返回(RETF)时:
    • 总结
  • 调用门
    • 门描述符
    • 调用门(无参)
      • 实验:构造一个无参调用门
        • 第一步:初步构造参数
        • 第二步:确定 Offset in Segment
        • 第三步:将门描述符写入GDT表
        • 第四步:继续执行第二步代码
        • 第五步:再次运行程序,观察寄存器与堆栈的变化
        • 第三步:修改代码
    • 调用门(有参)
      • 实验:构造一个带参数的调用门
        • 第一步:初步构造参数
        • 第二步:执行代码
    • 总结

要点回顾

通过JMP FAR可以实现段间的跳转,如果要实现跨段的调用就必须要学习CALL FAR,也就是长调用

CALL FARJMP FAR 要复杂,JMP并不影响堆栈,但CALL指令会影响


长调用与短调用

一、短调用

指令格式:

CALL 立即数 / 寄存器 / 内存


发生改变的寄存器:ESP EIP

二、长调用(跨段不提权)

指令格式:

CALL CS:EIP(EIP是废弃的)


发生改变的寄存器:ESP EIP CS

三、长调用(跨段并提权)

指令格式:

CALL CS:EIP(EIP是废弃的)

长调用执行时:


发生改变的寄存器:ESP EIP CS SS

注意:长调用执行后,堆栈已经不是原来的堆栈,而是0环的堆栈(ESP0)

执行返回(RETF)时:


发生改变的寄存器:ESP EIP CS SS

总结

  1. 跨段调用时,一旦有权限切换,就会切换堆栈

  2. CS的权限一旦改变,SS的权限也要随着改变,CS与SS的等级必须一样

  3. JMP FAR 只能跳转到同级非一致代码段,但CALL FAR可以通过调用门提权,提升CPL的权限

SS与ESP从哪里来?参见TSS段

调用门

指令格式:

CALL CS:EIP(EIP是废弃的)

执行步骤:

  1. 根据CS的值查GDT表,找到对应的段描述符 这个描述符是一个调用门
  2. 在调用门描述符中存储另一个代码段的段选择子
  3. 段选择子指向的段 段.Base + 偏移地址 就是真正要执行的地址

门描述符

结构图:

注意

  1. S位(第12位)必须为0,只有当S位为0时,段描述符才是系统段描述符;此时,当Type域为1100时,该描述符是门描述符
  2. 低四字节的16~31位是决定 调用的代码存在于哪个段段选择子
  3. 当长调用执行时:真正要执行的代码地址=门描述符中段选择子所指向的代码段的Base+门描述符高四字节的16~31位+门描述符低四字节的0~15位

调用门(无参)

实验:构造一个无参调用门
第一步:初步构造参数
Offset in Segment 31:16 = 0x0000        //暂定P = 1DPL = 二进制:11Param.Count = 二进制:00000Segment Selector = 0x0008
Offset in Segment 15:00 = 0x0000       //暂定

由上述参数构造出的门描述符为:0000EC00`00080000

第二步:确定 Offset in Segment

在VC6中执行如下代码并中断

#include "stdafx.h"
#include <windows.h>void __declspec(naked) GetRegister()
{__asm{int 3retf        // 注意返回,不能是ret}
}int main(int argc, char* argv[])
{char buff[6];*(DWORD*)&buff[0] = 0x12345678;          // 在这行设置断点*(WORD*)&buff[4] = 0x48;             // 段选择子所在偏移__asm{call fword ptr[buff]               // 长调用}getchar();return 0;
}

右键进入反汇编窗口,查看GetRegister函数起始地址,我这里是00401010

至此,门描述符的最终确定为:0040EC00`00081010

第三步:将门描述符写入GDT表

第四步:继续执行第二步代码

运行后,虚拟机成功中断至WinDbg

第五步:再次运行程序,观察寄存器与堆栈的变化

长调用执行前

长调用执行后

寄存器:

堆栈:

结果和需求完全一致,调用门执行成功!

第三步:修改代码

将代码修改为如下:

#include <windows.h>BYTE GDT[6] = {0};
DWORD dwH2GValue;void __declspec(naked) GetRegister()
{__asm{pushadpushfdmov eax,0x8003f00c   // 读取高2G内存mov ebx,[eax]mov dwH2GValue,ebxsgdt GDT;          // 读取GDTpopfdpopadretf}
}void PrintRegister()
{DWORD GDT_ADDR = *(PDWORD)(&GDT[2]);WORD GDT_LIMIT = *(PWORD)(&GDT[0]);printf("%x %x %x \n", dwH2GValue, GDT_ADDR, GDT_LIMIT);
}int main(int argc, char* argv[])
{__asm{mov ebx,ebxmov ebx,ebx}char buff[6];*(DWORD*)&buff[0] = 0x12345678;*(WORD*)&buff[4] = 0x48;    // segment select__asm{call fword ptr[buff]}PrintRegister();getchar();return 0;
}

注意:若GetRegister函数起始地址发生改变,则需要修调相应的门描述符

执行结果:

成功读取了GDT,提权成功!


修正:sgdt命令实际上并不需要0环权限【大写尴尬】

调用门(有参)

实验:构造一个带参数的调用门
第一步:初步构造参数
Offset in Segment 31:16 = 0x0000        // 暂定P = 1DPL = 二进制:11Param.Count = 二进制:00011    // 注意变化!Segment Selector = 0x0008
Offset in Segment 15:00 = 0x0000       // 暂定
第二步:执行代码

代码如下:

#include <windows.h>DWORD x;
DWORD y;
DWORD z;void __declspec(naked) CateProc()
{__asm{pushadpushfdmov eax,[esp+0x24+8+8]mov dword ptr ds:[x],eaxmov eax,[esp+0x24+8+4]mov dword ptr ds:[y],eaxmov eax,[esp+0x24+8+0]mov dword ptr ds:[z],eaxpopfdpopadretf 0xC            // 注意堆栈平衡 写错蓝屏}
}void PrintRegister()
{printf("%x %x %x \n", x, y, z);
}int main(int argc, char* argv[])
{char buff[6];*(DWORD*)&buff[0] = 0x12345678;*(WORD*)&buff[4] = 0x48;__asm{push 1                 // 参数1push 2                    // 参数2push 3                    // 参数3call fword ptr[buff]}PrintRegister();getchar();return 0;
}

注意:需要将门描述符的段偏移修改为CateProc函数的起始地址

执行结果:

传入的参数被成功输出,有参调用门构造成功!

思考:pushad、pushfd、popfd、popad 这几条指令有什么意义?是必须的吗?

总结

  1. 当通过门,权限不变的时候,只会PUSH两个值:CS返回地址,新的CS的值由调用门决定
  2. 当通过门,权限改变的时候,会PUSH四个值:SSESPCS返回地址,新的CS的值由调用门决定,新的SS和ESP由TSS提供
  3. 通过门调用时,要执行哪行代码由调用门决定;但使用RETF返回时,由堆栈中压入的值决定;这就是说,进门时只能按指定路线走,出门时可以翻墙(只要改变堆栈里面的值就可以想去哪去哪)
  4. 问:可不可以再建个门出去呢?也就是再用CALL出去
    答:当然可以了,前"门"进,后"门"出

Windows保护模式学习笔记(三)—— 长调用/短调用/调用门相关推荐

  1. Windows保护模式学习笔记(五)—— 任务段任务门

    Windows保护模式学习笔记(五)-- 任务段&任务门 要点回顾 任务段 TSS (Task-state segment ) TR段寄存器 TR段寄存器的读写 TSS段描述符 实验:加载自定 ...

  2. Windows保护模式学习笔记(十三)—— PWTPCD

    Windows保护模式学习笔记(十三)-- PWT&PCD 要点回顾 CPU缓存 CPU缓存与TLB的区别 PWT(Page Write Through) PCD(Page Cache Dis ...

  3. Windows保护模式学习笔记(十二)—— 控制寄存器

    Windows保护模式学习笔记(十二)-- 控制寄存器 控制寄存器 Cr0寄存器 Cr2寄存器 Cr4寄存器 控制寄存器 描述: 控制寄存器有五个,分别是:Cr0 Cr1 Cr2 Cr3 Cr4 Cr ...

  4. Windows保护模式学习笔记(十)—— TLB

    Windows保护模式学习笔记(十)-- TLB 地址解析 10-10-12分页 2-9-9-12分页 TLB TLB结构 TLB种类 练习1:体验TLB的存在 第一步:运行代码 第二步:设置中断门描 ...

  5. Windows保护模式学习笔记(九)—— 2-9-9-12分页

    Windows保护模式学习笔记(九)-- 2-9-9-12分页 要点回顾 10-10-12分页 原理 环境配置 2-9-9-12分页 原理 PDPTE PDE PTE XD/NX标志位 环境配置 实验 ...

  6. Windows保护模式学习笔记(八)—— 页目录表基址/页表基址

    Windows保护模式学习笔记(八)-- 页目录表基址/页表基址 要点回顾 一.页目录表基址 实验:拆分线性地址C0300000,并查看其对应的物理页 第一步:打开一个进程,获得它的Cr3 第二步:查 ...

  7. Windows保护模式学习笔记(七)—— PDEPTE

    Windows保护模式学习笔记(七)-- PDE&PTE Cr3 PDE(页目录表项) PTE(页表项) 物理页的属性 10-10-12分页的补充 实验1:证明PTE的特征1 第一步:选择一个 ...

  8. Windows保护模式学习笔记(六)—— 10-10-12分页

    Windows保护模式学习笔记(六)-- 10-10-12分页 基本概念 4GB内存空间 有效地址-线性地址-物理地址 有效地址与线性地址 物理地址 控制寄存器:Cr3 10-10-12分页 实验:通 ...

  9. Windows保护模式学习笔记(四)—— 中断门陷阱门

    Windows保护模式学习笔记(四)-- 中断门&陷阱门 要点回顾 中断描述符表(IDT) 一.中断门 实验:构造一个中断门 第一步:初步构造参数 第二步:确定 Offset in Segme ...

最新文章

  1. 计算机一级判断题2016,2016年12月计算机一级考试WPS判断题及答案
  2. java jolt调用tuxedo_Jolt调用Tuxedo服务,该怎么处理
  3. flask项目从本地迁移到服务器上遇到net::ERR_CONNECTION_R问题
  4. 《剑指offer》孩子们的游戏---约瑟夫问题
  5. python赋值语句格式_Python赋值语句后逗号的作用分析
  6. react直接使用bootstrap失效的原因
  7. Python命令行参数
  8. c++11 常用语法
  9. 《软件体系结构》 第四章 软件体系结构描述
  10. mac 右键 启动终端
  11. 16S 扩增子分析工具:Swarm 聚类OTU流程介绍
  12. Wamp下载及安装问题
  13. Task5 | CFA (Amos+Mplus) | 五因素心智觉知度量表:正念是什么?
  14. 计算机如何连接wifi台式,台式机怎么连接wifi_台式机连接wifi教程-太平洋IT百科...
  15. Windows桌面端录屏采集实现
  16. android app后台收不到消息,不打开智能关怀App收不到手表发的消息
  17. Python, Python, Python
  18. poj 2228 Naptime(DP的后效性处理)
  19. 八、QOS队列调度与报文丢弃
  20. 【模拟集成电路】环路滤波器(LPF)设计

热门文章

  1. DL之SPP-Net:SPP-Net算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
  2. Py之neurolab:Python库之neurolab的简介、安装、使用方法之详细攻略
  3. app微信支付的集成步骤
  4. 【bzoj3884】上帝与集合的正确用法 扩展欧拉定理
  5. 直接取HANA数据库数据,动态QUERY
  6. ios APP开发简单实例
  7. leetcode 211. Add and Search Word - Data structure design Trie树
  8. jquery,angular 对象数组的克隆和深度克隆
  9. Android如何在java代码中设置margin
  10. CFG_GCR全局配置寄存器设置