首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
软件逆向
发新帖
24
1
[转帖]系统调用,从用户态进入系统态(_KiSystemService() _KiFastCallEntry)
发表于: 2013-8-25 13:30
16963
[转帖]系统调用,从用户态进入系统态(_KiSystemService() _KiFastCallEntry)
PPTV
2013-8-25 13:30
16963
1、内核与系统调用基础
对于应用程序进程来说,操作系统内核的作用体现在一组可供调用的函数,称为系统调用(也成"系统服务")。
从程序运行的角度来看,进程是主动、活性的,是发出调用请求的一方;而内核是被动的,只是应进程要求而提供服务。从整个系统运行角度看,内核也有活性的一面,具体体现在进程调度。
系统调用所提供的服务(函数)是运行在内核中的,也就是说,在"系统空间"中。而应用软件则都在用户空间中,二者之间有着空间的间隔(CPU运行模式不同)。
综上所述,应用软件若想进行系统调用,则应用层和内核层之间,必须存在"系统调用接口",即一组接口函数,这组接口运行于用户空间。
对于windows来说,其系统调用接口并不公开,公开是的一组对系统调用接口的封装函数,称为windowsAPI
。
2、用户空间中的进程如何进行系统调用?
用户空间与系统空间所在的内存区间不一样,同样,对于这两种区间,CPU的运行状态也不一样。
在用户空间中,CPU处于"用户态";在系统空间中,CPU处于"系统态"。
CPU从系统态进入用户态是容易的,因为可以执行一些系统态特有的特权指令,从而进入用户态。
而相反,用户态进入系统态则不容易,因为用户态是无法执行特权指令的。
所以,
一般有三种手段,使CPU进入系统态(即转入系统空间执行)
:
①中断:来自于外部设备的中断请求。当有中断请求到来时,CPU自动进入系统态,并从某个预定地址开始执行指令。中断只发生
在两条指令之间,不影响正在执行的指令。
②异常:无论是在用户空间或系统空间,执行指令失败时都会引起异常,CPU会因此进入系统态(如果原先不在系统空间),从而
在系统空间中对异常做出处理。异常发生在执行一条指令的过程中,所以当前执行的指令已经半途而废了。
③自陷:以上两种都CPU被动进入系统态。而自陷是CPU通过自陷指令主动进入系统态。多数CPU都有自陷指令,系统调用函数一般都是靠自陷指令实现的。一条
自陷指令的作用相当于一次子程序调用,子程序存在于系统空间
。
3、通过自陷指令调用系统服务流程:
windows系统通过
自陷指令"int 0x2e"
进入系统空间实现系统调用。
①CPU执行int 0x2e,CPU运行状态切换为系统态
②从任务状态段TSS装入本线程的系统空间的SS和ESP
③依次把用户空间的SS、ESP、EFLAGS、CS、EIP的内容压入系统空间堆栈
每个线程都有自己的系统空间堆栈,其堆栈段寄存器SS和堆栈指针ESP的内容保存在一个称为"任务状态段"既TSS的数据结构里面。
与此相应,CPU中有个 称为
"任务寄存器"即
TR
的段寄存器.每当从用户空间进入系统空间时,CPU就自动根据TR的指引从TSS中获取当前进程的SS和ESP两个寄存器的值. 然后在把上面提到的几个寄存器中的内容压入这个堆栈.当然,还要根据
IDTR
即"中断描述符表寄存器"
的指引获取CS和EIP. 这个过程所涉及的"时钟周期"显然不会少.正因为这样,后来才有了"快速系统调用"指令sysenter和sysexit的出现。
④从中断向量表中(Interrupt Descriptor Table)以0x2e为中断向量,开始执行系统空间中的程序。
⑤程序执行后,通过iret(中断返回)指令实现上述过程的逆过程
__declspec(naked) __stdcall NtReadFile(int dummy0,int dummy2,int dummy3)
{
__asm{
push ebp
mov ebp,esp
mov eax,152
//将NtReadFile()的系统调用号存入EAX
lea edx,8[ebp]
//使EDX指向堆栈上参数块的起点,返回地址+Filehandle = 8 bytes
int 0x2E
//进入内核
pop ebp
ret 9
//在堆栈上共有9个参数(win32汇编应该是9*4 :ret 36,)
}
}
//注意:此函数的参数在函数中并没有用到,因此其实是可有可无的
4、windows中介函数详解
所有windows基本系统调用的中介函数存在于ntdll.dll中
。这些中介函数拥有相同的样式(都是执行自陷指令,然后调用相应的内核函数)
,所以reactOS用工具自动生成这些中介函数。
函数名、系统调用号、参数个数,来自文件sysfuncs.lst中,例如:
NtAcceptConnectPort 6
NtAccessCheck 8
NtAccessCheckAndAuditAlarm 11
NtAccessCheckByType 11
NtAccessCheckByTypeAndAuditAlarm 16
NtAccessCheckByTypeResultList 11
NtAccessCheckByTypeResultListAndAuditAlarm 16
NtAccessCheckByTypeResultListAndAuditAlarmByHandle 17
NtAddAtom 3
...
这里,
NtAcceptConnerPort就是调用号为0的系统调用函数
,它有六个参数。其他的调用函数类似。
5、何谓CPU进入系统空间?
①CPU的运行状态从用户态转为系统态,拥有了执行"特权指令"的能力。
②CPU进入系统态后,可以访问内存中的系统区(内核所在的区域),而在用户态下是无法访问的。
③当前进程使用的堆栈,从用户态切换到系统态。堆栈原先的内容(用户态),以及用户空间的堆栈指针,被压入系统空间堆栈。同时被压入的,还有EFLAGS、CS、EIP的内容。
④关闭中断,依照中断向量从IDT中找到相应的表项,并根据表项提供的程序入口进入相应的中断服务程序。
6、windows提供的自陷指令
int 3:程序入口为_KiTrap3()。用于debug时设置断点。
int 0x2e:程序入口为_KiSystemService()。用于实现windows系统调用。
int 0x2a:程序入口为_KiGetTickCount()。让用户空间程序获取高精度时钟计数。
int 0x2b:程序入口为_KiCallbackReturn()。特殊自陷入口。用于在内核中回调用户空间中的子程序,执行完后,通过0x2b返回系统空间。
int 0x2c/int 0x2d:用于dubug。
7、_KiSystemService()
_KiSystemService()是所有的系统调用入口函数。对应于中断向量0x2e。所以,当中间函数执行int 0x2e时,CPU就进入系统空间中的这个函数。
进入系统空间时,CPU自动将下列信息压入系统空间堆栈:
①用户空间的堆栈位置,包括SS和ESP的内容
②EFLAGS的内容
③用户空间指令位置,包括CS和EIP的内容
这些信息是将来返回用户空间所必须的。
8、快速系统调用
x86系列从P2开始增设了两条指令和三个寄存器用来用来实现快速系统调用。分别是:
sysenter和sysexit(对应于自陷方式中的int/call和iret/ret)
sysenter_cs_msr
sysenter_ip_msr
sysenter_esp_msr
快速系统调用实现更为高效。
采用快速系统调用的总入口时_KiFastCallEntry(对应于_KiSystemService)。
快速系统调用代码摘要:
__decksoec(naked) __stdcall NtReadFile(int dummy, int dummy1, int dummy2)
{
__asm{
mov eax,152
mov ecx, KUSER_SHARED_SYSCALL
CALL [ecx]
ret 9
}
}
其中,
KUSER_SHARED_SYSCALL指向用户空间的一个地址(0x7ffe0300),这个位置存储了一个函数指针,指向KiIntSystemCall()或KiFastSystemCall()两个函数其中之一。系统在初始化的时候根据CPU是否支持快速系统调用而使该指针指向KiIntSystemCall()或KiFastSystemCall()
。
_KiIntSystemCall@0:
lea edx, [esp+8]
int 0x2e
ret
_KiFastSystemCall@0:
mov edx,csp
sysenter
_KiFastSystemCallRet@0:
ret
不难看出KiIntSystemCall()就是原先采用中断方式进入内核。而KiFastSystemCall()则是采用快速系统调用进入内核。
内核在初始化阶段根据处理器的CPUID判断其是否支持快速系统调用,而从ntdll.dll的映像中找到
KiIntSystemCall()或KiFastSystemCall()
的地址,
将其写入用户空间的地址
。
0x7ffe0300.实际上CPU写入的时系统空间的地址0xffdf0300,但是系统空间0xffdf0000与用户空间0x7ffe0000的地方就好像是一条隧道的两端,两块64KB的虚存空间都映射到同一块物理内存。
快速系统调用流程图:
9、从内核中发起系统调用
在内核中不能直接调用NtReadFile之类的实现函数。一般也是通过中介函数进行调用。
以NtReadFile为例,其在内核中的中介函数由工具生成,其名称为ZwReadFile。
代码:
__declspec(naked) _stdcall ZwReadFile(int dummy0, int dummy1, int dummy2)
{
asm{
mov eax 152
lea edx,[esp+4]
push KGDT_R0_CODE
call _KiSystemservice
ret 36
}
}
流程图:
(PS:为了使其看起来更舒适,编辑了一个多小时,权当自己的一次笔记吧
)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
#系统底层
上传的附件:
01.png
(39.30kb,4次下载)
02.jpg
(18.04kb,2次下载)
03.jpg
(31.97kb,2次下载)
04.jpg
(34.29kb,2次下载)
05.jpg
(14.35kb,5次下载)
收藏
・
24
免费
・
1
支持
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
lifeandi
为你点赞~
2020-11-4 16:38
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
12
)
淡然出尘
雪 币:
4
活跃值:
(781)
能力值:
( LV2,RANK:10 )
在线值:
发帖
7
回帖
112
粉丝
0
关注
私信
淡然出尘
2
楼
为了使其看起来更舒适,编辑了一个多小时
支持 辛苦了
2013-8-25 13:56
0
Aipsa
雪 币:
19
活跃值:
(25)
能力值:
( LV3,RANK:20 )
在线值:
发帖
12
回帖
122
粉丝
0
关注
私信
Aipsa
3
楼
可以收藏,不过任务状态段...
2013-8-25 14:55
0
装逼兄
雪 币:
7
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
42
回帖
179
粉丝
0
关注
私信
装逼兄
4
楼
支持了...
2013-8-25 14:58
0
IDGHOST
雪 币:
115
活跃值:
(46)
能力值:
( LV4,RANK:40 )
在线值:
发帖
16
回帖
197
粉丝
1
关注
私信
IDGHOST
5
楼
1.在平坦内存模式下,段寄存器在R0、R3是不是一样的,ds等可以为相同的段?
2.在内核态调用Native Api还需要切换到内核?
2013-8-25 15:45
0
永驻零一
雪 币:
46
活跃值:
(14)
能力值:
( LV2,RANK:10 )
在线值:
发帖
11
回帖
337
粉丝
0
关注
私信
永驻零一
6
楼
楼主辛苦了
2013-8-25 18:49
0
光Light
雪 币:
7
活跃值:
(56)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
21
粉丝
1
关注
私信
光Light
7
楼
不错不错。。学习了。。
2013-8-25 19:10
0
phpskycn
雪 币:
110
活跃值:
(34)
能力值:
(RANK:50 )
在线值:
发帖
29
回帖
395
粉丝
0
关注
私信
phpskycn
1
8
楼
段寄存器是不一样的,因为段寄存器的值和CPL(代码特权级)也相关,但是段的设置却相似,RING0下内存依旧是平坦的。
所谓Native API只是个桩函数,简单地填写了下调用号,最后进入内核后系统服务分发器根据这个调用号查SSDT得到调用的服务的处理例程(nt!NtXXXXXX函数,基本和Native API同名),这类函数部分可以在内核直接调用(但是有些并未导出)
2013-8-26 00:41
0
icestrong
雪 币:
5
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
3
粉丝
0
关注
私信
icestrong
9
楼
学习了,困惑过这里。
2013-8-26 11:18
0
losed
雪 币:
184
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
3
回帖
27
粉丝
1
关注
私信
losed
10
楼
楼主牛逼
2013-8-26 11:27
0
PPTV
雪 币:
9698
活跃值:
(2506)
能力值:
( LV2,RANK:10 )
在线值:
发帖
4
回帖
153
粉丝
0
关注
私信
PPTV
11
楼
谢谢大家的指导,俺是菜菜一枚啊~
2013-8-26 12:22
0
xieminwen
雪 币:
15
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
7
粉丝
0
关注
私信
xieminwen
12
楼
这个比较好。收藏了
2013-9-30 22:13
0
朱哥哥
雪 币:
57
活跃值:
(49)
能力值:
( LV2,RANK:10 )
在线值:
发帖
3
回帖
33
粉丝
0
关注
私信
朱哥哥
13
楼
mark
2017-2-21 20:27
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
PPTV
4
发帖
153
回帖
10
RANK
关注
私信
他的文章
[求助]QQ来自什么设备登录
2869
[求助]为什么内存不能修改(更改后马上还原)
7663
[转帖]系统调用,从用户态进入系统态(_KiSystemService() _KiFastCallEntry)
16964
终于转正了~庆祝一下!
2206
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
谁下载
×
枫雨程伦
谁下载
×
谁下载
×
谁下载
×
谁下载
×
eastocean
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部