获取一个进程的所有物理地址上的内存

Posted zengjianrong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取一个进程的所有物理地址上的内存相关的知识,希望对你有一定的参考价值。

1. 获取进程的所有PTE表项,从而得到所有物理地址

  参考:https://www.cnblogs.com/pengdonglin137/p/6802108.html

  通过/proc/pid/pagemap

  

技术图片
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <assert.h>
 5 #include <errno.h>
 6 #include <stdint.h>
 7 #include <string.h>
 8 
 9 #define PAGEMAP_ENTRY 8
10 #define GET_BIT(X,Y) (X & ((uint64_t)1<<Y)) >> Y
11 #define GET_PFN(X) X & 0x7FFFFFFFFFFFFF
12 
13 const int __endian_bit = 1;
14 #define is_bigendian() ( (*(char*)&__endian_bit) == 0 )
15 
16 int i, c, pid, status;
17 unsigned long virt_addr; 
18 uint64_t read_val, file_offset, page_size;
19 char path_buf [0x100] = ;
20 FILE * f;
21 char *end;
22 
23 int read_pagemap(char * path_buf, unsigned long virt_addr);
24 
25 int main(int argc, char ** argv)
26     if(argc!=3)
27         printf("Argument number is not correct!\\n pagemap PID VIRTUAL_ADDRESS\\n");
28         return -1;
29     
30     if(!memcmp(argv[1],"self",sizeof("self")))
31         sprintf(path_buf, "/proc/self/pagemap");
32         pid = -1;
33     
34     else
35         pid = strtol(argv[1],&end, 10);
36         if (end == argv[1] || *end != \\0 || pid<=0) 
37             printf("PID must be a positive number or ‘self‘\\n");
38             return -1;
39         
40     
41     virt_addr = strtoll(argv[2], NULL, 16);
42     if(pid!=-1)
43         sprintf(path_buf, "/proc/%u/pagemap", pid);
44 
45     page_size = getpagesize();
46     read_pagemap(path_buf, virt_addr);
47     return 0;
48 
49 
50 int read_pagemap(char * path_buf, unsigned long virt_addr)
51     printf("Big endian? %d\\n", is_bigendian());
52     f = fopen(path_buf, "rb");
53     if(!f)
54         printf("Error! Cannot open %s\\n", path_buf);
55         return -1;
56     
57 
58     //Shifting by virt-addr-offset number of bytes
59     //and multiplying by the size of an address (the size of an entry in pagemap file)
60     file_offset = virt_addr / page_size * PAGEMAP_ENTRY;
61     printf("Vaddr: 0x%lx, Page_size: %lld, Entry_size: %d\\n", virt_addr, page_size, PAGEMAP_ENTRY);
62     printf("Reading %s at 0x%llx\\n", path_buf, (unsigned long long) file_offset);
63     status = fseek(f, file_offset, SEEK_SET);
64     if(status)
65         perror("Failed to do fseek!");
66         return -1;
67     
68     errno = 0;
69     read_val = 0;
70     unsigned char c_buf[PAGEMAP_ENTRY];
71     for(i=0; i < PAGEMAP_ENTRY; i++)
72         c = getc(f);
73         if(c==EOF)
74             printf("\\nReached end of the file\\n");
75             return 0;
76         
77         if(is_bigendian())
78             c_buf[i] = c;
79         else
80             c_buf[PAGEMAP_ENTRY - i - 1] = c;
81         printf("[%d]0x%x ", i, c);
82     
83     for(i=0; i < PAGEMAP_ENTRY; i++)
84         //printf("%d ",c_buf[i]);
85         read_val = (read_val << 8) + c_buf[i];
86     
87     printf("\\n");
88     printf("Result: 0x%llx\\n", (unsigned long long) read_val);
89     if(GET_BIT(read_val, 63)) 
90         uint64_t pfn = GET_PFN(read_val);
91         printf("PFN: 0x%llx (0x%llx)\\n", pfn, pfn * page_size + virt_addr % page_size);
92      else
93         printf("Page not present\\n");
94     if(GET_BIT(read_val, 62))
95         printf("Page swapped\\n");
96     fclose(f);
97     return 0;
98 
View Code

 

2. 通过mmap /dev/mem获取物理地址的存储内容

  参考:https://blog.csdn.net/zhanglei4214/article/details/6653568

 

3. 获取之后:就有很多好玩的东东啦

  a. 比如做crc校验,找出是否有人踩这个内存

  b. 比如可以篡改内容,搞挂别人的程序

  。。。

以上是关于获取一个进程的所有物理地址上的内存的主要内容,如果未能解决你的问题,请参考以下文章

linux进程内存相关

服务监控-开发眼里的内存是什么

linux内核内存虚拟地址映射物理地址

内存管理

malloc内存分配原理 [linux]--mallocbrkmmap

malloc内存分配原理 [linux]--mallocbrkmmap