Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

realport.rb 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. # -*- coding: binary -*-
  2. require 'msf/core'
  3. require 'msf/core/exploit/tcp'
  4. module Msf
  5. ###
  6. #
  7. # This module provides methods for working with the RealPort protocol
  8. #
  9. ###
  10. module Exploit::Remote::RealPort
  11. include Msf::Exploit::Remote::Tcp
  12. #
  13. # Initializes an instance of an auxiliary module that uses RealPort
  14. #
  15. def initialize(info = {})
  16. super
  17. register_options( [
  18. Opt::RPORT(771)
  19. ], Msf::Exploit::Remote::RealPort )
  20. end
  21. @@REALPORT_BAUD_MAP = {
  22. '2400' => "\x03\x00",
  23. '9600' => "\x00\xc0",
  24. '19200' => "\x00\x60",
  25. '38400' => "\x00\x20",
  26. '57600' => "\x00\x30",
  27. '76800' => "\x00\x10",
  28. '115200' => "\x00\x10", # Yup, same as above
  29. '230400' => "\x00\x08",
  30. '460800' => "\x00\x04",
  31. '921600' => "\x00\x02",
  32. }
  33. # Connect to the RealPort service and send the initial handshake
  34. # This has the benefit of retrieving the port count and product
  35. # Returns true if it succeeds and nil otherwise
  36. def realport_connect
  37. connect
  38. sock.put("\xfb\x01\xfb\x02\xfb\x18")
  39. res = sock.get_once(12, 5)
  40. return unless (res and res.length == 12)
  41. unless res[0,2] == "\xfc\x01"
  42. vprint_error("#{rhost}:#{rport} Bad reply: #{res.inspect}")
  43. return
  44. end
  45. len = res[2,2].unpack("n").first
  46. return unless len > 0
  47. res = sock.get_once(len, 5)
  48. unless res.length == len
  49. vprint_error("#{rhost}:#{rport} Bad length: #{res.length} wanted #{len}")
  50. return
  51. end
  52. name,info = res.split("\xfc\x02", 2)
  53. fields = info.unpack("n*")
  54. @realport_port_count = fields[1].to_i
  55. @realport_name = name.gsub(/[\r\n]/, '')
  56. # The server also sends us an additional four-byte packet we can ignore here
  57. # This throws away a \xFC\x18\x00\x04 sequence
  58. sock.get_once(-1, 5)
  59. return true
  60. end
  61. def realport_disconnect
  62. disconnect
  63. end
  64. def realport_baud_to_speed(baud)
  65. @@REALPORT_BAUD_MAP[baud]
  66. end
  67. def realport_recv_banner(port=0, timeout=30, max_data=4096)
  68. #
  69. # Data is received here, header is:
  70. # a2 00 01 82 XX
  71. # ^ [ counter ] [ length ] [ data ]
  72. #
  73. # Can also see f0 here (keep alive)
  74. banner = ""
  75. stime = Time.now.to_f
  76. dcnt = 0
  77. pcnt = 0
  78. while banner.length < max_data and (Time.now.to_f - stime) < timeout
  79. res = sock.get_once(1, 1)
  80. unless res
  81. if banner.length == 0 or pcnt < 3
  82. # Send a new line to wake up the remote end
  83. realport_send(port, "\r")
  84. pcnt += 1
  85. next
  86. else
  87. # Allow three empty reads *after* we have sent at least one probe and have data
  88. dcnt += 1
  89. break if dcnt > 3
  90. next
  91. end
  92. end
  93. bit = res.unpack("C").first
  94. case bit
  95. when (0xA0 + port)
  96. # Read the packet sequence number (two bytes)
  97. res = sock.get_once(2, 1)
  98. when 0xF0
  99. # Skip this keep-alive response
  100. when (0x80 + port)
  101. # Read the one-byte length value
  102. res = sock.get_once(1, 1)
  103. if res
  104. len = res.unpack("C").first
  105. res = sock.get_once(len, 1)
  106. if res
  107. banner << res
  108. end
  109. end
  110. end
  111. end
  112. banner
  113. end
  114. def realport_send(port=0, data="")
  115. sock.put( [port].pack("C") + data )
  116. end
  117. def realport_close(port=0)
  118. cprt = [ 0xb0 + port ].pack("C")
  119. pkt = cprt + "\x28\x00\xc0\x00\xb0\x00\x01\x00\x00\x00\x00" + cprt + "\x0a\x03"
  120. # Response
  121. # b2 0b 03 00 00 02
  122. # Send a close request
  123. sock.put(pkt)
  124. res = sock.get_once(-1, 5)
  125. vprint_status("#{target_host}:#{rport} Port:#{port} Close:#{ res.inspect }")
  126. return
  127. end
  128. def realport_open(port=0, baud='9600')
  129. @realport_banner = ''
  130. cprt = [ 0xb0 + port ].pack("C")
  131. aprt = [ 0xa0 + port ].pack("C")
  132. speed = realport_baud_to_speed(baud)
  133. # Open port
  134. pkt1 = "\xf0" + cprt + "\x0a"+ "\x00"
  135. # Response
  136. # b2 0b 00 00 00 02
  137. # ^ ^ <- port number
  138. # Open the port
  139. sock.put(pkt1)
  140. res = sock.get_once(-1, 5)
  141. vprint_status("#{target_host}:#{rport} Port:#{port} Baud:#{baud} Open:#{ res.inspect }")
  142. # Access the port
  143. pkt2 =
  144. cprt + "\x0e" +
  145. cprt + "\x2a\x02\xc0\xf3" +
  146. cprt + "\x10" +
  147. cprt + "\x14" +
  148. cprt + "\x16" +
  149. cprt + "\x2c\x03\x00\x00"
  150. # Response (GOOD)
  151. # b2 0f 00 00 00 00 b2 15 0f ff 0f ff b2 11 00 00
  152. # 13 b2 17 01 02 00 2f 06 a8 00 1c 20 00 00 00 00
  153. # 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00
  154. # 00
  155. # Response (BAD)
  156. # \xFF \x17 Access to unopened port\x00
  157. # Send negotiate request
  158. sock.put(pkt2)
  159. res = sock.get_once(-1, 5)
  160. if res.to_s =~ /^\xff/n
  161. vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
  162. return :closed
  163. end
  164. vprint_status("#{target_host}:#{rport} Port:#{port} Baud:#{baud} Negotiate:#{ res.inspect }")
  165. # Terminal settings
  166. pkt3 =
  167. cprt + "\x30\x03\xff\x00\x64" +
  168. cprt + "\x2d\x03\xff\x0b\xff" +
  169. cprt + "\x28" + speed + "\x04" +
  170. cprt + "\x00\x01\x00\x00\x00\x00" +
  171. cprt + "\x2c\x00\x12\x00" +
  172. cprt + "\x2e\x11\x13\x16\x00\x00" +
  173. cprt + "\x2f\x03\xff\x00\x64" +
  174. cprt + "\x40\x37" + aprt + "\x0f\xff"
  175. # Response
  176. # c2 12 00 00 f0
  177. # ^
  178. # Send terminal settings request
  179. sock.put(pkt3)
  180. res = sock.get_once(-1, 5)
  181. if res.to_s =~ /^\xff/n
  182. vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
  183. return :closed
  184. end
  185. vprint_status("#{target_host}:#{rport} Port:#{port} Baud:#{baud} Settings:#{ res.inspect }")
  186. return :open
  187. end
  188. end
  189. end