首页
社区
课程
招聘
[原创]windows7内核分析之x86&x64第二章系统调用
发表于: 2017-4-12 19:21 16143

[原创]windows7内核分析之x86&x64第二章系统调用

2017-4-12 19:21
16143

2.1内核与系统调用

上节讲到进入内核五种方式 其中一种就是 系统调用 syscall/sysenter或者int 2e( 64 位环境里统一使用 syscall/sysret 指令,在 32 位环境里统一使用 sysenter/sysexit compatibility 模式下必须切换到 64 位模式,然后使用 syscall/sysret 指令 注释:32cpux86模式 也叫legacy模式 再说清楚点 就是包含了实模式:可以执行以前的16位程序 也包含了保护模式:可以执行32位的程序 64cpulong模式:分为两种 64位模式:只执行64位的程序和compatibility模式:可以执行x86模式的程序 老式的cpu不支持 不提供sysenter指令,只能由int 2e模拟中断方式进入内核,调用系统服务)这两者什么区别呢?

1,Int 2e速度慢 首先从TSS中加载内核堆栈的ss esp->保存5个寄存器的现场(ss esp eip eflags cs)->然后还要去IDT中查找isr,这个过程消耗的时间太多

2,sysenter 提供了三个MSR寄存器 分别是SYSENTER_CS_MSR SYSENTER_EIP_MSR SYSENTER_ESP_MSR 分别指示了内核对应处理例程的cs选择子(函数所在段的选择子 通过选择子找到GDT 从逻辑地址转换为线性地址 最后访问线性地址 会根据四级表转换为物理地址)和内核函数地址和内核堆栈地址 这样就省去了查找idtTSS段 获得内核函数地址和内核堆栈地址 节省了大量时间

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++以下是X64syscall 讲解 参考总结++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

syscall 的内核入口点是 KiSystemCall64() ,系统在 KiInitializeBootStructures() 里对 syscall/sysret 执行环境进行了设置:

MSR_STAR 寄存器里的值被设为 23001000000000h,它意味着:

SYSCALL_EIP 0

SYSCALL_CS 0x10

SYSRET_CS 0x23

SYSRET_CS 中,SYSRET_CS.RPL = 3 返回的权限级别是 3 级(用户代码)。

 

MSR_CSTAR 寄存器被设为 nt!KiSystemCall32 (fffff800`03cc4c00) 地址值,这是为了 compaitibility 模式代码调用而设置的。

MSR_LSTAR 寄存器被设为 nt!KiSystemCall64 (fffff800`03cc4ec0) 地址值,是为 64-bit 模式而准备的。CSTAR 寄存器为 compatibility 模式下的代码提供 rip 值,当 processor comatibility 模式下运行时,执行了 syscall 指令,此时 rip 值将从 MSR_STAR 寄存器中加载。请记住:只能在 AMD processor 使用 compaitibility 模式下的调用。照顾通用性,为了在 Intel AMD processor 上都能够使用 fast call 功能,操作系统的设计者应该要避免在 comaptibility 模式下使用 syscall 指令。前面提到过,建议在 compatibility 模式下先切换到 64-bit 模式后,再执行 syscall 指令

MSR_SFMASK 寄存器设为 4700h,意味着:

NT DF IF TF

这些 rflags 寄存器中的标志位在进入 KiSystemCall64() 后会被清 0

long mode(win7 x64 ) 下,当执行 syscall 指令时,当前的 rflags 寄存器值被保存在 r11 寄存器,processor 在执行 syscall 时,准备的目标执行环境中,rflags 将会根据 SFMASK 寄存器的值进行设置:如果 SFMASK 寄存器的某一位置为 1,那么 rflags 寄存器中相应的位将会被清 0,置为 0 时,rflags 寄存器中相应位不变

它的逻辑 C 描述为:

rflags = rflags & (~sfmask);

你应该在系统服务例程先保存 r11 值(原来的 rflags 寄存器值),以便 sysret 执行返回时可以恢复原来的 rflags

 

那么,对于要进入系统调用的代码来说:

执行 syscall 后,rcx 会保存返回值,因此应该要保存 rcx 原来的值

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++以下是X86sysenter 讲解 参考总结++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 


 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++以下是int 2e 讲解  参考总结+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

   


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  CCkicker   +1.00 2017/05/08
最新回复 (14)
雪    币: 74
活跃值: (748)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持分享,学习一下
2017-4-12 19:51
0
雪    币: 346
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
继续顶!
2017-4-12 20:30
0
雪    币: 1746
活跃值: (227)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
4
排版有点乱,最好把代码用代码格式刷一遍,这样看起来清楚一点。
2017-4-12 21:00
0
雪    币: 1176
活跃值: (1264)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
5
同上    现在完全可以用那个代码格式化一下  看着舒服些 
2017-4-12 21:02
0
雪    币: 719
活跃值: (777)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
6
mark写的很好
2017-4-13 11:20
0
雪    币: 31
活跃值: (87)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
7
mark
2017-4-13 11:30
0
雪    币: 35
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不错!
2017-4-13 11:43
0
雪    币: 171
活跃值: (519)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
哥们注意身体!!!非常感谢您分享!!!很不错的文章。佩服您的专研精神。
2017-4-13 18:39
0
雪    币: 1696
活跃值: (2297)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
支持支持!好牛逼
2017-5-11 07:41
0
雪    币: 300
活跃值: (2477)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
mark
2019-8-19 18:05
0
雪    币: 367
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
好文章!
2019-12-7 20:25
0
雪    币: 83
活跃值: (1087)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
13
感谢分享  来这里一起学习啊  一群二群被封了  这个482999345 最近也被封了 加这个吧1038217653
最后于 2020-2-13 06:35 被killpy编辑 ,原因:
2019-12-27 13:35
0
雪    币: 338
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
大佬我也看了一下那本书,有几个地方是不是作者的失误啊,比如int 2e内核入口函数的里

作者说上面这几句是检查系统调用号的bit12位是否为1,但是edi右移了8位之后再and 10h,我怎么看and 10h都是检查第13位啊,难道我的理解有误?



还有这里 and eax,0fffh 就是取eax的低12位,低12位最大也就是0xfff,也就是说无论如何都比0x1000小,到了下面一句cmp却说是判断系统调用号是否为0x1000或0x1000以上,低12位怎么可能会比0x1000大,这不是很矛盾的事吗?

2020-1-11 13:10
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
感谢分享!
2022-7-10 19:50
0
游客
登录 | 注册 方可回帖
返回
//