线程的切换分为主动切换和被动切换两种方式
主动切换主要是通过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位置

线程的主动切换——KiSwapThreadKiSwapContext逆向相关推荐

  1. java 切换主线程_Java线程状态及切换、关闭线程的正确姿势分享

    前言 在讲线程之前有必要讨论一下进程的定义:进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位.进程实体由程序段, 数据段 PCB(进程控制块)组成.线程又是什么?线程可以 ...

  2. java焦点图_javascript焦点图(能够自己主动切换 )

    /* 思路总结: 1.实现图片滚动的function.鼠标经时候获取当前li的index.设置ndex自己主动递增的函数.实现淡入淡出效果的函数 2.整个实现效果一传递index为主线 3.我的编写代 ...

  3. 从0到1写RT-Thread内核——线程定义及切换的实现

    从0写RT-Thread内核之线程定义及切换的实现具体可以分为以下六步来实现 一:分别定义线程栈.线程函数.线程控制块: ALIGN(RT_ALIGN_SIZE)//设置4字节对齐 /* 定义线程栈 ...

  4. Vrep线程之间的切换

    在使用vrep的thread scirpt的时候我竟然会对这么简单的一个问题产生疑惑,但是为了要多学习,多进步,还是把这个问题记录一下: 一个文件里有许多的函数.一个函数执行完了,会执行到另外一个函数 ...

  5. javascript焦点图(能够自己主动切换 )

    /* 思路总结: 1.实现图片滚动的function.鼠标经时候获取当前li的index.设置ndex自己主动递增的函数.实现淡入淡出效果的函数 2.整个实现效果一传递index为主线 3.我的编写代 ...

  6. 什么是线程上下文的切换?

    什么是线程上下文的切换 对于单核CPU来说(对于多核CPU,此处就理解为一个核),CPU在一个时刻只能运行一个线程,当在运行一个线程的过程中转去运行另外一个线程,这个叫做线程上下文切换(对于进程也是类 ...

  7. 6.windows线程切换_主动切换

    ida 分析KiSwapThread sub esp, 10h mov [esp+10h+var_4], ebx ;保存当前线程寄存器现场 mov [esp+10h+var_8], esi mov [ ...

  8. Spring Boot 动态数据源(多数据源自己主动切换)

    本文实现案例场景: 某系统除了须要从自己的主要数据库上读取和管理数据外.另一部分业务涉及到其它多个数据库,要求能够在不论什么方法上能够灵活指定详细要操作的数据库. 为了在开发中以最简单的方法使用,本文 ...

  9. 总结:线程间频繁切换为什么耗费资源?

    2019独角兽企业重金招聘Python工程师标准>>> 因为线程切换的时候,CPU需要将此线程的所有执行状态保存起来,如线程编号,执行到的位置等,然后再去执行其它线程. 转载于:ht ...

最新文章

  1. Hexo 个人博客 SEO 优化(3):改造你的博客,提升搜索引擎排名
  2. Service Worker ——这应该是一个挺全面的整理
  3. 理解 e.clientX,e.clientY e.pageX e.pageY e.offsetX e.offsetY
  4. android文件系统\busybox文件系统的启动介绍
  5. Haproxy + Pacemaker 实现高可用负载均衡(二)
  6. mysql+phpmyadmin配置流程
  7. acer软件保护卡清除工具clear_使用Windows 10内置工具释放硬盘空间的最佳方法
  8. 球谐函数的概念与应用:可视化理解傅里叶级数
  9. 苹果mac误删文件怎样快速找回?
  10. Acwing 1243 糖果 - IDA*估值函数
  11. 基于HMM的语音识别技术原理
  12. 【python-NOJ-季总结】—【第八季:Pandas库】—表格Dataframe的建立和使用
  13. 贵圈似乎有点乱:“5G手机”居然比5G网络先到了?
  14. 【JAVA自学笔记 DAY01】Java基础入门
  15. 什么是二极管钳位电路
  16. 后端再进阶一步,MySQL 优化学习第1天
  17. mongo如何删除数据后相应的删除空间和内存占用
  18. 今天组里新入职一个31岁的校招生
  19. ECharts 之引用ECharts
  20. MATLAB利用均值滤波的方法去除图像的噪声,将滤除噪声前后的图像输出。

热门文章

  1. java面试题答案大全超详细(持续更新)
  2. 修复AirPods不断与iPhone断开连接的10种方法
  3. 输入摄氏度温度值,转化为华氏温度值并输出
  4. 从100个男人里面挑选37个, 问这里面存在最优秀的男人的概率是多少?
  5. 2005年感悟做男人100条
  6. 创业篇之四:宗教式的团队
  7. 乾胤电商:2022拼多多白底图怎么拍?
  8. 设置电子围栏 高德地图_地理围栏-辅助功能-开发指南-iOS 定位SDK | 高德地图API...
  9. 计算机老师中专教学论文,中职计算机教学中的应用论文
  10. 微信三方登录与注册逻辑处理