# -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function def main(): from frida.application import ConsoleApplication class PSApplication(ConsoleApplication): def _add_options(self, parser): parser.add_option("-a", "--applications", help="list only applications", action='store_true', dest="list_only_applications", default=False) parser.add_option("-i", "--installed", help="include all installed applications", action='store_true', dest="include_all_applications", default=False) def _initialize(self, parser, options, args): if options.include_all_applications and not options.list_only_applications: parser.error("-i cannot be used without -a") self._list_only_applications = options.list_only_applications self._include_all_applications = options.include_all_applications def _usage(self): return "usage: %prog [options]" def _start(self): if self._list_only_applications: try: applications = self._device.enumerate_applications() except Exception as e: self._update_status("Failed to enumerate applications: %s" % e) self._exit(1) return if not self._include_all_applications: applications = list(filter(lambda app: app.pid != 0, applications)) if len(applications) > 0: pid_column_width = max(map(lambda app: len("%d" % app.pid), applications)) name_column_width = max(map(lambda app: len(app.name), applications)) identifier_column_width = max(map(lambda app: len(app.identifier), applications)) else: pid_column_width = 0 name_column_width = 0 identifier_column_width = 0 header_format = "%" + str(pid_column_width) + "s " + \ "%-" + str(name_column_width) + "s " + \ "%-" + str(identifier_column_width) + "s" self._print(header_format % ("PID", "Name", "Identifier")) self._print("%s %s %s" % (pid_column_width * "-", name_column_width * "-", identifier_column_width * "-")) line_format = "%" + str(pid_column_width) + "s " + \ "%-" + str(name_column_width) + "s " + \ "%-" + str(identifier_column_width) + "s" for app in sorted(applications, key=cmp_to_key(compare_applications)): if app.pid == 0: self._print(line_format % ("-", app.name, app.identifier)) else: self._print(line_format % (app.pid, app.name, app.identifier)) else: try: processes = self._device.enumerate_processes() except Exception as e: self._update_status("Failed to enumerate processes: %s" % e) self._exit(1) return pid_column_width = max(map(lambda p: len("%d" % p.pid), processes)) name_column_width = max(map(lambda p: len(p.name), processes)) header_format = "%" + str(pid_column_width) + "s %s" self._print(header_format % ("PID", "Name")) self._print("%s %s" % (pid_column_width * "-", name_column_width * "-")) line_format = "%" + str(pid_column_width) + "d %s" for process in sorted(processes, key=cmp_to_key(compare_processes)): self._print(line_format % (process.pid, process.name)) self._exit(0) def compare_applications(a, b): a_is_running = a.pid != 0 b_is_running = b.pid != 0 if a_is_running == b_is_running: if a.name > b.name: return 1 elif a.name < b.name: return -1 else: return 0 elif a_is_running: return -1 else: return 1 def compare_processes(a, b): a_has_icon = a.get_small_icon() is not None b_has_icon = b.get_small_icon() is not None if a_has_icon == b_has_icon: if a.name > b.name: return 1 elif a.name < b.name: return -1 else: return 0 elif a_has_icon: return -1 else: return 1 def cmp_to_key(mycmp): "Convert a cmp= function into a key= function" class K: def __init__(self, obj, *args): self.obj = obj def __lt__(self, other): return mycmp(self.obj, other.obj) < 0 def __gt__(self, other): return mycmp(self.obj, other.obj) > 0 def __eq__(self, other): return mycmp(self.obj, other.obj) == 0 def __le__(self, other): return mycmp(self.obj, other.obj) <= 0 def __ge__(self, other): return mycmp(self.obj, other.obj) >= 0 def __ne__(self, other): return mycmp(self.obj, other.obj) != 0 return K app = PSApplication() app.run() if __name__ == '__main__': main()