/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
|