Linux x64 -- 内核程序(驱动程序)读取任意进程数据实现
四级页表结构
现在的64位Linux系统中,并没有使用全部的64位地址空间,而是使用其低48位,高16位并没有使用.
其中
39至47这9位用于索引PGD(page global directory),其中读取的值是PUD(page upper directory)的地址
30至38这9位用于索引PUD以获取PMD(page middle directory)的地址
21至29这9位用于索引PMD以获取PTE(the lowest level page table)的地址
12至20这9位用于索引PTE以获数据所在物理page frame的地址
最后的12位是page frame 的偏移,用于定位具体的数据所在地址
图形表示如图:
注:
原来的三级页表为:PGD-->PMD-->PTE
二级页表为:PGD(PGD)-->PTE
获取系统的page size
$ getconf PAGE_SIZE
获取当前内核使用多少级的页表结构
通过编译内核的config文件,搜索CONFIG_PGTABLE_LEVELS,既可以知道使用的是多少级的页表结构
内核地址空间中物理地址与虚拟地址的转换
#include <asm/io.h>
static inline void *phys_to_virt(phys_addr_t address);//__pa
static inline phys_addr_t virt_to_phys(volatile void *address)__va
读取任意程序内存实现
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/mm_types.h>
#include <asm/pgtable.h>
static ulong data_addr = 0;
static int data_len = 0;
static int target_pid = 0;
module_param(data_addr,ulong,S_IRUGO);
module_param(data_len,int,S_IRUGO);
module_param(target_pid,int,S_IRUGO);
static int __init main_init(void)
{
struct task_struct *task;
char *vaddr;
int retval = 0;
int i = 0;
pgd_t *pgd = NULL;
pud_t *pud = NULL;
pmd_t *pmd = NULL;
pte_t *pte = NULL;
unsigned long paddr = 0;
unsigned long page_addr = 0;
unsigned long page_offset = 0;
if(data_addr == 0 || data_len == 0 || target_pid == 0){
printk("insmod main <data_addr=?> <data len=?> <target_pid=?>\n");
return 0;
}
printk("data_addr:0x%lX, data_len:%d, target_pid:%d\n",data_addr,data_len,target_pid);
for_each_process(task){
if(task->pid == target_pid)
{
printk("find task:%s\n",task->comm);
retval = 1;
break;
}
}
if(retval == 0){
printk("not find task\n");
return -1;
}
pgd = pgd_offset(task->mm,data_addr);
if(pgd_none(*pgd)){
printk("not mapped in pgd\n");
return -1;
}
pud = pud_offset((p4d_t*)pgd,data_addr);
if(pud_none(*pud)){
printk("not mapped in pud\n");
return -1;
}
pmd = pmd_offset(pud,data_addr);
if(pmd_none(*pmd)){
printk("not mapped in pmd\n");
return -1;
}
pte = pte_offset_kernel(pmd,data_addr);
if(pte_none(*pte)){
printk("not mapped in pte\n");
return -1;
}
page_addr = pte_val(*pte) & PTE_PFN_MASK;
page_offset = (data_addr) & (0xFFF);
paddr = page_addr | page_offset;
vaddr = __va(paddr);
for(i = 0;i<data_len;i++){
printk("0x%X('%c')\n",vaddr[i],vaddr[i]);
}
return 0;
}
static void __exit main_exit(void)
{
}
module_init(main_init);
module_exit(main_exit);
MODULE_LICENSE("GPL");
makefile:
obj-m := main.o
all:
make -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) modules
clean:
make -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) clean
参考资料
How The Kernel Manages Your Memory:
https://manybutfinite.com/post/how-the-kernel-manages-your-memory/
Five-level page tables:
https://lwn.net/Articles/717293/
Page Table Management:
https://www.kernel.org/doc/gorman/html/understand/understand006.html
Page table
https://github.com/lorenzo-stoakes/linux-vm-notes/blob/master/sections/page-tables.md
Virtual memory map
https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt
Linux 内存管理分析
https://www.jianshu.com/p/fc719d1cfbc2
Linux中的虚拟地址转换物理地址实现
http://lzz5235.github.io/2014/12/10/linux.html
Linux x64 -- 内核程序(驱动程序)读取任意进程数据实现的更多相关文章
- 12_通过 CR3 切换_读取指定进程数据
注意: cr3 切换 ,导致eip 指向的页面,改变为对应cr3 的页面:所以代码也变了:这里需要将这部分代码放入公共区域. 解决: 使用 类似前面 山寨 systemfastcallentry 的方 ...
- 一个I/O线程可以并发处理N个客户端连接和读写操作 I/O复用模型 基于Buf操作NIO可以读取任意位置的数据 Channel中读取数据到Buffer中或将数据 Buffer 中写入到 Channel 事件驱动消息通知观察者模式
Tomcat那些事儿 https://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng==&mid=2650860016&idx=2&sn=549 ...
- linux服务器开发二(系统编程)--进程相关
进程相关的概念 程序与进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(CPU.内存.打开的文件.设备.锁等等). 进程,是一个抽象的概念,与操作系统原理联系紧密.进程是活跃的程序,占用系 ...
- Linux下触摸屏驱动程序分析
[摘要: 本文以linux3.5--Exynos4412仄台,剖析触摸屏驱动焦点内容.Linux下触摸屏驱动(以ft5x06_ts为例)须要懂得以下学问: 1. I2C协定 2. Exynos4412 ...
- Linux中的两种守护进程stand alone和xinetd
Linux中的两种守护进程stand alone和xinetd --http://www.cnblogs.com/itech/archive/2010/12/27/1914846.html#top 一 ...
- Linux内核分析(四)----进程管理|网络子系统|虚拟文件系统|驱动简介
原文:Linux内核分析(四)----进程管理|网络子系统|虚拟文件系统|驱动简介 Linux内核分析(四) 两天没有更新了,上次博文我们分析了linux的内存管理子系统,本来我不想对接下来的进程管理 ...
- 【转载】 java利用snmp4j包来读取snmp协议数据(Manager端)
https://www.cnblogs.com/xdp-gacl/p/4187089.html http://doc.okbase.net/yuanfy008/archive/265663.html ...
- [转帖]Linux系统进程的知识总结,进程与线程之间的纠葛...
Linux系统进程的知识总结,进程与线程之间的纠葛... https://cloud.tencent.com/developer/article/1500509 当一个程序开始执行后,在开始执行到执行 ...
- Linux的启动过程及init进程
Linux下有三个特殊进程: idle进程(pid=0)idle进程其前身是系统创建的第一个进程,0号进程,也唯一一个没有通过fork()或者kernel_thread产生的进程,由系统自动创建,运行 ...
随机推荐
- Swagger2限定接口范围
前面在使用Swagger2时遇到的坑中简单介绍了Swagger的使用. 不过默认情况下,Swagger2会把项目中的所有接口都展示在列表里,特别是你用了Springboot/SpringCloud之后 ...
- Nginx学习笔记(三)--- Nginx实现反向代理和配置负载均衡
1.反向代理 2.Nginx反向代理流程图 3.安装多个tomcat 3.1把tomcat的压缩包传到Linux上 3.2 解压tomcat 3.3 给压缩好的tomcat改个名字用来区分一下 3.4 ...
- sublime3安装ctags追踪插件
sublime3经常要用到函数追踪插件,怎做的?下面看安装步骤: 1.安装package control 按快捷键 ctrl+shift+p 2.安装搜索 ctags插件 3.下载ctags可执行程序 ...
- js实现的玫瑰花
<html> <head> <meta charset="utf-8"> <title>开心快乐每一天</title> ...
- blfs(systemd版本)学习笔记-编译安装openssh软件包
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! openssh项目地址:http://www.linuxfromscratch.org/blfs/view/stable/pos ...
- Python 简单分页思路
一: li = [] for i in range(1000): li.append(i) while True: p = input('input page: ') p = int(p) start ...
- [Android] ubuntu 下不识别 Android 设备
之前的android手机给家人用了,手里现在有一个旧手机,调试过程又出现不识别的问题,这次要记录一下. 首先,需要把手机开发者选项打开,在设置里对着android版本或者型号多点几次,就会打开. 原文 ...
- Fiddler抓包使用教程-乱码处理 Decode
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/73350344 本文出自[赵彦军的博客] 在 Fiddler 的工具栏中有一个 De ...
- 关于《SQLSERVER走起》微信账号自动回复功能的升级
关于SQLSERVER走起微信账号自动回复功能的升级 由于腾讯对微信公众账号的升级,本公众账号也增加了关键词自动回复功能, 只需要输入某些特定关键词,本公众账号就会进行自动回复. 例如: 输入 sql ...
- 关于MySQL checkpoint
Ⅰ.Checkpoint 1.1 checkpoint的作用 缩短数据库的恢复时间 缓冲池不够用时,将脏页刷到磁盘 重做日志不可用时,刷新脏页 1.2 展开分析 page被缓存在bp中,page在bp ...