线程的主动切换——KiSwapThread&KiSwapContext逆向

线程的切换分为主动切换和被动切换两种方式
主动切换主要是通过KiSwapThread进行的。
KiSwapThread逆向

.text:004050BF 8B FF                         mov     edi, edi
.text:004050C1 56                            push    esi
.text:004050C2 57                            push    edi
.text:004050C3                               db      3Eh                             ; eax=prcb
.text:004050C3 3E A1 20 F0 DF FF             mov     eax, ds:0FFDFF020h
.text:004050C9 8B F0                         mov     esi, eax
.text:004050CB 8B 46 08                      mov     eax, [esi+_KPRCB.NextThread]
.text:004050CE 85 C0                         test    eax, eax                        ; 判断是否为空
.text:004050D0 8B 7E 04                      mov     edi, [esi+_KPRCB.CurrentThread]
.text:004050D3 0F 85 D6 B8 00 00             jnz     loc_4109AF

1.首先判断下个线程是否为空

.text:004050D9 53                            push    ebx
.text:004050DA 0F BE 5E 10                   movsx   ebx, [esi+_KPRCB.Number]        ; 判断kpcr在哪个核上
.text:004050DE 33 D2                         xor     edx, edx
.text:004050E0 8B CB                         mov     ecx, ebx
.text:004050E2 E8 6B FF FF FF                call    @KiFindReadyThread@8            ; 寻找一个可以执行在当前核上的线程
.text:004050E2
.text:004050E7 85 C0                         test    eax, eax                        ; 判断是否找到
.text:004050E9 0F 84 96 99 00 00             jz      loc_40EA85                      ; 空闲线程

2.寻找到一个可以运行在当前核上的线程,通过KiFindReadyThread在就绪态的线程中寻找,如果找不到则在空闲线程中寻址。无论通过哪种方式eax等于下个线程的位置

.text:004050EF 5B                            pop     ebx
.text:004050EF
.text:004050F0
.text:004050F0                               loc_4050F0:                             ; CODE XREF: KiSwapThread()+B8F4↓j
.text:004050F0 8B C8                         mov     ecx, eax                        ; 下一个线程
.text:004050F2 E8 31 F7 FF FF                call    @KiSwapContext@4                ; KiSwapContext(x)

3.然后调用KiSwapContext进行上下文的交换,最后再进行一些寄存器值的交换,到这里线程切换结束。

KiSwapContext逆向

.text:00404828 83 EC 10                      sub     esp, 10h
.text:0040482B 89 5C 24 0C                   mov     [esp+10h+var_4], ebx
.text:0040482F 89 74 24 08                   mov     [esp+10h+var_8], esi            ; ecx 下一个线程
.text:00404833 89 7C 24 04                   mov     [esp+10h+var_C], edi
.text:00404837 89 2C 24                      mov     [esp+10h+var_10], ebp
.text:0040483A 8B 1D 1C F0 DF FF             mov     ebx, ds:0FFDFF01Ch              ; kpcr.selfpcr
.text:00404840 8B F1                         mov     esi, ecx
.text:00404842 8B BB 24 01 00 00             mov     edi, [ebx+_KPCR.PrcbData.CurrentThread]
.text:00404848 89 B3 24 01 00 00             mov     [ebx+_KPCR.PrcbData.CurrentThread], esi ; 把当前线程设为下个线程
.text:0040484E 8A 4F 58                      mov     cl, [edi+_ETHREAD.Tcb.WaitIrql] ; 等待Irpl
.text:00404851 E8 CE 00 00 00                call    SwapContext
.text:00404851
.text:00404856 8B 2C 24                      mov     ebp, [esp+10h+var_10]
.text:00404859 8B 7C 24 04                   mov     edi, [esp+10h+var_C]
.text:0040485D 8B 74 24 08                   mov     esi, [esp+10h+var_8]
.text:00404861 8B 5C 24 0C                   mov     ebx, [esp+10h+var_4]
.text:00404865 83 C4 10                      add     esp, 10h
.text:00404868 C3                            retn

4.KiSwapContext首先把KPCR结构中的CurrentThread设置为寻找到的新线程,然后调用SwapContext

SwapContext

