(24)[进程与线程] 分析SwapContext

SwapContext有几个参数

esi : 当前线程 (_ETHREAD)
edi : 要切换的线程 (_ETHREAD)
ebx : _KPCR
cl : _KTHREAD.WaitIrql ,进去就被改了


SwapContext在哪里实现了线程切换

在这里插入图片描述


哪里进行了进程切换(修改CR3)

在这里插入图片描述

这里的 _ETHREAD + 0x44为养父母,当前在读取哪个进程的数据就填哪个进程
_ETHREAD + 0x220为亲父母,一定是创建自己的进程

所以这里的语义是,当 前线程读取的进程 与 下一个线程读取的进程 是否为同一个。与创建自己的进程无关

如果我们自己修改CR3,那么如果在读取数据的时候线程被切走了,那么线程重新回来的时候,CR3又变回_EHTREAD + 0x44了。
所以自己修改CR3的时候有两个办法:
1.关中断后,修改CR3之
2.把_ETHREAD + 0x44也改了,之后再改回来


TSS存储当前的 SS0 : ESP0

在这里插入图片描述


FS:[0]在3环总能正确指向当前TEB

在这里插入图片描述

先回顾一下TSS段描述符,我们假设当前段寄存器值为3B,那么就有上图

在这里插入图片描述
为什么是FS段选择子是0x3B?当然也可以是其他的,只要3环和0环规定使用同一个选择子就行了,这样他们就能通过同一个选择子读到同一块内存 (GDT[selector.index].base)


异常链表的切换

上一幅图 pop ecx 我有写注释,这也是异常链表切换的一部分
在这里插入图片描述
这幅图在切换堆栈之前push ecx,将异常链表存入了旧的堆栈中

完整分析代码

