线程切换 ——逆向分析 KiSwapThread

简介

Windows 内核中,线程的切换是通过 API 函数 KiSwapThread 实现获取将要执行的线程 _KTHREAD 结构体指针,再调用 KiSwapContex/SwapContex 函数实现线程上下文的切换,以实现线程的切换。


KiSwapThread/KiSwapContex/SwapContex 直接的调用关系如下:

在这里插入图片描述


KiSwapThread


内核函数 KiSwapThread 的汇编代码分析如下:

.text:004050BF ; =============== S U B R O U T I N E =======================================
.text:004050BF
.text:004050BF
.text:004050BF ; _DWORD __cdecl KiSwapThread()
.text:004050BF @KiSwapThread@0 proc near               ; CODE XREF: KeDelayExecutionThread(x,x,x):loc_405017↑p
.text:004050BF                                         ; KeWaitForSingleObject(x,x,x,x,x):loc_40513E↓p ...
.text:004050BF
.text:004050BF ; FUNCTION CHUNK AT .text:0040EA85 SIZE 00000015 BYTES
.text:004050BF ; FUNCTION CHUNK AT .text:004109AF SIZE 00000009 BYTES
.text:004050BF
.text:004050BF                 mov     edi, edi
.text:004050C1                 push    esi
.text:004050C2                 push    edi
.text:004050C3                 db      3Eh             ; EAX指向_KPRCB
.text:004050C3                 mov     eax, ds:0FFDFF020h
.text:004050C9                 mov     esi, eax        ; ESI指向_KPCR._KPRCB结构体
.text:004050CB                 mov     eax, [esi+_KPCR._KPRCB.NextThread] 
													   ; EAX获取NextThread的_KTHREAD地址
.text:004050CE                 test    eax, eax        ; 判断NextThread是否为空
.text:004050D0                 mov     edi, [esi+_KPCR._KPRCB.CurrentThread] 
													   ; EDI将会指向当前线程的_KTHREAD
.text:004050D3                 jnz     loc_4109AF      ; 已经获取到NextThread
.text:004050D3                                         ; 将_KPCR._KPRCB.NextThread的值清空
.text:004050D9                 push    ebx             ; 未获取到NextThread的_KTHREAD
.text:004050D9                                         ; 说明当前的CPU中没有其他就绪线程
.text:004050DA                 movsx   ebx, byte ptr [esi+_KPCR._KPRCB.Number] ; 获取CPU的编号
.text:004050DE                 xor     edx, edx
.text:004050E0                 mov     ecx, ebx
.text:004050E2                 call    @KiFindReadyThread@8 ; 在线程就绪队列中寻找就绪线程
.text:004050E7                 test    eax, eax        ; EAX是指向就绪线程_KTHREAD的指针
.text:004050E9                 jz      loc_40EA85      
											; EAX的值为空, 表示此时还没有就绪线程, 将会默认执行空闲线程
.text:004050E9                                         ; EAX将会获取到空闲线程的_KTHREAD
.text:004050EF
.text:004050EF loc_4050EF:                             ; CODE XREF: KiSwapThread()+99D6↓j
.text:004050EF                 pop     ebx             ; 已经获取到就绪线程
.text:004050EF                                         ; 就绪线程的_KTHRTEAD存储在EAX中
.text:004050F0
.text:004050F0 loc_4050F0:                             ; CODE XREF: KiSwapThread()+B8F4↓j
.text:004050F0                 mov     ecx, eax        ; 此时已经获取到将要执行的线程的_KTHREAD
.text:004050F0                                         ; EAX指向要切换的线程的_KTHREAD
.text:004050F2                 call    @KiSwapContext@4 ; 调用线程上下文切换函数
.text:004050F2                                         ; 该函数只有一个参数, 即ECX指向要切换的线程_KTHREAD
.text:004050F7                 test    al, al
.text:004050F9                 mov     cl, [edi+_KTHREAD.WaitIrql] ; NewIrql
.text:004050FC                 mov     edi, [edi+_KTHREAD.WaitStatus]
.text:004050FF                 mov     esi, ds:__imp_@KfLowerIrql@4 ; KfLowerIrql(x)
.text:00405105                 jnz     loc_415ADB
.text:0040510B
.text:0040510B loc_40510B:                             ; CODE XREF: IopCompleteRequest(x,x,x,x,x)+24A↓j
.text:0040510B                 call    esi ; KfLowerIrql(x) ; KfLowerIrql(x)
.text:0040510D                 mov     eax, edi
.text:0040510F                 pop     edi
.text:00405110                 pop     esi
.text:00405111                 retn
.text:00405111 @KiSwapThread@0 endp

函数逻辑流程图


函数 KiSwapThread 的逻辑流程图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值