.text:00404924 0A C9                         or      cl, cl
.text:00404926 26 C6 46 2D 02                mov     es:[esi+_ETHREAD.Tcb.State], 2  ; 修改线程的状态
.text:00404926                                                                       ; esi等于下个线程
.text:0040492B 9C                            pushf
.text:0040492B
.text:0040492C
.text:0040492C                               loc_40492C:                             ; CODE XREF: KiIdleLoop()+5A↓j
.text:0040492C 8B 0B                         mov     ecx, [ebx+_KPCR.NtTib.ExceptionList]
.text:0040492E 83 BB 94 09 00 00 00          cmp     [ebx+_KPCR.PrcbData.DpcRoutineActive], 0 ; 判断当前cpu是否正在执行dpc
.text:00404935 51                            push    ecx                             ; 异常链压栈
.text:00404936 0F 85 34 01 00 00             jnz     loc_404A70                      ; 如果dpc执行,则kebugcheck蓝屏
.text:00404936
.text:0040493C 83 3D 0C B1 48 00 00          cmp     ds:_PPerfGlobalGroupMask, 0
.text:00404943 0F 85 FE 00 00 00             jnz     loc_404A47

5.SwapContext首先修改线程的状态,然后判断DpcRoutineActive和PPerfGlobalGroupMask。

.text:00404949 0F 20 C5                      mov     ebp, cr0
.text:0040494C 8B D5                         mov     edx, ebp
.text:0040494E 8A 4E 2C                      mov     cl, [esi+_ETHREAD.Tcb.DebugActive]
.text:00404951 88 4B 50                      mov     [ebx+_KPCR.DebugActive], cl     ; 设置KPCR的DebugActive
.text:00404954 FA                            cli                                     ; 关中断
.text:00404955 89 67 28                      mov     [edi+_ETHREAD.Tcb.KernelStack], esp ; 保存之前的esp
.text:00404955                                                                       ; edi交换之前的线程
.text:00404958 8B 46 18                      mov     eax, [esi+_ETHREAD.Tcb.InitialStack]
.text:0040495B 8B 4E 1C                      mov     ecx, [esi+_ETHREAD.Tcb.StackLimit]
.text:0040495E 2D 10 02 00 00                sub     eax, 210h                       ; init陷阱桢大小
.text:00404963 89 4B 08                      mov     [ebx+_KPCR.NtTib.StackLimit], ecx
.text:00404966 89 43 04                      mov     [ebx+_KPCR.NtTib.StackBase], eax ; 初始化栈
.text:00404969 33 C9                         xor     ecx, ecx
.text:0040496B 8A 4E 31                      mov     cl, [esi+_ETHREAD.Tcb.NpxState] ; 浮点寄存器状态
.text:0040496E 83 E2 F1                      and     edx, 0FFFFFFF1h                 ; 关闭CR0的一些位
.text:00404971 0B CA                         or      ecx, edx
.text:00404973 0B 88 0C 02 00 00             or      ecx, [eax+_FX_SAVE_AREA.Cr0NpxState]
.text:00404979 3B E9                         cmp     ebp, ecx                        ; 判断Cr0NpxState和cr0de值是否相等
.text:0040497B 0F 85 BE 00 00 00             jnz     loc_404A3F                      ; 不相等则赋值给cr0
.text:0040497B
.text:00404981 8D 09                         lea     ecx, [ecx]

6.设置DebugActive,并对CR0进行一些列操作

.text:00404983                               loc_404983:                             ; CODE XREF: SwapContext+11E↓j
.text:00404983 F7 40 E4 00 00 02 00          test    dword ptr [eax-1Ch], 20000h     ; 陷阱桢-1c == EFLAGS
.text:0040498A 75 03                         jnz     short loc_40498F                ; 判断是否虚拟模式
.text:0040498A
.text:0040498C 83 E8 10                      sub     eax, 10h                        ; eax = HardwareSegSs
.text:0040498C
.text:0040498F
.text:0040498F                               loc_40498F:                             ; CODE XREF: SwapContext+66↑j
.text:0040498F 8B 4B 40                      mov     ecx, [ebx+_KPCR.TSS]
.text:00404992 89 41 04                      mov     [ecx+_KTSS.Esp0], eax           ; esp0 = HardwareSegSs
.text:00404995 8B 66 28                      mov     esp, [esi+_ETHREAD.Tcb.KernelStack]
.text:00404998 8B 46 20                      mov     eax, [esi+_ETHREAD.Tcb.Teb]
.text:0040499B 89 43 18                      mov     [ebx+_KPCR.NtTib.Self], eax     ; teb放入 nttib
.text:0040499E FB                            sti

