coercer.protocols.MS_FSRVP

  1#!/usr/bin/env python3
  2# -*- coding: utf-8 -*-
  3# File name          : MS_FSRVP.py
  4# Author             : Podalirius (@podalirius_)
  5# Date created       : 6 Jul 2022
  6
  7
  8import sys
  9from coercer.utils.RPCProtocol import RPCProtocol, DCERPCSessionError
 10from impacket.dcerpc.v5.ndr import NDRCALL
 11from impacket.dcerpc.v5.dtypes import WSTR
 12from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_PRIVACY
 13
 14
 15class IsPathShadowCopied(NDRCALL):
 16    opnum = 9
 17    structure = (
 18        ('ShareName', WSTR),  # Type: LPWSTR
 19    )
 20
 21
 22class IsPathShadowCopiedResponse(NDRCALL):
 23    structure = ()
 24
 25
 26class IsPathSupported(NDRCALL):
 27    opnum = 8
 28    structure = (
 29        ('ShareName', WSTR),  # Type: LPWSTR
 30    )
 31
 32
 33class IsPathSupportedResponse(NDRCALL):
 34    structure = ()
 35
 36
 37class MS_FSRVP(RPCProtocol):
 38    name = "[MS-FSRVP]: File Server Remote VSS Protocol"
 39    shortname = "MS-FSRVP"
 40    uuid = "a8e0653c-2744-4389-a61d-7373df8b2292"
 41    version = "1.0"
 42    available_pipes = [r"\PIPE\Fssagentrpc"]
 43
 44    auth_type = RPC_C_AUTHN_WINNT
 45    auth_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY
 46
 47    def IsPathSupported(self, listener, share="NETLOGON", max_retries=3):
 48        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/6813bfa8-1538-4c5f-982a-ad58caff3c1c
 49        # Finding credits: @topotam77 and @_nwodtuhs
 50        call_name, call_opnum = "IsPathSupported", 8
 51        if self.dce is not None:
 52            tries = 0
 53            while tries <= max_retries:
 54                tries += 1
 55                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="")
 56                sys.stdout.flush()
 57                try:
 58                    request = IsPathSupported()
 59                    request['ShareName'] = '\\\\%s\\%s\\\x00' % (listener, share)
 60                    if self.debug:
 61                        request.dump()
 62                    self.dce.request(request)
 63                except Exception as e:
 64                    if self.verbose:
 65                        print(e)
 66        else:
 67            if self.verbose:
 68                print("[!] Error: dce is None, you must call connect() first.")
 69
 70    def IsPathShadowCopied(self, listener, share="NETLOGON", max_retries=3):
 71        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/6813bfa8-1538-4c5f-982a-ad58caff3c1c
 72        # Finding credits: @topotam77 and @_nwodtuhs
 73        call_name, call_opnum = "IsPathShadowCopied", 9
 74        if self.dce is not None:
 75            tries = 0
 76            while tries <= max_retries:
 77                tries += 1
 78                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="")
 79                sys.stdout.flush()
 80                try:
 81                    request = IsPathShadowCopied()
 82                    request['ShareName'] = '\\\\%s\\%s\x00' % (listener, share)
 83                    if self.debug:
 84                        request.dump()
 85                    self.dce.request(request)
 86                except Exception as e:
 87                    print(e)
 88        else:
 89            print("[!] Error: dce is None, you must call connect() first.")
 90
 91    @classmethod
 92    def list_coerce_methods(cls):
 93        return [
 94            ("IsPathSupported", 8, None),
 95            ("IsPathShadowCopied", 9, None)
 96        ]
 97
 98    def perform_coerce_calls(self, listener):
 99        if listener is not None:
100            self.IsPathSupported(listener)
101            self.IsPathShadowCopied(listener)
class IsPathShadowCopied(impacket.dcerpc.v5.ndr.NDRCALL):
16class IsPathShadowCopied(NDRCALL):
17    opnum = 9
18    structure = (
19        ('ShareName', WSTR),  # Type: LPWSTR
20    )

