x64内核实验7-线程

news2024/12/23 14:58:56

x64内核实验7-线程

TOC
线程是比较重要的内核结构,思考一下其实可以想到线程结构体在64位下的变化应该不会很大最多只是扩充了一些内容,因为从我们之前分析段页时候会发现cpu更新的这些内容大部分不影响xp时候的线程切换机制,下面我们来验证一下

线程结构体介绍

ETHREAD和KPCR都有点大就不全贴出来了只说一些常用的字段,一般熟悉了内核机制的话看名字很多都能猜出来

KTHREAD + 0x000     struct _DISPATCHER_HEADER Header;   跟之前的进程结构体一样是可等待对象都有的头部结构体
KTHREAD + 0x018    VOID*        SListFaultAddress   上一次用户模式互锁单链表POP操作发生页面错误的地址。
KTHREAD + 0x028     VOID*        InitialStack;            内核栈的原始栈位置(高地址)
KTHREAD + 0x030     VOID*        StackLimit;             内核栈低地址
KTHREAD + 0x038    VOID*        StackBase;              内核栈的栈基址
KTHREAD + 0x058    VOID*        KernelStack;            内核调用栈开始位置
KTHREAD + 0x0C8     INT64        WaitStatus            等待的结果状态
KTHREAD + 0x0F0     VOID*        Teb                         三环使用的线程环境块
----------------------------------Apc相关的后面说Apc时候会讲
KTHREAD + 0x098      ApcState         _KAPC_STATE        ApcState结构体
KTHREAD + 0x258     SavedApcState   KAPC_STATE    备份ApcState结构体
KTHREAD + 0x24a     ApcStateIndex    UChar                索引ApcState时候用的
----------------------------------Apc相关的后面说Apc时候会讲
KTHREAD + 0x184     State             UChar                    线程当前状态
KTHREAD + 0x090     TrapFrame    _KTRAP_FRAME            指向Trap_Frame结构体
KTHREAD + 0x232     PreviousMode   Char                存储了当前线程之前的模式是内核模式还是用户模式
KTHREAD + 0x2f8     ThreadListEntry  _LIST_ENTRY            KTHREAD里的双向链表串起当前进程的所有线程



ETHREAD + 0x4e8     ThreadListEntry  _LIST_ENTRY         在Ethread里的这个链表也是圈起来了当前进程所有的线程
ETHREAD + 0x478     Cid              _CLIENT_ID        线程的Cid
ETHREAD + 0x220     Process          Ptr64 _KPROCESS        指向当前进程结构体


KPCR结构体介绍

KPCR是cpu控制区,一个核心一个KPCR对象,里面存放的大多是cpu相关的一些数据以及进程线程相关的一些常用数据
因为0环时候gs:0指向它所以无论在那个内核函数里都能很快的访问到这个结构体
KPCR和NTTIB比较小直接全贴出来了

0: kd> dt _NT_TIB
ntdll!_NT_TIB
   +0x000 ExceptionList    : Ptr64 _EXCEPTION_REGISTRATION_RECORD        当前的0环异常链表
   +0x008 StackBase        : Ptr64 Void                                   从线程里复制出来的栈位置
   +0x010 StackLimit       : Ptr64 Void                                    从线程里复制出来的栈低地址
   +0x018 SubSystemTib     : Ptr64 Void
   +0x020 FiberData        : Ptr64 Void
   +0x020 Version          : Uint4B
   +0x028 ArbitraryUserPointer : Ptr64 Void
   +0x030 Self             : Ptr64 _NT_TIB                            指向自己