7.进行堆栈初始化以及堆栈修改操作

.text:0040499F 8B 47 44                      mov     eax, [edi+_ETHREAD.Tcb.ApcState.Process]
.text:004049A2 3B 46 44                      cmp     eax, [esi+_ETHREAD.Tcb.ApcState.Process] ; 判断新线程和旧线程是否处于同一个进程中
.text:004049A5 C6 47 50 00                   mov     [edi+_ETHREAD.Tcb.IdleSwapBlock], 0 ; 设置锁
.text:004049A9 74 2C                         jz      short loc_4049D7
.text:004049AB 8B 7E 44                      mov     edi, [esi+_ETHREAD.Tcb.ApcState.Process]
.text:004049AE 66 F7 47 20 FF FF             test    [edi+_EPROCESS.Pcb.LdtDescriptor.LimitLow], 0FFFFh
.text:004049B4 75 5B                         jnz     short loc_404A11                ; 判断是否dos系统
.text:004049B4
.text:004049B6 33 C0                         xor     eax, eax
.text:004049B6
.text:004049B8
.text:004049B8                               loc_4049B8:                             ; CODE XREF: SwapContext+116↓j
.text:004049B8 0F 00 D0                      lldt    ax                              ; 加载LDTR段描述符 0
.text:004049BB 33 C0                         xor     eax, eax
.text:004049BD 8E E8                         mov     gs, eax
.text:004049BF                               assume gs:GAP
.text:004049BF 8B 47 18                      mov     eax, [edi+_EPROCESS.Pcb.DirectoryTableBase] ; 活动新线程的活动进程的cr3
.text:004049C2 8B 6B 40                      mov     ebp, [ebx+_KPCR.TSS]
.text:004049C5 8B 4F 30                      mov     ecx, dword ptr [edi+_EPROCESS.Pcb.IopmOffset] ; IOPM位置(I/O权限表)
.text:004049C8 89 45 1C                      mov     [ebp+_KTSS.CR3], eax            ; 修改CR3
.text:004049CB 0F 22 D8                      mov     cr3, eax
.text:004049CE 66 89 4D 66                   mov     [ebp+_KTSS.IoMapBase], cx       ; 填入I/O权限表
.text:004049D2 EB 03                         jmp     short loc_4049D7

.text:004049D7                               loc_4049D7:                             ; CODE XREF: SwapContext+85↑j
.text:004049D7                                                                       ; SwapContext+AE↑j
.text:004049D7 8B 43 18                      mov     eax, [ebx+_KPCR.NtTib.Self]
.text:004049DA 8B 4B 3C                      mov     ecx, [ebx+_KPCR.GDT]
.text:004049DD 66 89 41 3A                   mov     [ecx+3Ah], ax
.text:004049E1 C1 E8 10                      shr     eax, 10h
.text:004049E4 88 41 3C                      mov     [ecx+3Ch], al
.text:004049E7 88 61 3F                      mov     [ecx+3Fh], ah                   ; 修改fs
.text:004049EA FF 46 4C                      inc     [esi+_ETHREAD.Tcb.ContextSwitches] ; 环境切换次数加1
.text:004049ED FF 83 1C 06 00 00             inc     [ebx+_KPCR.PrcbData.KeContextSwitches] ; KPCR记录的切换次数+1
.text:004049F3 59                            pop     ecx
.text:004049F4 89 0B                         mov     [ebx+_KPCR.NtTib.ExceptionList], ecx ; 修改异常链
.text:004049F6 80 7E 49 00                   cmp     [esi+_ETHREAD.Tcb.ApcState.KernelApcPending], 0 ; 判断有内核模式APC 对象正在等待交付
.text:004049FA 75 04                         jnz     short loc_404A00
.text:004049FA
.text:004049FC 9D                            popf
.text:004049FD 33 C0                         xor     eax, eax
.text:004049FF C3                            retn

8.判断新线程和旧线程是否在一个进程内,如果在一个进程内,修改FS设置一些值返回。如果不在一个进程内,则修改CR3并在tss中填入IOPM位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值