上篇只要函數調用SwitchContext就能實現主動切換,Windows中主動切換函數:KiSwapContext函數,它在ntoskrnl.exe中
下面我們用IDA來看看這個函數
; __fastcall KiSwapContext(x)
.text:0046A8F4 @KiSwapContext@4 proc near ; CODE XREF: KiSwapThread()+41↑p
.text:0046A8F4
.text:0046A8F4 var_10 = dword ptr -10h
.text:0046A8F4 var_C = dword ptr -0Ch
.text:0046A8F4 var_8 = dword ptr -8
.text:0046A8F4 var_4 = dword ptr -4
.text:0046A8F4
.text:0046A8F4 sub esp, 10h
.text:0046A8F7 mov [esp+10h+var_4], ebx ; 保存當前線程寄存器現場
.text:0046A8FB mov [esp+10h+var_8], esi
.text:0046A8FF mov [esp+10h+var_C], edi
.text:0046A903 mov [esp+10h+var_10], ebp
.text:0046A906 mov ebx, ds:0FFDFF01Ch ; 取出KPCR,當前正在運行的線程沒有存在鏈表中而是存在KPCR中
.text:0046A90C mov esi, ecx ; ESI中存儲的是要切換線程的_KTHREAD
.text:0046A90E mov edi, [ebx+124h] ; 取出運行當前代碼的_KTHREAD
.text:0046A914 mov [ebx+124h], esi ; 修改KPCR中的線程爲目標線程
.text:0046A91A mov cl, [edi+58h]
.text:0046A91D call SwapContext ; 真正的線程切換時在這個函數中實現的
.text:0046A922 mov ebp, [esp+10h+var_10]
.text:0046A925 mov edi, [esp+10h+var_C]
.text:0046A929 mov esi, [esp+10h+var_8]
.text:0046A92D mov ebx, [esp+10h+var_4]
.text:0046A931 add esp, 10h
.text:0046A934 retn
.text:0046A934 @KiSwapContext@4 endp
.text:0046A934
Windows中絕大部分API都調用了SwapContext函數,也就是說,當線程只要調用了API,就是導致線程切換
線程切換時會比較是否屬於同一進城,如果不是就會切換CR3,CR3換了,進程也就換了,進程切換本質就是線程切換