2021-04-10 21:52:47 +02:00
|
|
|
#!/usr/bin/env python3
|
2021-05-31 21:11:26 +02:00
|
|
|
import io
|
2021-04-10 21:52:47 +02:00
|
|
|
import os
|
|
|
|
import base64
|
2021-05-30 06:24:12 +02:00
|
|
|
import subprocess
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-30 06:24:12 +02:00
|
|
|
import pytest
|
2021-06-13 23:15:22 +02:00
|
|
|
|
2021-05-30 06:24:12 +02:00
|
|
|
from pwncat.util import random_string
|
2021-05-31 21:11:26 +02:00
|
|
|
from pwncat.platform.windows import PowershellError
|
2021-04-10 21:52:47 +02:00
|
|
|
|
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
def test_platform_file_io(session):
|
2021-05-30 06:24:12 +02:00
|
|
|
""" Test file read/write of printable data """
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
# Generate random binary data
|
2021-05-30 06:24:12 +02:00
|
|
|
contents = os.urandom(1024)
|
2021-05-31 03:01:57 +02:00
|
|
|
|
|
|
|
# Create a new temporary file
|
2021-05-30 06:24:12 +02:00
|
|
|
with session.platform.tempfile(mode="wb") as filp:
|
|
|
|
filp.write(contents)
|
|
|
|
path = filp.name
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
# Ensure it exists
|
2021-05-30 06:24:12 +02:00
|
|
|
assert session.platform.Path(path).exists()
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
# Read the data back and ensure it matches
|
2021-05-30 06:24:12 +02:00
|
|
|
with session.platform.open(path, "rb") as filp:
|
|
|
|
assert contents == filp.read()
|
2021-04-10 21:52:47 +02:00
|
|
|
|
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
def test_platform_dir_io(session):
|
|
|
|
""" Test creating a directory and interacting with the contents """
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
# Create a path object representing the new remote directory
|
2021-05-30 06:24:12 +02:00
|
|
|
path = session.platform.Path(random_string())
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
# Create the directory
|
2021-05-30 06:24:12 +02:00
|
|
|
path.mkdir()
|
2021-05-31 03:01:57 +02:00
|
|
|
|
|
|
|
# We construct a new path object to avoid cached stat results
|
2021-05-30 06:24:12 +02:00
|
|
|
assert session.platform.Path(str(path)).is_dir()
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-31 03:01:57 +02:00
|
|
|
# Create a file
|
|
|
|
(path / "test.txt").touch()
|
|
|
|
|
|
|
|
assert "test.txt" in [item.name for item in path.iterdir()]
|
|
|
|
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-30 06:24:12 +02:00
|
|
|
def test_platform_run(session):
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-30 06:24:12 +02:00
|
|
|
# Ensure command output works
|
|
|
|
output_remote = session.platform.run(
|
2021-05-31 03:01:57 +02:00
|
|
|
["echo", "hello world"], shell=True, capture_output=True, text=True, check=True
|
2021-05-30 06:24:12 +02:00
|
|
|
)
|
|
|
|
assert output_remote.stdout == "hello world\n"
|
2021-04-10 21:52:47 +02:00
|
|
|
|
2021-05-30 06:24:12 +02:00
|
|
|
# Ensure we capture the process return code properly
|
|
|
|
with pytest.raises(subprocess.CalledProcessError):
|
|
|
|
session.platform.run("this_command_doesnt_exist", shell=True, check=True)
|
2021-05-31 03:01:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_platform_su(session):
|
|
|
|
""" Test running `su` """
|
|
|
|
|
|
|
|
try:
|
|
|
|
session.platform.su("john", "P@ssw0rd")
|
|
|
|
session.platform.refresh_uid()
|
|
|
|
|
|
|
|
assert session.current_user().name == "john"
|
|
|
|
|
|
|
|
with pytest.raises(PermissionError):
|
|
|
|
session.platform.su("caleb", "wrongpassword")
|
|
|
|
|
|
|
|
except NotImplementedError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def test_platform_sudo(session):
|
|
|
|
""" Testing running `sudo` """
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
# We have permission to run `/bin/sh *`, so this should succeed
|
|
|
|
proc = session.platform.sudo(
|
|
|
|
"whoami", user="john", shell=True, stdout=subprocess.PIPE, text=True
|
|
|
|
)
|
|
|
|
output = proc.stdout.read().strip()
|
|
|
|
|
|
|
|
assert proc.wait() == 0
|
|
|
|
assert output == "john"
|
|
|
|
|
|
|
|
# We don't have permission to run a bare `whoami`, so this should fail
|
|
|
|
proc = session.platform.sudo(
|
|
|
|
["whoami"], user="john", shell=False, stdout=subprocess.PIPE, text=True
|
|
|
|
)
|
|
|
|
output = proc.stdout.read().strip()
|
|
|
|
|
|
|
|
assert proc.wait() != 0
|
|
|
|
assert output != "john"
|
|
|
|
except NotImplementedError:
|
|
|
|
pass
|
2021-05-31 21:11:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
def test_windows_powershell(windows):
|
|
|
|
""" Test powershell execution """
|
|
|
|
|
|
|
|
# Run a real powershell snippet
|
|
|
|
r = windows.platform.powershell("$PSVersionTable.PSVersion")
|
|
|
|
assert len(r) == 1
|
|
|
|
assert isinstance(r[0], dict)
|
|
|
|
|
|
|
|
# Ensure we get an exception
|
|
|
|
with pytest.raises(PowershellError):
|
|
|
|
windows.platform.powershell("CommandletDoes-NotExist")
|
|
|
|
|
|
|
|
# Run from a file descriptor
|
|
|
|
filp = io.BytesIO(b"""$PSVersionTable.PSVersion""")
|
|
|
|
r = windows.platform.powershell(filp)
|
|
|
|
assert len(r) == 1
|
|
|
|
assert isinstance(r[0], dict)
|