Umap v0.7


SUBMITTED BY: Guest

DATE: Dec. 5, 2013, 2:41 p.m.

FORMAT: Python

SIZE: 43.1 kB

HITS: 695

  1. ###############################
  2. ###############################
  3. ### ###
  4. ### README ###
  5. ### ###
  6. ###############################
  7. ###############################
  8. Umap v0.7
  9. By Daniel Garcia
  10. formatez@toor.do
  11. Dependencies
  12. -------
  13. Not much is needed, just Python > 2.6 and Python SoapPy.
  14. Executing
  15. -------
  16. Umap works with a curses interface. Here are the arguments used by the program.
  17. -h: Help
  18. -c: Curses mode (Don't recommend NOT using curses)
  19. -v: Verbose output
  20. -p: Port / Port range (Internal Scanning)
  21. -l: List of IP blocks
  22. -i: Target IP
  23. -s: SOCKSv4 Proxy mode
  24. -b: IP SOCKS should bind to.
  25. -t: Number of maximum threads
  26. Here are some common ways to use Umap:
  27. (SOCKSv4 Proxy mode) - <iplist> is the location of a filename containing an IP per line for scanning, it will automatically scan
  28. the whole class C block if specified on the list. If specified by the -i argument you can specify single ip's. On curses use the 'd' and 'u'
  29. keys to move around the iplist for the selection of positive hosts found, 'e' to execute upnp commands and 'q' to quit.
  30. ./umap.py -c -s -l <iplist> -t 254
  31. (Scanning internal network mode) - Scans an IP looking for available IGD control points, if it finds one it attempts to map internal hosts for scanning.
  32. ./umap.py -c -i <ip>
  33. (Scanning internal network mode) - Same as above but only scans ports specified in <port>
  34. ./umap.py -c -i <ip> -p <port>
  35. ###############################
  36. ###############################
  37. ### ###
  38. ### list ###
  39. ### ###
  40. ###############################
  41. ###############################
  42. # Format: x.x.x.x(per line)
  43. # Will scan the whole Class C block for each IP listed
  44. # example: 1.2.3.4
  45. ###############################
  46. ###############################
  47. ### ###
  48. ### umap.py ###
  49. ### ###
  50. ###############################
  51. ###############################
  52. #!/usr/bin/python
  53. # Umap v0.7 (UPNP Map)
  54. # formatez@toor.do (Daniel Garcia)
  55. # http://www.toor.do/
  56. #
  57. # UPNP NAT Hole puncher/Scanner
  58. # --------------------------------
  59. # This program attempts to
  60. # 1) Scan open TCP ports on the hosts behind a UPNP enabled Internet Gateway Device(IGD) NAT.
  61. # 2) Add port forward using open WAN control points
  62. # 3) Act as a SOCKS v4 using port forwarding from open WAN control points
  63. #
  64. #
  65. # For more information on the subject:
  66. # http://www.upnp-hacks.org/
  67. # http://www.gnucitizen.org/
  68. # http://www.sourcesec.com/2008/11/07/miranda-upnp-administration-tool/
  69. #
  70. #
  71. #
  72. # Code docs/comments coming soon.
  73. #import sys
  74. import os
  75. import socket, SocketServer
  76. import urllib2
  77. import getopt
  78. import xml.dom.minidom as minidom
  79. import threading
  80. import Queue
  81. import random
  82. import time
  83. import uscan, usocks, upnpscan, uctui
  84. import curses
  85. from SOAPpy import *
  86. # The format for the XML descriptor locations is 'XML location | TCP Port | Type'
  87. knownLocations = ['/upnp/IGD.xml|80|0', '/allxml/|5431|1', '/devicedesc.xml|80|2', '/IGatewayDeviceDescDoc|2869|3', '/igd.xml|80|4', '/gatedesc.xml|49152|5', '/rootDesc.xml|5000|6']
  88. # Default scanned ports
  89. commonPorts = ['21','22','23','80','137','138','139','443','445','8080']
  90. # Uscan queue
  91. queue = Queue.Queue()
  92. # IP List
  93. upnpList = []
  94. # Mappings list
  95. mapList = []
  96. threadList = []
  97. def main():
  98. socks = 0
  99. max_threads = 16
  100. upnp_type = False
  101. verbose = False
  102. cursesMode = False
  103. portLow = 0
  104. portHigh = 0
  105. ip = ''
  106. file = ''
  107. bindIP = ''
  108. portList = []
  109. selectedIP = 0
  110. current_ip = 0
  111. mapDict = {}
  112. selectedIPXML = {}
  113. headers = {
  114. 'USER-AGENT':'Umap/0.7',
  115. 'CONTENT-TYPE':'text/xml; charset="utf-8"'
  116. }
  117. try:
  118. opts, args = getopt.getopt(sys.argv[1:], "hcvst:i:p:l:b:", ["help", "curses", "verbose", "socks",
  119. "threads=", "ip=", "port=", "list=", "bind="])
  120. except getopt.GetoptError, err:
  121. print str(err)
  122. sys.exit(2)
  123. if len(opts) == 0:
  124. print "No arguments specified"
  125. printhelp()
  126. sys.exit(2)
  127. for o,a in opts:
  128. if o == "-h":
  129. printhelp()
  130. sys.exit(2)
  131. if o == "-v":
  132. verbose = 1
  133. if o == "-c":
  134. cursesMode = 1
  135. if o == "-i":
  136. ip = a
  137. if o == "-p":
  138. if ',' in a:
  139. for port in a.split(','):
  140. if port.isdigit():
  141. portList.append(port)
  142. else:
  143. print "[E] Wrong port number"
  144. elif '-' in a:
  145. (portLow, portHigh) = a.split('-')
  146. if portLow.isdigit() and portHigh.isdigit():
  147. portLow = int(portLow)
  148. portHigh = int(portHigh)
  149. while portLow <= portHigh:
  150. portList.append(portLow)
  151. portLow += 1
  152. else:
  153. if a.isdigit:
  154. portList.append(a)
  155. else:
  156. print "[E] Wrong port number"
  157. sys.exit()
  158. if o == "-t":
  159. if a.isdigit() and int(a) < 255:
  160. max_threads = a
  161. else:
  162. print "Error in threads"
  163. sys.exit()
  164. if o == "-s":
  165. socks = 1
  166. if o == "-b":
  167. bindIP = a
  168. if not a:
  169. print "Error in bind IP"
  170. sys.exit()
  171. if o == "-l":
  172. if os.path.exists(a):
  173. file = a
  174. else:
  175. print "File doesn't exist!"
  176. sys.exit()
  177. if len(portList) == 0:
  178. for port in commonPorts:
  179. portList.append(port)
  180. if not ip and not socks:
  181. print "[E] Either target IP or socks option must be specified"
  182. sys.exit()
  183. if socks and (not file and not ip):
  184. print "[E] Must specify IP block list file or IP target"
  185. sys.exit()
  186. if ip and not socks:
  187. if cursesMode:
  188. scr = uctui.uCTUI(0, selectedIP, selectedIPXML, upnpList, mapList)
  189. scr.mainScreen.nodelay(1)
  190. scr.printMessage("Trying "+ip)
  191. scr.draw()
  192. upnpScan = upnpscan.UPNPScan(ip, upnpList, scr, selectedIPXML)
  193. upnpScan.setDaemon(True)
  194. upnpScan.start()
  195. upnpScan.join()
  196. if len(upnpList) == 0:
  197. scr.printMessage("[E] Couldn't find a match")
  198. else:
  199. splitUPnP = upnpList[0].split('|')
  200. location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
  201. scanned = upnpScan.getInfo(location, ip, 1)
  202. guessIP()
  203. try:
  204. while True:
  205. if(threading.activeCount() < max_threads):
  206. current_ip = queue.get()
  207. if cursesMode:
  208. umap = uscan.Uscan(ip, current_ip, scanned, queue, verbose, portList, mapList, scr)
  209. else:
  210. umap = uscan.Uscan(ip, current_ip, scanned, queue, verbose, portList, mapList)
  211. umap.setDaemon(True)
  212. umap.start()
  213. if umap.stopIt.isSet():
  214. break
  215. time.sleep(0.5)
  216. scr.draw()
  217. input = scr.mainScreen.getch()
  218. if input == ord('q'):
  219. scr.exitCurse()
  220. break
  221. except KeyboardInterrupt:
  222. scr.printMEssage("Caught interrupt! waiting for threads and exiting")
  223. umap.stopIt.set()
  224. umap.join()
  225. scr.exitCurse()
  226. if socks and (file or ip):
  227. scr = uctui.uCTUI(1, selectedIP, selectedIPXML, upnpList, mapList)
  228. if file:
  229. ipListfh = open(file, 'r')
  230. ipList = ipListfh.readlines()
  231. for line in ipList:
  232. c = 1
  233. if line.find('#') != -1: continue
  234. splitIP = line.split('.')
  235. if len(splitIP) == 4:
  236. while c < 255:
  237. ip = str(splitIP[0])+"."+str(splitIP[1])+"."+str(splitIP[2])+"."+str(c)
  238. if c == 1:
  239. dip = ip.split('.')
  240. scr.printMessage("Adding block: "+ip)
  241. queue.put(ip)
  242. c += 1
  243. else:
  244. scr.printMessage("[E]Error in format!")
  245. if ip:
  246. scr.printMessage("Adding: "+ip)
  247. queue.put(ip)
  248. try:
  249. socksServer = usocks.UsocksServer((bindIP, 1081), usocks.UsocksHandle)
  250. except:
  251. print "Error binding"
  252. sys.exit(0)
  253. socksServer.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  254. socksThread = threading.Thread(target=socksServer.serve_forever)
  255. socksThread.setDaemon(True)
  256. socksThread.start()
  257. totalCount = 0
  258. try:
  259. while True:
  260. if not queue.empty():
  261. current_ip = queue.get()
  262. upnpScan = upnpscan.UPNPScan(current_ip, upnpList, scr, selectedIPXML)
  263. scr.mainScreen.nodelay(1)
  264. time.sleep(0.5)
  265. scr.draw()
  266. input = scr.mainScreen.getch()
  267. lenUPnP = len(upnpList)
  268. scan = ()
  269. if lenUPnP > 0 and selectedIP < lenUPnP and len(scr.selectedIPXML) == 0:
  270. splitUPnP = upnpList[scr.selectedIP].split('|')
  271. location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
  272. scan = upnpScan.getInfo(location, upnpList[scr.selectedIP].split('|')[0], 1)
  273. if input == ord('q'):
  274. socksServer.shutdown()
  275. socksThread.join()
  276. scr.exitCurse()
  277. break
  278. if input == ord('r'):
  279. scr.mainScreen.refresh()
  280. if input == ord('e'):
  281. if lenUPnP == 0:
  282. scr.printMessage("No positive matches")
  283. return False
  284. scr.mainScreen.nodelay(0)
  285. scr.drawExecute()
  286. scr.mainScreen.nodelay(1)
  287. if input == ord('u') and selectedIP >= 0:
  288. scr.cursorUp()
  289. splitUPnP = upnpList[scr.selectedIP].split('|')
  290. location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
  291. scr.selectedIPXML = {}
  292. mapDict = {}
  293. if input == ord('d') and selectedIP < lenUPnP:
  294. scr.cursorDown()
  295. splitUPnP = upnpList[scr.selectedIP].split('|')
  296. location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
  297. scr.selectedIPXML = {}
  298. mapDict = {}
  299. socksServer.scan = scan
  300. socksServer.IPlist = upnpList
  301. socksServer.map = mapDict
  302. socksServer.scr = scr
  303. socksServer.selectedIP = selectedIP
  304. if(threading.activeCount() < int(max_threads)):
  305. totalCount += 1
  306. if queue.empty() and current_ip == 0:
  307. continue
  308. else:
  309. scr.printMessage("Scanning("+str(threading.activeCount())+","+str(totalCount)+"): "+current_ip)
  310. upnpScan.setDaemon(True)
  311. upnpScan.start()
  312. threadList.append(upnpScan)
  313. current_ip = 0
  314. else:
  315. for t in threadList:
  316. t.join()
  317. if upnpScan.stopIt.isSet():
  318. break
  319. except KeyboardInterrupt:
  320. scr.printMessage("Caught interrupt! waiting for threads and exiting")
  321. upnpScan.stopIt.set()
  322. upnpScan.join()
  323. scr.exitCurse()
  324. def guessIP():
  325. # TODO
  326. # Best guess of IP (10.0.0.0)
  327. ipGuess = '10.0.0.1'
  328. # ipGuess = base.split('://')[1].split(':')[0]
  329. (a,b,c,d) = ipGuess.split('.')
  330. d = int(d)
  331. originald = d
  332. d = 1
  333. while d < 255:
  334. if d == originald:
  335. d += 1
  336. continue
  337. d += 1
  338. ipGuess = a+'.'+b+'.'+c+'.'+str(d)
  339. queue.put(ipGuess)
  340. def printhelp():
  341. print "------------"
  342. print "Umap v0.7"
  343. print "By FormateZ"
  344. print "formatez@toor.do"
  345. print "------------"
  346. print "-h: Help"
  347. print "-b: Bind IP of SOCKS"
  348. print "-c: Curses mode"
  349. print "-v: Verbose output"
  350. print "-p: Port / Port range (Internal Scanning)"
  351. print "-l: File with list of IP's to be scanned"
  352. print "-i: Target IP"
  353. print "-s: SOCKSv4 Proxy mode"
  354. print "-t: Number of maximum threads"
  355. if __name__ == '__main__':
  356. main()
  357. ###############################
  358. ###############################
  359. ### ###
  360. ### upnpscan.py ###
  361. ### ###
  362. ###############################
  363. ###############################
  364. #!/usr/bin/python
  365. import urllib2
  366. import asyncore
  367. import threading, random, socket
  368. import random
  369. from SOAPpy import *
  370. import xml.dom.minidom as minidom
  371. import sys
  372. import time
  373. # Much thanks to Dan Kaminsky for supplying most of these description XML's
  374. knownLocations = ['/upnp/IGD.xml|80|0',
  375. '/DeviceDescription.xml|80|1',
  376. '/allxml/|5431|2',
  377. '/devicedesc.xml|80|3',
  378. '/IGatewayDeviceDescDoc|2869|4',
  379. '/igd.xml|80|5',
  380. '/gatedesc.xml|49152|6',
  381. '/rootDesc.xml|5000|7',
  382. '/RootDevice.XML|50718|9',
  383. '/UPNP_rootDesc.xml|5819|10',
  384. '/rtdevdsc.xml|1900|11',
  385. '/gateway.xml|49152|12',
  386. '/rootDesc.xml|5555|13',
  387. '/upnp/igdrootdesc.xml|80|14',
  388. '/x_internetgatewaydevice.xml|80|15',
  389. '/desc.xml|80|16',
  390. '/DeviceDescrption.xml|9007|17',
  391. '/Public_UPNP_gatedesc.xml|80|18',
  392. '/gen-desc.xml|4004|19',
  393. '/__rootDevice|30888|20',
  394. '/gateconnSCPD.xml|80|21',
  395. '/RootDevice.xml|8008|22',
  396. '/device.xml|51004|23',
  397. '/upnp/service/descrip.xml|80|24',
  398. '/rootDesc.xml|8200|25',
  399. '/DeviceDescription.xml|62802|26',
  400. '/rootDesc.xml|65535|27',
  401. '/rootDesc.xml|8588|29',
  402. '/InternetGatewayDevice.xml|2800|30',
  403. '/UPNP_rootDesc.xml|5819|31',
  404. '/InternetGatewayDevice.xml|1780|32',
  405. '/RootDevice.xml|64340|33',
  406. '/igddesc.xml|49000|34',
  407. '/RootDevice.xml|34137|35']
  408. class UPNPScan(threading.Thread, asyncore.dispatcher):
  409. def __init__(self, ip, upnpList, scr, selectedIPXML):
  410. threading.Thread.__init__ (self)
  411. asyncore.dispatcher.__init__(self)
  412. self.stopIt = threading.Event()
  413. self.ip = ip
  414. self.upnpList = upnpList
  415. self.selectedIPXML = selectedIPXML
  416. self.scr = scr
  417. def run(self):
  418. headers = {
  419. 'USER-AGENT':'Umap/0.7',
  420. 'CONTENT-TYPE':'text/xml; charset="utf-8"'
  421. }
  422. for location in knownLocations:
  423. data = False
  424. (link, port, upnpType) = location.split('|')
  425. requestLocation = "http://%s:%s%s" % (self.ip, port, link)
  426. try:
  427. socket.setdefaulttimeout(6)
  428. request = urllib2.Request(requestLocation, None)
  429. response = urllib2.urlopen(request)
  430. headers = response.info()
  431. data = response.read()
  432. except Exception, err:
  433. continue
  434. if data and data.find('xml') != -1:
  435. upnp_type = location
  436. self.scr.printMessage("[*] Positive match "+requestLocation)
  437. self.soapInfo = self.getInfo(location, self.ip, 0)
  438. try:
  439. self.upnpList.append(str(self.ip)+"|"+str(self.soapInfo[2])+"|"+str(port)+"|"+str(location)+"|"+str(self.soapInfo[1])+"|"+str(self.soapInfo[0])+"|"+str(self.soapInfo[6]))
  440. except:
  441. continue
  442. break
  443. def getInfo(self, location, ip, paint):
  444. st = time.time()
  445. (link, port, upnpType) = location.split('|')
  446. requestLocation = "http://%s:%s%s" % (ip, port, link)
  447. on = 0
  448. out = {}
  449. newXml = ''
  450. location = ''
  451. data = ''
  452. base = ''
  453. tags = ['URLBase', 'friendlyName', 'modelDescription', 'modelName', 'modelNumber', 'serialNumber', 'UDN']
  454. try:
  455. request = urllib2.Request(requestLocation, None)
  456. response = urllib2.urlopen(request)
  457. headers = response.info()
  458. xmlData = response.read()
  459. except Exception, err:
  460. return False
  461. ed = time.time()
  462. for line in xmlData.split('\n'):
  463. if '<?xml ' in line or on == 1:
  464. on = 1
  465. newXml += line+'\n'
  466. if '</root' in line:
  467. on = 0
  468. break
  469. try:
  470. xmlRoot = minidom.parseString(newXml)
  471. except Exception, err:
  472. self.scr.printMessage("[E] Error parsing XML")
  473. return False
  474. for service in xmlRoot.getElementsByTagName('service'):
  475. try:
  476. serviceType = service.getElementsByTagName('serviceType')[0].childNodes[0].data
  477. wanXml = service.getElementsByTagName('SCPDURL')[0].childNodes[0].data
  478. controlURL = service.getElementsByTagName('controlURL')[0].childNodes[0].data
  479. except Exception, err:
  480. self.scr.printMessage("[E] Error fetching main tags")
  481. return False
  482. if 'WANPPP' in serviceType or 'WANIP' in serviceType:
  483. # if 'WANIP' in serviceType:
  484. for tag in tags:
  485. try:
  486. out[tag] = xmlRoot.getElementsByTagName(tag)[0].childNodes[0].data
  487. if paint == 1: self.scr.selectedIPXML[tag] = xmlRoot.getElementsByTagName(tag)[0].childNodes[0].data
  488. except:
  489. pass
  490. timing = (ed-st)*1000.0
  491. if 'URLBase' in out:
  492. base = out['URLBase']
  493. return (serviceType, wanXml, controlURL, base, port, link, timing)
  494. ###############################
  495. ###############################
  496. ### ###
  497. ### uscan.py ###
  498. ### ###
  499. ###############################
  500. ###############################
  501. #!/usr/bin/python
  502. import threading, random, socket
  503. import random
  504. from SOAPpy import *
  505. class Uscan(threading.Thread):
  506. def __init__(self, uip, ip, soapInfo, queue, verbose, portList, mapList, scr):
  507. threading.Thread.__init__ (self)
  508. self.stopIt = threading.Event()
  509. self.portList = portList
  510. self.verbose = verbose
  511. self.scr = scr
  512. self.ip = ip
  513. self.uip = uip
  514. self.soapInfo = soapInfo
  515. self.port = soapInfo[4]
  516. self.queue = queue
  517. self.mapList = mapList
  518. def run(self):
  519. for port in self.portList:
  520. if self.stopIt.isSet():
  521. break
  522. sys.exit()
  523. open = False
  524. thisport = random.randint(30000, 40000)
  525. if self.verbose: self.scr.printMessage("[*] Trying port "+str(port)+" on "+self.ip+" "+self.uip+":"+str(thisport))
  526. endpoint = "http://%s:%s%s" % (self.uip, self.port, self.soapInfo[2])
  527. namespace = self.soapInfo[0]
  528. soapaction = namespace+'#AddPortMapping'
  529. server = SOAPProxy(endpoint, namespace)
  530. try:
  531. server._sa(soapaction).AddPortMapping(NewRemoteHost="",
  532. NewExternalPort=thisport,
  533. NewProtocol="TCP",
  534. NewInternalPort=port,
  535. NewInternalClient=self.ip,
  536. NewEnabled=1,
  537. NewPortMappingDescription=thisport,
  538. NewLeaseDuration=0)
  539. except Exception, err:
  540. self.scr.printMessage("[E]Couldn't add port "+str(thisport)+" with "+str(port)+" on "+self.uip+":"+str(err))
  541. try:
  542. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  543. s.connect((self.uip, thisport))
  544. open = 1
  545. self.mapList.append(self.uip+":"+str(thisport)+"|"+self.ip+":"+str(port))
  546. self.scr.printMessage("Mapped: "+self.uip+":"+str(thisport)+"<->"+self.ip+":"+str(port))
  547. s.close()
  548. except Exception, err:
  549. open = 0
  550. s.close()
  551. if self.verbose: self.scr.printMessage("Closed port "+str(err))
  552. if not open:
  553. endpoint = "http://%s:%s%s" % (self.uip, self.port, self.soapInfo[2])
  554. namespace = self.soapInfo[0]
  555. soapaction = namespace+"#DeletePortMapping"
  556. server = SOAPProxy(endpoint, namespace)
  557. try:
  558. self.scr.printMessage("Deleting: "+str(thisport))
  559. server._sa(soapaction).DeletePortMapping(NewRemoteHost="",
  560. NewExternalPort=thisport,
  561. NewProtocol="TCP")
  562. except Exception, err:
  563. self.scr.printMessage("[E] Error deleting port "+str(thisport))
  564. ###############################
  565. ###############################
  566. ### ###
  567. ### usocks.py ###
  568. ### ###
  569. ###############################
  570. ###############################
  571. #!/usr/bin/python
  572. import thread
  573. import SocketServer, socket
  574. import struct
  575. import sys
  576. import random
  577. import string
  578. from SOAPpy import *
  579. from time import time
  580. class UsocksHandle(SocketServer.BaseRequestHandler):
  581. def pipe(self,src,dest):
  582. while 1:
  583. try:
  584. r = src.recv(4096)
  585. except Exception as e:
  586. self.server.scr.printMessage("Receive "+str(e))
  587. src.close()
  588. dest.close()
  589. break
  590. if not r:
  591. src.close()
  592. dest.close()
  593. break
  594. try:
  595. dest.send(r)
  596. except Exception as e:
  597. self.server.scr.printMessage("Send "+str(e))
  598. src.close()
  599. dest.close()
  600. break
  601. def handle(self):
  602. outData = []
  603. inData = []
  604. selectedIP = self.server.scr.selectedIP
  605. positive = self.server.IPlist
  606. mapDict = self.server.map
  607. scr = self.server.scr
  608. sys.stdout = open("/dev/null")
  609. sys.stderr = open("/dev/null")
  610. socksFormat = '!BBH4s'
  611. socksResponseOK = struct.pack('!BBHI',0,0x5a,0,0)
  612. socksFail = struct.pack('!BBHI',0,0x5b,0,0)
  613. while 1:
  614. initialData = self.request.recv(struct.calcsize(socksFormat))
  615. if not initialData:
  616. scr.printMessage("Dropped request")
  617. break
  618. (socks_ver,command,target_port,target_addr) = struct.unpack(socksFormat,initialData)
  619. (target_addr_int,) = struct.unpack('!I',target_addr)
  620. target_addr = socket.inet_ntoa(target_addr)
  621. if len(positive) == 0:
  622. scr.printMessage("[E] Can't processs request without positive matches")
  623. self.request.send(socksFail)
  624. self.request.close()
  625. continue
  626. if command == 1:
  627. port = target_port
  628. ip = target_addr
  629. lenPositives = len(positive)
  630. scr.printMessage("Processing("+str(selectedIP)+"): "+ip+" from "+str(self.client_address[0]))
  631. rhost = positive[selectedIP].split('|')[0]
  632. rendpoint = positive[selectedIP].split('|')[1]
  633. rendpointport = positive[selectedIP].split('|')[2]
  634. serviceType = positive[selectedIP].split('|')[7]
  635. self.rhost = rhost
  636. rport = random.randint(10000,20000)
  637. self.rport = rport
  638. #
  639. # TODO
  640. if mapDict.has_key(ip+':'+str(port)):
  641. thisMap = mapDict[ip+':'+str(port)].split(':')
  642. rhost = thisMap[0]
  643. rport = thisMap[1]
  644. self.rhost = rhost
  645. self.rport = rport
  646. scr.printMessage("Already mapped "+rhost+":"+rport)
  647. else:
  648. endpoint = "http://"+rhost+":"+str(rendpointport)+rendpoint
  649. scr.printMessage("Trying to add: "+str(rhost)+":"+str(rport)+"|"+str(ip)+":"+str(port))
  650. namespace = serviceType
  651. server = SOAPProxy(endpoint, namespace)
  652. soapaction = serviceType+"#AddPortMapping"
  653. try:
  654. server._sa(soapaction).AddPortMapping(NewRemoteHost="",
  655. NewExternalPort=rport,
  656. NewProtocol="TCP",
  657. NewInternalPort=port,
  658. NewInternalClient=ip,
  659. NewEnabled=1,
  660. NewPortMappingDescription=7,
  661. NewLeaseDuration=0)
  662. mapDict[ip+":"+str(port)] = rhost+":"+str(rport)+":"+str(int(time()))
  663. except Exception, err:
  664. scr.printMessage("Exception adding "+str(err)+rendpoint)
  665. self.request.send(socksFail)
  666. self.request.close()
  667. continue
  668. if mapDict.has_key(ip+':'+str(port)):
  669. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  670. try:
  671. sock.connect((rhost, int(rport)))
  672. except:
  673. scr.printMessage("Couldn't connect to mapped port")
  674. self.request.send(socksFail)
  675. self.request.close()
  676. continue
  677. else:
  678. mapDict[ip+':'+str(port)] = rhost+':'+str(rport)+':'+str(time())
  679. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  680. sock.setdefaulttimeout(20)
  681. try:
  682. sock.connect((rhost, int(rport)))
  683. except:
  684. scr.printMessage("Couldn't connect to mapped port")
  685. self.request.send(socksFail)
  686. self.request.close()
  687. continue
  688. self.request.send(socksResponseOK)
  689. thread.start_new_thread(self.pipe,(self.request,sock))
  690. thread.start_new_thread(self.pipe,(sock,self.request))
  691. if mapDict.has_key(ip+':'+str(port)):
  692. current = time()
  693. if (int(current) - int(mapDict[ip+':'+str(port)].split(':')[2])) > 60:
  694. scr.printMessage("Closing up "+self.rhost+" "+str(self.rport))
  695. endpoint = "http://"+self.rhost+"/upnp/control/igd/wanpppcInternet"
  696. soapaction = serviceType+"#DeletePortMapping"
  697. try:
  698. server = SOAPProxy(endpoint, namespace)
  699. server._sa(soapaction).DeletePortMapping(NewRemoteHost="",
  700. NewExternalPort=self.rport,
  701. NewProtocol="TCP")
  702. del mapDict[ip+':'+str(port)]
  703. except:
  704. scr.printMessage("Exception deleting")
  705. pass
  706. class UsocksServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
  707. pass
  708. ###############################
  709. ###############################
  710. ### ###
  711. ### uctui.py ###
  712. ### ###
  713. ###############################
  714. ###############################
  715. #!/usr/bin/python
  716. import curses
  717. import collections
  718. import copy
  719. import xml.dom.minidom as minidom
  720. import urllib2
  721. from SOAPpy import *
  722. UPnPActions = ['SetConnectionType',
  723. 'GetConnectionTypeInfo',
  724. 'ConfigureConnection',
  725. 'RequestConnection',
  726. 'RequestTermination',
  727. 'ForceTermination',
  728. 'SetAutoDisconnectTime',
  729. 'SetIdleDisconnectTime',
  730. 'SetWarnDisconnectDelay',
  731. 'GetStatusInfo',
  732. 'GetLinkLayerMaxBitRates',
  733. 'GetPPPEncryptionProtocol',
  734. 'GetPPPCompressionProtocol',
  735. 'GetPPPAuthenticationProtocol',
  736. 'GetUserName',
  737. 'GetPassword',
  738. 'GetAutoDisconnectTime',
  739. 'GetIdleDisconnectTime',
  740. 'GetWarnDisconnectDelay',
  741. 'GetNATRSIPStatus',
  742. 'GetGenericPortMappingEntry',
  743. 'GetSpecificPortMappingEntry',
  744. 'AddPortMapping',
  745. 'DeletePortMapping',
  746. 'GetExternalIPAddress']
  747. class uCTUI():
  748. def __init__(self, type, selectedIP, selectedIPXML, upnpList, mapList):
  749. self.type = type
  750. self.scan = ''
  751. self.mapList = mapList
  752. self.upnpList = upnpList
  753. self.selectedIPXML = selectedIPXML
  754. self.messagesQueue = collections.deque()
  755. self.positiveQueue = collections.deque()
  756. self.cursorPos = 0
  757. self.selectedIP = selectedIP
  758. self.qSize = 0
  759. self.mainScreen = curses.initscr()
  760. self.mainMax = self.mainScreen.getmaxyx()
  761. self.mainScreen.clear()
  762. self.mainScreen.subwin(self.mainMax[0], self.mainMax[1], 0, 0)
  763. self.messagesLimit = self.mainMax[1]
  764. self.mainScreen.box()
  765. curses.noecho()
  766. curses.cbreak()
  767. self.mainScreen.refresh()
  768. def draw(self):
  769. start = 0
  770. if self.type == 1:
  771. self.positiveWindow = curses.newwin(20,20,1,1)
  772. self.positiveWindow.box()
  773. self.positiveWindow.addstr(0,1,"Positive IP's",curses.A_REVERSE)
  774. self.positiveWindow.refresh()
  775. self.detailWindow = curses.newwin(20,self.mainMax[1]-25,1,22)
  776. self.detailWindow.box()
  777. if len(self.upnpList) > 0:
  778. dselectedIP = self.upnpList[self.selectedIP].split('|')[0]
  779. dselectedService = self.upnpList[self.selectedIP].split('|')[7].split(':')[3]
  780. dselectedTiming = self.upnpList[self.selectedIP].split('|')[8].split('.')[0]
  781. else:
  782. dselectedIP = ''
  783. dselectedService = ''
  784. dselectedTiming = '-'
  785. self.detailWindow.addstr(0,1,"UPnP Details - |Selected IP: "+dselectedIP+" |Total positives: "+str(len(self.upnpList))+" |Service: "+dselectedService+" |Timing: "+dselectedTiming+"ms",curses.A_REVERSE)
  786. dcount = 1
  787. for k in self.selectedIPXML:
  788. if dcount < 20: self.detailWindow.addstr(dcount,1,str(k)+": "+str(self.selectedIPXML[k]))
  789. dcount = dcount + 1
  790. self.detailWindow.refresh()
  791. self.messagesWindow = curses.newwin(self.mainMax[0]-22, self.mainMax[1]-4, 21, 1)
  792. self.messagesWindow.box()
  793. self.messagesWindow.addstr(0,1,"Messages",curses.A_REVERSE)
  794. self.messagesWindow.refresh()
  795. count = 1
  796. if self.selectedIP >= range(19,254,19)[0]:
  797. start = self.selectedIP
  798. end = self.selectedIP+19
  799. elif self.selectedIP >= range(19,254,19)[1]:
  800. start = self.selectedIP
  801. end = self.selectedIP+19
  802. for positive in self.upnpList:
  803. if count < start+1:
  804. count += 1
  805. continue
  806. if self.selectedIP < start+19 and start > 18 and count < end:
  807. self.positiveWindow.addstr(count-start,1,str(count-start)+"-"+positive.split('|')[0])
  808. count = count + 1
  809. if self.selectedIP == count-1:
  810. self.positiveWindow.addstr(count-start,1,str(count-start)+"+"+positive.split('|')[0],curses.A_REVERSE)
  811. count = count + 1
  812. continue
  813. if count < 19 and start == 0:
  814. self.positiveWindow.addstr(count,1,str(count)+"-"+positive.split('|')[0])
  815. count = count + 1
  816. self.positiveWindow.refresh()
  817. else:
  818. self.mappingWindow = curses.newwin(20,47,1,1)
  819. self.mappingWindow.box()
  820. self.mappingWindow.addstr(0,1,"Mappings",curses.A_REVERSE)
  821. mcount = 1
  822. for map in self.mapList:
  823. if mcount < 20:
  824. self.mappingWindow.addstr(mcount,1,str(map))
  825. mcount = mcount + 1
  826. self.mappingWindow.refresh()
  827. self.detailWindow = curses.newwin(20,self.mainMax[1]-52,1,48)
  828. self.detailWindow.box()
  829. self.detailWindow.addstr(0,1,"UPnP Details",curses.A_REVERSE)
  830. dcount = 1
  831. for k in self.selectedIPXML:
  832. if dcount < 20: self.detailWindow.addstr(dcount,1,str(k)+": "+str(self.selectedIPXML[k]))
  833. dcount = dcount + 1
  834. self.detailWindow.refresh()
  835. it = self.mainMax[0]-22
  836. self.messagesWindow = curses.newwin(self.mainMax[0]-22, self.mainMax[1]-4, 21, 1)
  837. self.messagesWindow.box()
  838. self.messagesWindow.addstr(0,1,"Messages",curses.A_REVERSE)
  839. self.messagesWindow.refresh()
  840. count = 1
  841. for map in self.mapList:
  842. if count < 20: self.mappingWindow.addstr(count,1,str(count)+"-"+map)
  843. count = count + 1
  844. qCopy = copy.deepcopy(self.messagesQueue)
  845. count = 1
  846. for message in qCopy:
  847. self.messagesWindow.addstr(count,1,str(message))
  848. count = count + 1
  849. self.messagesWindow.refresh()
  850. def drawExecute(self):
  851. actionNumber = {}
  852. actionList = []
  853. argumentDict = {}
  854. stateVars = {}
  855. inputArgs = {}
  856. if len(self.upnpList) == 0:
  857. return False
  858. self.executeWindow = curses.newwin(40,self.mainMax[1]-25,3,5)
  859. self.executeWindow.box()
  860. self.executeWindow.refresh()
  861. try:
  862. nowIP = self.upnpList[self.selectedIP].split('|')[0]
  863. nowPort = self.upnpList[self.selectedIP].split('|')[2]
  864. nowXML = self.upnpList[self.selectedIP].split('|')[6]
  865. scpd = "http://"+nowIP+":"+nowPort+nowXML
  866. request = urllib2.Request(scpd, None)
  867. response = urllib2.urlopen(request)
  868. headers = response.info()
  869. xmlData = response.read()
  870. except Exception, err:
  871. return False
  872. xmlRoot = minidom.parseString(xmlData)
  873. for stateVar in xmlRoot.getElementsByTagName('stateVariable'):
  874. stateVarName = stateVar.getElementsByTagName('name')[0].childNodes[0].data
  875. stateVarType = stateVar.getElementsByTagName('dataType')[0].childNodes[0].data
  876. stateVars[str(stateVarName)] = str(stateVarType)
  877. for action in xmlRoot.getElementsByTagName('action'):
  878. actionName = action.getElementsByTagName('name')[0].childNodes[0].data
  879. actionList.append(str(actionName))
  880. argumentDict[actionName] = ''
  881. for argument in action.getElementsByTagName('argument'):
  882. lenAction = len(actionList)
  883. nowArg = argument.getElementsByTagName('name')[0].childNodes[0].data
  884. relatedVar = argument.getElementsByTagName('relatedStateVariable')[0].childNodes[0].data
  885. direction = argument.getElementsByTagName('direction')[0].childNodes[0].data
  886. if argumentDict[actionName] == '':
  887. argumentDict[actionName] = nowArg+":"+stateVars[relatedVar]+":"+direction
  888. else:
  889. argumentDict[actionName] = argumentDict[actionName]+"|"+nowArg+":"+stateVars[relatedVar]+":"+direction
  890. count = 1
  891. for action in actionList:
  892. strCount = str(count)
  893. self.executeWindow.addstr(count,1,strCount+"-"+str(action))
  894. actionNumber[strCount] = str(action)
  895. count = count + 1
  896. for action in UPnPActions:
  897. strCount = str(count)
  898. if action in actionList: continue
  899. self.executeWindow.addstr(count,1,strCount+"-"+str(action),curses.A_BOLD)
  900. actionNumber[strCount] = str(action)
  901. count = count + 1
  902. self.executeWindow.refresh()
  903. selection = self.executeWindow.getstr()
  904. if not selection.isdigit() or int(selection) > count:
  905. self.mainScreen.clear()
  906. self.mainScreen.refresh()
  907. self.printMessage("Error in selection")
  908. return False
  909. try:
  910. nowAction = actionNumber.get(selection)
  911. if argumentDict.has_key(nowAction):
  912. nowArgs = argumentDict[nowAction].split('|')
  913. else:
  914. nowArgs = ''
  915. for nowArg in nowArgs:
  916. nowArg = nowArg.split(':')
  917. if nowArg[2] == 'out': continue
  918. self.executeWindow.clear()
  919. self.executeWindow.refresh()
  920. curses.echo()
  921. self.executeWindow.addstr(1,1,"Insert("+str(nowArg[1])+") "+str(nowArg[0])+":")
  922. input = self.executeWindow.getstr()
  923. curses.noecho()
  924. inputArgs[str(nowArg[0])] = str(input)+"|"+str(nowArg[1])
  925. self.executeWindow.refresh()
  926. except Exception, err:
  927. self.printMessage("Error in selection "+str(err))
  928. return False
  929. sendParms = self.upnpList[self.selectedIP].split('|')
  930. if selection == '99':
  931. soapRequest = self.sendSoap(sendParms[1], sendParms[0], sendParms[2], sendParms[7], "GetPPPAuthenticationProtocol", inputArgs)
  932. else:
  933. soapRequest = self.sendSoap(sendParms[1], sendParms[0], sendParms[2], sendParms[7], actionNumber.get(selection), inputArgs)
  934. newXML = ''
  935. if not soapRequest or 'faultString' in soapRequest:
  936. self.printMessage("Error in UPnP Request")
  937. return False
  938. try:
  939. for s in soapRequest:
  940. newXML += s+'\n'
  941. xmlResponse = minidom.parseString(newXML)
  942. ecount = 1
  943. self.executeWindow.clear()
  944. self.executeWindow.refresh()
  945. if argumentDict.has_key(nowAction):
  946. nowArgs = argumentDict[nowAction].split('|')
  947. for nowArg in nowArgs:
  948. nowArg = nowArg.split(':')
  949. if nowArg[2] == 'in': continue
  950. responseValue = xmlResponse.getElementsByTagName(nowArg[0])[0].childNodes[0].data
  951. if not responseValue: continue
  952. self.executeWindow.addstr(ecount,1,nowArg[0]+": "+responseValue)
  953. ecount = ecount + 1
  954. else:
  955. nowArgs = ''
  956. for r in xmlResponse.getElementsByTagName('s:Body'):
  957. outerBody = r.childNodes[1]
  958. inner = outerBody.childNodes[1].toxml()
  959. if not inner: continue
  960. self.executeWindow.addstr(ecount,1,inner)
  961. self.executeWindow.addstr(ecount+5,1,"Press any key to continue")
  962. self.executeWindow.refresh()
  963. self.executeWindow.getch()
  964. except Exception, err:
  965. self.printMessage("Exception: "+str(err))
  966. return False
  967. del self.executeWindow
  968. self.mainScreen.clear()
  969. self.mainScreen.refresh()
  970. def sendSoap(self, control, ip, port, device, action, inputArgs = ''):
  971. body = []
  972. bodyStr = '<ns1:'+action+' xmlns:ns1="'+device+'" SOAP-ENC:root="1">\n'
  973. if len(inputArgs) > 0:
  974. for k,v in inputArgs.iteritems():
  975. splitv = v.split('|')
  976. try:
  977. body.append("<"+k+" xsi:type=\"xsd:"+splitv[1]+"\">"+splitv[0]+"</"+k+">")
  978. except Exception, err:
  979. self.printMessage("Exception "+str(v))
  980. for b in body:
  981. bodyStr = bodyStr+str(b)+"\n"
  982. bodyStr = bodyStr+"</ns1:"+action+">"
  983. payload = """<?xml version="1.0" encoding="UTF-8"?>
  984. <SOAP-ENV:Envelope
  985. SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
  986. xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  987. xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  988. xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  989. xmlns:xsd="http://www.w3.org/1999/XMLSchema"
  990. >
  991. <SOAP-ENV:Body>"""+bodyStr+"""
  992. </SOAP-ENV:Body>
  993. </SOAP-ENV:Envelope>
  994. \r\n\r\n
  995. """
  996. head = """POST """+control+""" HTTP/1.0\r
  997. Host: """+ip+"""\r
  998. User-agent: Umap v0.5 UPnP/1.1 None\r
  999. Content-type: text/xml; charset="UTF-8"\r
  1000. Content-length: """+str(len(payload))+"""\r
  1001. SOAPAction: """+'"'+device+'#'+action+'"'+"""\r
  1002. \r\n"""
  1003. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  1004. try:
  1005. sock.connect((ip, int(port)))
  1006. except Exception, err:
  1007. self.printMessage("Error connecting for SOAP request")
  1008. return False
  1009. sock.send(head+payload)
  1010. soapRcvStr = ''
  1011. while 1:
  1012. try:
  1013. soapRcv = sock.recv(2048)
  1014. except Exception, err:
  1015. self.printMessage("Error receiving "+str(err))
  1016. return False
  1017. if not soapRcv: break
  1018. soapRcvStr += soapRcv
  1019. sock.close
  1020. f = 0
  1021. response = []
  1022. for s in soapRcvStr.split('\n'):
  1023. if '<?xml ' in s: f = 1
  1024. if f == 1:
  1025. response.append(s)
  1026. return response
  1027. def printMessage(self, message):
  1028. queueSize = len(self.messagesQueue)
  1029. self.qSize = queueSize
  1030. total = self.mainMax[0]-24
  1031. min = total+1
  1032. max = total-1
  1033. count = 1
  1034. if queueSize == total:
  1035. popleft = self.messagesQueue.popleft()
  1036. self.messagesQueue.append(message)
  1037. else:
  1038. self.messagesQueue.append(message)
  1039. def printInfo(self, out):
  1040. count = 1
  1041. for k in out:
  1042. if count < 20: self.detailWindow.addstr(count,1,str(k)+": "+str(out[k]))
  1043. count = count + 1
  1044. self.detailWindow.refresh()
  1045. def cursorUp(self):
  1046. self.selectedIPXML = {}
  1047. if self.cursorPos == 1 or self.selectedIP <= 0:
  1048. return self.cursorPos
  1049. else:
  1050. self.cursorPos = self.cursorPos - 1
  1051. self.selectedIP = self.selectedIP - 1
  1052. return self.cursorPos
  1053. def cursorDown(self):
  1054. self.selectedIPXML = {}
  1055. if len(self.upnpList) == self.cursorPos or self.selectedIP == len(self.upnpList)-1:
  1056. return self.cursorPos
  1057. else:
  1058. self.cursorPos = self.cursorPos + 1
  1059. self.selectedIP = self.selectedIP + 1
  1060. return self.cursorPos
  1061. def allRefresh(self):
  1062. self.mainScreen.refresh()
  1063. self.positiveWindow.refresh()
  1064. self.detailWindow.refresh()
  1065. self.messagesWindow.refresh()
  1066. def exitCurse(self):
  1067. curses.nocbreak()
  1068. curses.echo()
  1069. curses.endwin()

comments powered by Disqus