.text:00404924 SwapContext proc near                   ; CODE XREF: KiUnlockDispatcherDatabase(x)+72↑p
.text:00404924                                         ; KiSwapContext(x)+29↑p ...
.text:00404924         or      cl, cl
.text:00404926         mov     es:[esi+_ETHREAD.Tcb.State], 2 ; esi 新Thread
.text:0040492B         pushf
.text:0040492C
.text:0040492C loc_40492C:                             ; CODE XREF: KiIdleLoop()+5A↓j
.text:0040492C         mov     ecx, [ebx+_KPCR.NtTib.ExceptionList] ; ebx = _KPCR
.text:0040492E         cmp     dword ptr [ebx+994h], 0
.text:00404935         push    ecx                     ; 将旧的线程的异常链表存入旧堆栈
.text:00404936         jnz     loc_404A70
.text:0040493C         cmp     ds:_PPerfGlobalGroupMask, 0
.text:00404943         jnz     loc_404A47
.text:00404949
.text:00404949 loc_404949:                             ; CODE XREF: SwapContext+12B↓j
.text:00404949                                         ; SwapContext+13C↓j ...
.text:00404949         mov     ebp, cr0
.text:0040494C         mov     edx, ebp
.text:0040494E         mov     cl, [esi+_ETHREAD.Tcb.DebugActive]
.text:00404951         mov     [ebx+_KPCR.DebugActive], cl
.text:00404954         cli
.text:00404955         mov     [edi+_ETHREAD.Tcb.KernelStack], esp ; edi 当前Thread
.text:00404958         mov     eax, [esi+_ETHREAD.Tcb.InitialStack]
.text:0040495B         mov     ecx, [esi+_ETHREAD.Tcb.StackLimit]
.text:0040495E         sub     eax, 210h
.text:00404963         mov     [ebx+_KPCR.NtTib.StackLimit], ecx
.text:00404966         mov     [ebx+_KPCR.NtTib.StackBase], eax
.text:00404969         xor     ecx, ecx
.text:0040496B         mov     cl, [esi+_ETHREAD.Tcb.NpxState]
.text:0040496E         and     edx, 0FFFFFFF1h
.text:00404971         or      ecx, edx
.text:00404973         or      ecx, [eax+20Ch]
.text:00404979         cmp     ebp, ecx
.text:0040497B         jnz     loc_404A3F
.text:00404981         lea     ecx, [ecx]
.text:00404983
.text:00404983 loc_404983:                             ; CODE XREF: SwapContext+11E↓j
.text:00404983         test    dword ptr [eax-1Ch], 20000h ; 是否为8086保护模式
.text:0040498A         jnz     short loc_40498F        ; (!= 保护模式) 实模式,跳转
.text:0040498C         sub     eax, 10h                ; (== 保护模式),跳过填充实模式的四个值
.text:0040498C                                         ; Trap_Frame + 0x88 --> Trap_Frame + 0x78
.text:0040498F
.text:0040498F loc_40498F:                             ; CODE XREF: SwapContext+66↑j
.text:0040498F         mov     ecx, [ebx+_KPCR.TSS]    ; ecx = TSS (准备修改当前线程的TSS)
.text:00404992         mov     [ecx+4], eax            ; TSS.esp0 = newEsp (修正正在使用的TSS.esp0)
.text:00404995         mov     esp, [esi+_ETHREAD.Tcb.KernelStack] ; 切换堆栈
.text:00404998         mov     eax, [esi+_ETHREAD.Tcb.Teb]
.text:0040499B         mov     [ebx+_KPCR.NtTib.Self], eax
.text:0040499E         sti
.text:0040499F         mov     eax, [edi+_ETHREAD.Tcb.ApcState.Process]
.text:004049A2         cmp     eax, [esi+_ETHREAD.Tcb.ApcState.Process]
.text:004049A5         mov     [edi+_ETHREAD.Tcb.IdleSwapBlock], 0
.text:004049A9         jz      short loc_4049D7        ; if (curProcess == newProcess) jmp
.text:004049A9                                         ; else 修改CR3 (进程切换)
.text:004049AB         mov     edi, [esi+_ETHREAD.Tcb.ApcState.Process] ; edi = _EPROCESS
.text:004049AE         test    word ptr [edi+20h], 0FFFFh
.text:004049B4         jnz     short loc_404A11
.text:004049B6         xor     eax, eax
.text:004049B8
.text:004049B8 loc_4049B8:                             ; CODE XREF: SwapContext+116↓j
.text:004049B8         lldt    ax
.text:004049BB         xor     eax, eax
.text:004049BD         mov     gs, eax
.text:004049BF         assume gs:GAP
.text:004049BF         mov     eax, [edi+_EPROCESS.Pcb.DirectoryTableBase]
.text:004049C2         mov     ebp, [ebx+_KPCR.TSS]
.text:004049C5         mov     ecx, dword ptr [edi+_EPROCESS.Pcb.IopmOffset]
.text:004049C8         mov     [ebp+1Ch], eax          ; TSS.CR3 = newCR3
.text:004049CB         mov     cr3, eax
.text:004049CE         mov     [ebp+66h], cx           ; TSS.I/O Map Base Address = _EPROCESS.Pcb.IopmOffset
.text:004049CE                                         ; 我也不懂
.text:004049D2         jmp     short loc_4049D7
.text:004049D2 ; ---------------------------------------------------------------------------
.text:004049D4         db 8Dh, 49h, 0
.text:004049D7 ; ---------------------------------------------------------------------------
.text:004049D7
.text:004049D7 loc_4049D7:                             ; CODE XREF: SwapContext+85↑j
.text:004049D7                                         ; SwapContext+AE↑j
.text:004049D7         mov     eax, [ebx+_KPCR.NtTib.Self]
.text:004049DA         mov     ecx, [ebx+_KPCR.GDT]
.text:004049DD         mov     [ecx+3Ah], ax           ; Base Address 15:00
.text:004049E1         shr     eax, 10h                ; 取高16.text:004049E4         mov     [ecx+3Ch], al           ; Base Address 23:16
.text:004049E7         mov     [ecx+3Fh], ah           ; Base Address 31:24
.text:004049EA         inc     [esi+_ETHREAD.Tcb.ContextSwitches]
.text:004049ED         inc     [ebx+_KPCR.PrcbData.KeContextSwitches]
.text:004049F3         pop     ecx                     ; 当前线程的异常链表 (上面已经切换过堆栈了,所以这里是新的异常链表)
.text:004049F3                                         ; 最开始的push ecx,旧的异常链表被放入了旧的堆栈中
.text:004049F4         mov     [ebx+_KPCR.NtTib.ExceptionList], ecx
.text:004049F6         cmp     [esi+_ETHREAD.Tcb.ApcState.KernelApcPending], 0
.text:004049FA         jnz     short loc_404A00
.text:004049FC         popf
.text:004049FD         xor     eax, eax
.text:004049FF         retn
          
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值