文章目录

  • 进程挂靠
    • 进程与线程的关系
    • 线程与进程如何关联
    • 为什么需要ApcState.Process
    • CR3的值可以随便改吗
    • 分析NtReadVirtualMemory函数
    • 总结
  • 跨进程读写内存
    • 跨进程操作
    • NtReadVirtualMemory流程解析

进程挂靠

进程与线程的关系

一个进程可以包含多个线程

一个进程至少要有一个线程

进程为线程提供资源,也就是提供CR3的值,CR3中存储的是页目录表的基址,CR3确定了线程能访问的内存也就确定了

mov eax,dowrd ptr ds:[0x12345678]

CPU如何解析0x12345678这个地址呢?

  1. CPU解析线性地址时要通过页目录表来找到对应的物理页,页目录表基址存在CR3寄存器中
  2. 当前的CR3的值来源于当前的进程(_KPROCESS.DirectoryTableBase(+0x018))

线程与进程如何关联

ETHREAD结构体:+0x034 ApcState+0x000 ApcListHead +0x010 Process +0x014 KernelApcInProgress+0x015 KernelApcPending+0x016 UserApcPending+0x220 ThreadsProcess

ETHREAD结构体+0x220的位置存储的就是当前线程所属的进程。

另外在KTHREAD结构体0x34的位置是子结构体ApcState,ApcState也有一个成员Process指向了当前线程所属的进程。

这就存在一个问题,同一个线程结构体里存了两份指针,这两份指针代表什么?

为什么需要ApcState.Process

下面分析SwapContext函数:

这里首先取出目标线程的ApcState.Process存到eax里,然后比较当前线程的ApcState.Process和目标线程的这个成员是否相同,如果不相同就说明不属于同一个进程

代码继续往下走,就会切换CR3的值

线程切换的时候,会比较KTHREAD结构体0x044处指定的EPROCESS是否为同一个,如果不是同一个,会将eax的值取出,赋给CR3。eax此时存储的是目标线程的ApcState.Process。这个时候就发生了进程切换

所以,线程需要的CR3的值来源于0x44处偏移指定的EPROCESS

总结:

0x220亲生父母:这个线程谁创建的

0x44 养父母:谁在为这个线程提供资源,也就是提供CR3

一般情况下,0x220与0x44指向的是同一个进程

CR3的值可以随便改吗

正常情况下,CR3的值是由养父母提供的,但CR3的值也可以改成和当前线程毫不相关的其他进程的DirectoryTableBase

线程代码:

mov cr3,A.DirectoryTableBase
mov eax,dword ptr ds:[0x12345678]       //A进程的0x12345678内存
mov cr3,B.DirectoryTableBase
mov eax,dword ptr ds:[0x12345678]       //B进程的0x12345678内存
mov cr3,C.DirectoryTableBase
mov eax,dword ptr ds:[0x12345678]       //C进程的0x12345678内存

将当前cr3的值改为其他进程,称为进程挂靠

分析NtReadVirtualMemory函数

接下来就通过分析NtReadVirtualMemory函数,来看看是怎么读取其他进程的内存。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hprSWzoq-1581511027410)(assets/1581507589446.png)]

首先找到NtReadVirtualMemory函数

这个函数在内部调用了MmCopyVirtualMemory,继续跟进

真正COPY的函数是MiDoMappedCopy,继续跟进

在开始读取之前先调用了KeStackAttachProcess,也就是之前说过的进程挂靠,继续

这个函数又继续调用了KiAttachProcess,继续跟进

这里先将该线程的+0x44位置的ApcState.Process修改为要读取的进程的KPROCESS

然后又调用KiSwapProcess,真正的挂靠是通过这个函数实现的,继续跟进

真正关键的代码是上面两行,首先取出要读取进程的CR3,+0x18的位置是DirectoryTableBase页目录表基址,然后修改CR3为要读取进程的CR3

NtReadVirtualMemory流程总结

  1. NtReadVirtualMemory
  2. MmCopyVirtualMemory
  3. MiDoMappedCopy
  4. KeStackAttachProcess
  5. KiAttachProcess 修改当前线程的ApcState.Process为要挂靠的进程
  6. KiSwapProcess修改CR3为要挂靠的进程的CR3

既然修改CR3就可以读取目标进程的内存,那么NtReadVirtualMemory可不可以只修改CR3,不修改当前线程的ApcState.Process为要挂靠的进程。

答案是不可以。

回顾一下之前的为什么需要ApcState.Process的问题就会发现,当调用SwapContext进行线程切换的时候,给CR3赋值的时候赋的是ApcState.Process的值。

如果没有修改ApcState.Process,那就意味着ApcState.Process指向的不是挂靠的进程,而是自己的父进程,一旦这个时候发生线程切换并且在线程切换回来的时候,NtReadVirtualMemory读取的就是自己进程的内存了。

如果我们自己来写这个代码,在切换CR3后关闭中断,并且不调用会导致线程切换的API,就可以不用修改养父母的值

总结

正常情况下,当前线程使用的CR3是由其所属进程提供的(ETHREAD 0x44偏移处指定的EPROCESS),正因为如此,A进程中的线程只能访问A进程的内存

如果要让A进程中的内容能够访问B进程的内存,就必须修改CR3的值为B进程的页目录表基址(DirectoryTableBase),这就是所谓的进程挂靠

跨进程读写内存

跨进程的本质就是进程挂靠,也就是修改CR3的值为目标进程的页目录表基址

跨进程操作

A进程中的线程代码

mov cr3,B.DirectoryTableBase         //切换Cr3的值为B进程
mov eax,dword ptr ds:[0x12345678]       //将进程B 0x12345678的值存的eax中
mov dword ptr ds:[0x00401234],eax       //将数据存储到0x00401234中
mov cr3,A.DirectoryTableBase            //切换回Cr3的值

