欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]利用内核知识,自己实现ReadProcessMemory

[原创]利用内核知识,自己实现ReadProcessMemory

前言

转眼来到科锐学习已经超过一年的时间了,眼看三阶段已经进入尾声,内核的学习也快要结束,记录一下笔记和心得,也给刚接触的朋友做一个参考。当然,学习新知识最好的办法就是带着目的来学习,所以在文章后半部分,介绍如何自己实现了Windows的一个API:ReadProcessMemory,为什么要选这个API呢?首先在软件保护上,任何开发者都不会希望别人可以随意查看自己的内存内容,于是多数人会选择在这个函数上挂钩,监视并保护内存,那么我们可以绕过他的保护,用自己的函数来查看进程内存。

本篇文章主要涉及两个部分:
  • 介绍内核基础知识
  • 自己实现ReadProcessMemory

环境介绍:真机64位Windows10,虚拟机:32位XP_sp3

学习内核的本质其实是学习操作系统的原理,而学习的过程应该是从CPU架构出发,操作系统作为使用CPU提供功能的例子。

第一部分:内核基础知识

内核可以分成两类:

  • 宏内核:追求性能,大部分系统代码放在0环,代表:Linux
  • 微内核:追求维护性,大部分系统代码在3环,代表:Minix(Linux作者老师的作品),其中著名的设计:动态链接库,在Windows中也使用

Windows算是微内核和宏内核特点都具有的操作系统。

80x86处理器的工作模式:

8086处理器有三种工作模式,分别是:实模式,保护模式,虚拟86模式,其中关系为:

16位汇编中 iret可以进入保护模式。

分段式内存管理

如何保证操作内存的动作是否合法?

GDT、LDT

操作系统通电后进入实模式,做了一系列初始化的动作后进入到保护模式,在保护模式中,CPU执行所有和内存有关的操作都会通过查表来确定操作是否合法,这个表就是GDT和LDT表,表的格式由CPU厂商决定,所以为了能兼容多款CPU,操作系统代码里多用条件宏来实现。

地址的转换

  • 逻辑地址:在程序调试中见到的地址,实际上是:段+偏移的形式
  • 线性地址:逻辑地址转物理地址的中间层,逻辑地址是段中的偏移地址然后加上基地址就是线性地址。
  • 物理地址:物理内存条上的真实地址

逻辑地址如何转换到物理地址?

首先通过逻辑地址的偏移查第一次表得到线性地址,再查第二次表得到物理地址。为什么要查第二次表呢?因为第二张表实际上是为了实现虚拟内存,那么就是说这段内存可能是在磁盘上的,访问的时候会先查表,然后从磁盘上调到内存中,有些情况下(关闭了虚拟内存)查第一次表的结果等价于物理地址。

为什么要叫线性地址?

从逻辑地址转换到线性地址,是一块平坦且连续的地址,实际上对应到物理地址上,并不是连续的。

如何计算线性地址的范围?

例如:

  • 设段A的基地址等于00012345H,段界限等于5678H,并且段界限以字节为单位(G=0),那么段A对应线性地址空间中从00012345H-000179BDH的区域。
  • 如果段界限以4K字节为单位 (G=1),那么段A对应线性地址空间中从00012345H-0568B344H(=00012345H+5678000H+0FFFH) 的区域。

如何从逻辑地址 ===查表===>> 线性地址?

这个表也叫做分段表,结构如下图:

这种奇葩的做法来源于为了兼容286的历史遗留问题。

描述符

用于表示上述定义段的三个参数的数据结构称为描述符。每个描述符长8个字节。在保护方式下,每一个段都有一个相应的描述符来描述。

存储段描述符

存储段是存放可由程序直接进行访问的代码和数据的段。存储段描述符描述存储段,所以存储段描述符也被称为代码和数据段描述符。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功