Ejemplo n.º 1
0
    def __init__(self, case, iosource_name, profile, map):
        ## Try to open the image
        self.iosource_name = iosource_name
        self.case = case
        self.map = map
        self.tasks = {}
        print "Opening memory image"
        path_to_profiles = "%s/%s" % (config.memory_profile_dir,
                                      profile)

        print path_to_profiles
        profile_file_name = [ m for m in os.listdir(path_to_profiles) \
                              if m.endswith(".py") ][0]

        print "Profile name %s" % profile_file_name
        self.profile = load_profile_from_file("%s/%s" % (path_to_profiles,
                                                                    profile_file_name))
        try:
            symdict = load_symboltable_from_file("%s/%s" % (path_to_profiles,
                                                                   map))
            self.symtable = SymbolTable(symdict)
        except:
            raise RuntimeError("Invalid or corrupt Symbol Table file %s/%s" % (path_to_profiles, profile_file_name))

        pgd = self.symtable.lookup('swapper_pg_dir')
        iosrc = IO.open(self.case, iosource_name)
        phyAS = IOSourceAddressSpace(iosrc)
        self.addr_space = IA32PagedMemory(phyAS, pgd - 0xc0000000)
        self.theProfile = Profile(abstract_types = self.profile)
Ejemplo n.º 2
0
    def load(self, mount_point, iosource_name, loading_scanners = None):
        """ Sets up the schema for loading the filesystem.

        Note that derived classes need to actually do the loading
        after they call the base class.

        loading_scanners are the scanners which need to be run on
        every new Inode.
        """
        self.mount_point = mount_point
        dbh=DB.DBO(self.case)
        
        ## Commented out to fix Bug0035. This should be (and is) done
        ## by VFSCreate, since we want to avoid duplicate mount
        ## points.  mic: This is here because skfs.load does not use
        ## VFSCreate for speed reasons and therefore does not
        ## necessarily create the mount points when needed.  Ensure
        ## the VFS contains the mount point:
        self.VFSCreate(None, "I%s" % iosource_name, mount_point, 
                       directory=True)

        dbh.insert("filesystems",
                   iosource = iosource_name,
                   property = 'mount point',
                   value = mount_point)
        
        ## Ensure that we have the IOSource available
        self.iosource = IO.open(self.case, iosource_name)
Ejemplo n.º 3
0
    def load(self, mount_point, iosource_name, scanners = None, directory=None):
        ## Ensure that mount point is normalised:
        self.iosource_name = iosource_name
        mount_point = os.path.normpath(mount_point)
        self.mount_point = mount_point
        
        FileSystem.DBFS.load(self, mount_point, iosource_name)
        
        # open the iosource
        self.iosrc = IO.open(self.case, iosource_name)

        ## Make a volatility object available FIXME allow options in
        ## here
        op = vutils.get_standard_parser("")

        ## Create an address space for the kernel
        self.kernel_VA_inode_id = self.VFSCreate(None, "I%s|A0"  % iosource_name,
                                                 "%s/mem" % self.mount_point)
        
        ## Build a fake command line
        self.filename = '%s/%s' % (self.case, iosource_name)
        self.args = ['-f', self.filename ]
        opts, args = op.parse_args(self.args)

        ## This identifies the image
        (self.addr_space, self.symtab, self.types) = vutils.load_and_identify_image(op, opts)

        for loader in Registry.FSLOADERS.classes:
            if loader.filesystem != "WindowsMemory": continue
            
            ## Instantiate them
            loader = loader()
            
            ## Ask them to load this memory image
            loader.load(self)
Ejemplo n.º 4
0
 def __init__(self, name, mode='rb', fast=False):
     self.case, self.iosource = name.split("/",1)
     fd = IO.open(self.case, self.iosource)
     self.fhandle = fd
     self.fsize = fd.size
     self.fast_fhandle = fd
     self.fname = name
     self.name = name
