From 4cdb94f12ce84a08165e9fafeae2c864ac8409cc Mon Sep 17 00:00:00 2001 From: Doron Shem Tov Date: Mon, 18 Apr 2022 13:44:43 +0300 Subject: [PATCH] Add support for custom named pipe permissions --- analyzer/windows/analyzer.py | 9 ++++-- analyzer/windows/lib/common/defines.py | 2 ++ analyzer/windows/lib/core/pipe.py | 41 ++++++++++++++++++++------ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/analyzer/windows/analyzer.py b/analyzer/windows/analyzer.py index 60b6957cb14..1616a86f12d 100644 --- a/analyzer/windows/analyzer.py +++ b/analyzer/windows/analyzer.py @@ -260,8 +260,10 @@ def prepare(self): # Initialize and start the Pipe Servers. This is going to be used for # communicating with the injected and monitored processes. - - self.command_pipe = PipeServer(PipeDispatcher, self.config.pipe, message=True, + custom_sddl = self.options.get("custom_pipe_sddl") + if custom_sddl: + log.info("Using custom pipe sddl: %s", custom_sddl) + self.command_pipe = PipeServer(PipeDispatcher, self.config.pipe, message=True, custom_sddl=custom_sddl, dispatcher=CommandPipeHandler(self)) self.command_pipe.daemon = True self.command_pipe.start() @@ -270,7 +272,8 @@ def prepare(self): # open up a pipe that monitored processes will use to send logs to # before they head off to the host machine. destination = self.config.ip, self.config.port - self.log_pipe_server = PipeServer(PipeForwarder, self.config.logpipe, destination=destination) + self.log_pipe_server = PipeServer(PipeForwarder, self.config.logpipe, custom_sddl=custom_sddl, + destination=destination) # We update the target according to its category. If it's a file, then # we store the path. diff --git a/analyzer/windows/lib/common/defines.py b/analyzer/windows/lib/common/defines.py index d99a33d7d7d..5be3f53dc54 100644 --- a/analyzer/windows/lib/common/defines.py +++ b/analyzer/windows/lib/common/defines.py @@ -117,6 +117,8 @@ TRUNCATE_EXISTING = 5 CREATE_NO_WINDOW = 0x08000000 +SDDL_REVISION_1 = 1 + class STARTUPINFO(Structure): _fields_ = [ diff --git a/analyzer/windows/lib/core/pipe.py b/analyzer/windows/lib/core/pipe.py index 98c1e78c7ca..7b57d8a5a22 100644 --- a/analyzer/windows/lib/core/pipe.py +++ b/analyzer/windows/lib/core/pipe.py @@ -10,13 +10,14 @@ from ctypes import create_string_buffer, c_uint, byref, sizeof, addressof -from lib.common.defines import KERNEL32, PIPE_ACCESS_INBOUND, ERROR_MORE_DATA +from lib.common.defines import KERNEL32, PIPE_ACCESS_INBOUND, ERROR_MORE_DATA, PVOID from lib.common.defines import PIPE_TYPE_BYTE, PIPE_WAIT, ERROR_PIPE_CONNECTED from lib.common.defines import PIPE_UNLIMITED_INSTANCES, INVALID_HANDLE_VALUE -from lib.common.defines import FILE_FLAG_WRITE_THROUGH, PIPE_READMODE_BYTE +from lib.common.defines import PIPE_READMODE_BYTE from lib.common.defines import ERROR_BROKEN_PIPE, PIPE_TYPE_MESSAGE from lib.common.defines import PIPE_ACCESS_DUPLEX, PIPE_READMODE_MESSAGE -from lib.common.defines import SECURITY_DESCRIPTOR, SECURITY_ATTRIBUTES, ADVAPI32 +from lib.common.defines import SECURITY_DESCRIPTOR, SECURITY_ATTRIBUTES, ADVAPI32, SDDL_REVISION_1 + log = logging.getLogger(__name__) BUFSIZE = 0x10000 @@ -150,26 +151,48 @@ def stop(self): class PipeServer(threading.Thread): """Accept incoming pipe handlers and initialize them in a new thread.""" - def __init__(self, pipe_handler, pipe_name, message=False, **kwargs): + def __init__(self, pipe_handler, pipe_name, message=False, custom_sddl=None, **kwargs): threading.Thread.__init__(self) self.pipe_handler = pipe_handler self.pipe_name = pipe_name self.message = message + self.custom_sddl = custom_sddl self.kwargs = kwargs self.do_run = True self.handlers = set() + def get_custom_security_descriptor(self): + if not self.custom_sddl: + return None + + sd = PVOID(0) + result = ADVAPI32.ConvertStringSecurityDescriptorToSecurityDescriptorW( + self.custom_sddl, SDDL_REVISION_1, addressof(sd), 0) + if result == 0: + err = KERNEL32.GetLastError() + log.warning("ConvertStringSecurityDescriptorToSecurityDescriptorW Failed. Err: %s", err) + return None + + return sd + def run(self): while self.do_run: # Create the Named Pipe. - sd = SECURITY_DESCRIPTOR() + if self.custom_sddl: + lp_security_descriptor = self.get_custom_security_descriptor() + if lp_security_descriptor is None: + log.warning("Failed to create pipe server security attributes.") + continue + else: + sd = SECURITY_DESCRIPTOR() + ADVAPI32.InitializeSecurityDescriptor(byref(sd), 1) + ADVAPI32.SetSecurityDescriptorDacl(byref(sd), True, None, False) + lp_security_descriptor = addressof(sd) + sa = SECURITY_ATTRIBUTES() - ADVAPI32.InitializeSecurityDescriptor(byref(sd), 1) - ADVAPI32.SetSecurityDescriptorDacl(byref(sd), True, None, False) sa.nLength = sizeof(SECURITY_ATTRIBUTES) sa.bInheritHandle = False - sa.lpSecurityDescriptor = addressof(sd) - # flags = FILE_FLAG_WRITE_THROUGH + sa.lpSecurityDescriptor = lp_security_descriptor if self.message: pipe_handle = KERNEL32.CreateNamedPipeW(