获取一个进程的所有物理地址上的内存
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 }
2. 通过mmap /dev/mem获取物理地址的存储内容
参考:https://blog.csdn.net/zhanglei4214/article/details/6653568
3. 获取之后:就有很多好玩的东东啦
a. 比如做crc校验,找出是否有人踩这个内存
b. 比如可以篡改内容,搞挂别人的程序
。。。