线程的主动切换——KiSwapThreadKiSwapContext逆向
线程的切换分为主动切换和被动切换两种方式
主动切换主要是通过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逆向相关推荐
- java 切换主线程_Java线程状态及切换、关闭线程的正确姿势分享
前言 在讲线程之前有必要讨论一下进程的定义:进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位.进程实体由程序段, 数据段 PCB(进程控制块)组成.线程又是什么?线程可以 ...
- java焦点图_javascript焦点图(能够自己主动切换 )
/* 思路总结: 1.实现图片滚动的function.鼠标经时候获取当前li的index.设置ndex自己主动递增的函数.实现淡入淡出效果的函数 2.整个实现效果一传递index为主线 3.我的编写代 ...
- 从0到1写RT-Thread内核——线程定义及切换的实现
从0写RT-Thread内核之线程定义及切换的实现具体可以分为以下六步来实现 一:分别定义线程栈.线程函数.线程控制块: ALIGN(RT_ALIGN_SIZE)//设置4字节对齐 /* 定义线程栈 ...
- Vrep线程之间的切换
在使用vrep的thread scirpt的时候我竟然会对这么简单的一个问题产生疑惑,但是为了要多学习,多进步,还是把这个问题记录一下: 一个文件里有许多的函数.一个函数执行完了,会执行到另外一个函数 ...
- javascript焦点图(能够自己主动切换 )
/* 思路总结: 1.实现图片滚动的function.鼠标经时候获取当前li的index.设置ndex自己主动递增的函数.实现淡入淡出效果的函数 2.整个实现效果一传递index为主线 3.我的编写代 ...
- 什么是线程上下文的切换?
什么是线程上下文的切换 对于单核CPU来说(对于多核CPU,此处就理解为一个核),CPU在一个时刻只能运行一个线程,当在运行一个线程的过程中转去运行另外一个线程,这个叫做线程上下文切换(对于进程也是类 ...
- 6.windows线程切换_主动切换
ida 分析KiSwapThread sub esp, 10h mov [esp+10h+var_4], ebx ;保存当前线程寄存器现场 mov [esp+10h+var_8], esi mov [ ...
- Spring Boot 动态数据源(多数据源自己主动切换)
本文实现案例场景: 某系统除了须要从自己的主要数据库上读取和管理数据外.另一部分业务涉及到其它多个数据库,要求能够在不论什么方法上能够灵活指定详细要操作的数据库. 为了在开发中以最简单的方法使用,本文 ...
- 总结:线程间频繁切换为什么耗费资源?
2019独角兽企业重金招聘Python工程师标准>>> 因为线程切换的时候,CPU需要将此线程的所有执行状态保存起来,如线程编号,执行到的位置等,然后再去执行其它线程. 转载于:ht ...
最新文章
- Hexo 个人博客 SEO 优化(3):改造你的博客,提升搜索引擎排名
- Service Worker ——这应该是一个挺全面的整理
- 理解 e.clientX,e.clientY e.pageX e.pageY e.offsetX e.offsetY
- android文件系统\busybox文件系统的启动介绍
- Haproxy + Pacemaker 实现高可用负载均衡(二)
- mysql+phpmyadmin配置流程
- acer软件保护卡清除工具clear_使用Windows 10内置工具释放硬盘空间的最佳方法
- 球谐函数的概念与应用:可视化理解傅里叶级数
- 苹果mac误删文件怎样快速找回?
- Acwing 1243 糖果 - IDA*估值函数
- 基于HMM的语音识别技术原理
- 【python-NOJ-季总结】—【第八季:Pandas库】—表格Dataframe的建立和使用
- 贵圈似乎有点乱:“5G手机”居然比5G网络先到了?
- 【JAVA自学笔记 DAY01】Java基础入门
- 什么是二极管钳位电路
- 后端再进阶一步,MySQL 优化学习第1天
- mongo如何删除数据后相应的删除空间和内存占用
- 今天组里新入职一个31岁的校招生
- ECharts 之引用ECharts
- MATLAB利用均值滤波的方法去除图像的噪声,将滤除噪声前后的图像输出。
热门文章
- java面试题答案大全超详细(持续更新)
- 修复AirPods不断与iPhone断开连接的10种方法
- 输入摄氏度温度值,转化为华氏温度值并输出
- 从100个男人里面挑选37个, 问这里面存在最优秀的男人的概率是多少?
- 2005年感悟做男人100条
- 创业篇之四:宗教式的团队
- 乾胤电商:2022拼多多白底图怎么拍?
- 设置电子围栏 高德地图_地理围栏-辅助功能-开发指南-iOS 定位SDK | 高德地图API...
- 计算机老师中专教学论文,中职计算机教学中的应用论文
- 微信三方登录与注册逻辑处理