Ejemplo n.º 5
0
def process(case,subsys,extension=None):
    """ A generator to produce all the recoverable files within the io object identified by identifier

    @arg subsys: Either an IO object to use, or the string name of an io object that will be opened using IO.open().
    @arg extension: A list of extensions we would like to see
    """
    if type(subsys)==types.StringType:
        io=IO.open(case,subsys)
    else:
        io=subsys
        
    blocksize=1024*1024*10
    windowsize=100
    count=0
    bytes_read=0
    window=''
    while(1):
        ## This implements a sliding window of window bytes to ensure
        ## we do not miss a signature that was split across blocksize:
        try:
            data=io.read(blocksize)
            if not len(data): break
        except IOError:
            break
        
        f=window+data
        bytes_read+=len(data)
        pyflaglog.log(pyflaglog.INFO,"Processed %u Mb" % (bytes_read/1024/1024))
        for cut in definitions:
            if extension and cut['Extension'] not in extension: continue
            pos=0
            while pos<blocksize:
                match=cut['CStartRE'].search(f,pos)
                if match:
                    offset=match.start()+count-len(window)
                    length=cut['MaxLength']
                    ## If there is an end RE, we try to read the entire length in, and then look for the end to we can adjust the length acurately. This is essential for certain file types which do not tolerate garbage at the end of the file, e.g. pdfs.
                    if cut.has_key('CEndRE'):
                        tell=io.tell()
                        io.seek(offset)
                        file_data=io.read(length)
                        io.seek(tell)

                        end_match=cut['CEndRE'].search(file_data,0)
                        if end_match:
                            length=end_match.end()
                  
                    yield({'offset':offset,'length':length,'type':cut['Extension']})
                    pos=match.start()+1
                else:
                    pos=blocksize

        window=f[-windowsize:]
        count+=blocksize
        
    io.close()
Ejemplo n.º 6
0
def write_stream(con_id):
    dbh2= dbh.clone()
    dbh.execute("select pcap.id as id,iosource,offset,pcap.length from `connection`,pcap where pcap.id=`connection`.packet_id and con_id = %r order by packet_id" % con_id)
    for row in dbh:
        ## This should not be too slow as its cached in the IO module
        ## Store
        io = IO.open(options.case, row['iosource'])
        io.seek(row['offset'])
        data = io.read(row['length'])
        outfd.write(data)
Ejemplo n.º 7
0
    def __init__(self, case, fd, inode):
        FileSystem.File.__init__(self, case, fd, inode)

        ## The format of the inode is Iname .Where name is the name of
        ## the IO source.
        self.name = inode[1:]
        self.io = IO.open(case, self.name)
        self.size = self.io.size

        ## This source should not be scanned directly.
        self.ignore = True
Ejemplo n.º 8
0
    def form(self, query, result):
        result.start_table()
        try:
            result.case_selector()
            result.ruler()
            result.selector(
                "Select IO Data Source",
                "iosource",
                "select name as `key`,name as `value` from iosources",
                case=query["case"],
            )

            # initialise/open the subsystem
            fd = IO.open(query["case"], query["iosource"])

            ## We need to ask all our filesystems to have a go at
            ## this:
            metadata = {}
            order = []
            for c in Registry.FILESYSTEMS.classes:
                c = c(query["case"], query)
                guess = c.guess(fd, result, metadata)
                if guess > 0:
                    order.append((guess, c.name))

            ## Sort according to the guess value
            order.sort(lambda x, y: y[0] - x[0])

            ## We only show those whose guess is within 100 off
            ## the top - this allows a strong guess to bump out
            ## weaker guesses.
            maximum = order[0][0]
            fs_types = [x[1] for x in order if x[0] > maximum - 100]

            ## If only one option is possible here,
            if len(fs_types) == 1:
                result.hidden("fstype", fs_types[0], exclusive=True)
            else:
                result.const_selector("Enter Filesystem type", "fstype", fs_types, fs_types)

            result.textfield("VFS Mount Point:", "mount_point")
            result.ruler()

            ## Allow the filesystem to draw a form:
            try:
                c = Registry.FILESYSTEMS.dispatch(query["fstype"])
                c = c(query["case"], query)
                c.form(query, result)
            except KeyError:
                pass

        except IOError, e:
            result.text("IOError %s" % e, style="red")
