mirror of
https://github.com/volatilityfoundation/volatility
synced 2026-06-08 18:04:46 +00:00
148 lines
4.5 KiB
Python
148 lines
4.5 KiB
Python
# Volatility
|
|
#
|
|
# Authors:
|
|
# attc - atcuno@gmail.com
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or (at
|
|
# your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
import volatility.obj as obj
|
|
import volatility.addrspace as addrspace
|
|
import volatility.debug as debug
|
|
|
|
class LimeTypes(obj.ProfileModification):
|
|
|
|
def modification(self, profile):
|
|
|
|
profile.vtypes.update({
|
|
'lime_header': [ 0x20, {
|
|
'magic': [0x0, ['unsigned int']],
|
|
'version': [0x4, ['unsigned int']],
|
|
'start': [0x8, ['unsigned long long']],
|
|
'end': [0x10, ['unsigned long long']],
|
|
'reserved': [0x18, ['unsigned long long']],
|
|
}],
|
|
})
|
|
|
|
class segment(object):
|
|
|
|
def __init__(self, start, end, offset):
|
|
|
|
self.start = start
|
|
self.end = end
|
|
self.offset = offset
|
|
|
|
class LimeAddressSpace(addrspace.BaseAddressSpace):
|
|
"""
|
|
Address space for Lime
|
|
"""
|
|
order = 2
|
|
|
|
def __init__(self, base, config, *args, **kwargs):
|
|
self.as_assert(base, "lime: need base")
|
|
|
|
addrspace.BaseAddressSpace.__init__(self, base, config, *args, **kwargs)
|
|
|
|
sig = base.read(0, 4)
|
|
|
|
## ARM processors are bi-endian, but little is the default and currently
|
|
## the only mode we support; unless it comes a common request.
|
|
if sig == '\x4c\x69\x4d\x45':
|
|
debug.debug("Big-endian ARM not supported, please submit a feature request")
|
|
|
|
self.as_assert(sig == '\x45\x4D\x69\x4c', "Invalid Lime header signature")
|
|
|
|
self.addr_cache = {}
|
|
self.segs = []
|
|
self.parse_lime()
|
|
|
|
def parse_lime(self):
|
|
# get the segments
|
|
self.segs = []
|
|
|
|
offset = 0
|
|
|
|
header = obj.Object("lime_header", offset = offset, vm = self.base)
|
|
|
|
while header.magic.v() == 0x4c694d45:
|
|
|
|
#print "new segment at %x end %x size: %d offset %d | %x" % (header.start, header.end, header.end - header.start, offset, offset)
|
|
seg = segment(header.start, header.end, offset + self.profile.get_obj_size("lime_header"))
|
|
self.segs.append(seg)
|
|
|
|
seglength = header.end - header.start
|
|
|
|
offset = offset + seglength + 1 + self.profile.get_obj_size("lime_header")
|
|
|
|
header = obj.Object("lime_header", offset = offset, vm = self.base)
|
|
|
|
def read(self, addr, length):
|
|
return self.__read_bytes(addr, length)
|
|
|
|
def zread(self, addr, length):
|
|
return self.__read_bytes(addr, length, True)
|
|
|
|
def __read_bytes(self, addr, length, pad = False):
|
|
firstram = self.segs[0].start
|
|
|
|
if addr < firstram:
|
|
addr = firstram + addr
|
|
|
|
key = "{0:d}:{1:d}".format(addr, length)
|
|
|
|
if key in self.addr_cache:
|
|
return self.addr_cache[key]
|
|
|
|
offset = self.__get_offset(addr)
|
|
|
|
if offset:
|
|
(_, where) = offset
|
|
ret = self.base.read(where, length)
|
|
self.addr_cache[key] = ret
|
|
|
|
elif pad:
|
|
ret = "\x00" * length
|
|
else:
|
|
ret = None
|
|
|
|
return ret
|
|
|
|
def __get_offset(self, addr):
|
|
for seg in self.segs:
|
|
if seg.start <= addr <= seg.end:
|
|
|
|
delta = addr - seg.start
|
|
|
|
where = seg.offset + delta
|
|
|
|
# find offset into seg and return place inside file
|
|
ret = [addr, where]
|
|
|
|
return ret
|
|
|
|
return None
|
|
|
|
# returns a tuple of (start of segment, size of segment) for each segment
|
|
# we do not need special logic to ensure multiple tuples aren't contiguos
|
|
# because lime only creates segments for non-contig RAM sections
|
|
def get_available_addresses(self):
|
|
for seg in self.segs:
|
|
|
|
seglength = seg.end - seg.start
|
|
|
|
yield (seg.start, seglength)
|
|
|
|
def is_valid_address(self, addr):
|
|
return self.__get_offset(addr) != None
|