0: kd> dt _KPCR
ntdll!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 GdtBase          : Ptr64 _KGDTENTRY64
   +0x008 TssBase          : Ptr64 _KTSS64                            指向Tss
   +0x010 UserRsp          : Uint8B                                    指向用户层的栈
   +0x018 Self             : Ptr64 _KPCR                                指向自己
   +0x020 CurrentPrcb      : Ptr64 _KPRCB                               指向自己的KPRCB的位置
   +0x028 LockArray        : Ptr64 _KSPIN_LOCK_QUEUE                    
   +0x030 Used_Self        : Ptr64 Void
   +0x038 IdtBase          : Ptr64 _KIDTENTRY64                            指向IDT表基址
   +0x040 Unused           : [2] Uint8B                            
   +0x050 Irql             : UChar                                         存储了当前的irql
   +0x051 SecondLevelCacheAssociativity : UChar        
   +0x052 ObsoleteNumber   : UChar    
   +0x053 Fill0            : UChar
   +0x054 Unused0          : [3] Uint4B
   +0x060 MajorVersion     : Uint2B
   +0x062 MinorVersion     : Uint2B
   +0x064 StallScaleFactor : Uint4B
   +0x068 Unused1          : [3] Ptr64 Void
   +0x080 KernelReserved   : [15] Uint4B
   +0x0bc SecondLevelCacheSize : Uint4B
   +0x0c0 HalReserved      : [16] Uint4B
   +0x100 Unused2          : Uint4B
   +0x108 KdVersionBlock   : Ptr64 Void
   +0x110 Unused3          : Ptr64 Void
   +0x118 PcrAlign1        : [24] Uint4B
   +0x180 Prcb             : _KPRCB                                下面是KPRCB一个很大的结构体

KPRCB有点大只介绍常用的字段了

KPRCB + 0x008 CurrentThread    : Ptr64 _KTHREAD  当前线程
KPRCB + 0x004 LegacyNumber     : UChar             是否是兼容模式,兼容模式时候启动是是32位内核了
KPRCB + 0x010 NextThread       : Ptr64 _KTHREAD    下一个线程
KPRCB + 0x018 IdleThread       : Ptr64 _KTHREAD    空闲线程,一般cpu空闲时候就会执行这个线程
KPRCB + 0x028 RspBase          : Uint8B            内核栈
KPRCB + 0x8e88 RspBaseShadow    : Uint8B            kpti开启时候使用的跳板0环栈
KPRCB + 0x8e90 UserRspShadow    : Uint8B            3环栈
KPRCB + 0x7e9a DeepSleep        : UChar             深睡眠模式,在线程切换时候会查询不过不用太多关注跟硬件也有关系
KPRCB + 0x7e80 InterruptCount   : Uint4B            中断次数,在下面的逆向代码里能看到增加这个中断次数的代码
KPRCB + 

寻找线程切换函数

根据白皮书里描述30号中断为时钟中断,线程切换一定跟时钟中断相关,那么我们就先找一下时钟中断的函数叫什么

1: kd> !idt 30

Dumping IDT: ffffba81de9d5000

30:	fffff80281402230 nt!KiHvInterrupt

通过在windbg里查看可以知道时钟中断函数是KiHvInterrupt,我们到ida里搜一下可以搜到下面几个
在这里插入图片描述

因为我的虚拟机环境默认是没开kpti的所以中断函数直接指向了KiHvInterrupt如果开了的话则是指向KiHvInterruptShadow,不过不要紧我们之前分析过int 3的那个Shadow函数这个KiHvInterruptShadow跟那个基本一样,我这里只贴个图上来就不详细说这个跳板函数了
在这里插入图片描述

下面我们就看一下这个KiHvInterrupt函数
一开始就还是熟悉的保存trapframe流程
在这里插入图片描述

中间是硬件相关的一堆调用不管
在这里插入图片描述

然后就是存浮点相关,之后是一些检测然后增加中断次数跳到KiHvInterruptDispatch
我们再看一下KiHvInterruptDispatch
在这里插入图片描述

我们再看一下KiDpcInterruptBypass
在这里插入图片描述

又调用了KiDispatchInterrupt
在这里插入图片描述

在跟进去会发现我们要找的函数,swapContext
在这里插入图片描述

swapContext就是我们要找的线程切换函数
现在我们记录一下win10系统下时钟中断进入线程切换的函数调用流程吧

  1. KiHvInterruptShadow(开了kpti的话有这一步)
  2. KiHvInterrupt
  3. KiHvInterruptDispatch
  4. KiDpcInterruptBypass
  5. KiDispatchInterrupt
  6. KxDispatchInterrupt
  7. SwapContext

这个流程里有大量的代码有兴趣深入研究的可以按照这个流程看一下,线程切换涉及到了很多系统内核的其他内容我们这里下面直接分析SwapContext

线程切换函数逆向分析

先看一下进入SwapContext之前都传了那些参数进来,可以看到先是调用KiQueueReadyThread找到要切换的线程
大家可以自己到这个函数里分析一下
从KiDpcInterruptBypass这里开始看