Ejemplo n.º 9
0
    def form(self,query,result):
        result.start_table()
        try:
            result.case_selector()
            result.ruler()
            result.selector('Select IO Data Source', 'iosource',
                            "select name as `key`,name as `value` from iosources",
                            case=query['case'])
            
            # initialise/open the subsystem
            fd=IO.open(query['case'],query['iosource'])

            ## We need to ask all our filesystems to have a go at
            ## this:
            metadata = {}
            order = []
            for c in Registry.FILESYSTEMS.classes:
                c = c(query['case'], query)
                guess = c.guess(fd, result, metadata)
                if guess>0:
                    order.append((guess , c.name))

            ## Sort according to the guess value
            order.sort(lambda x,y: y[0] - x[0])
                    
            ## We only show those whose guess is within 100 off
            ## the top - this allows a strong guess to bump out
            ## weaker guesses.
            maximum = order[0][0]
            fs_types = [ x[1] for x in order if x[0] > maximum - 100 ]

            ## If only one option is possible here, 
            if len(fs_types)==1:
                result.hidden('fstype',fs_types[0], exclusive = True)
            else:
                result.const_selector("Enter Filesystem type",'fstype',fs_types,fs_types)

            result.textfield("VFS Mount Point:","mount_point")
            result.ruler()

            ## Allow the filesystem to draw a form:
            try:
                c = Registry.FILESYSTEMS.dispatch(query['fstype'])
                c = c(query['case'], query)
                c.form(query, result)
            except KeyError:
                pass

        except IOError,e:
            result.text("IOError %s" % e,style='red')
Ejemplo n.º 10
0
parser.add_option("-f", "--file", default=None,
                  help = "A single file of connection ids, one per line")

(options, args) = parser.parse_args()

if not options.case or not options.write:
    print "Mandatory args missing - run me with --help for help"
    sys.exit(1)

## Create the PCAP header for the new file:
dbh=DB.DBO(options.case)
dbh.execute("select * from pcap limit 1")
row = dbh.fetch()

io = IO.open(options.case, row['iosource'])
fd = Buffer(fd=io)

## Read the header:
header = PCAP.FileHeader(fd)

io.seek(0)
data = io.read(header.start_of_data)

## Open file for writing:
outfd = open(options.write, 'w')
outfd.write(data)

## Now grab the data packets for all the relevant streams:
def write_stream(con_id):
    dbh2= dbh.clone()
Ejemplo n.º 11
0
    def display(self,query,result):
        dbh = DB.DBO(query['case'])
        dbh.execute("select * from pcap where id=%r limit 1", query['id'])
        row=dbh.fetch()
        
        io = IO.open(query['case'], row['iosource'])
        packet = pypcap.PyPCAP(io)
        packet.seek(row['offset'])
        dissected_packet = packet.dissect()
        
        id = int(query['id'])
        
        def get_node(branch):
            """ Locate the node specified by the branch.

            branch is a list of attribute names.
            """
            result = dissected_packet
            for b in branch:
                try:
                    result = getattr(result, b)
                except: pass

            return result
        
        def tree_cb(path):
            branch = FlagFramework.splitpath(path)
            
            node = get_node(branch)
            try:
                for field in node.list():
                    if field.startswith("_"): continue

                    child = getattr(node, field)
                    try:
                        yield  ( field, child.get_name(), 'branch')
                    except AttributeError:
                        yield  ( field, field, 'leaf')

            except AttributeError:
                pass
            
            return
        
        def pane_cb(path,result):
            branch = FlagFramework.splitpath(path)
            
            node = get_node(branch)

            result.heading("Packet %s" % id)
            data = dissected_packet.serialise()
            
            h=FlagFramework.HexDump(data, result)
            try:
                result.text("%s" % node.get_name(), font='bold')
                result.text('',style='black', font='normal')
                start,length = node.get_range()
                
            except AttributeError:
                result.text("%s\n" % node, style='red', wrap='full', font='typewriter', sanitise='full')
                result.text('',style='black', font='normal')
                node = get_node(branch[:-1])
                start,length = node.get_range(branch[-1])

            h.dump(highlight=[[start,length,'highlight'],])

            return

        result.tree(tree_cb=tree_cb, pane_cb=pane_cb, branch=[''])

        ## We add forward and back toolbar buttons to let people move
        ## to next or previous packet:
        dbh.execute("select min(id) as id from pcap")
        row = dbh.fetch()

        new_query=query.clone()
        if id>row['id']:
            del new_query['id']
            new_query['id']=id-1
            result.toolbar(text="Previous Packet",icon="stock_left.png",link=new_query)
        else:
            result.toolbar(text="Previous Packet",icon="stock_left_gray.png")
            
        dbh.execute("select max(id) as id from pcap")
        row = dbh.fetch()
        
        if id<row['id']:
            del new_query['id']
            new_query['id']=id+1
            result.toolbar(text="Next Packet",icon="stock_right.png",link=new_query)
        else:
            result.toolbar(text="Next Packet",icon="stock_right_gray.png")
