Removed references to printable streams

Also added the initial tests for all GTFO bins.
This commit is contained in:
Caleb Stewart 2021-09-18 23:40:07 -04:00
parent 052bf9b00d
commit 78b12ff915
2 changed files with 239 additions and 18 deletions

View File

@ -172,11 +172,6 @@
"payload": "{command} 'BEGIN {{system(\"{shell} -p\")}}'",
"exit": "exit"
},
{
"type": "read",
"stream": "print",
"payload": "{command} // {lfile}"
},
{
"type": "read",
"stream": "raw",
@ -439,7 +434,7 @@
{
"type": "read",
"stream": "print",
"payload": "{command}",
"payload": "{command} 2>/dev/null",
"args": [
"--line-format=%L",
"/dev/null",
@ -909,8 +904,9 @@
{
"type": "read",
"stream": "print",
"payload": "{command}",
"payload": "{command} | {head} --bytes=-1",
"args": [
"-a",
"''",
"{lfile}"
]
@ -1368,11 +1364,6 @@
"type": "shell",
"payload": "{command} 'BEGIN {{system(\"{shell} -p\")}}'"
},
{
"type": "read",
"stream": "print",
"payload": "{command} // {lfile}"
},
{
"type": "read",
"stream": "raw",
@ -1445,11 +1436,6 @@
"type": "shell",
"payload": "{command} 'BEGIN {{system(\"{shell} -p\")}}'"
},
{
"type": "read",
"stream": "print",
"payload": "{command} // {lfile}"
},
{
"type": "read",
"stream": "raw",
@ -2386,7 +2372,7 @@
{
"type": "read",
"stream": "print",
"payload": "{command}",
"payload": "{command} | {head} --bytes=-1",
"args": [
"-m",
"{lfile}"

View File

@ -1,6 +1,13 @@
#!/usr/bin/env python3
import json
import subprocess
import pytest
import pkg_resources
from pwncat.util import random_string
from pwncat.gtfobins import Stream, Capability
from pwncat.platform.linux import LinuxReader, LinuxWriter
def do_file_test(session, content):
@ -47,3 +54,231 @@ def test_large_binary(session):
contents = bytes(list(range(32))) * 400
do_file_test(session, contents)
# Load the GTFObins database to get test cases
with open(pkg_resources.resource_filename("pwncat", "data/gtfobins.json")) as filp:
gtfobins = json.load(filp)
gtfobin_raw_writers = [
key
for key, payloads in gtfobins.items()
if any(
[
payload["type"] == "write"
and "stream" in payload
and payload["stream"] == "raw"
for payload in payloads
]
)
]
gtfobin_print_writers = [
key
for key, payloads in gtfobins.items()
if any(
[
payload["type"] == "write"
and ("stream" not in payload or payload["stream"] == "print")
for payload in payloads
]
)
]
gtfobin_raw_readers = [
key
for key, payloads in gtfobins.items()
if any(
[
payload["type"] == "read"
and "stream" in payload
and payload["stream"] == "raw"
for payload in payloads
]
)
]
gtfobin_print_readers = [
key
for key, payloads in gtfobins.items()
if any(
[
payload["type"] == "read"
and ("stream" not in payload or payload["stream"] == "print")
for payload in payloads
]
)
]
gtfobin_shells = [
key
for key, payloads in gtfobins.items()
if len([payload["type"] == "shell" for payload in payloads])
]
@pytest.mark.parametrize("binary", gtfobin_print_readers)
def test_gtfobin_read_print(binary, linux):
# Find the local binary
binary_path = linux.platform.which(binary)
# Skip if binary not available
if binary_path is None:
pytest.skip("binary not available")
for method in linux.platform.gtfo.iter_binary(
binary_path, caps=Capability.READ, stream=Stream.PRINT
):
payload, input_data, exit_cmd = method.build(
gtfo=linux.platform.gtfo, lfile="/tests/print", suid=False
)
popen = linux.platform.Popen(
payload,
shell=True,
stdin=subprocess.PIPE,
bootstrap_input=input_data.encode("utf-8"),
)
stream = LinuxReader(
popen,
on_close=lambda filp: filp.popen.platform.channel.send(
exit_cmd.encode("utf-8")
),
name="/tests/print",
)
with stream:
assert stream.read() == "Hello\nWorld".encode("utf-8")
@pytest.mark.parametrize("binary", gtfobin_raw_readers)
def test_gtfobin_read_raw(binary, linux):
# Find the local binary
binary_path = linux.platform.which(binary)
# Skip if binary not available
if binary_path is None:
pytest.skip("binary not available")
for method in linux.platform.gtfo.iter_binary(
binary_path, caps=Capability.READ, stream=Stream.RAW
):
payload, input_data, exit_cmd = method.build(
gtfo=linux.platform.gtfo, lfile="/tests/raw", suid=False
)
popen = linux.platform.Popen(
payload,
shell=True,
stdin=subprocess.PIPE,
bootstrap_input=input_data.encode("utf-8"),
)
stream = LinuxReader(
popen,
on_close=lambda filp: filp.popen.platform.channel.send(
exit_cmd.encode("utf-8")
),
name="/tests/raw",
)
with stream:
assert stream.read() == bytes(list(range(256)))
@pytest.mark.parametrize("binary", gtfobin_raw_writers)
def test_gtfobin_write_raw(binary, linux):
# Find the local binary
binary_path = linux.platform.which(binary)
# Skip if binary not available
if binary_path is None:
pytest.skip("binary not available")
for method in linux.platform.gtfo.iter_binary(
binary_path, caps=Capability.WRITE, stream=Stream.RAW
):
payload, input_data, exit_cmd = method.build(
gtfo=linux.platform.gtfo, lfile="/tmp/write_raw", suid=False
)
popen = linux.platform.Popen(
payload,
shell=True,
stdin=subprocess.PIPE,
bootstrap_input=input_data.encode("utf-8"),
)
stream = LinuxWriter(
popen,
on_close=lambda filp: filp.popen.platform.channel.send(
exit_cmd.encode("utf-8")
),
name="/tmp/write_raw",
)
with stream:
assert stream.write(bytes(list(range(256)))) == 256
with linux.platform.open("/tmp/write_raw", "rb") as filp:
assert filp.read() == bytes(list(range(256)))
linux.platform.unlink("/tmp/write_raw")
@pytest.mark.parametrize("binary", gtfobin_print_writers)
def test_gtfobin_write_print(binary, linux):
content = b"Hello\nWorld"
# Find the local binary
binary_path = linux.platform.which(binary)
# Skip if binary not available
if binary_path is None:
pytest.skip("binary not available")
for method in linux.platform.gtfo.iter_binary(
binary_path, caps=Capability.WRITE, stream=Stream.PRINT
):
payload, input_data, exit_cmd = method.build(
gtfo=linux.platform.gtfo, lfile="/tmp/write_print", suid=False
)
popen = linux.platform.Popen(
payload,
shell=True,
stdin=subprocess.PIPE,
bootstrap_input=input_data.encode("utf-8"),
)
stream = LinuxWriter(
popen,
on_close=lambda filp: filp.popen.platform.channel.send(
exit_cmd.encode("utf-8")
),
name="/tmp/write_print",
)
with stream:
assert stream.write(content) == len(content)
with linux.platform.open("/tmp/write_print", "rb") as filp:
assert filp.read() == content
linux.platform.unlink("/tmp/write_print")
# @pytest.mark.parametrize("binary", gtfobin_writers)
# def test_gtfobin_write(binary, session):
#
# # Skip if binary not available
# if session.platform.which(binary) is None:
# pytest.skip("binary not available")
#
# return
#
#
# @pytest.mark.parametrize("binary", gtfobin_shells)
# def test_gtfobin_shell(binary, session):
#
# # Skip if binary not available
# if session.platform.which(binary) is None:
# pytest.skip("binary not available")
#
# return