在这里插入图片描述

现在的寄存器值是
rsp = trapframe
rbp =TRAP_FRAME + 80
rcx = CurrentThread
然后走到KiDispatchInterrupt
在这里插入图片描述

看图中圈出来的位置,rsp在调用KxDispatchInterrupt之前又恢复成了trapframe,所以现在的寄存器状态还是
rsp = trapframe
rbp = TRAP_FRAME + 80
rcx = CurrentThread
rbx = kpcr + 20

在这里插入图片描述

再看一下SwapContext都干了什么,我这里不一行一行去说了这个函数超级长,我把主要流程截图出来大家最好自己去逆一下会有自己的理解
先是判断要切换的线程是不是就是当前线程,是的话就不处理了,不是的话走下面更改线程状态
在这里插入图片描述

在这里插入图片描述

这里是切换线程的栈
在这里插入图片描述

判断俩线程是不是同一个进程不是的话要切换cr3
在这里插入图片描述

在这里插入图片描述

走到这里再往下就是收尾的动作了,就是复制进程和线程内容到kpcr里的过程
在这里插入图片描述

总结

我们最后总结一下
线程切换的流程(这个总体流程跟xp时候差不多只不过调用的函数链路变了而且多了不少的检测和动作):

  1. 当前线程保存上下文环境到内核栈
  2. 找到一个就绪线程
  3. 切换线程的内核栈
  4. 如果需要切换cr3就切换
  5. 复制信息到kpcr,比如线程结构体里的内核栈位置或者往tss里存进0环时候要用的ist0
  6. 从刚切换的线程内核栈里恢复上下文环境

触发线程切换的条件(这里只带大家看了时钟中断其他的几个场景大家可以自己去验证一下):

  1. 时钟中断
  2. 缺页异常
    环境到内核栈
  3. 找到一个就绪线程
  4. 切换线程的内核栈
  5. 如果需要切换cr3就切换
  6. 复制信息到kpcr,比如线程结构体里的内核栈位置或者往tss里存进0环时候要用的ist0
  7. 从刚切换的线程内核栈里恢复上下文环境

触发线程切换的条件(这里只带大家看了时钟中断其他的几个场景大家可以自己去验证一下):

  1. 时钟中断
  2. 缺页异常
  3. 系统api出0环

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1066880.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无法打开软件,因为计算机中找不到MSVCP140.dll的解决方法

msvcp140.dll是Microsoft Visual C 2015 Redistributable的一个动态链接库文件,它是Microsoft Visual Studio 2015的一部分。这个文件包含了许多用于运行C程序所需的运行时函数和数据。当计算机上安装了Visual Studio 2015或更高版本时,msvcp140.dll文件…

嵌入式Linux裸机开发(四)IMX6U主频和时钟配置

系列文章目录 文章目录 系列文章目录介绍时钟来源PLL时钟源内核时钟PFD时钟AHB、 IPG 和 PERCLK 根时钟设置 结语 介绍 默认配置下 I.MX6U 工作频率为 396MHz,但该系列标准工作频率事528MHz,有些型号甚至可以工作到696MHz。 默认情况下内部 boot rom 会…

阿里云服务器ECS经济型e实例租用价格表

阿里云服务器e系列优惠价格:2核2G配置182元一年、2核4G配置365元一年、2核8G配置522元一年,e系列即ECS经济型e实例,CPU采用Intel Xeon Platinum可扩展处理器,系统盘支持ESSD Entry云盘(推荐)、ESSD云盘、ES…

【SpringBoot】| Thymeleaf 模板引擎

目录 Thymeleaf 模板引擎 1. 第一个例子 2. 表达式 ①标准变量表达式 ②选择变量表达式(星号变量表达式) ③链接表达式(URL表达式) 3. Thymeleaf的属性 ①th:action ②th:method ③th:href ④th:src ⑤th:text ⑥th:…

【yolo系列:yolov7改进wise-iou】

yolo系列文章目录 学习视频: YOLOV7改进-Wise IoU_哔哩哔哩_bilibili 代码地址: objectdetection_script/yolov7-iou.py at master z1069614715/objectdetection_script (github.com) 文章目录 yolo系列文章目录一、在yolov7之上进行替换二、在loss.p…

