def _syncDevice(self, serial): print('connecting device %s (%s)' % (self.devices[serial]['name'], serial)) device = Device(self.devices[serial]['device']) device.open() syncing = True GLib.idle_add(self._changeIcon, True) devMap = device.walk(device.SEP) print('syncing device %s (%s)' % (self.devices[serial]['name'], serial)) for directory in devMap.keys(): osDirectory = directory.replace(device.SEP, os.sep) d = devMap[directory] files = [e for e in d.entries if not e.name.endswith(os.sep)] for file in files: parserFailed = False if '.BPB' in file.name: data = device.read_file('%s%s' % (directory, file.name)) dataFileName = '%s%s%s' % ( serial, directory.replace(os.sep, '-').lower(), os.path.splitext(file.name)[0].lower()) if file.name in self.FILE_MAPPINGS.keys(): parser = self.FILE_MAPPINGS[file.name]() if file.name == 'SAMPLES.GZB': data = zlib.decompress(data) f = '%s/.local/polartray/%s.json' % ( os.environ['HOME'], dataFileName) try: parser.ParseFromString(bytes(bytearray(data))) with open(f, 'w') as fh: fh.write(MessageToJson(parser)) except Exception as err: parserFailed = True print('failed to decode %s' % (dataFileName)) print(err) if file.name not in self.FILE_MAPPINGS.keys( ) or parserFailed == True: f = '%s/.local/polartray/%s%s' % ( os.environ['HOME'], dataFileName, os.path.splitext(file.name)[1].lower()) with open(f, 'wb') as fh: fh.write(bytearray(data)) GLib.idle_add(self._changeIcon, False) print('disconnecting device %s (%s)' % (self.devices[serial]['name'], serial)) device.close()
class LoopholeCli(cmd.Cmd): """ Loophole command line interface class. """ __PROMPT = 'loophole({})>' def __init__(self): """Constructor. """ cmd.Cmd.__init__(self) self.prompt = LoopholeCli.__PROMPT.format('no device') self.device = None # end-of-method __init__ def do_exit(self, _): """Quit. Usage: exit """ if self.device is not None: self.device.close() sys.exit(0) # end-of-method do_exit def do_list(self, _): """List available Polar devices. Usage: list """ devs = Device.list() if len(devs) > 0: for i, dev in enumerate(devs): try: info = Device.get_info(dev) except ValueError as err: print "Device no: %i" % i print "Device info:" print dev print "-" * 79 if 'langid' in err.message: raise ValueError( ("Can't get device info. Origin Error: %s\n" "Maybe this is a permission issue.\n" "Please read section 'permission' in README ;)") % err) raise # raise origin error print '{} - {} ({})'.format(i, info['product_name'], info['serial_number']) else: print '[!] No Polar devices found!' print # end-of-method do_list def do_connect(self, dev_no): """Connect Polar device. Run 'list' to see available devices. Usage: connect <device_no> """ try: dev_no = int(dev_no) except ValueError: print '[!] You need to specify the device number. Run \'list\' to see available devices.' print return try: devs = Device.list() dev = devs[dev_no] serial = Device.get_info(dev)['serial_number'] self.prompt = LoopholeCli.__PROMPT.format(serial) self.device = Device(dev) self.device.open() print '[+] Device connected.' print except IndexError: print '[!] Device not found or failed to open it. Run \'list\' to see available devices.' print # end-of-method do_connect @check_if_device_is_connected def do_disconnect(self, _): """Disconnect Polar device. """ self.device.close() self.device = None self.prompt = LoopholeCli.__PROMPT.format('no device') print '[+] Device disconnected.' print # end-of-method do_disconnect @check_if_device_is_connected def do_get(self, line): """Read file from device and store in under local_path. Usage: get <device_path> <local_path> """ try: src, dest = line.strip().split() data = self.device.read_file(src) with open(dest, 'wb') as outfile: outfile.write(bytearray(data)) print '[+] File \'{}\' saved to \'{}\''.format(src, dest) print except ValueError: print '[!] Invalid command usage.' print '[!] Usage: get <source> <destination>' print # end-of-method do_get @check_if_device_is_connected def do_delete(self, line): """Delete file from device. Usage: delete <device_path> """ path = line.strip() _ = self.device.delete(path) # end-of-method do_delete @check_if_device_is_connected def do_dump(self, path): """Dump device memory. Path is local folder to store dump. Usage: dump <local_path> """ print '[+] Reading files tree...' dev_map = self.device.walk(self.device.SEP) for directory in dev_map.keys(): fixed_directory = directory.replace(self.device.SEP, os.sep) full_path = os.path.abspath(os.path.join(path, fixed_directory[1:])) if not os.path.exists(full_path): os.makedirs(full_path) d = dev_map[directory] files = [e for e in d.entries if not e.name.endswith('/')] for file in files: with open(os.path.join(full_path, file.name), 'wb') as fh: print '[+] Dumping {}{}'.format(directory, file.name) data = self.device.read_file('{}{}'.format( directory, file.name)) fh.write(bytearray(data)) print '[+] Device memory dumped.' print # end-of-method do_dump @check_if_device_is_connected def do_info(self, _): """Print connected device info. Usage: info """ info = Device.get_info(self.device.usb_device) print '{:>20s} - {}'.format('Manufacturer', info['manufacturer']) print '{:>20s} - {}'.format('Product name', info['product_name']) print '{:>20s} - {}'.format('Vendor ID', info['vendor_id']) print '{:>20s} - {}'.format('Product ID', info['product_id']) print '{:>20s} - {}'.format('Serial number', info['serial_number']) try: data = self.device.read_file('/DEVICE.BPB') resp = ''.join(chr(c) for c in data) d = pb_device.PbDeviceInfo() d.ParseFromString(resp) bootloader_version = '{}.{}.{}'.format(d.bootloader_version.major, d.bootloader_version.minor, d.bootloader_version.patch) print '{:>20s} - {}'.format('Bootloader version', bootloader_version) platform_version = '{}.{}.{}'.format(d.platform_version.major, d.platform_version.minor, d.platform_version.patch) print '{:>20s} - {}'.format('Platform version', platform_version) device_version = '{}.{}.{}'.format(d.device_version.major, d.device_version.minor, d.device_version.patch) print '{:>20s} - {}'.format('Device version', device_version) print '{:>20s} - {}'.format('SVN revision', d.svn_rev) print '{:>20s} - {}'.format('Hardware code', d.hardware_code) print '{:>20s} - {}'.format('Color', d.product_color) print '{:>20s} - {}'.format('Product design', d.product_design) except: print '[!] Failed to get extended info.' print ' ' # end-of-method do_info @check_if_device_is_connected def do_fuzz(self, _): import polar num = _.strip() if len(num) > 0: num = int(num) resp = self.device.send_raw([0x01, num] + [0x00] * 62) print 'req: {} '.format(num), if resp: print 'err code: {}'.format(polar.PFTP_ERROR[resp[0]]) return for i in xrange(256): #raw_input('Sending [{}]...<press enter>'.format(i)) if (i & 0x03) == 2: continue if i in [3, 251, 252]: continue resp = self.device.send_raw([0x01, i] + [0x00] * 62) print 'resp: {} '.format(i), if resp: print 'err code: {}'.format(polar.PFTP_ERROR[resp[0]]) else: print # end-of-method do_fuzz @check_if_device_is_connected def do_put_file(self, line): path, filename = line.split() self.device.put_file(path.strip(), filename.strip()) # end-of-method do_put_file @check_if_device_is_connected def do_walk(self, path): """Walk file system. Default device_path is device root folder. Usage: walk [device_path] """ if not path.endswith('/'): path += '/' fs = self.device.walk(path) keyz = fs.keys() keyz.sort() for k in keyz: print k d = fs[k] files = [e for e in d.entries if not e.name.endswith('/')] files.sort() for f in files: print '{}{} ({} bytes)'.format(k, f.name, f.size) print # end-of-method do_walk pass
class LoopholeCli(cmd.Cmd): """ Loophole command line interface class. """ __PROMPT = 'loophole({})>' def __init__(self): """Constructor. """ cmd.Cmd.__init__(self) self.prompt = LoopholeCli.__PROMPT.format('no device') self.device = None # end-of-method __init__ def do_exit(self, _): """Quit. """ if self.device is not None: self.device.close() sys.exit(0) # end-of-method do_exit def do_list(self, _): """List available Polar devices. """ devs = Device.list() if len(devs) > 0: for i, dev in enumerate(devs): info = Device.get_info(dev) print '{} - {} ({})'.format(i, info['product_name'], info['serial_number']) else: print '[!] No Polar devices found!' print # end-of-method do_list def do_connect(self, dev_no): """Connect Polar device. Run 'list' to see available devices. """ try: dev_no = int(dev_no) devs = Device.list() dev = devs[dev_no] serial = Device.get_info(dev)['serial_number'] self.prompt = LoopholeCli.__PROMPT.format(serial) self.device = Device(dev) self.device.open() print '[+] Device connected.' print except IndexError: print '[!] Device not found or failed to open it. Run \'list\' to see available devices.' print # end-of-method do_connect @check_if_device_is_connected def do_disconnect(self, _): """Disconnect Polar device. """ self.device.close() self.device = None self.prompt = LoopholeCli.__PROMPT.format('no device') print '[+] Device disconnected.' print # end-of-method do_disconnect @check_if_device_is_connected def do_get(self, line): """Read file from device. Usage: get <src> <dest> """ try: src, dest = line.strip().split() data = self.device.read_file(src) with open(dest, 'wb') as outfile: outfile.write(bytearray(data)) print '[+] File \'{}\' saved to \'{}\''.format(src, dest) print except ValueError: print '[!] Invalid command usage.' print '[!] Usage: get <source> <destination>' print # end-of-method do_get def do_dump(self, path): """Dump device memory. Usage: dump <path> """ print '[+] Reading files tree...' dev_map = self.device.walk(self.device.SEP) for directory in dev_map.keys(): fixed_directory = directory.replace(self.device.SEP, os.sep) full_path = os.path.abspath(os.path.join(path, fixed_directory[1:])) if not os.path.exists(full_path): os.makedirs(full_path) d = dev_map[directory] files = [e for e in d.entries if not e.name.endswith('/')] for file in files: with open(os.path.join(full_path, file.name), 'wb') as fh: print '[+] Dumping {}{}'.format(directory, file.name) data = self.device.read_file('{}{}'.format(directory, file.name)) fh.write(bytearray(data)) print '[+] Device memory dumped.' print # end-of-method do_dump @check_if_device_is_connected def do_info(self, _): """Print connected device info. """ info = Device.get_info(self.device.usb_device) print '{:>20s} - {}'.format('Manufacturer', info['manufacturer']) print '{:>20s} - {}'.format('Product name', info['product_name']) print '{:>20s} - {}'.format('Vendor ID', info['vendor_id']) print '{:>20s} - {}'.format('Product ID', info['product_id']) print '{:>20s} - {}'.format('Serial number', info['serial_number']) try: data = self.device.read_file('/DEVICE.BPB') resp = ''.join(chr(c) for c in data) d = pb_device.PbDeviceInfo() d.ParseFromString(resp) bootloader_version = '{}.{}.{}'.format(d.bootloader_version.major, d.bootloader_version.minor, d.bootloader_version.patch) print '{:>20s} - {}'.format('Bootloader version', bootloader_version) platform_version = '{}.{}.{}'.format(d.platform_version.major, d.platform_version.minor, d.platform_version.patch) print '{:>20s} - {}'.format('Platform version', platform_version) device_version = '{}.{}.{}'.format(d.device_version.major, d.device_version.minor, d.device_version.patch) print '{:>20s} - {}'.format('Device version', device_version) print '{:>20s} - {}'.format('SVN revision', d.svn_rev) print '{:>20s} - {}'.format('Hardware code', d.hardware_code) print '{:>20s} - {}'.format('Color', d.product_color) print '{:>20s} - {}'.format('Product design', d.product_design) except: print '[!] Failed to get extended info.' print ' ' # end-of-method do_info @check_if_device_is_connected def do_walk(self, path): """Walk file system. Usage: walk [path] """ if not path.endswith('/'): path += '/' fs = self.device.walk(path) keyz = fs.keys() keyz.sort() for k in keyz: print k d = fs[k] files = [e for e in d.entries if not e.name.endswith('/')] files.sort() for f in files: print '{}{} ({} bytes)'.format(k, f.name, f.size) print # end-of-method do_walk pass
class LoopholeCli(cmd.Cmd): """ Loophole command line interface class. """ __PROMPT = 'loophole({})>' def __init__(self): """Constructor. """ cmd.Cmd.__init__(self) self.prompt = LoopholeCli.__PROMPT.format('no device') self.device = None # end-of-method __init__ def do_exit(self, _): """Quit. """ if self.device is not None: self.device.close() sys.exit(0) # end-of-method do_exit def do_list(self, _): """List available Polar devices. """ devs = Device.list() if len(devs) > 0: for i, dev in enumerate(devs): print '{} - {} ({})'.format(i, dev.product_name, dev.serial_number) else: print '[!] No Polar devices found!' print # end-of-method do_list def do_connect(self, dev_no): """Connect Polar device. Run 'list' to see available devices. """ try: dev_no = int(dev_no) devs = Device.list() dev = devs[dev_no] self.prompt = LoopholeCli.__PROMPT.format(dev.serial_number) self.device = Device(dev) print '[+] Device connected.' print except IndexError: print '[!] Device not found. Run \'list\' to see available devices.' print # end-of-method do_connect def do_disconnect(self, _): """Disconnect Polar device. """ if self.device is not None: self.device.close() self.device = None self.prompt = LoopholeCli.__PROMPT.format('no device') print '[+] Device disconnected.' print # end-of-method do_disconnect @check_if_device_is_connected def do_get(self, line): """Read file from device. Usage: get <src> <dest> """ try: src, dest = line.strip().split() data = self.device.read_file(src) with open(dest, 'wb') as outfile: outfile.write(bytearray(data)) print '[+] File \'{}\' saved to \'{}\''.format(src, dest) print except ValueError: print '[!] Invalid command usage.' print '[!] Usage: get <source> <destination>' print # end-of-method do_get def do_dump(self, path): """Dump device memory. Usage: dump <path> """ print '[+] Reading files tree...' dev_map = self.device.walk(self.device.SEP) for directory in dev_map.keys(): fixed_directory = directory.replace(self.device.SEP, os.sep) full_path = os.path.abspath(os.path.join(path, fixed_directory[1:])) if not os.path.exists(full_path): os.makedirs(full_path) d = dev_map[directory] files = [e for e in d.entries if not e.name.endswith('/')] for file in files: with open(os.path.join(full_path, file.name), 'wb') as fh: print '[+] Dumping {}{}'.format(directory, file.name) data = self.device.read_file('{}{}'.format(directory, file.name)) fh.write(bytearray(data)) print '[+] Device memory dumped.' print # end-of-method do_dump @check_if_device_is_connected def do_info(self, _): """Print connected device info. """ info = self.device.get_info() for k, v in info.items(): print '{:>20s} - {}'.format(k, v) print # end-of-method do_info @check_if_device_is_connected def do_walk(self, path): """Walk file system. Usage: walk [path] """ if not path.endswith('/'): path += '/' fs = self.device.walk(path) keyz = fs.keys() keyz.sort() for k in keyz: print k d = fs[k] files = [e for e in d.entries if not e.name.endswith('/')] files.sort() for f in files: print '{}{} ({} bytes)'.format(k, f.name, f.size) print # end-of-method do_walk pass