This file is indexed.

/usr/share/pyshared/impacket/dcerpc/srvsvcserver.py is in python-impacket 0.9.10-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# Copyright (c) 2003-2012 CORE Security Technologies
#
# This software is provided under under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# $Id: srvsvcserver.py 717 2012-09-13 14:39:12Z bethus@gmail.com $
#
# Author: Alberto Solino
#
# Description:
#   A minimalist DCE RPC Server, just for the purpose (for now) 
#   of making smbserver to work better with Windows 7, when being asked
#   for shares
#


import array
from impacket.dcerpc import dcerpc
from impacket import ntlm
from impacket import uuid
from impacket.uuid import uuidtup_to_bin, generate, stringver_to_bin, bin_to_uuidtup
import socket
import struct

class DCERPCServer():
    def __init__(self):
        self._listenPort    = 4343
        self._listenAddress = '0.0.0.0'
        self._listenUUIDS   = []
        self._callbacks     = {}
        self._boundUUID     = ''
        self._sock          = None
        self._clientSock    = None
        self._callid        = 1
        self._max_frag       = None
        self._max_xmit_size = 4280
 

    def addCallbacks(self, UUID, callbacks):
        # Format is [opnum] =  callback
        self._callbacks[uuidtup_to_bin(UUID)] = callbacks
        self._listenUUIDS.append(uuidtup_to_bin(UUID))
        print "Callback added for UUID %s V:%s" % UUID

    def setListenPort(self, portNum):
        self._listenPort = portNum

    def recv(self):
        finished = False
        forceRecv = 0
        retAnswer = ''
        while not finished:
            # At least give me the MSRPCRespHeader, especially important for TCP/UDP Transports
            self.response_data = self._clientSock.recv(dcerpc.MSRPCRespHeader._SIZE)
            # No data?, connection might have closed
            if self.response_data == '':
                return None
            self.response_header = dcerpc.MSRPCRespHeader(self.response_data)
            # Ok, there might be situation, especially with large packets, that the transport layer didn't send us the full packet's contents
            # So we gotta check we received it all
            while ( len(self.response_data) < self.response_header['frag_len'] ):
               self.response_data += self._clientSock.recv(self.response_header['frag_len']-len(self.response_data))
            self.response_header = dcerpc.MSRPCRespHeader(self.response_data)
            if self.response_header['flags'] & dcerpc.MSRPC_LASTFRAG:
                # No need to reassembly DCERPC
                finished = True
            else:
                # Forcing Read Recv, we need more packets!
                forceRecv = 1
            answer = self.response_header['pduData']
            auth_len = self.response_header['auth_len']
            if auth_len:
                auth_len += 8
                auth_data = answer[-auth_len:]
                ntlmssp   = ntlm.DCERPC_NTLMAuthHeader(data = auth_data)
                answer = answer[:-auth_len]
                if ntlmssp['auth_pad_len']:
                    answer = answer[:-ntlmssp['auth_pad_len']]
              
            retAnswer += answer
        return self.response_data
    
    def run(self):
        self._sock = socket.socket()
        self._sock.bind((self._listenAddress,self._listenPort))
        self._sock.listen(10)
        while True:
            self._clientSock, address = self._sock.accept()
            print "Connected from ", address
            try:
                while True:
                    data = self.recv()
                    if data is None:
                        # No data.. connection closed
                        break
                    answer = self.processRequest(data)
                    if answer != None:
                        self.send(answer)
            except Exception, e:
                #print e 
                print "Connection Finished!"
            self._clientSock.close()

    def send(self, data):
        max_frag       = self._max_frag
        if len(data['pduData']) > self._max_xmit_size - 32:
            max_frag   = self._max_xmit_size - 32    # XXX: 32 is a safe margin for auth data

        if self._max_frag:
            max_frag   = min(max_frag, self._max_frag)
        if max_frag and len(data['pduData']) > 0:
            packet     = data['pduData']
            offset     = 0
            while 1:
                toSend = packet[offset:offset+max_frag]
                if not toSend:
                    break
                flags  = 0
                if offset == 0:
                    flags |= dcerpc.MSRPC_FIRSTFRAG
                offset += len(toSend)
                if offset == len(packet):
                    flags |= dcerpc.MSRPC_LASTFRAG
                data['flags']   = flags
                data['pduData'] = toSend
                self._clientSock.send(data.get_packet())
        else:
            self._clientSock.send(data.get_packet())
        self._callid += 1

    def bind(self,packet, bind):
        # Standard NDR Representation
        NDRSyntax   = ('8a885d04-1ceb-11c9-9fe8-08002b104860', '2.0')
        resp = dcerpc.MSRPCBindAck()

        resp['type']             = dcerpc.MSRPC_BINDACK
        resp['flags']            = packet['flags']
        resp['frag_len']         = 0
        resp['auth_len']         = 0
        resp['auth_data']        = ''
        resp['call_id']          = packet['call_id'] 
        resp['max_tfrag']        = bind['max_tfrag']
        resp['max_rfrag']        = bind['max_rfrag']
        resp['assoc_group']      = 0x1234
        resp['SecondaryAddrLen'] = 4
        resp['SecondaryAddr']    = '135'
        resp['Pad']              ='A'*((4-((resp["SecondaryAddrLen"]+dcerpc.MSRPCBindAck._SIZE) % 4))%4)
        resp['ctx_num']          = 0

        data      = bind['ctx_items']
        ctx_items = ''
        for i in range(bind['ctx_num']):
            result = dcerpc.MSRPC_CONT_RESULT_USER_REJECT
            item   = dcerpc.CtxItem(data)
            data   = data[len(item):]

            # First we check the Transfer Syntax is NDR32, what we support
            #print "Trying to bind to: %s %s / %s %s" % (bin_to_uuidtup(item['AbstractSyntax']) + bin_to_uuidtup(item['TransferSyntax'])),

            if item['TransferSyntax'] == uuidtup_to_bin(NDRSyntax):
                # Now Check if the interface is what we listen
                reason = 1 # Default, Abstract Syntax not supported
                for i in self._listenUUIDS:
                    if item['AbstractSyntax'] == i:
                        # Match, we accept the bind request
                        reason           = 0
                        self._boundUUID = i
            else:
                # Fail the bind request for this context
                reason = 2 # Transfer Syntax not supported
            if reason == 0:
               result = dcerpc.MSRPC_CONT_RESULT_ACCEPT
               #print "... OK!"
            #else:
            #   print "... ERROR!"

            resp['ctx_num']             += 1
            itemResult                   = dcerpc.CtxItemResult()
            itemResult['Result']         = result
            itemResult['Reason']         = reason
            itemResult['TransferSyntax'] = uuidtup_to_bin(NDRSyntax)
            ctx_items                   += str(itemResult)

        resp['ctx_items'] = ctx_items
        resp['frag_len']  = len(str(resp))

        self._clientSock.send(str(resp)) 
        return None

    def processRequest(self,data):
        packet = dcerpc.MSRPCHeader(data)
        if packet['type'] == dcerpc.MSRPC_BIND:
            bind   = dcerpc.MSRPCBind(packet['pduData'])
            packet = self.bind(packet, bind)
        elif packet['type'] == dcerpc.MSRPC_REQUEST:
            request          = dcerpc.MSRPCRequestHeader(data)
            response         = dcerpc.MSRPCRespHeader(data)
            response['type'] = dcerpc.MSRPC_RESPONSE
            # Serve the opnum requested, if not, fails
            if self._callbacks[self._boundUUID].has_key(request['op_num']):
                # Call the function 
                returnData          = self._callbacks[self._boundUUID][request['op_num']](request['pduData'])
                response['pduData'] = returnData
            else:
                response['type']    = dcerpc.MSRPC_FAULT
                response['pduData'] = struct.pack('<L',0x000006E4L)
            response['frag_len'] = len(response)
            return response
        else:
            # Defaults to a fault
            packet         = dcerpc.MSRPCRespHeader(data)
            packet['type'] = dcerpc.MSRPC_FAULT

        return packet

