PageRenderTime 48ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pentest/voiper/sulley/impacket/dcerpc/transport.py

https://github.com/sullivanmatt/Raspberry-Pwn
Python | 348 lines | 322 code | 10 blank | 16 comment | 9 complexity | 813af8d178de21a87ebd6fb506adfdc6 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, MPL-2.0-no-copyleft-exception, GPL-2.0, GPL-3.0
  1. # Copyright (c) 2003-2006 CORE Security Technologies
  2. #
  3. # This software is provided under under a slightly modified version
  4. # of the Apache Software License. See the accompanying LICENSE file
  5. # for more information.
  6. #
  7. # $Id: transport.py,v 1.5 2006/05/23 21:19:26 gera Exp $
  8. #
  9. # Description:
  10. # Transport implementations for the DCE/RPC protocol.
  11. #
  12. import re
  13. import socket
  14. from impacket import smb
  15. from impacket import nmb
  16. from impacket.structure import pack
  17. from impacket.dcerpc import dcerpc, dcerpc_v4
  18. class DCERPCStringBinding:
  19. parser = re.compile(r'(?:([a-fA-F0-9-]{8}(?:-[a-fA-F0-9-]{4}){3}-[a-fA-F0-9-]{12})@)?' # UUID (opt.)
  20. +'([_a-zA-Z0-9]*):' # Protocol Sequence
  21. +'([^\[]*)' # Network Address (opt.)
  22. +'(?:\[([^\]]*)\])?') # Endpoint and options (opt.)
  23. def __init__(self, stringbinding):
  24. match = DCERPCStringBinding.parser.match(stringbinding)
  25. self.__uuid = match.group(1)
  26. self.__ps = match.group(2)
  27. self.__na = match.group(3)
  28. options = match.group(4)
  29. if options:
  30. options = options.split(',')
  31. self.__endpoint = options[0]
  32. try:
  33. self.__endpoint.index('endpoint=')
  34. self.__endpoint = self.__endpoint[len('endpoint='):]
  35. except:
  36. pass
  37. self.__options = options[1:]
  38. else:
  39. self.__endpoint = ''
  40. self.__options = []
  41. def get_uuid(self):
  42. return self.__uuid
  43. def get_protocol_sequence(self):
  44. return self.__ps
  45. def get_network_address(self):
  46. return self.__na
  47. def get_endpoint(self):
  48. return self.__endpoint
  49. def get_options(self):
  50. return self.__options
  51. def __str__(self):
  52. return DCERPCStringBindingCompose(self.__uuid, self.__ps, self.__na, self.__endpoint, self.__options)
  53. def DCERPCStringBindingCompose(uuid=None, protocol_sequence='', network_address='', endpoint='', options=[]):
  54. s = ''
  55. if uuid: s += uuid + '@'
  56. s += protocol_sequence + ':'
  57. if network_address: s += network_address
  58. if endpoint or options:
  59. s += '[' + endpoint
  60. if options: s += ',' + ','.join(options)
  61. s += ']'
  62. return s
  63. def DCERPCTransportFactory(stringbinding):
  64. sb = DCERPCStringBinding(stringbinding)
  65. na = sb.get_network_address()
  66. ps = sb.get_protocol_sequence()
  67. if 'ncadg_ip_udp' == ps:
  68. port = sb.get_endpoint()
  69. if port:
  70. return UDPTransport(na, int(port))
  71. else:
  72. return UDPTransport(na)
  73. elif 'ncacn_ip_tcp' == ps:
  74. port = sb.get_endpoint()
  75. if port:
  76. return TCPTransport(na, int(port))
  77. else:
  78. return TCPTransport(na)
  79. elif 'ncacn_http' == ps:
  80. port = sb.get_endpoint()
  81. if port:
  82. return HTTPTransport(na, int(port))
  83. else:
  84. return HTTPTransport(na)
  85. elif 'ncacn_np' == ps:
  86. named_pipe = sb.get_endpoint()
  87. if named_pipe:
  88. named_pipe = named_pipe[len(r'\pipe'):]
  89. return SMBTransport(na, filename = named_pipe)
  90. else:
  91. return SMBTransport(na)
  92. else:
  93. raise Exception, "Unknown protocol sequence."
  94. class DCERPCTransport:
  95. DCERPC_class = dcerpc.DCERPC_v5
  96. def __init__(self, dstip, dstport):
  97. self.__dstip = dstip
  98. self.__dstport = dstport
  99. self._max_send_frag = None
  100. self._max_recv_frag = None
  101. self.set_credentials('','','','')
  102. def connect(self):
  103. raise RuntimeError, 'virtual function'
  104. def send(self,data=0, forceWriteAndx = 0, forceRecv = 0):
  105. raise RuntimeError, 'virtual function'
  106. def recv(self):
  107. raise RuntimeError, 'virtual function'
  108. def disconnect(self):
  109. raise RuntimeError, 'virtual function'
  110. def get_socket(self):
  111. raise RuntimeError, 'virtual function'
  112. def get_dip(self):
  113. return self.__dstip
  114. def set_dip(self, dip):
  115. "This method only makes sense before connection for most protocols."
  116. self.__dstip = dip
  117. def get_dport(self):
  118. return self.__dstport
  119. def set_dport(self, dport):
  120. "This method only makes sense before connection for most protocols."
  121. self.__dstport = dport
  122. def get_addr(self):
  123. return (self.get_dip(), self.get_dport())
  124. def set_addr(self, addr):
  125. "This method only makes sense before connection for most protocols."
  126. self.set_dip(addr[0])
  127. self.set_dport(addr[1])
  128. def set_max_fragment_size(self, send_fragment_size):
  129. # -1 is default fragment size: 0 (don't fragment)
  130. # 0 is don't fragment
  131. # other values are max fragment size
  132. if send_fragment_size == -1:
  133. self.set_default_max_fragment_size()
  134. else:
  135. self._max_send_frag = send_fragment_size
  136. def set_default_max_fragment_size(self):
  137. # default is 0: don'fragment.
  138. # subclasses may override this method
  139. self._max_send_frag = 0
  140. def get_credentials(self):
  141. return (
  142. self._username,
  143. self._password,
  144. self._nt_hash,
  145. self._lm_hash)
  146. def set_credentials(self, username, password, lm_hash='', nt_hash=''):
  147. self._username = username
  148. self._password = password
  149. self._nt_hash = nt_hash
  150. self._lm_hash = lm_hash
  151. class UDPTransport(DCERPCTransport):
  152. "Implementation of ncadg_ip_udp protocol sequence"
  153. DCERPC_class = dcerpc_v4.DCERPC_v4
  154. def __init__(self,dstip, dstport = 135):
  155. DCERPCTransport.__init__(self, dstip, dstport)
  156. self.__socket = 0
  157. def connect(self):
  158. try:
  159. self.__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  160. self.__socket.settimeout(30)
  161. except socket.error, msg:
  162. self.__socket = None
  163. raise Exception, "Could not connect: %s" % msg
  164. return 1
  165. def disconnect(self):
  166. try:
  167. self.__socket.close()
  168. except socket.error, msg:
  169. self.__socket = None
  170. return 0
  171. return 1
  172. def send(self,data, forceWriteAndx = 0, forceRecv = 0):
  173. self.__socket.sendto(data,(self.get_dip(),self.get_dport()))
  174. def recv(self):
  175. buffer, self.__recv_addr = self.__socket.recvfrom(8192)
  176. return buffer
  177. def get_recv_addr(self):
  178. return self.__recv_addr
  179. def get_socket(self):
  180. return self.__socket
  181. class TCPTransport(DCERPCTransport):
  182. "Implementation of ncacn_ip_tcp protocol sequence"
  183. def __init__(self, dstip, dstport = 135):
  184. DCERPCTransport.__init__(self, dstip, dstport)
  185. self.__socket = 0
  186. def connect(self):
  187. self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  188. try:
  189. self.__socket.settimeout(300)
  190. self.__socket.connect((self.get_dip(), self.get_dport()))
  191. except socket.error, msg:
  192. self.__socket.close()
  193. raise Exception, "Could not connect: %s" % msg
  194. return 1
  195. def disconnect(self):
  196. try:
  197. self.__socket.close()
  198. except socket.error, msg:
  199. self.__socket = None
  200. return 0
  201. return 1
  202. def send(self,data, forceWriteAndx = 0, forceRecv = 0):
  203. if self._max_send_frag:
  204. offset = 0
  205. while 1:
  206. toSend = data[offset:offset+self._max_send_frag]
  207. if not toSend:
  208. break
  209. self.__socket.send(toSend)
  210. offset += len(toSend)
  211. else:
  212. self.__socket.send(data)
  213. def recv(self):
  214. buffer = self.__socket.recv(8192)
  215. return buffer
  216. def get_socket(self):
  217. return self.__socket
  218. class HTTPTransport(TCPTransport):
  219. "Implementation of ncacn_http protocol sequence"
  220. def connect(self):
  221. TCPTransport.connect(self)
  222. self.__socket.send('RPC_CONNECT ' + self.get_dip() + ':593 HTTP/1.0\r\n\r\n')
  223. data = self.__socket.recv(8192)
  224. if data[10:13] != '200':
  225. raise Exception("Service not supported.")
  226. class SMBTransport(DCERPCTransport):
  227. "Implementation of ncacn_np protocol sequence"
  228. def __init__(self, dstip, dstport = 445, filename = '', username='', password='', lm_hash='', nt_hash=''):
  229. DCERPCTransport.__init__(self, dstip, dstport)
  230. self.__socket = None
  231. self.__smb_server = 0
  232. self.__tid = 0
  233. self.__filename = filename
  234. self.__handle = 0
  235. self.__pending_recv = 0
  236. self.set_credentials(username, password, lm_hash, nt_hash)
  237. def setup_smb_server(self):
  238. if not self.__smb_server:
  239. self.__smb_server = smb.SMB('*SMBSERVER',self.get_dip(), sess_port = self.get_dport())
  240. def connect(self):
  241. self.setup_smb_server()
  242. if self.__smb_server.is_login_required():
  243. if self._password != '' or (self._password == '' and self._nt_hash == '' and self._lm_hash == ''):
  244. self.__smb_server.login(self._username, self._password)
  245. elif self._nt_hash != '' or self._lm_hash != '':
  246. self.__smb_server.login(self._username, '', '', self._lm_hash, self._nt_hash)
  247. self.__tid = self.__smb_server.tree_connect_andx('\\\\*SMBSERVER\\IPC$')
  248. self.__handle = self.__smb_server.nt_create_andx(self.__tid, self.__filename)
  249. # self.__handle = self.__smb_server.open_file_andx(self.__tid, r"\\PIPE\%s" % self.__filename, smb.SMB_O_CREAT, smb.SMB_ACCESS_READ)[0]
  250. # self.__handle = self.__smb_server.open_file(self.__tid, r"\\PIPE\%s" % self.__filename, smb.SMB_O_CREAT, smb.SMB_ACCESS_READ)[0]
  251. self.__socket = self.__smb_server.get_socket()
  252. return 1
  253. def disconnect(self):
  254. self.__smb_server.disconnect_tree(self.__tid)
  255. self.__smb_server.logoff()
  256. def send(self,data, noAnswer = 0, forceWriteAndx = 0, forceRecv = 0):
  257. if self._max_send_frag:
  258. offset = 0
  259. while 1:
  260. toSend = data[offset:offset+self._max_send_frag]
  261. if not toSend:
  262. break
  263. self.__smb_server.write_andx(self.__tid, self.__handle, toSend, offset = offset)
  264. offset += len(toSend)
  265. else:
  266. if forceWriteAndx:
  267. self.__smb_server.write_andx(self.__tid, self.__handle, data)
  268. else:
  269. self.__smb_server.TransactNamedPipe(self.__tid,self.__handle,data, noAnswer = noAnswer, waitAnswer = 0)
  270. if forceRecv:
  271. self.__pending_recv += 1
  272. def recv(self):
  273. if self._max_send_frag or self.__pending_recv:
  274. # _max_send_frag is checked because it's the same condition we checked
  275. # to decide whether to use write_andx() or send_trans() in send() above.
  276. if self.__pending_recv:
  277. self.__pending_recv -= 1
  278. return self.__smb_server.read_andx(self.__tid, self.__handle, max_size = self._max_recv_frag)
  279. else:
  280. s = self.__smb_server.recv_packet()
  281. if self.__smb_server.isValidAnswer(s,smb.SMB.SMB_COM_TRANSACTION):
  282. trans = smb.TRANSHeader(s.get_parameter_words(), s.get_buffer())
  283. data = trans.get_data()
  284. return data
  285. return None
  286. def get_smb_server(self):
  287. return self.__smb_server
  288. def get_socket(self):
  289. return self.__socket