This will be the base class for all DCERPC NDR Types and represents a NDR Primitive Type

Inherited Members
impacket.dcerpc.v5.ndr.NDRCALL
NDRCALL
dump
getData
fromString
impacket.dcerpc.v5.ndr.NDRCONSTRUCTEDTYPE
isPointer
isUnion
getDataReferents
getDataReferent
calcPackSize
getArrayMaximumSize
getArraySize
fromStringReferents
fromStringReferent
calcUnPackSize
impacket.dcerpc.v5.ndr.NDR
changeTransferSyntax
getDataLen
isNDR
dumpRaw
getAlignment
calculatePad
pack
unpack
class IsPathShadowCopiedResponse(impacket.dcerpc.v5.ndr.NDRCALL):
23class IsPathShadowCopiedResponse(NDRCALL):
24    structure = ()

This will be the base class for all DCERPC NDR Types and represents a NDR Primitive Type

Inherited Members
impacket.dcerpc.v5.ndr.NDRCALL
NDRCALL
dump
getData
fromString
impacket.dcerpc.v5.ndr.NDRCONSTRUCTEDTYPE
isPointer
isUnion
getDataReferents
getDataReferent
calcPackSize
getArrayMaximumSize
getArraySize
fromStringReferents
fromStringReferent
calcUnPackSize
impacket.dcerpc.v5.ndr.NDR
changeTransferSyntax
getDataLen
isNDR
dumpRaw
getAlignment
calculatePad
pack
unpack
class IsPathSupported(impacket.dcerpc.v5.ndr.NDRCALL):
27class IsPathSupported(NDRCALL):
28    opnum = 8
29    structure = (
30        ('ShareName', WSTR),  # Type: LPWSTR
31    )

This will be the base class for all DCERPC NDR Types and represents a NDR Primitive Type

Inherited Members
impacket.dcerpc.v5.ndr.NDRCALL
NDRCALL
dump
getData
fromString
impacket.dcerpc.v5.ndr.NDRCONSTRUCTEDTYPE
isPointer
isUnion
getDataReferents
getDataReferent
calcPackSize
getArrayMaximumSize
getArraySize
fromStringReferents
fromStringReferent
calcUnPackSize
impacket.dcerpc.v5.ndr.NDR
changeTransferSyntax
getDataLen
isNDR
dumpRaw
getAlignment
calculatePad
pack
unpack
class IsPathSupportedResponse(impacket.dcerpc.v5.ndr.NDRCALL):
34class IsPathSupportedResponse(NDRCALL):
35    structure = ()

This will be the base class for all DCERPC NDR Types and represents a NDR Primitive Type

