12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
三国霸业 战车-珍宝-觉醒-攻城掠地SF-全新玩法 免费玩新区 攻城掠地私服 进入游戏
手游私服盒子 各类免费游戏 0.1折送海量资源 各类手游私服 进入游戏
皇家MU2 《奇迹 2:传奇》韩国网禅公司《奇迹》正统续作。 3D锁视角Mmrpg 暗黑3+传奇+流放之路+奇迹 进入游戏
查看: 297|回复: 0

保护模式笔记二 段寄存器

[复制链接]

3782

主题

3782

帖子

214748万

积分

超级版主

Rank: 8Rank: 8

积分
2147483647
发表于 2021-5-7 23:02:18 | 显示全部楼层 |阅读模式
媒介

所有保护模式索引链接:保护模式条记一 保护模式介绍
先前提到了保护模式下的两大特点:段的机制和页的机制
先从段的机制开始学习,而要学习段的机制,首先要了解的便是段寄存器
段寄存器

什么是段寄存器

在先前的逆向根本条记五 标志寄存器中,有提到过段寄存器的概念
当使用汇编来操作一个内存地点时,就会涉及到段寄存器,只不过先前并没有太过在意
如:
mov dword ptr ds:[0x123456],eax留意汇编语句中的 ds,它就是一个段寄存器
实际上真正读取的内存地点为:ds.base+0x123456
段寄存器有哪些

段寄存器共8个: CS DS ES SS  FS GS LDTR TR
CS

代码段寄存器,用于存放代码段的段基址
DS

数据段寄存器,用于存放数据段的段基址
ES

附加段寄存器,用于存放附加段的段基址
SS

堆栈段寄存器,用于存放堆栈段的段基址,指示堆栈段区域的位置
FS

附加段寄存器,F为上一个附加段寄存器字母E后的字母,没有对应的名称
指向一种被称为线程信息块(TIB)的结构,这种结构是由内核在创建线程时创建的,用于支持操作系统相干功能、服务和API
GS

附加段寄存器,G为上一个附加段寄存器字母F后的字母,没有对应的名称
在32位Windows上GS保留供将来使用
在x64模式下,FS和GS段寄存器已交换
Win64使用GS的缘故原由是该FS寄存器用于32位兼容性层(称为Wow64)
32位应用程序永世不会导致GS更改,而64位应用程序永世不会导致FS更改
留意,在Win64和Wow64中GS是非零的,这可以用来检测一个32位应用程序是否在64位Windows中运行,在一个“真正“的32位Windows中GS总是零
IDTR

中断形貌符表寄存器,用于存放中断形貌符表IDT的32位线性基地点和16位表长度值
TR

任务寄存器,用于存放当前任务TSS段的16位段选择符、32位基地点、16位段长度和形貌符属性值
段寄存器的结构

组成BaseLimitAttributeSelector数据宽度32位32位16位16位是否可见不可见不可见不可见可见形貌基地点(当前段的起始地点)大小限制(当前段的整个长度)属性(当前段是否可读可写可执行)段选择子struct Segment{    WORD Selector;    WORD Attribute;    DWORD Base;    DWORD Limit;}段寄存器的属性

拿OD随便载入一个程序,观察寄存器窗口:

得到了当前的盘算机的段寄存器信息(不同盘算机段寄存器信息不肯定相同)
段寄存器SelectorAttributeBaseLimitES0023可读、可写00xFFFFFFFFCS001B可读、可执行00xFFFFFFFFSS0023可读、可写00xFFFFFFFFDS0023可读、可写00xFFFFFFFFFS003B可读、可写0x7FFDE0000xFFFGS----段寄存器的读写

对于段寄存器可以使用MOV指令进行读写(LDTR和TR除外)
读段寄存器

#include #include int main(){    WORD selector=0;    _asm{        mov selector, es    }    printf("%x\n",selector);    return 0;}对段寄存器的读操作只能读取段寄存器的16位Selector部分(可见部分)
运行结果


能够正确地读出es段寄存器的selector
写段寄存器

