mirror of
https://github.com/naksyn/PythonMemoryModule
synced 2026-06-06 16:24:25 +00:00
db1893910c
This update include support to passing command line parameters to unmanaged exe via PEB stomping. This technique is not working with every executable since it depends on which functions are used to pass arguments. Generally, to get a universally working technique would be required to hook GetCommandlineA GetCommandlineW __getmainargs and __wgetmainargs since PEB stomping won't cover all cases, more details here: https://blog-30cm-tw.translate.goog/2020/08/windows-c-mainargc-argv.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=it&_x_tr_pto=wapp However, during my testing I found that mimikatz and several go binaries are working just by doing PEB stomping. On the other hand, cmdline passing via PEB stomping alone to mingw and VS compiled binaries won't likely work.
127 lines
4.3 KiB
Python
127 lines
4.3 KiB
Python
import windows
|
|
from windows import winproxy
|
|
import windows.generated_def as gdef
|
|
import ctypes
|
|
|
|
from windows.pycompat import is_py3
|
|
|
|
if is_py3:
|
|
from multiprocessing.connection import PipeConnection as native_PipeConnection
|
|
else:
|
|
from _multiprocessing import PipeConnection as native_PipeConnection
|
|
|
|
# Inspired from 'multiprocessing\connection.py'
|
|
|
|
def full_pipe_address(addr):
|
|
"""Return the full address of the pipe `addr`"""
|
|
if not isinstance(addr, bytes):
|
|
addr = addr.encode("ascii")
|
|
if addr.startswith(b"\\\\"):
|
|
return addr
|
|
return br"\\.\pipe" + "\\".encode() + addr
|
|
|
|
class PipeConnection(object): # Cannot inherit: crash the interpreter
|
|
"""A wrapper arround :class:`_multiprocessing.PipeConnection` able to work as a ContextManager"""
|
|
BUFFER_SIZE = 0x2000
|
|
|
|
def __init__(self, connection, name=None, server=False):
|
|
self.handle = connection.fileno()
|
|
self.connection = connection
|
|
self.name = name
|
|
self.server = server
|
|
|
|
@classmethod
|
|
def from_handle(cls, phandle, *args, **kwargs):
|
|
"""Create a :class:`PipeConnection` from pipe handle `phandle`"""
|
|
connection = native_PipeConnection(phandle)
|
|
return cls(connection, *args, **kwargs)
|
|
|
|
@classmethod
|
|
def create(cls, addr, security_descriptor=None):
|
|
"""Create a namedpipe pipe ``addr``
|
|
|
|
:returns type: :class:`PipeConnection`
|
|
"""
|
|
addr = full_pipe_address(addr)
|
|
|
|
security_attributes = None
|
|
if security_descriptor is not None:
|
|
if isinstance(security_descriptor, str):
|
|
security_descriptor = windows.security.SecurityDescriptor.from_string(security_descriptor)
|
|
security_attributes = gdef.SECURITY_ATTRIBUTES()
|
|
security_attributes.nLength = ctypes.sizeof(security_attributes)
|
|
security_attributes.lpSecurityDescriptor = security_descriptor # Accept as arg ?
|
|
security_attributes.bInheritHandle = True # Accept as arg ?
|
|
|
|
|
|
pipehandle = winproxy.CreateNamedPipeA(
|
|
addr, gdef.PIPE_ACCESS_DUPLEX,
|
|
gdef.PIPE_TYPE_MESSAGE | gdef.PIPE_READMODE_MESSAGE |
|
|
gdef.PIPE_WAIT,
|
|
gdef.PIPE_UNLIMITED_INSTANCES, cls.BUFFER_SIZE, cls.BUFFER_SIZE,
|
|
gdef.NMPWAIT_WAIT_FOREVER, security_attributes
|
|
)
|
|
return cls.from_handle(pipehandle, name=addr, server=True)
|
|
|
|
@classmethod
|
|
def connect(cls, addr):
|
|
"""Connect to the named pipe ``addr``
|
|
|
|
:returns type: :class:`PipeConnection`
|
|
"""
|
|
addr = full_pipe_address(addr)
|
|
pipehandle = winproxy.CreateFileA(addr, gdef.GENERIC_READ | gdef.GENERIC_WRITE, 0, None, gdef.OPEN_EXISTING, 0, None)
|
|
winproxy.SetNamedPipeHandleState(pipehandle, gdef.ULONG(gdef.PIPE_READMODE_MESSAGE), None, None)
|
|
return cls.from_handle(pipehandle, name=addr, server=False)
|
|
|
|
def send(self, *args, **kwargs):
|
|
"""Send an object on the pipe"""
|
|
return self.connection.send(*args, **kwargs)
|
|
|
|
def recv(self, *args, **kwargs):
|
|
"""Send an object from the pipe"""
|
|
return self.connection.recv(*args, **kwargs)
|
|
|
|
def wait_connection(self):
|
|
"""Wait for a client process to connect to the named pipe"""
|
|
return winproxy.ConnectNamedPipe(self.handle, None)
|
|
|
|
def get_security_descriptor(self):
|
|
return windows.security.SecurityDescriptor.from_handle(self.handle)
|
|
|
|
def set_security_descriptor(self, sd):
|
|
if isinstance(sd, basestring):
|
|
sd = windows.security.SecurityDescriptor.from_string(sd)
|
|
sd._apply_to_handle_and_type(self.handle)
|
|
|
|
security_descriptor = property(get_security_descriptor, set_security_descriptor)
|
|
|
|
def close(self):
|
|
"""Close the handle of the pipe"""
|
|
self.connection.close()
|
|
self.handle = None
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, *args, **kwargs):
|
|
self.close()
|
|
|
|
def __repr__(self):
|
|
return """<{0} name="{1}" server={2}>""".format(type(self).__name__, self.name, self.server)
|
|
|
|
|
|
connect = PipeConnection.connect
|
|
create = PipeConnection.create
|
|
|
|
def send_object(addr, obj):
|
|
"""Send `obj` on pipe ``addr``"""
|
|
with connect(addr) as np:
|
|
np.send(obj)
|
|
return None
|
|
|
|
def recv_object(addr):
|
|
"""Receive an object from pipe ``addr``"""
|
|
with create(addr) as np:
|
|
np.wait_connection()
|
|
return np.recv() |