Ejemplo n.º 12
0
    def load(self, mount_point, iosource_name,scanners = None):
        DBFS.load(self, mount_point, iosource_name)
        
        ## Open the file descriptor
        self.fd = IO.open(self.case, iosource_name)

        ## Use the C implementation to read the pcap files:
        pcap_file = pypcap.PyPCAP(self.fd)

        ## Build our streams:
        pyflaglog.log(pyflaglog.DEBUG, "Reassembling streams, this might take a while")
        pcap_dbh = DB.DBO(self.case)
        pcap_dbh.mass_insert_start("pcap")

        pcap_dbh.execute("select max(id) as m from pcap")
        max_id = pcap_dbh.fetch()['m'] or 0
        cookie, processor = self.make_processor(iosource_name, scanners)

        ## Process the file with it:
        while 1:
            try:
                packet = pcap_file.dissect()
                max_id += 1

                ## FIXME - this is a bottleneck. For now we use mass
                ## insert but this will break when we have multiple
                ## concurrent loaders.  Record the packet in the pcap
                ## table:
                args = dict(
                    iosource = iosource_name,
                    offset = packet.offset,
                    length = packet.caplen,
                    _ts_sec =  "from_unixtime('%s')" % packet.ts_sec,
                    ts_usec = packet.ts_usec,
                    )

                ## Try to insert the ipid field
                try:
                    args['ipid']= packet.root.eth.payload.id
                except: pass

                pcap_dbh.mass_insert(**args)
                #pcap_id = pcap_dbh.autoincrement()
                pcap_id = max_id
                pcap_file.set_id(pcap_id)

                
                ## Some progress reporting
                if pcap_id % 10000 == 0:
                    pyflaglog.log(pyflaglog.DEBUG, "processed %s packets (%s bytes)" % (pcap_id, packet.offset))

                processor.process(packet)
            except StopIteration:
                break

        processor.flush()

        pcap_dbh.check_index("connection_details",'src_ip')
        pcap_dbh.check_index("connection_details",'src_port')
        pcap_dbh.check_index("connection_details",'dest_ip')
        pcap_dbh.check_index("connection_details",'dest_port')
        pcap_dbh.check_index('connection_details','inode_id')
Ejemplo n.º 13
0
#!/usr/bin/env python
import pyflag.IO as IO
import sys
import sk
from stat import *

#img = open(sys.argv[1],'r')
#print "Will open %s" % sys.argv[1]

## This assumes that we have a case loaded
img = IO.open('winxp','test')
fs = sk.skfs(img)

def readfile(fs,inode):
    print "reading: %s" % inode
    fd = fs.open(inode=inode)
    while True:
        if not fd.read(4000000):
            break

# walk the directory tree
for root, dirs, files in fs.walk('/', unalloc=True, inodes=True):
    for f in files:
        try:
            print "processing: (%u) %s" % (f[0], f[1])
            s=fs.stat(inode=str(f[0]))
            print "length %s" % s[ST_SIZE]
            if int(f[0])==0: continue
            readfile(fs,str(f[0]))
        except IOError, e:
            print "Got error: %s" % e
