Package rekall :: Package plugins :: Package addrspaces :: Module mips
[frames] | no frames]

Source Code for Module rekall.plugins.addrspaces.mips

  1  # Rekall Memory Forensics 
  2  # 
  3  # Authors: 
  4  # Karl Vogel <karl.vogel@gmail.com> 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or (at 
  9  # your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, but 
 12  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 14  # General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 19  # 
 20   
 21  import struct 
 22   
 23  from rekall import addrspace 
 24  from rekall import config 
 25  from rekall.plugins.addrspaces import intel 
 26   
27 -class MIPS32PagedMemory(intel.IA32PagedMemory):
28 ''' 29 Address space to handle the MIPS Linux memory layout, which is: 30 31 0x0000 0000 - 0x7FFF FFFF kuseg: User mapped pages 32 0x8000 0000 - 0x9FFF FFFF k0seg: Kernel non paged memory, this maps to 33 address range 0x0000 0000 - 0x1FFF FFFF 34 0xA000 0000 - 0xBFFF FFFF k1seg: Kernel non paged, non cached memory, 35 this maps to address range 36 0x0000 0000 - 0x1FFF FFFF 37 0xC000 0000 - 0xFFFF FFFF k2seg: Kernel paged memory using init_mm.pgd 38 39 See page 8 on: 40 http://www.eecs.harvard.edu/~margo/cs161/notes/vm-mips.pdf 41 42 Derives from IA32PagedMemory as the only major difference is the special 43 layout as shown above and minor details like no large pages and a difference 44 in the PTE to PFN translation, which is taken care of by the 45 pte_paddr function. 46 ''' 47 48 # MIPS32 doesn't have a valid flag on PDE's, they're always valid 49 valid_mask = (1 << 32) - 1 50
51 - def _pa(self, x):
52 ''' 53 Convert a physical address to the actual physical memory location. 54 ''' 55 if x < 0x80000000: 56 return x 57 elif x >= 0xA0000000: 58 return x - 0xA0000000 59 else: 60 return x - 0x80000000
61
62 - def page_size_flag(self, entry):
63 ''' 64 MIPS32 doesn't have a page size flag, always return False 65 ''' 66 return False
67
68 - def read_long_phys(self, addr):
69 ''' 70 Returns an unsigned 32-bit integer from the address addr in 71 physical memory. If unable to read from that location, returns None. 72 ''' 73 string = self.base.read(self._pa(addr), 4) 74 return struct.unpack('>I', string)[0]
75
76 - def vtop(self, vaddr):
77 ''' 78 Translates virtual addresses into physical offsets. 79 The function should return either None (no valid mapping) 80 or the offset in physical memory where the address maps. 81 ''' 82 if (vaddr >= 0x80000000) and (vaddr < 0xC0000000): 83 return self._pa(vaddr) 84 85 return super(MIPS32PagedMemory, self).vtop(vaddr)
86
87 - def pte_paddr(self, pte):
88 ''' 89 Return the physical address for the given PTE. 90 This should return: 91 (pte >> pfn_shift) << page_shift 92 93 On MIPS pfn_shift is 11, while page_shift is 12 94 ''' 95 return pte << 1
96
97 - def get_phys_addr(self, vaddr, pte_value):
98 ''' 99 Return the offset in a 4KB memory page from the given virtual 100 address and Page Table Entry. 101 102 Bits 31:12 are from the PTE 103 Bits 11:0 are from the original linear address 104 ''' 105 if pte_value & self.valid_mask: 106 return (self.pte_paddr(pte_value) & 0xfffff000) | (vaddr & 0xfff)
107
108 - def get_available_addresses(self, start=0):
109 """Enumerate all valid memory ranges. 110 111 Yields: 112 tuples of (starting virtual address, size) for valid the memory 113 ranges. 114 """ 115 # Need to find out if we're mapping for kernel space 116 # or userspace 117 sym = self._pa(self.session.profile.get_constant('swapper_pg_dir')) 118 if self.dtb == sym: 119 num_pde = 1024 120 else: 121 num_pde = 512 122 123 # Pages that hold PDEs and PTEs are 0x1000 bytes each. 124 # Each PDE and PTE is four bytes. Thus there are 0x1000 / 4 = 0x400 125 # PDEs and PTEs we must test 126 # On MIPS, the userspace PDEs are limited to 512 entries 127 for pde in range(0, num_pde): 128 vaddr = pde << 22 129 next_vaddr = (pde+1) << 22 130 if start > next_vaddr: 131 continue 132 133 if (vaddr >= 0x80000000) and (vaddr < 0xC0000000): 134 yield (vaddr, self._pa(vaddr), 1 << 22) 135 continue 136 137 pde_value = self.get_pde(vaddr) 138 139 # This reads the entire PTE table at once - On 140 # windows where IO is extremely expensive, its 141 # about 10 times more efficient than reading it 142 # one value at the time - and this loop is HOT! 143 pte_table_addr = ((pde_value & 0xfffff000) | 144 ((vaddr & 0x3ff000) >> 10)) 145 146 data = self.base.read(self._pa(pte_table_addr), 4 * 0x400) 147 pte_table = struct.unpack(">" + "I" * 0x400, data) 148 149 tmp1 = vaddr 150 for i, pte_value in enumerate(pte_table): 151 vaddr = tmp1 | i << 12 152 next_vaddr = tmp1 | ((i+1) << 12) 153 154 if start > next_vaddr: 155 continue 156 157 if pte_value & self.valid_mask: 158 yield (vaddr, 159 self.get_phys_addr(vaddr, pte_value), 160 0x1000)
161