Inherited Members
impacket.dcerpc.v5.ndr.NDRCALL
NDRCALL
dump
getData
fromString
impacket.dcerpc.v5.ndr.NDRCONSTRUCTEDTYPE
isPointer
isUnion
getDataReferents
getDataReferent
calcPackSize
getArrayMaximumSize
getArraySize
fromStringReferents
fromStringReferent
calcUnPackSize
impacket.dcerpc.v5.ndr.NDR
changeTransferSyntax
getDataLen
isNDR
dumpRaw
getAlignment
calculatePad
pack
unpack
class MS_FSRVP(coercer.utils.RPCProtocol.RPCProtocol):
 38class MS_FSRVP(RPCProtocol):
 39    name = "[MS-FSRVP]: File Server Remote VSS Protocol"
 40    shortname = "MS-FSRVP"
 41    uuid = "a8e0653c-2744-4389-a61d-7373df8b2292"
 42    version = "1.0"
 43    available_pipes = [r"\PIPE\Fssagentrpc"]
 44
 45    auth_type = RPC_C_AUTHN_WINNT
 46    auth_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY
 47
 48    def IsPathSupported(self, listener, share="NETLOGON", max_retries=3):
 49        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/6813bfa8-1538-4c5f-982a-ad58caff3c1c
 50        # Finding credits: @topotam77 and @_nwodtuhs
 51        call_name, call_opnum = "IsPathSupported", 8
 52        if self.dce is not None:
 53            tries = 0
 54            while tries <= max_retries:
 55                tries += 1
 56                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="")
 57                sys.stdout.flush()
 58                try:
 59                    request = IsPathSupported()
 60                    request['ShareName'] = '\\\\%s\\%s\\\x00' % (listener, share)
 61                    if self.debug:
 62                        request.dump()
 63                    self.dce.request(request)
 64                except Exception as e:
 65                    if self.verbose:
 66                        print(e)
 67        else:
 68            if self.verbose:
 69                print("[!] Error: dce is None, you must call connect() first.")
 70
 71    def IsPathShadowCopied(self, listener, share="NETLOGON", max_retries=3):
 72        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/6813bfa8-1538-4c5f-982a-ad58caff3c1c
 73        # Finding credits: @topotam77 and @_nwodtuhs
 74        call_name, call_opnum = "IsPathShadowCopied", 9
 75        if self.dce is not None:
 76            tries = 0
 77            while tries <= max_retries:
 78                tries += 1
 79                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="")
 80                sys.stdout.flush()
 81                try:
 82                    request = IsPathShadowCopied()
 83                    request['ShareName'] = '\\\\%s\\%s\x00' % (listener, share)
 84                    if self.debug:
 85                        request.dump()
 86                    self.dce.request(request)
 87                except Exception as e:
 88                    print(e)
 89        else:
 90            print("[!] Error: dce is None, you must call connect() first.")
 91
 92    @classmethod
 93    def list_coerce_methods(cls):
 94        return [
 95            ("IsPathSupported", 8, None),
 96            ("IsPathShadowCopied", 9, None)
 97        ]
 98
 99    def perform_coerce_calls(self, listener):
100        if listener is not None:
101            self.IsPathSupported(listener)
102            self.IsPathShadowCopied(listener)

Documentation for class RPCProtocol

def IsPathSupported(self, listener, share='NETLOGON', max_retries=3):
48    def IsPathSupported(self, listener, share="NETLOGON", max_retries=3):
49        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/6813bfa8-1538-4c5f-982a-ad58caff3c1c
50        # Finding credits: @topotam77 and @_nwodtuhs
51        call_name, call_opnum = "IsPathSupported", 8
52        if self.dce is not None:
53            tries = 0
54            while tries <= max_retries:
55                tries += 1
56                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="")
57                sys.stdout.flush()
58                try:
59                    request = IsPathSupported()
60                    request['ShareName'] = '\\\\%s\\%s\\\x00' % (listener, share)
61                    if self.debug:
62                        request.dump()
63                    self.dce.request(request)
64                except Exception as e:
65                    if self.verbose:
66                        print(e)
67        else:
68            if self.verbose:
69                print("[!] Error: dce is None, you must call connect() first.")
def IsPathShadowCopied(self, listener, share='NETLOGON', max_retries=3):
71    def IsPathShadowCopied(self, listener, share="NETLOGON", max_retries=3):
72        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/6813bfa8-1538-4c5f-982a-ad58caff3c1c
73        # Finding credits: @topotam77 and @_nwodtuhs
74        call_name, call_opnum = "IsPathShadowCopied", 9
75        if self.dce is not None:
76            tries = 0
77            while tries <= max_retries:
78                tries += 1
79                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="")
80                sys.stdout.flush()
81                try:
82                    request = IsPathShadowCopied()
83                    request['ShareName'] = '\\\\%s\\%s\x00' % (listener, share)
84                    if self.debug:
85                        request.dump()
86                    self.dce.request(request)
87                except Exception as e:
88                    print(e)
89        else:
90            print("[!] Error: dce is None, you must call connect() first.")
@classmethod
def list_coerce_methods(cls):
92    @classmethod
93    def list_coerce_methods(cls):
94        return [
95            ("IsPathSupported", 8, None),
96            ("IsPathShadowCopied", 9, None)
97        ]
def perform_coerce_calls(self, listener):
 99    def perform_coerce_calls(self, listener):
100        if listener is not None:
101            self.IsPathSupported(listener)
102            self.IsPathShadowCopied(listener)