双馈风力发电机-900V直流混合储能并网系统Simulink仿真

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

C++默认参数(实参)

在本文中,您将学习什么是默认参数,如何使用它们以及使用它的必要声明。在C 编程中,您可以提供函数参数的默认值。默认参数背后的想法很简单。如果通过传递参数调用函数,则这些参数将由函数使用。但是,如果在调用函数时…

几道web题目

总结几道国庆写的web题目 [ACTF2020 新生赛]Include1 点进去发现就一个flag.php,源代码和抓包都没拿到好东西 结合题目猜是文件包含,构建payload ?filephp://filter/readconvert.base64-encode/resourceflag.php 得到base64编码过的flag,解码即可 此题…

榜单发布!AR-HUD进入LCoS时代,哪些企业正在领跑

高工智能汽车研究院监测数据显示,今年1-7月中国市场(不含进出口)乘用车前装标配W/AR HUD交付108.35万辆,同比增长47.98%,前装搭载率升至9.82%。 其中,从价位区间分布来看,30万元及以上车型标配W…

【Overload游戏引擎分析】画场景栅格的Shader分析

Overload引擎地址: GitHub - adriengivry/Overload: 3D Game engine with editor 一、栅格绘制基本原理 Overload Editor启动之后,场景视图中有栅格线,这个在很多软件中都有。刚开始我猜测它应该是通过绘制线实现的。阅读代码发现&#xff0…

2023年,有哪些好用的互联网项目管理软件?

项目管理是为了使工作项目能够按照预定的需求、成本、进度、质量顺利完成,而对人员、产品、过程和项目进行分析和管理的活动。 一直以来,项目管理被企业管理人员和各级人员所重视,项目管理是一个项目的灵魂,只有做好了项目管理&am…

IO流 Java

IO 字节输入流 1:我使用while遍历 用循环来遍历文件里的数据 读取性能很差 读取汉字和维语字 会乱码 无法避免的 流使用完毕之后 必须关闭 释放系统资源 out.close();//关闭流 package IO_TEST;import java.io.File; import java.io.FileInputStream;import java…

用《斗破苍穹》的视角打开C#委托2 委托链 / 泛型委托 / GetInvocationList

委托链 经过不懈地努力,我终于成为了斗师,并成功掌握了两种斗技——八极崩和焰分噬浪尺。于是,我琢磨着,能不能搞一套连招,直接把对方带走。 using System; using System.Collections.Generic; using System.Linq; u…

项目环境搭建

注册中心网关配置 spring:cloud:gateway:globalcors:add-to-simple-url-handler-mapping: truecorsConfigurations:[/**]:allowedHeaders: "*"allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTIONroutes:# 平台管理- id: useruri: lb://…

基于SpringBoot的植物健康系统

目录 前言 一、技术栈 二、系统功能介绍 系统首页 咨询专家 普通植物检查登记 珍贵植物检查登记 植物救治用料登记 植物救治材料管理 植物疾病案例管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&am…

使用MATLAB进行傅里叶变换

1、定义 T1;% 周期0-1 N20;% 最大谐波 k-N:N;% -20:20——-20表示a_(20)e^(j*20*w0*t) N1length(k);%N141 % ceil(N1/2)21%即21是N1的中位数tlinspace(0,T,100); Ntlength(t); ttlinspace(-4*T,4*T,1024); Nttlength(tt);2、原函数 w02*pi/T; % 0-T xt(t>T/4).* 1.0; fig…

支付宝sdk商户私钥 如何生成?

1、先下载密钥工具 https://opendocs.alipay.com/isv/02kipk 2、安装后生成密钥 3、配置密钥 4、将工具生成的公钥复制进去生成公钥 简单来说就是私钥是用工具生成的,不会在页面上显示 商户私钥 支付宝公钥

Python-Scrapy框架(框架学习)

一、概述 Scrapy是一个用于爬取网站数据的Python框架,可以用来抓取web站点并从页面中提取结构化的数据。 基本组件: 引擎(Engine):负责控制整个爬虫的流程,包括调度请求、处理请求和响应等。 调度器(Scheduler):负责…

基于SSM的资源共享平台设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

基于YOLOv8模型的车载摄像头下车辆目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要:基于YOLOv8模型的车载摄像头下车辆目标检测系统可用于日常生活中检测与定位车辆目标,利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算…