This repository has been archived on 2024-09-30. You can view files and clone it, but cannot push or open issues/pull-requests.
hook-frida/venv/Lib/site-packages/frida_tools/ls.py

140 lines
4.3 KiB
Python

import argparse
import codecs
import os
from datetime import datetime, timezone
from operator import itemgetter
from typing import Any, List
from colorama import Fore, Style
from frida_tools.application import ConsoleApplication
STYLE_DIR = Fore.BLUE + Style.BRIGHT
STYLE_EXECUTABLE = Fore.GREEN + Style.BRIGHT
STYLE_LINK = Fore.CYAN + Style.BRIGHT
STYLE_ERROR = Fore.RED + Style.BRIGHT
def main() -> None:
app = LsApplication()
app.run()
class LsApplication(ConsoleApplication):
def _add_options(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument("files", help="files to list information about", nargs="*")
def _usage(self) -> str:
return "%(prog)s [options] [FILE]..."
def _initialize(self, parser: argparse.ArgumentParser, options: argparse.Namespace, args: List[str]) -> None:
self._files = options.files
def _needs_target(self) -> bool:
return False
def _start(self) -> None:
try:
self._attach(0)
data_dir = os.path.dirname(__file__)
with codecs.open(os.path.join(data_dir, "fs_agent.js"), "r", "utf-8") as f:
source = f.read()
def on_message(message: Any, data: Any) -> None:
print(message)
assert self._session is not None
script = self._session.create_script(name="ls", source=source)
script.on("message", on_message)
self._on_script_created(script)
script.load()
groups = script.exports_sync.ls(self._files)
except Exception as e:
self._update_status(f"Failed to retrieve listing: {e}")
self._exit(1)
return
exit_status = 0
for i, group in enumerate(sorted(groups, key=lambda g: g["path"])):
path = group["path"]
if path != "" and len(groups) > 1:
if i > 0:
self._print("")
self._print(path + ":")
for path, message in group["errors"]:
self._print(STYLE_ERROR + message + Style.RESET_ALL)
exit_status = 2
rows = []
for name, target, type, access, nlink, owner, group, size, raw_mtime in group["entries"]:
mtime = datetime.fromtimestamp(raw_mtime / 1000.0, tz=timezone.utc)
rows.append((type + access, str(nlink), owner, group, str(size), mtime.strftime("%c"), name, target))
if len(rows) == 0:
break
widths = []
for column_index in range(len(rows[0]) - 2):
width = max(map(lambda row: len(row[column_index]), rows))
widths.append(width)
adjustments = [
"",
">",
"<",
"<",
">",
"<",
]
col_formats = []
for i, width in enumerate(widths):
adj = adjustments[i]
if adj != "":
fmt = "{:" + adj + str(width) + "}"
else:
fmt = "{}"
col_formats.append(fmt)
row_description = " ".join(col_formats)
for row in sorted(rows, key=itemgetter(6)):
meta_fields = row_description.format(*row[:-2])
name, target = row[6:8]
ftype_and_perms = row[0]
ftype = ftype_and_perms[0]
fperms = ftype_and_perms[1:]
name = format_name(name, ftype, fperms, target)
self._print(meta_fields + " " + name)
self._exit(exit_status)
def format_name(name: str, ftype: str, fperms: str, target) -> str:
if ftype == "l":
target_path, target_details = target
if target_details is not None:
target_type, target_perms = target_details
target_summary = format_name(target_path, target_type, target_perms, None)
else:
target_summary = STYLE_ERROR + target_path + Style.RESET_ALL
return STYLE_LINK + name + Style.RESET_ALL + " -> " + target_summary
if ftype == "d":
return STYLE_DIR + name + Style.RESET_ALL
if "x" in fperms:
return STYLE_EXECUTABLE + name + Style.RESET_ALL
return name
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
pass