mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04:15 +01:00
Added documentation for new compile method
This commit is contained in:
parent
668eadbaef
commit
ffa1059a43
@ -164,6 +164,68 @@ Starting, stopping or enabling a service is as easy as calling a method or setti
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
print("sshd doesn't exist!")
|
print("sshd doesn't exist!")
|
||||||
|
|
||||||
|
Compiling Code for the Victim
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
``pwncat`` provides an abstract capability to compile binaries in ``C`` for the victim. By setting
|
||||||
|
the ``cross`` configuration item to the path to valid C compiler on your attacking system capable
|
||||||
|
of generating compiled binaries for the victim, you can have ``pwncat`` compile exploits locally
|
||||||
|
and upload only the compiled binaries. This not only speeds up privilege escalation checks, but also
|
||||||
|
enables some methods in the case the remote host does not have a working C compiler. If no ``cross``
|
||||||
|
value is provided, ``pwncat`` will still check for an utilize a remote compiler if available.
|
||||||
|
|
||||||
|
To access, this functionality, you can use the ``pwncat.victim.compile`` method. This method takes
|
||||||
|
a list of source files, an output suffix, and a list of CFLAGS and LDFLAGS. The result is the path
|
||||||
|
to the compiled binary on the remote host. Ideally, it will utilize a local cross-compiler and upload
|
||||||
|
the binary, but it is also capable of uploading the specified source files and compiling remotely
|
||||||
|
as well.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: Compiling Local Source Files For A Victim
|
||||||
|
|
||||||
|
import pwncat
|
||||||
|
|
||||||
|
# Compile your code for the remote host
|
||||||
|
remote_path = pwncat.victim.compile(["main.c", "other.c"], cflags=["-static"], ldflags=["-lssl"])
|
||||||
|
# Run the new binary
|
||||||
|
pwncat.victim.run(remote_path)
|
||||||
|
# Track the new binary in the tamper database
|
||||||
|
pwncat.victim.tamper.created_file(remote_path)
|
||||||
|
|
||||||
|
The list of sources can also accept file objects instead of file paths. In this case, you can wrap
|
||||||
|
a literal string in a `io.StringIO` object in order to compile short source files from memory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: Compiling Source From Memory
|
||||||
|
|
||||||
|
import pwncat
|
||||||
|
import textwrap
|
||||||
|
import io
|
||||||
|
|
||||||
|
# Simple in-memory source file
|
||||||
|
source = textwrap.dedent(r"""
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
printf("Hello World!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
# Compile the source file
|
||||||
|
remote_path = pwncat.victim.compile([io.StringIO(source)])
|
||||||
|
# will print b"Hello World!\n"
|
||||||
|
print(pwncat.victim.run(remote_path))
|
||||||
|
|
||||||
|
You can also utilize the CFLAGS argument to produce shared libraries if needed:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: Compiling Shared Libraries
|
||||||
|
|
||||||
|
import pwncat
|
||||||
|
|
||||||
|
# Compile the source as a shared library
|
||||||
|
remote_path = pwncat.victim.compile(["main.c"], cflags=["-fPIC", "-shared"], suffix=".so")
|
||||||
|
|
||||||
The Victim Object
|
The Victim Object
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
@ -60,7 +60,9 @@ class Command(CommandDefinition):
|
|||||||
|
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
|
|
||||||
if args.action == "list":
|
if args.action == "install":
|
||||||
|
pwncat.victim.bootstrap_busybox(args.url)
|
||||||
|
elif args.action == "list":
|
||||||
if pwncat.victim.host.busybox is None:
|
if pwncat.victim.host.busybox is None:
|
||||||
util.error(
|
util.error(
|
||||||
"busybox hasn't been installed yet (hint: run 'busybox --install'"
|
"busybox hasn't been installed yet (hint: run 'busybox --install'"
|
||||||
@ -95,5 +97,3 @@ class Command(CommandDefinition):
|
|||||||
.scalar()
|
.scalar()
|
||||||
)
|
)
|
||||||
util.info(f"busybox provides {Fore.GREEN}{nprovides}{Fore.RESET} applets")
|
util.info(f"busybox provides {Fore.GREEN}{nprovides}{Fore.RESET} applets")
|
||||||
elif args.action == "install":
|
|
||||||
pwncat.victim.bootstrap_busybox(args.url)
|
|
||||||
|
@ -159,7 +159,7 @@ class Command(CommandDefinition):
|
|||||||
if not args.user:
|
if not args.user:
|
||||||
self.parser.error("you must specify a user")
|
self.parser.error("you must specify a user")
|
||||||
|
|
||||||
if not args.password and not args.identity:
|
if not (args.password or args.identity):
|
||||||
self.parser.error("either a password or identity file is required")
|
self.parser.error("either a password or identity file is required")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -397,10 +397,7 @@ class Command(CommandDefinition):
|
|||||||
|
|
||||||
data: Dict[str, Dict[str, List[pwncat.db.Fact]]] = {}
|
data: Dict[str, Dict[str, List[pwncat.db.Fact]]] = {}
|
||||||
|
|
||||||
if isinstance(typ, list):
|
types = typ if isinstance(typ, list) else [typ]
|
||||||
types = typ
|
|
||||||
else:
|
|
||||||
types = [typ]
|
|
||||||
|
|
||||||
util.progress("enumerating facts")
|
util.progress("enumerating facts")
|
||||||
for typ in types:
|
for typ in types:
|
||||||
@ -429,10 +426,6 @@ class Command(CommandDefinition):
|
|||||||
def flush_facts(self, typ: str, provider: str):
|
def flush_facts(self, typ: str, provider: str):
|
||||||
""" Flush all facts that match criteria """
|
""" Flush all facts that match criteria """
|
||||||
|
|
||||||
if isinstance(typ, list):
|
types = typ if isinstance(typ, list) else [typ]
|
||||||
types = typ
|
|
||||||
else:
|
|
||||||
types = [typ]
|
|
||||||
|
|
||||||
for typ in types:
|
for typ in types:
|
||||||
pwncat.victim.enumerate.flush(typ, provider)
|
pwncat.victim.enumerate.flush(typ, provider)
|
||||||
|
Loading…
Reference in New Issue
Block a user