Ejemplo n.º 14
0
    def load(self, mount_point, iosource_name, scanners = None, directory=None):
        ## Ensure that mount point is normalised:
        self.iosource_name = iosource_name
        mount_point = os.path.normpath(mount_point)
        self.mount_point = mount_point
        
        DBFS.load(self, mount_point, iosource_name)
        
        # open the iosource
        iosrc = IO.open(self.case, iosource_name)

        ## Get a db handle
        dbh = DB.DBO(self.case)
        dbh.mass_insert_start('tasks')
        
        (addr_space, symtab, types) = load_and_identify_image(iosrc)
        self.load_open_files(dbh, addr_space, types, symtab)

        ## process_list should probably be a generator here (or not,
        ## the list is unlikely to be that big)
        for task in process_list(addr_space, types, symtab):
            ## Skip invalid tasks (This should probably be done in
            ## process_list itself so it doesnt yield rubbish)
            if not addr_space.is_valid_address(task): continue
            pid = process_pid(addr_space, types, task) or -1
            create_time = process_create_time(addr_space, types, task)

            task_info = {
                'iosource':        iosource_name,
                'image_file_name': process_imagename(addr_space, types, task) or "UNKNOWN",
                'pid':             pid,
                'offset':          task,
                'active_threads':  process_num_active_threads(addr_space, types, task) or -1,
                'inherited_from':  process_inherited_from(addr_space, types,task) or -1,
                'handle_count':    process_handle_count(addr_space, types, task) or -1,
                '_create_time':    "from_unixtime('%s')" % create_time
                }

            ## Put the data in the db
            dbh.mass_insert(**task_info)

            ## Create some VFS nodes:
            new_inode = "I%s|N%s" % (iosource_name, task)
            inode_id = self.VFSCreate(None, new_inode,
                                      "%s/%s/exe" % (mount_point, task_info['pid']),
                                      _mtime = create_time,
                                      link = task_info['image_file_name'],
                                      _fast = True)

            ## Try to read the PEB:
            peb = process_peb(addr_space, types, task)
            process_address_space = process_addr_space(addr_space, types, task, None)
            command_line = process_command_line(process_address_space, types, peb)
            if command_line:
                dbh.insert('xattr',
                           inode_id=inode_id,
                           property = "command_line",
                           value = command_line,
                           _fast = True)

            if peb:
                modules = process_ldrs(process_address_space, types, peb)
                for module in modules:
                    if not process_address_space.is_valid_address(module): continue
                    path = module_path(process_address_space, types, module)
                    base = module_base(process_address_space, types, module) or 0
                    size = module_size(process_address_space, types, module)

                    dbh.insert("modules", iosource = iosource_name,
                               pid = pid,
                               path = path,
                               base = base,
                               _fast = True
                               )

                    self.VFSCreate(None, None,
                                   "%s/%s/Modules/Base 0x%X" % ( mount_point,
                                                                 task_info['pid'],
                                                                 base),
                                   _mtime = create_time,
                                   link = path,
                                   size = size,
                                   _fast = True)
                    
        ## Now look for the connections:
        for connection in tcb_connections(addr_space, types, symtab):
            if not addr_space.is_valid_address(connection):
                continue

            dbh.insert("mconnections",
                       pid = connection_pid(addr_space, types, connection),
                       lport   = connection_lport(addr_space, types, connection),
                       laddr   = connection_laddr(addr_space, types, connection),
                       rport   = connection_rport(addr_space, types, connection),
                       raddr   = connection_raddr(addr_space, types, connection),
                       iosource = iosource_name,
                       _fast = True)

        ## Now do the sockets:
        for socket in open_sockets(addr_space, types, symtab):
            if not addr_space.is_valid_address(connection):
                continue

            dbh.insert("sockets",
                       pid   = socket_pid(addr_space, types, socket),
                       proto = socket_protocol(addr_space, types, socket),
                       port  = socket_local_port(addr_space, types, socket),
                       _create_time  = "from_unixtime('%s')" % socket_create_time(addr_space, types, socket),
                       iosource = iosource_name
                       )