#include #include WORD data=0x0610;WORD readData=0;__declspec(naked) void fuction(){     __asm{                //保留调用前堆栈                push ebp                //提升堆栈                mov ebp,esp                sub esp,0x40                //保护现场                push ebx                push esi                push edi                //初始化提升的堆栈,填充缓冲区                mov eax,0xCCCCCCCC                mov ecx,0x10                lea edi,dword ptr ds:[ebp-0x40]                rep stosd                //函数核心功能                push ds         //保存ds段寄存器                mov ax,cs       //将cs段寄存器的段选择子赋值给ax                mov ds,ax       //使用cs段寄存器覆盖ds段寄存器                mov ax,word ptr ds:[data]       //使用修改后的段寄存器ds读取,这里相称于mov ax,word ptr cs:[data]                pop ds          //还原ds段寄存器                mov readData,ax //将读出来的数据赋值给变量                //恢复现场                pop edi                pop esi                pop ebx                //低落堆栈                mov esp,ebp                pop ebp                                //返回                ret         }        }int main(){        fuction();        printf("%X\n",readData);        return 0;}运行结果


可以看到代码是能够正常执行,而且输出对应的data
说明

上述代码使用了裸函数,避免了编译器的干扰;关于裸函数可以回首:逆向根本条记九 C语言内联汇编和调用协定
截取出关键代码:
push ds         //保存ds段寄存器mov ax,cs       //将cs段寄存器的段选择子赋值给axmov ds,ax       //使用cs段寄存器覆盖ds段寄存器mov ax,word ptr ds:[data]       //使用修改后的段寄存器ds读取,这里相称于mov ax,word ptr cs:[data]pop ds          //还原ds段寄存器mov readData,ax //将读出来的数据赋值给变量代码表明如上,就是个简单的覆盖段寄存器的操作
为什么明明替换了段寄存器,仍然能够正常运行呢?
首先要留意到,替换和被替换的段寄存器分别是:cs和ds;它们的base是相同的都为0,因此所访问的内存自然也是相同的
再来看权限题目:无论是cs还是ds,它们都具有可读的权限;这里也只对数据进行了读操作,于是可以正常运行
如果这里将读取data的代码修改为写data的代码,则会报错:
mov ax,word ptr ds:[data]   //使用cs段寄存器覆盖过的ds段寄存器,读取data//将上面的代码修改为:mov word ptr ds:[data],ax   //使用cs段寄存器覆盖过的ds段寄存器,修改data为什么会报错?由于此时的ds段寄存器已经被覆盖为了cs段寄存器,而cs段寄存器的权限为可读、可执行,没有可写的权限,所以会报错
报错截图:

可以看到,此时的data的地点明明是有用的,先前也验证了可以正确读取,但是在这里就会报错:Acccess Violation(非法访问)
就这里就是由于段寄存器权限不足导致的,也是为什么先前都是使用ds段寄存器来赋值,而不是用cs段寄存器
mov word ptr ds:[address],data  //使用ds段寄存器修改数据,可以正常修改mov word ptr cs:[address],data //使用cs段寄存器修改数据,会报错和前面对段寄存器的读操作不同,写寄存器是对整个96位的段寄存器进行修改
但是这里明明只给出了16位的段选择子Selector,剩下的80位呢?
这个就段形貌符有关了,这里暂且不谈,留作之后自会知晓,先记着写寄存器是对整个段寄存器进行修改即可
验证Limit

在前面的读写中,或多或少都验证了段寄存器的几个属性:Base、Selector、Attribute
现在最后验证一下Limit
#include #include int main(){    unsigned char base;    _asm{           mov al,fs:[0x1000]      //超过limit:0xfff,无法正常运行        mov base,al    }    printf("%x\n",base);    return 0;}
#include #include int main(){    unsigned char base;    _asm{           mov al,fs:[0xfff]       //在临界点可以正常运行        mov base,al    }    printf("%x\n",base);    return 0;}
总结


  • 段寄存器共96位,其中16位为可见部分,后80位为不可见部分
  • 不同盘算机段寄存器信息不肯定相同
  • FS和GS两个段寄存器分别在32位程序和64位程序发挥作用

来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-11-24 19:35 , Processed in 0.093750 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表