九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
NT 內(nèi)核的進程調(diào)度分析筆記
NT 內(nèi)核的進程調(diào)度分析筆記

Author:  sinister
Email:   sinister@whitecell.org
Homepage:http://www.whitecell.org
Date:    2005-11-16

2005-2-15  眾所周知 nt kernel 是多任務(wù)搶占試方式運行的,在非 SMP 系統(tǒng)上,每個進程分配特定的CPU 時間片來達到執(zhí)行目的,這樣看上去就象多個任務(wù)在同時運行。而 nt kernel又是以線程調(diào)度為核心的,這樣線程切換了也就意味著當前進程的切換。系統(tǒng)不斷重復這個過程,來使每個進程得以運行。在介紹流程前,需要先了解幾個系統(tǒng)內(nèi)部結(jié)構(gòu):KPCR、ETHREAD、EPROCESS、可以說,涉及到進程調(diào)度的函數(shù)基本都是對這幾個重要結(jié)構(gòu)的設(shè)置與填充。關(guān)于各結(jié)構(gòu)的細節(jié),對系統(tǒng)內(nèi)核有所了解的人自然都很熟悉,我就不再多廢話了。這里是結(jié)合進程調(diào)度來說。KPCR 這個結(jié)構(gòu)存放的是當前 CPU 所正在處理的各種信息,其中包括了當前正在運行的線程 ETHREAD 結(jié)構(gòu)。而 ETHREAD 結(jié)構(gòu)又與 EPROCESS 結(jié)構(gòu)是相互關(guān)聯(lián)的。這也就是很多核心函數(shù)通過 KPCR 啟始地址 0xFFDFF000 + 偏移就能夠得到當前正在運行的線程與進程的原因,如 KeGetCurrentThread()、IoGetCurrentProcess() 等。這也表明在非 SMP 系統(tǒng)上,某時間段內(nèi)當前 CPU 處理的進程只可能有一個。當進行進程調(diào)度時系統(tǒng)將根據(jù)當前所存活的進程來選擇讓哪個線程 ETHREAD 結(jié)構(gòu)來替換 KPCR 中的 ETHREAD,使其變?yōu)檎谶\行的狀態(tài)。那么又是如何觸發(fā)進程調(diào)度請求能讓所有進程均得以執(zhí)行的呢?開始已經(jīng)提到過,每個進程分配特定的 CPU 時間片來達到執(zhí)行目的,而系統(tǒng)的 CPU 時鐘中斷確定了每個進程分配的時間片。也就是當系統(tǒng) CPU 時鐘中斷觸發(fā)時,產(chǎn)生的進程調(diào)度請求。在詳細分析調(diào)度流程與各函數(shù)分支前,我們先來看一下大致的流程。首先當 CPU 時鐘中斷觸發(fā)時,系統(tǒng)將調(diào)用 KiDispatchInterrupt(),比較當前進程分配的時間片,如用完后會調(diào)用 KiQuantumEnd() 根據(jù)各線程優(yōu)先級等信息用特定的調(diào)度算法選擇新的線程(ETHREAD),然后將其返回值,一個 ETHREAD 結(jié)構(gòu)作為參數(shù),來調(diào)用 SwapContext() 設(shè)置 ETHREAD,EPROCESS 中的各項參數(shù),并替換 KPCR 中的相應結(jié)構(gòu)完成線程切換,調(diào)度到另一個進程(EPROCESS)的線程(ETHREAD)繼續(xù)執(zhí)行。(當線程等待某一事件(Event)或信號量(Semaphore)時會自動放棄當前時間片) 。通過上面的大致分析,我們可以看出與進程調(diào)度密切相關(guān)的幾個函數(shù),KiDispatchInterrupt() 與 SwapContext(),下面我們將就這兩個關(guān)鍵的調(diào)度函數(shù)進行詳細的分析。  首先來看下 KiDispatchInterrupt() 函數(shù),當調(diào)用此函數(shù)時,首先得到當前 KPCR 自身結(jié)構(gòu)與DCP鏈表頭,并比較當前是否有 DPC 正在處理,如果有 DPC 正在處理,則設(shè)置 DPC 異常煉。如果沒有,則直接跳轉(zhuǎn)到比較 KPCR 中 QuantumEnd 值,QuantumEnd 表示當前 KPCR 中正在處理的線程時間片總數(shù)。此值是是根據(jù)當前運行線程 ETHREAD->Quantum 中的值來填充的,就是說 KPCR 中 QuantumEnd 值不為0并不代表當前線程不允許切換,此時還需要調(diào)用 KiQuantumEnd() 來近一步判斷是否允許切換。所以當前值不為0時則跳轉(zhuǎn)到 KiQuantumEnd() 函數(shù)處做進一步判斷。KiQuantumEnd() 函數(shù)會取當前線程(ETHREAD)結(jié)構(gòu)中的 Quantum 值來進行判斷是否為0,根據(jù)線程優(yōu)先等參數(shù)調(diào)用 KiFindReadyThread() 函數(shù)來選擇一個新的線程填充 KPCR中的 NextThread ,并將 NextThread作為函數(shù)返回值,跳轉(zhuǎn)到相應地址繼續(xù)進行線程切換。如果返回值返為空,則表示無法進行切換,函數(shù)返回。但如果 KPCR 中的 QuantumEnd 本身已為0,則表示當前線程 ETHREAD分配時間片已經(jīng)用完,可以進行線程換,所以繼續(xù)比較 KPCR 中是否有下一個線程(偏移NextThread),如果KPCR 中下一線程(偏移NextThread)偏移為空,則表示沒有就緒線程可切換,直接跳轉(zhuǎn)到返回地址,完成函數(shù)調(diào)用。如果不為空的話,則可繼續(xù)進行線程切換。到此所需的基本參數(shù)都已經(jīng)準備就緒,下面要做的就是把 KPCR 中下一個線程(偏移NextThread),替換成 KPCR 中當前線程(偏移CurrentThread),并將 KPCR 中下一線程(偏移NextThread)清0,調(diào)用 KiReadyThread() 就緒剛剛設(shè)置好的下一線程(偏移NextThread),也就是現(xiàn)在為當前線程 (偏移CurrentThread)。最后調(diào)用 SwapContext() 函數(shù)完成最終的切換。  下面來看一下 SwapContext() 函數(shù)的實現(xiàn),上面提到過 SwapContext() 是在 KiDispatchInterrupt() 函數(shù)中調(diào)用的,用來完成最終的線程切換。函數(shù)首先設(shè)置要切換的新線程狀態(tài)(NextThread->Status) 為運行狀態(tài)。接下來判斷當前是否有 DCP 列程正在運行( KPCR 中的 DpcRoutineActive 是否為 0,不為0則表示當前有 DPC 處理,微軟規(guī)定在進行線程調(diào)度時不允許 DPC 列程運行,否則將系統(tǒng)崩潰,其實這不是必須的,僅僅是微軟的規(guī)定而已) 如果有則跳轉(zhuǎn)到調(diào)用 KeBugCheck() 函數(shù)處,系統(tǒng)崩潰。如果沒有則繼續(xù)取要切換的新線程(NextThread->DebugActive)調(diào)試標志狀態(tài),并賦給 KPCR 中 DebugActive 。保存 ESP 到要被切換的舊線程 (CurrentThread->KernelStack)內(nèi)核堆棧中,并將要切換的新線程(NextThread->InitalStack,NextThread->StackLimit)中的堆棧啟始地址與大小賦給 KPCR 中的相應位置。繼續(xù)取要切換的新線程(NextThread->NpxState)中的 NPX 狀態(tài)與CR0 的 NPX 狀態(tài)進行比較,如不相等跳轉(zhuǎn)到重新設(shè)置 CR0 處進行處理。刷新 CR0 后回跳轉(zhuǎn)回來繼續(xù)下面的運行。(CR0 中的 NPX 位狀態(tài)是 CPU 通過某幾個指令觸發(fā)一個異常后進入一個特殊的狀態(tài)來處理浮點指令,這時是不允許線程切換的,所以不相同的情況下需要重新刷新 CR0 狀態(tài)。 )接下來進行模式判斷,判斷要切換的新線程(NextThread)是否運行在 V86 模式下,如果是繼續(xù)調(diào)整內(nèi)核堆棧空間。如果不是則跳過調(diào)整。從 KPCR 中得到KTSS 地址,并將 NPX 標志位保存到 KTSS 中的 ESP0 處(這樣不論是否為 V86 模式下運行的線程都可以共享)。此時各項標志,結(jié)構(gòu)與參數(shù)都已就緒,下面的工作就是要進行具體的切換過程了。首先取要切換的新線程(NextThread->KernelStack)的內(nèi)核堆棧賦與當前內(nèi)核堆棧指針ESP,并設(shè)置 KPCR 中的用戶堆棧(TEB)為要切換的新線程(NextThread->TEB)的用戶堆棧(TEB)。然后將用戶堆棧(TEB)放入 KPCR中 GDT 的相應結(jié)構(gòu)中。比較要被切換的舊線程(CurrentThread->EPROCESS)中的進程,是否與要切換的新線程(NextThread->EPROCESS)中的進程相等?也就是判斷要切換的進程是否為當前進程,如果是則不刷新當前頁目錄表(CR3)以及其他相關(guān)值,而直接跳轉(zhuǎn)到添加當前進程切換計數(shù)與判斷當前線程是否存在 Pending 的 APC 調(diào)用處,然后退出,完成切換。如果要切換的線程不是當前進程,則從要切換的新線程(NextThread->EPROCESS)中取出當前進程,并從當前進程(EPROCESS->DirectoryTableBase)中得到頁目錄表來更新KPCR 中 KTSS 中的 TSSCR3 的值與 CR3 寄存器中的值,(這也就是為什么 CR3 總指向當前進程頁目錄地址)繼續(xù)將當前進程(EPROCESS->IopmOffset)中 IOPM 值賦與 KPCR 中 KTSS 中的 IOPM。再比較當前進程(EPROCESS->LdtDescriptor)中的 LDT 是否為空,如果不為空則從 KPCR中取得 KGDT 的位置,并從 KGDT 中索引到 LDT,把當前進程(EPROCESS->LdtDescriptor)中的 LDT 賦與 KPCR 中的LDT。再得到 KPCR 中 KIDT 的位置,把當前進程(EPROCESS->Int21Descriptor)中的 INT 21中斷賦與 KPCR 中 KIDT中的相應位置,使當前進程可以調(diào)用 INT 21 。最后調(diào)用 LLDT 使當前所有設(shè)置生效。(按理說 NT 內(nèi)核中 32 位應用程序是不使用 LDT 的但為什么在線程切換中會有設(shè)置LDT的部分呢?這是為了向下兼容 16 位的應用程序,當調(diào)度到一個 16 位的應用程時則會特意為它分配 LDT 并且使 IDT 中的 INT 21 有效,玩過 DOS 的人都知道 INT 21 是 DOS 下的系統(tǒng)調(diào)用,可以試著運行一個 16 位的 DOS 程序,然后觀察下 IDT 表就會發(fā)現(xiàn),原來沒有用到的 INT21 會被設(shè)置成一個 16 位的 TrapGate)否則如果為空則設(shè)置成不使用 LDT,把要切換的新線程(NextThread->ContextSwitches)中的切換次數(shù)與 KPCR 中的切換總和各加一,恢復異常鏈,并比較要切換的新線程(NextThread->KernelApcPending)中的 APC 調(diào)用是否沒有完成 ,如果當前 APC 狀態(tài)沒有完成的話則判斷當前是否可以處理 APC 調(diào)用,如果不能則設(shè)置返回標志為 Pending 完成線程切換的所有工作并返回。否則設(shè)置當前 IRQL 為 APC LEVEL 并調(diào)用 HalRequestSoftwareInterrupt() 函數(shù)來處理 APC Pending狀態(tài),處理完成后清除 Pending 狀態(tài),完成線程切換的所有工作并返回。如果當前 APC狀態(tài)完成的話,則恢復各寄存器和標志寄存器的值并返回,完成線程切換的所有工作。當調(diào)用 KiDispatchInterrupt() 函數(shù)時,:u KiDispatchInterrupt l 1000ntoskrnl!KiDispatchInterrupt0008:80467DD0  MOV       EBX,[FFDFF01C]0008:80467DD6  LEA       EAX,[EBX+00000800]得到當前 KPCR 自身結(jié)構(gòu)與DCP鏈表頭,EAX=DPC,EBX=KPCR0008:80467DDC  CLI0008:80467DDD  CMP       EAX,[EAX]0008:80467DDF  JZ       80467DFE關(guān)中斷,并比較當前 DPC 是否為空,如果為空,直接跳轉(zhuǎn)到比較 KPCR 中QuantumEnd 值和比較是否有下一個線程(ETHREAD)結(jié)構(gòu)0008:80467DE1  PUSH      EBP0008:80467DE2  PUSH      DWORD PTR [EBX]0008:80467DE4  MOV       DWORD PTR [EBX],FFFFFFFF0008:80467DEA  MOV       EDX,ESP0008:80467DEC  MOV       ESP,[EBX+0000081C]  注釋: 得到 DPC 堆棧0008:80467DF2  PUSH      EDX0008:80467DF3  MOV       EBP,EAX0008:80467DF5  CALL     804633E7   注釋: KiRetireDpcList()函數(shù)0008:80467DFA  POP       ESP0008:80467DFB  POP       DWORD PTR [EBX]0008:80467DFD  POP       EBP設(shè)置 DPC 異常鏈0008:80467DFE  STI0008:80467DFF  CMP       DWORD PTR [EBX+00000870],00   注釋: QuantumEnd 線程時間片0008:80467E06  JNZ      80467E5A如果 KPCR 中 QuantumEnd 值不為 0 則表示可能當前線程(ETHREAD)時間片沒有用完,跳轉(zhuǎn)到判斷當前線程(ETHREAD) 是否可以進行切換。0008:80467E08  CMP       DWORD PTR [EBX+00000128],00   注釋: NextThread (ETHREAD結(jié)構(gòu))0008:80467E0F  JZ       80467E59是否有下一個線程,如果 KPCR 中下一線程 NextThread(ETHREAD)偏移為空,則直接跳轉(zhuǎn)到返回地址,完成函數(shù)調(diào)用。0008:80467E11  MOV       EAX,[EBX+00000128]  此時 EAX = NextThread (ETHREAD結(jié)構(gòu))0008:80467E17  SUB       ESP,0C0008:80467E1A  MOV       [ESP+08],ESI0008:80467E1E  MOV       [ESP+04],EDI0008:80467E22  MOV       [ESP],EBP0008:80467E25  MOV       ESI,EAX  0008:80467E27  MOV       EDI,[EBX+00000124]  注釋: CurrentThread (ETHREAD結(jié)構(gòu))0008:80467E2D  MOV       DWORD PTR [EBX+00000128],000000000008:80467E37  MOV       [EBX+00000124],ESI0008:80467E3D  MOV       ECX,EDI0008:80467E3F  CALL      8042F944  注釋: KiReadyThread函數(shù)把 KPCR 中下一個線程 NextThread (ETHREAD) 結(jié)構(gòu),替換成 KPCR 中當前 CurrentThread(ETHREAD)線程結(jié)構(gòu),并將 KPCR 中下一線程 NextThread (ETHREAD) 偏移清0,調(diào)用 KiReadyThread() 就緒剛剛設(shè)置好的下一線程 NextThread(ETHREAD) 結(jié)構(gòu),現(xiàn)在為當前線程 CurrentThread (ETHREAD) 結(jié)構(gòu)。0008:80467E44  MOV       CL,01 設(shè)置 APC IRQL 標志,SwapContext() 調(diào)用會先設(shè)置當前IRQL 為 APC_LEVEL。0008:80467E46  CALL      80467E70 注釋: SwapContext函數(shù)0008:80467E4B  MOV       EBP,[ESP]0008:80467E4E  MOV       EDI,[ESP+04]0008:80467E52  MOV       ESI,[ESP+08]0008:80467E56  ADD       ESP,0C調(diào)用 SwapContext() 完成線程切換。(__fastcall 調(diào)用規(guī)范,平衡堆棧)0008:80467E59  RET  注釋: KiDispatchInterrupt 函數(shù)調(diào)用完畢,返回。0008:80467E5A  MOV       DWORD PTR [EBX+00000870],00000000  注釋: QuantumEnd 0008:80467E64  CALL     804306D2                            注釋: KiQuantumEnd 0008:80467E69  OR        EAX,EAX                            注釋: EAX = NextThread(ETHREAD)0008:80467E6B  JNZ      80467E17  0008:80467E6D  RET 注釋: KiDispatchInterrupt 函數(shù)調(diào)用完畢,返回。設(shè)置 KPCR 中 QuantumEnd 值為 0,并調(diào)用 KiQuantumEnd 相應處理,KiQuantumEnd 函數(shù)會取當前線程(ETHREAD)結(jié)構(gòu)中的 Quantum 值來進行判斷是否為0,如果可以進行線程切換,則根據(jù)線程優(yōu)先等參數(shù)調(diào)用 KiFindReadyThread() 函數(shù)來選擇一個新的線程填充 KPCR 中的 NextThread (ETHREAD結(jié)構(gòu)),并將 NextThread (ETHREAD結(jié)構(gòu)) 賦給 EAX,并跳轉(zhuǎn)到線程切換地址進行切換。如果 EAX 返回為空,則表示無法進行切換,函數(shù)返回。_______________________________________________________________________________________  以上基本把線程調(diào)度各分之走完,可以大概看出一個進程交替運行的流程,下面的 SwapContext 函數(shù)完成實際切換。SwapContext()  EBX = KPCRESI = NextThreadEDI = CurrentThread0008:80467E6E  MOV       EDI,EDI0008:80467E70  OR        CL,CL0008:80467E72  MOV       BYTE PTR ES:[ESI+2D],02 (ETHREAD->State)設(shè)置要切換的新線程NextThread(ETHREAD)為運行狀態(tài)。0008:80467E77  PUSHFD0008:80467E78  MOV       ECX,[EBX]0008:80467E7A  CMP       DWORD PTR [EBX+0000080C],000008:80467E81  PUSH      ECX0008:80467E82  JNZ      80467F7D線程切換時不允許有 DPC 列程產(chǎn)生,所以先比較 KPCR 中的DpcRoutineActive 是否為 0,不為0則表示當前有 DPC 處理,跳轉(zhuǎn)到 KeBugCheck() 函數(shù)處顯示藍屏。0008:80467E88  MOV       EBP,CR0     注釋:EBP = CR00008:80467E8B  MOV       EDX,EBP     注釋:EDX = CR0 0008:80467E8D  MOV       CL,[ESI+2C]0008:80467E90  MOV       [EBX+50],CL取要切換的新線程NextThread(ETHREAD)調(diào)試標志狀態(tài),并賦給 KPCR 中DebugActive 相應標志。0008:80467E93  CLI0008:80467E94  MOV       [EDI+28],ESP 將堆棧指針賦給要被切換的舊線程 CurrentThread(ETHREAD)中的 KernelStack。0008:80467E97  MOV       EAX,[ESI+18]0008:80467E9A  MOV       ECX,[ESI+1C]0008:80467E9D  SUB       EAX,000002100008:80467EA2  MOV       [EBX+08],ECX0008:80467EA5  MOV       [EBX+04],EAX將要切換的新線程NextThread(ETHREAD)中的初始化堆棧(InitalStack)與堆棧大小(StackLimit)賦給 KPCR 中的相應位置,以便處理。0008:80467EA8  XOR       ECX,ECX0008:80467EAA  MOV       CL,[ESI+31]0008:80467EAD  AND       EDX,-0F0008:80467EB0  OR        ECX,EDX0008:80467EB2  OR        ECX,[EAX+0000020C]0008:80467EB8  CMP       EBP,ECX0008:80467EBA  JNZ      80467F75取要切換的新線程NextThread(ETHREAD)中的 NPX 位與 CR0 的 NPX 位進行比較,如不相等跳轉(zhuǎn)到重新設(shè)置 CR0 處進行處理。0008:80467EC0  TEST      DWORD PTR [EAX-1C],000200000008:80467EC7  JNZ      80467ECC判斷當前是否為 V86模式,如果不是直接跳到取得 KTSS 處。0008:80467EC9  SUB       EAX,10如果是 V86 模式則繼續(xù)調(diào)整內(nèi)核堆??臻g。0008:80467ECC  MOV       ECX,[EBX+40]   注釋:ECX = KPCR->KTSS0008:80467ECF  MOV       [ECX+04],EAX0008:80467ED2  MOV       ESP,[ESI+28]   0008:80467ED5  MOV       EAX,[ESI+20]0008:80467ED8  MOV       [EBX+18],EAX   注釋:EAX = TEB從 KPCR 中得到 KTSS 地址,并將 NPX 位保存到 KTSS 中的 ESP0 處,取要切換的新線程NextThread(ETHREAD)的內(nèi)核堆棧(KernelStack )賦與ESP,并設(shè)置 KPCR 中的用戶堆棧(TEB) 為要切換的新線程NextThread(ETHREAD)的用戶堆棧(TEB)。0008:80467EDB  STI0008:80467EDC  MOV       ECX,[EBX+3C]  注釋:ECX = KPCR->GDT 0008:80467EDF  MOV       [ECX+3A],AX0008:80467EE3  SHR       EAX,100008:80467EE6  MOV       [ECX+3C],AL0008:80467EE9  SHR       EAX,080008:80467EEC  MOV       [ECX+3F],AL0008:80467EEF  MOV       EAX,[EDI+44]0008:80467EF2  CMP       EAX,[ESI+44]0008:80467EF5  JZ       80467F20將用戶堆棧(TEB)放入 KPCR 中 GDT 的相應結(jié)構(gòu)中。比較要被切換的舊線程 CurrentThread(ETHREAD)中的 EPROCESS,與要切換的新線程NextThread(ETHREAD)中的 EPROCESS 是否相等?也就是判斷要切換的是否為當前進程,如果是則不設(shè)置當前頁目錄表(CR3)以及其他相關(guān)值,而直接跳轉(zhuǎn)到添加當前進程切換計數(shù)與判斷當前線程是否存在 Pending 的 APC 調(diào)用處,然后退出,完成切換。0008:80467EF7  MOV       EDI,[ESI+44]  注釋:EDI = NextThread->EPROCESS0008:80467EFA  XOR       EAX,EAX0008:80467EFC  MOV       GS,AX0008:80467EFF  MOV       EAX,[EDI+18]  注釋:EAX = EPROCESS->DirectoryTableBase0008:80467F02  MOV       EBP,[EBX+40]  注釋:EBP = KPCR->KTSS0008:80467F05  MOV       ECX,[EDI+30]  注釋:EDI = EPROCESS->IopmOffset0008:80467F08  MOV       [EBP+1C],EAX0008:80467F0B  MOV       CR3,EAX       注釋:CR3 = EPROCESS->DirectoryTableBase0008:80467F0E  MOV       [EBP+66],CX0008:80467F12  XOR       EAX,EAX0008:80467F14  CMP       [EDI+20],AX   0008:80467F18  JNZ      80467F470008:80467F1A  LLDT      AX0008:80467F1D  LEA       ECX,[ECX+00]如果要切換的線程不是當前進程,則從要切換的新線程NextThread(ETHREAD)中取當前進程(EPROCESS),并從當前進程(EPROCESS)中得到頁目錄表來更新KPCR->KTSS中的TSSCR3的值與 CR3 寄存器中的值,繼續(xù)將當前進程(EPROCESS)中IOPM 值賦與 KPCR-KTSS 中的 IOPM。再比較當前進程(EPROCESS)中的 LDT 是否為空,如果不為空則跳轉(zhuǎn)到設(shè)置 LDT 處執(zhí)行。否則設(shè)置 LDT 為空。0008:80467F20  INC       DWORD PTR [ESI+4C]0008:80467F23  INC       DWORD PTR [EBX+000005C0]0008:80467F29  POP       ECX0008:80467F2A  MOV       [EBX],ECX0008:80467F2C  CMP       BYTE PTR [ESI+49],000008:80467F30  JNZ      80467F360008:80467F32  POPFD0008:80467F33  XOR       EAX,EAX0008:80467F35  RET  注釋: SwapContext 函數(shù)調(diào)用完畢,返回。把要切換的新線程NextThread(ETHREAD)中的 ContextSwitches 與 KPCR 中的KeContextSwitches 各加一,這兩個值表示進行線程切換的次數(shù)?;謴彤惓f?,并比較要切換的新線程NextThread(ETHREAD)中的 KernelApcPending,如果當前APC 狀態(tài)是 Pending 的話則跳轉(zhuǎn)到處理 APC Pending 地址繼續(xù)。不為 Pending 的話,則恢復各寄存器和標志寄存器的值并返回,完成線程切換的所有工作。0008:80467F36  POPFD0008:80467F37  JNZ      80467F3C0008:80467F39  MOV       AL,010008:80467F3B  RET判斷當前是否可以處理 APC 調(diào)用,如果不能則設(shè)置返回標志為 Pending 完成線程切換的所有工作并返回。否則跳轉(zhuǎn)到處理軟中斷地址繼續(xù)。0008:80467F3C  MOV       CL,01   注釋: IRQL = APC LEVEL0008:80467F3E  CALL      [HAL!HalRequestSoftwareInterrupt]0008:80467F44  XOR       EAX,EAX0008:80467F46  RET設(shè)置當前 IRQL 為 APC LEVEL 并調(diào)用 HalRequestSoftwareInterrupt() 函數(shù)來處理APC Pending 狀態(tài),處理完成后清除 Pending 狀態(tài),完成線程切換的所有工作并返回。0008:80467F47  MOV       EBP,[EBX+3C]    注釋: EBP = KPCR->KGDT0008:80467F4A  MOV       EAX,[EDI+20]    注釋: EAX = EPROCESS->LdtDescriptor0008:80467F4D  MOV       [EBP+48],EAX0008:80467F50  MOV       EAX,[EDI+24]0008:80467F53  MOV       [EBP+4C],EAX0008:80467F56  MOV       EAX,000000480008:80467F5B  MOV       EBP,[EBX+38]    注釋: EBP = KPCR->KIDT0008:80467F5E  MOV       ECX,[EDI+28]    注釋: ECX = EPROCESS->Int21Descriptor0008:80467F61  MOV       [EBP+00000108],ECX0008:80467F67  MOV       ECX,[EDI+2C]0008:80467F6A  MOV       [EBP+0000010C],ECX0008:80467F70  LLDT      AX0008:80467F73  JMP      80467F20從 KPCR 中取得 KGDT 的位置,并從 KGDT 中索引到 LDT,把當前進程(EPROCESS)中的LDT 賦與 KPCR 中的 LDT。再得到 KPCR 中 KIDT 的位置,把當前進程(EPROCESS)中的INT 21中斷賦與 KPCR 中 KIDT 中的相應位置,使當前進程可以調(diào)用 INT 21 。最后調(diào)用LLDT 使當前所有設(shè)置生效后跳轉(zhuǎn)回添加線程切換次數(shù)與判斷當前 APC Pending 處繼續(xù)運行。0008:80467F75  MOV       CR0,ECX0008:80467F78  JMP      80467EC0重新設(shè)置 CR0 的 NPX 位,并向上跳轉(zhuǎn)到判斷是否為 V86 模式處繼續(xù)。0008:80467F7D  PUSH      000000B80008:80467F82  CALL      ntoskrnl!KeBugCheck0008:80467F87  RET調(diào)用藍屏函數(shù),系統(tǒng)崩潰重新啟動。  筆記是今年春節(jié)利用放假時間寫的,當時分析到一半才發(fā)現(xiàn)原來 WIN2K 源代碼中已經(jīng)包含了此部分,無奈已經(jīng)把匯編進行了簡單的注釋,索性就這樣寫下去。錯誤之處再所難免,還望得到您的指正。參考資源: Windows 2000 源代碼感謝 FlashSky,SoBeIt 與我探討。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
不HOOK任何函數(shù),讓任務(wù)管理器、XueTr、360進程管理器無法結(jié)束保護進程
超級模塊(3.6正式版)
【原創(chuàng)】OllyDBG分析報告系列(4)
[原創(chuàng)]進程和線程
TestAsmStructs.pas Source View
逆向工程
更多類似文章 >>
生活服務(wù)
熱點新聞
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服