Files
greyhack/provision.py

205 lines
6.1 KiB
Python

#!/usr/bin/env python3
from pathlib import Path
import re
ROOT = Path(__file__).resolve().parent
SOURCE_DIR = ROOT / "source"
OUTPUT = ROOT / "provision.src"
DOWNLOADED_BINARIES = [
"nmap",
"smtp-user-list",
"ssh-server",
"http-server",
"ftp-server",
"chat-server",
"repository-server",
"wallet",
"decipher",
"rshell-interface",
"rshell-server",
"scanlib",
"scanrouter",
"sniffer",
]
DOWNLOADED_EXECUTABLES = ["Stocks.exe", "ExploitReport.exe", "AdminMonitor.exe"]
def variable_name(path: Path) -> str:
stem = re.sub(r"\W+", "_", path.stem.lower()).strip("_")
if not stem:
raise ValueError(f"cannot derive variable name from {path.name!r}")
if stem[0].isdigit():
stem = f"_{stem}"
return stem
def greyscript_string(value: str) -> str:
return '"' + value.replace('"', '""') + '"'
def content_lines(var: str, content: str) -> list[str]:
lines = [f'{var}_content = ""']
for line in content.splitlines():
lines.append(
f"{var}_content = {var}_content + {greyscript_string(line)} + NL"
)
return lines
def source_files() -> list[Path]:
files = sorted(SOURCE_DIR.glob("*.src"), key=lambda p: p.name)
bbuild = SOURCE_DIR / "bbuild.src"
if bbuild not in files:
raise RuntimeError(f"required bootstrap source missing: {bbuild}")
if bbuild in files:
files.remove(bbuild)
files.insert(0, bbuild)
return files
def chmod_lines(target: str, spec: str, indent: str = "") -> list[str]:
# Grey Hack File.chmod accepts one class per call, e.g. "u+rwx", not "u+rwx,g+rx".
return [f'{indent}{target}.chmod("{part}")' for part in spec.split(",")]
def install_binary_lines(var: str, bin_name: str) -> list[str]:
return install_file_lines(var, f"/bin/{bin_name}", bin_name)
def install_file_lines(var: str, path: str, name: str) -> list[str]:
return [
f'{var}_bin = cp.File("{path}")',
f'if not {var}_bin then exit("Failed to install {name}")',
f'{var}_bin.set_group("root")',
f'{var}_bin.set_owner("root")',
*chmod_lines(f"{var}_bin", "u+rwx,g+rx,o+rx"),
"",
]
def downloaded_program_lines(name: str, destination: str) -> list[str]:
var = variable_name(Path(name))
return [
f'{var}_bin = cp.File(home + "/{name}")',
f'if not {var}_bin then',
f'\tprint("Missing downloaded program: {name}")',
f'else',
f'\t{var}_bin.move("{destination}", "{name}")',
f'\t{var}_bin = cp.File("{destination}/{name}")',
f'\tif not {var}_bin then',
f'\t\tprint("Failed to install {name}")',
f'\telse',
f'\t\t{var}_bin.set_group("root")',
f'\t\t{var}_bin.set_owner("root")',
*chmod_lines(f"{var}_bin", "u+rwx,g+rx,o+rx", indent="\t\t"),
f'\tend if',
f'end if',
"",
]
def metaxploit_lines() -> list[str]:
return [
'metaxploit_lib = cp.File(home + "/metaxploit.so")',
"if not metaxploit_lib then",
'\tprint("Missing metaxploit.so")',
"else",
'\tmetaxploit_lib.copy(home + "/guest", "metaxploit.so")',
'\tmetaxploit_guest = cp.File(home + "/guest/metaxploit.so")',
"\tif not metaxploit_guest then",
'\t\tprint("Failed to copy metaxploit.so to guest")',
"\telse",
*chmod_lines("metaxploit_guest", "u+rwx,g+rx,o+rx", indent="\t\t"),
'\t\tmetaxploit_guest.set_group("guest")',
'\t\tmetaxploit_guest.set_owner("guest")',
"\tend if",
'\tmetaxploit_lib.move("/lib", "metaxploit.so")',
'\tmetaxploit_lib = cp.File("/lib/metaxploit.so")',
"\tif not metaxploit_lib then",
'\t\tprint("Failed to install metaxploit.so")',
"\telse",
'\t\tmetaxploit_lib.set_group("root")',
'\t\tmetaxploit_lib.set_owner("root")',
*chmod_lines("metaxploit_lib", "u+rw,g+rw,o+rw", indent="\t\t"),
"\tend if",
"end if",
"",
]
def build_provision() -> str:
sources = source_files()
if not sources:
raise RuntimeError(f"no .src files found in {SOURCE_DIR}")
output: list[str] = [
"cp = get_shell.host_computer",
'home = "/home/" + active_user',
"NL = char(10)",
'cp.create_folder(home, "source")',
'cp.create_folder(home, "guest")',
"",
]
for src in sources:
var = variable_name(src)
output.extend(
[
f'cp.touch(home + "/source/", "{src.name}")',
f'{var}_source = cp.File(home + "/source/{src.name}")',
*content_lines(var, src.read_text()),
f"{var}_source.set_content({var}_content)",
"",
]
)
for name in DOWNLOADED_BINARIES:
output.extend(downloaded_program_lines(name, "/bin"))
for name in DOWNLOADED_EXECUTABLES:
output.extend(downloaded_program_lines(name, "/usr/bin"))
output.extend(metaxploit_lines())
bbuild = sources[0]
bbuild_var = variable_name(bbuild)
output.extend(
[
f"build_result = get_shell.build({bbuild_var}_source.path, current_path)",
'if build_result != "" then exit(build_result)',
f'{bbuild_var}_bin = cp.File(current_path + "/bbuild")',
f'if not {bbuild_var}_bin then exit("Failed to build bbuild")',
f'{bbuild_var}_bin.move("/bin", "bbuild")',
*install_binary_lines(bbuild_var, "bbuild"),
]
)
for src in sources[1:]:
var = variable_name(src)
bin_name = src.stem
output.extend(
[
f'get_shell.launch("/bin/bbuild", {var}_source.path)',
*install_binary_lines(var, bin_name),
]
)
output.extend(
[
'provision_source = cp.File(home + "/provision.src")',
"if provision_source then provision_source.delete",
'provision_bin = cp.File(home + "/provision")',
"if provision_bin then provision_bin.delete",
]
)
return "\n".join(output) + "\n"
def main() -> None:
OUTPUT.write_text(build_provision())
if __name__ == "__main__":
main()