博客地址:http://home.cnblogs.com/u/zengjianrong/

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

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. 比如可以篡改内容,搞挂别人的程序

  。。。

posted @ 2019-07-11 11:51  black_man  阅读(1301)  评论(0编辑  收藏  举报