这段代码的问题在于,当我切换CR3为B进程的页目录基址时,读取的是B进程的内存,那么读取的这段数据该如何传递给A进程呢?不管将这段数据放在哪个位置,始终都是B进程的内存空间。

这里需要回顾一下进程的地址空间管理,低2GB是每个进程私有的,而高2GB的操作系统共享的。如果在B进程将读取的数据放到高2GB共享的内核空间,然后在切回CR3的时候,从高2GB取数据,就解决了这个问题

NtReadVirtualMemory流程解析

我们来看一下NtReadVirtualMemory是如何解决这个问题的:

  1. 首先切换CR3为目标进程的页目录基址
  2. 接着将数据复制到高2GB的某一个位置
  3. 然后切回CR3
  4. 最后从高2GB复制到目标位置

NtWriteVirtualMemory和NtReadVirtualMemory的执行流程类似

进程线程007 进程挂靠与跨进程读写内存相关推荐

  1. Linux的进程/线程/协程系列4:进程知识深入总结:上篇

    Linux的进程/线程/协程系列4:进程/线程相关知识总结 前言 本篇摘要: 1. 进程基础知识 1.1 串行/并行与并发 1.2 临界资源与共享资源 1.3 同步/异步与互斥 1.4 进程控制原语 ...

  2. linux的进程/线程/协程系列1:进程到协程的演化

    linux的进程/线程/协程系列1:进程到协程的演化 前言 摘要: 1. 一些历史:批处理时代 2. 现代操作系统启动过程 3. 进程(process)的出现 4. 线程(thread)与线程池 5. ...

  3. java 进程 线程数量_如何查询一个进程下面的线程数(进程和线程区别)

    在平时工作中,经常会听到应用程序的进程和线程的概念,那么它们两个之间究竟有什么关系或不同呢? 一.对比进程和线程 1)两者概念 -  进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程 ...

  4. python进程线程协程区别_Python中 进程 线程 协程

    一.进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在 ...

  5. java基础巩固-宇宙第一AiYWM:为了维持生计,四大基础之OS_Part_1整起(进程线程协程并发并行、进程线程切换进程间通信、死锁\进程调度策略、分段分页、交换空间、OS三大调度机制)

    PART0:OS,这货到底是个啥? OS,是个啥? OS的结构们: 存储器: 存储器的层次结构: 内存:我们的程序和数据都是存储在内存,我们的程序和数据都是存储在内存,每一个字节都对应一个内存地址.内 ...

  6. android任务 进程 线程详解,Android任务、进程、线程详解

    singleTop模式,基本上于standard分歧,仅正在请求的Activity反好位于栈顶时,无所区别.此时,配放成singleTop的Activity,不再会构制新的实例加入到Task栈外,而是 ...

  7. c语言面试进程 线程区别,面试必问题目“进程、线程对比”,包你会-博客

    简要说明 在C语言.C++等方向面试时,经常会被问道 进程.线程等问题,当然了10年前我刚开始找工作那会,也是各种煎熬"我又不写操作系统,为什么还要学这么底层的知识",真想不通面试 ...

  8. windows内核情景分析---进程线程2

    二.线程调度与切换 众所周知:Windows系统是一个分时抢占式系统,分时指每个线程分配时间片,抢占指时间片到期前,中途可以被其他更高优先级的线程强制抢占. 背景知识:每个cpu都有一个TSS,叫'任 ...

  9. Android 跨进程通信大总结

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/111553746 本文出自[赵彦军的博客] 文章目录 1.Android进程 2.修 ...

最新文章

  1. ubuntu10.10+android 搭建Opencv
  2. javaScript 实现多选框全选/反选及批量删除
  3. bootstrap模态框
  4. 阿卡接口_阿卡vs风暴
  5. ContextLoaderListener介绍
  6. HTML5 Canvas 裁剪区域
  7. 原创:关于Zend Studio 11.0.2使用localhost无法打开问题,附解决步骤
  8. 可能是全网最全的 Java 日志框架适配、冲突解决方案
  9. 蓝桥杯 BASIC-3 基础练习 字母图形
  10. C#基础知识梳理系列七:字符串
  11. ie浏览器升级的正确姿势
  12. Linux 学习笔记 (一)
  13. iPhone屏幕尺寸
  14. 2440 led-管道-控制应用程序详细解释(摘抄+解释部分)
  15. 国产_系统_加油 by tmddebaba
  16. 瘦了红颜, 多了寂寞
  17. 程序员得浪漫--十款表白小程序 一个比一个浪漫 赶紧收藏起来吧!!!
  18. layui之动态树形菜单
  19. Matlab 科研绘图汇总
  20. 数据库之考勤管理系统

热门文章

  1. 成功解决Exception unhandled AttributeError 'MainWindow' object has no attribute 'setDaemon'
  2. DayDayUp:2019.12.30吴晓波2020年终秀演讲《预见2020:来海边,拾起信心》读后有感
  3. Algorithm:【Algorithm算法进阶之路】之数据结构基础知识
  4. ML之回归预测:利用两种机器学习算法(LiR,XGBoost(调优+重要性可视化+特征选择模型))对无人驾驶汽车系统参数(2017年的data,18+2)进行回归预测值VS真实值
  5. TF之LSTM:利用LSTM算法对Boston(波士顿房价)数据集【13+1,506】进行回归预测(房价预测)
  6. 成功解决ModuleNotFoundError: No module named 'dataset'
  7. MVC案例——模糊查询
  8. centos 7 Chrony 集群同步时间
  9. P2730 魔板 Magic Squares (搜索)
  10. 《团队-团队编程项目作业名称-团队信息》