/telnetenable.py

https://github.com/semyazza/netgear-telenetenable · Python · 115 lines · 64 code · 22 blank · 29 comment · 12 complexity · 277b60d4c242dc13d22c8a5b1549025d MD5 · raw file

  1. # Copyright (c) 2009 Paul Gebheim
  2. #
  3. # Permission is hereby granted, free of charge, to any person obtaining a copy
  4. # of this software and associated documentation files (the "Software"), to deal
  5. # in the Software without restriction, including without limitation the rights
  6. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. # copies of the Software, and to permit persons to whom the Software is
  8. # furnished to do so, subject to the following conditions:
  9. #
  10. # The above copyright notice and this permission notice shall be included in
  11. # all copies or substantial portions of the Software.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. # THE SOFTWARE.
  20. import sys
  21. import socket
  22. import array
  23. from optparse import OptionParser
  24. from Crypto.Cipher import Blowfish
  25. from Crypto.Hash import MD5
  26. TELNET_PORT = 23
  27. # The version of Blowfish supplied for the telenetenable.c implementation
  28. # assumes Big-Endian data, but the code does nothing to convert the
  29. # little-endian stuff it's getting on intel to Big-Endian
  30. #
  31. # So, since Crypto.Cipher.Blowfish seems to assume native endianness, we need
  32. # to byteswap our buffer before and after encrypting it
  33. #
  34. # This helper does the byteswapping on the string buffer
  35. def ByteSwap(data):
  36. a = array.array('i')
  37. if(a.itemsize < 4):
  38. a = array.array('L')
  39. if(a.itemsize != 4):
  40. print "Need a type that is 4 bytes on your platform so we can fix the data!"
  41. exit(1)
  42. a.fromstring(data)
  43. a.byteswap()
  44. return a.tostring()
  45. def GeneratePayload(mac, username, password=""):
  46. # eventually reformat mac
  47. mac = mac.replace(":","").upper()
  48. # Pad the input correctly
  49. assert(len(mac) < 0x10)
  50. just_mac = mac.ljust(0x10, "\x00")
  51. assert(len(username) <= 0x10)
  52. just_username = username.ljust(0x10, "\x00")
  53. assert(len(password) <= 0x10)
  54. just_password = password.ljust(0x10, "\x00")
  55. cleartext = (just_mac + just_username + just_password).ljust(0x70, '\x00')
  56. md5_key = MD5.new(cleartext).digest()
  57. payload = ByteSwap((md5_key + cleartext).ljust(0x80, "\x00"))
  58. secret_key = "AMBIT_TELNET_ENABLE+" + password
  59. return ByteSwap(Blowfish.new(secret_key, 1).encrypt(payload))
  60. def SendPayload(ip, payload):
  61. for res in socket.getaddrinfo(ip, TELNET_PORT, socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_IP):
  62. af, socktype, proto, canonname, sa = res
  63. try:
  64. s = socket.socket(af, socktype, proto)
  65. except socket.error, msg:
  66. s = None
  67. continue
  68. try:
  69. s.connect(sa)
  70. except socket.error, msg:
  71. s.close()
  72. s= None
  73. continue
  74. break
  75. if s is None:
  76. print "Could not connect to '%s:%d'" % (ip, TELNET_PORT)
  77. else:
  78. s.send(payload)
  79. s.close()
  80. print "Sent telnet enable payload to '%s:%d'" % (ip, TELNET_PORT)
  81. def main():
  82. args = sys.argv[1:]
  83. if len(args) < 3 or len(args) > 4:
  84. print "usage: python telnetenable.py <ip> <mac> <username> [<password>]"
  85. ip = args[0]
  86. mac = args[1]
  87. username = args[2]
  88. password = ""
  89. if len(args) == 4:
  90. password = args[3]
  91. payload = GeneratePayload(mac, username, password)
  92. SendPayload(ip, payload)
  93. main()