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.

wdbrpc.rb 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. # -*- coding: binary -*-
  2. require 'msf/core'
  3. module Msf
  4. ###
  5. #
  6. # This module exposes methods for manipulating the WDRPC service
  7. #
  8. ###
  9. module Exploit::Remote::WDBRPC
  10. # WDB_TARGET_CONNECT2
  11. def wdbrpc_request_connect2(ip)
  12. ip += "\x00"
  13. while(ip.length % 4 != 0)
  14. ip << "\x00"
  15. end
  16. data = [
  17. 0x00000002,
  18. 0x00000000,
  19. 0x00000000,
  20. 0x00000001,
  21. ip.length
  22. ].pack("N*") + ip
  23. wdbrpc_request(0x7a, data)
  24. end
  25. # WDB_TARGET_CONNECT
  26. def wdbrpc_request_connect(ip)
  27. data = [ 0x00000002, 0x00000000, 0x00000000 ].pack("N*")
  28. wdbrpc_request(1, data)
  29. end
  30. # WDB_TARGET_DISCONNECT
  31. def wdbrpc_request_disconnect
  32. data = [ 0x00000002, 0x00000000, 0x00000000 ].pack("N*")
  33. wdbrpc_request(2, data)
  34. end
  35. def wdbrpc_request_regread(regset=0, offset=0, length=512, params=0)
  36. data = [ regset ].pack("N")
  37. # WDB_CTX
  38. data << [
  39. 0, # WDB_CTX_SYSTEM (3 for task)
  40. 0, # SYSTEM (or set for task)
  41. ].pack("N*")
  42. # WDB_MEM_REGION
  43. data << [
  44. offset, # baseAddress
  45. length, # numberOfBytes
  46. params, # params
  47. ].pack("N*")
  48. wdbrpc_request(40, data)
  49. end
  50. def wdbrpc_request_memread(offset=0, length=512, params=0)
  51. # WDB_MEM_REGION
  52. data = [
  53. offset, # baseAddress
  54. length, # numberOfBytes
  55. params, # params
  56. ].pack("N*")
  57. wdbrpc_request(10, data)
  58. end
  59. def wdbrpc_request_memwrite(offset=0, buff='', params=0)
  60. # Make sure its DWORD aligned
  61. while(buff.length % 4 != 0)
  62. buff << "\x00"
  63. end
  64. # WDB_MEM_XFER
  65. data = [
  66. buff.length,
  67. offset, # target
  68. buff.length
  69. ].pack("N*") + buff
  70. wdbrpc_request(11, data)
  71. end
  72. def wdbrpc_request_memscan(offset=0, depth=1024, buff='', params=0)
  73. # Make sure its DWORD aligned
  74. while(buff.length % 4 != 0)
  75. buff << "\x00"
  76. end
  77. # WDB_MEM_REGION
  78. data = [
  79. offset, # baseAddress
  80. depth, # numberOfBytes
  81. params, # params
  82. ].pack("N*")
  83. # WDB_MEM_XFER
  84. data << [
  85. buff.length,
  86. 0,
  87. buff.length
  88. ].pack("N*") + buff
  89. wdbrpc_request(11, data)
  90. end
  91. def wdbrpc_request_context_kill(ctx_type, ctx)
  92. # WDB_CTX
  93. data = [
  94. ctx_type, # WDB_CTX_SYSTEM (3 for task)
  95. ctx, # SYSTEM (or set for task)
  96. ].pack("N*")
  97. # options
  98. data << [ 0 ] .pack("N")
  99. wdbrpc_request(31, data)
  100. end
  101. def wdbrpc_parse_connect_reply(buff)
  102. info = {}
  103. head = buff.slice!(0,36)
  104. info[:agent_ver] = wdbrpc_decode_str(buff)
  105. info[:agent_mtu] = wdbrpc_decode_int(buff)
  106. info[:agent_mod] = wdbrpc_decode_int(buff)
  107. info[:rt_type] = wdbrpc_decode_int(buff)
  108. info[:rt_vers] = wdbrpc_decode_str(buff)
  109. info[:rt_cpu_type] = wdbrpc_decode_int(buff)
  110. info[:rt_has_fpp] = wdbrpc_decode_bool(buff)
  111. info[:rt_has_wp] = wdbrpc_decode_bool(buff)
  112. info[:rt_page_size] = wdbrpc_decode_int(buff)
  113. info[:rt_endian] = wdbrpc_decode_int(buff)
  114. info[:rt_bsp_name] = wdbrpc_decode_str(buff)
  115. info[:rt_bootline] = wdbrpc_decode_str(buff)
  116. info[:rt_membase] = wdbrpc_decode_int(buff)
  117. info[:rt_memsize] = wdbrpc_decode_int(buff)
  118. info[:rt_region_count] = wdbrpc_decode_int(buff)
  119. info[:rt_regions] = wdbrpc_decode_arr(buff, :int)
  120. info[:rt_hostpool_base] = wdbrpc_decode_int(buff)
  121. info[:rt_hostpool_size] = wdbrpc_decode_int(buff)
  122. info
  123. end
  124. def wdbrpc_request(procedure, data)
  125. pkt =
  126. [
  127. 0x00000000, # XID (ignored by checksum and length)
  128. 0x00000000,
  129. 0x00000002,
  130. 0x55555555, # Program
  131. 0x00000001, # Version
  132. procedure, # Procedure
  133. 0x00000000,
  134. 0x00000000,
  135. 0x00000000,
  136. 0x00000000
  137. ].pack("N*")
  138. pkt +=
  139. [
  140. 0x00000000, # Checksum
  141. 0x00000000, # Packet Size
  142. wdbrpc_request_seqno
  143. ].pack("N*")
  144. pkt += data
  145. # Length excludes the XID
  146. pkt[44, 4] = [ pkt.length - 4].pack("N")
  147. # Set the checksum flag and calculate the checksum
  148. pkt[42, 2] = [ wdbrpc_checksum(pkt) ].pack("n")
  149. pkt[40, 2] = [0xffff].pack("n")
  150. # Set the RPC XID
  151. pkt[ 0, 4] = [ rand(0x100000000) ].pack("N")
  152. pkt
  153. end
  154. def wdbrpc_request_seqno
  155. @wdbrpc_seqno ||= 0
  156. @wdbrpc_seqno += 1
  157. end
  158. def wdbrpc_checksum(data)
  159. sum = 0
  160. data.unpack("n*").each {|c| sum += c }
  161. sum = (sum & 0xffff) + (sum >> 16)
  162. (~sum)
  163. end
  164. def wdbrpc_decode_str(data)
  165. return if data.length < 4
  166. slen = data.slice!(0,4).unpack("N")[0]
  167. return "" if slen == 0
  168. while (slen % 4 != 0)
  169. slen += 1
  170. end
  171. data.slice!(0,slen).to_s.split("\x00")[0]
  172. end
  173. def wdbrpc_decode_int(data)
  174. return if data.length < 4
  175. data.slice!(0,4).unpack("N")[0]
  176. end
  177. def wdbrpc_decode_arr(data, dtype)
  178. return if data.length < 4
  179. res = []
  180. alen = data.slice!(0,4).unpack("N")[0]
  181. return res if alen == 0
  182. 1.upto(alen) do |idx|
  183. case dtype
  184. when :int
  185. res << wdbrpc_decode_int(data)
  186. when :str
  187. res << wdbrpc_decode_str(data)
  188. when :bool
  189. res << wdbrpc_decode_bool(data)
  190. end
  191. end
  192. res
  193. end
  194. def wdbrpc_decode_bool(data)
  195. return if data.length < 4
  196. (data.slice!(0,4).unpack("N")[0] == 0) ? false : true
  197. end
  198. end
  199. end