from impacket.dcerpc import srvsvc
from impacket import smbserver
import ConfigParser
import struct

class SRVSVCServer(DCERPCServer):
    def __init__(self):
        DCERPCServer.__init__(self)

        self._shares = {}

        self.srvsvcCallBacks = {
            15: self.NetShareEnumAll,
            16: self.NetrGetShareInfo,
            21: self.NetrServerGetInfo,
        }

        self.addCallbacks(('4B324FC8-1670-01D3-1278-5A47BF6EE188', '3.0'), self.srvsvcCallBacks)

    def processConfigFile(self, configFile):
       serverConfig = ConfigParser.ConfigParser()
       serverConfig.read(configFile)
       sections = serverConfig.sections()
       # Remove the global one
       del(sections[sections.index('global')])
       for i in sections:
           self._shares[i] = dict(serverConfig.items(i))

    def NetrGetShareInfo(self,data):
       request = srvsvc.SRVSVCNetrShareGetInfo(data)
       print "NetrGetShareInfo Level: %d" % request['Level']
       s = request['NetName'].decode('utf-16le')[:-1].upper().strip()
       share  = self._shares[s]
       answer = srvsvc.SRVSVCSwitchpShareInfo2()
       answer['Level']      = 1
       answer['InfoStruct'] = srvsvc.SRVSVCShareInfo1()
       answer['InfoStruct']['pNetName'] = id(share) & 0xffffffff
       answer['InfoStruct']['Type']     = int(share['share type'])
       answer['InfoStruct']['pRemark']  = (id(share) & 0xffffffff) + 1
       answer = str(answer)
       netName = srvsvc.NDRString()
       remark  = srvsvc.NDRString()
       netName['sName'] = request['NetName']
       remark['sName']  = (share['comment']+'\x00').encode('utf-16le')
       answer += str(netName) + str(remark)
       answer += struct.pack('<L',0)
       return answer

    def NetrServerGetInfo(self,data):
       request = srvsvc.SRVSVCNetrServerGetInfo(data)
       print "NetrServerGetInfo Level: %d" % request['Level']
       answer = srvsvc.SRVSVCServerpInfo101()
       answer['ServerInfo'] = srvsvc.SRVSVCServerInfo101()
       answer['ServerInfo']['Name']    = request['ServerName']
       answer['ServerInfo']['Comment'] = '\x00\x00'
       answer = str(answer) + '\x00'*4
       return answer

    def NetShareEnumAll(self, data):
       request = srvsvc.SRVSVCNetrShareEnum(data)
       print "NetrShareEnumAll Level: %d" % request['Level']
       shareEnum = srvsvc.SRVSVCNetrShareEnum1_answer()
       shareEnum['Info'] = srvsvc.SRVSVCShareEnumStruct()
       shareEnum['Info']['Level']    = 1
       shareEnum['Info']['Count']    = len(self._shares)
       shareEnum['Info']['MaxCount'] = len(self._shares)
       answer = str(shareEnum) 
       for i in self._shares:
          shareInfo = srvsvc.SRVSVCShareInfo1()
          shareInfo['pNetName'] = id(i) & 0xffffffff
          shareInfo['Type']     = int(self._shares[i]['share type'])
          shareInfo['pRemark']  = (id(i) & 0xffffffff)+1
          answer += str(shareInfo)

       for i in self._shares:
          netName = srvsvc.NDRString()
          remark = srvsvc.NDRString()
          netName['sName'] = (i+'\x00').encode('utf-16le')
          remark['sName']  = (self._shares[i]['comment']+'\x00').encode('utf-16le')
          answer += str(netName) + str(remark)

       # and the answer
       answer += struct.pack('<LLL',len(self._shares),0,0)
       return answer