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.

gdb.rb 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. # -*- coding: binary -*-
  2. require 'msf/core/exploit/tcp'
  3. module Msf
  4. #
  5. # Implement some helpers for communicating with a remote gdb instance.
  6. #
  7. # More info on the gdb protocol can be found here:
  8. # https://sourceware.org/gdb/current/onlinedocs/gdb/Overview.html#Overview
  9. #
  10. module Exploit::Remote::Gdb
  11. include Msf::Exploit::Remote::Tcp
  12. # thrown when an expected ACK packet is never received
  13. class BadAckError < RuntimeError; end
  14. # thrown when a response is incorrect
  15. class BadResponseError < RuntimeError; end
  16. # thrown when a checksum is invalid
  17. class BadChecksumError < RuntimeError; end
  18. # Default list of supported GDB features to send them to the target
  19. GDB_FEATURES = 'qSupported:multiprocess+;qRelocInsn+;qvCont+;'
  20. # Maps index of register in GDB that holds $PC to architecture
  21. PC_REGISTERS = {
  22. '08' => ARCH_X86,
  23. '10' => ARCH_X86_64
  24. }
  25. # Send an ACK packet
  26. def send_ack
  27. sock.put('+')
  28. vprint_status('Sending ack...')
  29. end
  30. # Reads an ACK packet from the wire
  31. # @raise [BadAckError] if a bad ACK is received
  32. def read_ack
  33. unless sock.get_once(1) == '+'
  34. raise BadAckError
  35. end
  36. vprint_status('Received ack...')
  37. end
  38. # Sends a command and receives an ACK from the remote.
  39. # @param cmd [String] the gdb command to run. The command is will be
  40. # wrapped '$' prefix and checksum.
  41. def send_cmd(cmd)
  42. full_cmd = '$' + cmd + '#' + checksum(cmd)
  43. vprint_status('Sending cmd: '+full_cmd)
  44. sock.put(full_cmd)
  45. read_ack
  46. end
  47. # Reads (and possibly decodes) from the socket and sends an ACK to verify receipt
  48. # @param opts [Hash] the options hash
  49. # @option opts :decode [Boolean] rle decoding should be applied to the response
  50. # @option opts :verify [Boolean] verify the response's checksum
  51. # @return [String] the response
  52. # @raise [BadResponseError] if the expected response is missing
  53. # @raise [BadChecksumError] if the checksum is invalid
  54. def read_response(opts={})
  55. decode, verify = opts.fetch(:decode, false), opts.fetch(:verify, true)
  56. res = sock.get_once
  57. raise BadResponseError if res.nil?
  58. raise BadChecksumError if (verify && !verify_checksum(res))
  59. res = decode_rle(res) if decode
  60. vprint_status('Result: '+res)
  61. send_ack
  62. res
  63. end
  64. # Implements decoding of gdbserver's Run-Length-Encoding that is applied
  65. # on some hex values to collapse repeated characters.
  66. #
  67. # https://sourceware.org/gdb/current/onlinedocs/gdb/Overview.html#Binary-Data
  68. #
  69. # @param msg [String] the message to decode
  70. # @return [String] the decoded result
  71. def decode_rle(msg)
  72. vprint_status "Before decoding: #{msg}"
  73. msg.gsub /.\*./ do |match|
  74. match.bytes.to_a.first.chr * (match.bytes.to_a.last - 29 + 1)
  75. end
  76. end
  77. # The two-digit checksum is computed as the modulo 256 sum of all characters
  78. # between the leading ‘$’ and the trailing ‘#’ (an eight bit unsigned checksum).
  79. # @param str [String] the string to calculate the checksum of
  80. # @return [String] hex string containing checksum
  81. def checksum(str)
  82. "%02x" % str.bytes.inject(0) { |b, sum| (sum+b)%256 }
  83. end
  84. # Verifies a response's checksum
  85. # @param res [String] the response to check
  86. # @return [Boolean] whether the checksum is valid
  87. def verify_checksum(res)
  88. msg, chksum = res.match(/^\$(.*)#(\h{2})$/)[1..2]
  89. checksum(msg) == chksum
  90. end
  91. # Writes the buffer +buf+ to the address +addr+ in the remote process's memory
  92. # @param buf [String] the buffer to write
  93. # @param addr [String] the hex-encoded address to write to
  94. def write(buf, addr)
  95. hex = Rex::Text.to_hex(buf, '')
  96. send_cmd "M#{addr},#{buf.length.to_s(16)}:#{hex}"
  97. read_response
  98. end
  99. # Steps execution and finds $PC pointer and architecture
  100. # @return [Hash] with :arch and :pc keys containing architecture and PC pointer
  101. # @raise [BadResponseError] if necessary data is missing
  102. def process_info
  103. data = step
  104. pc_data = data.split(';')[2]
  105. raise BadResponseError if pc_data.nil?
  106. pc_data = pc_data.split(':')
  107. my_arch = PC_REGISTERS[pc_data[0]]
  108. pc = pc_data[1]
  109. if my_arch.nil?
  110. raise RuntimeError, "Could not detect a supported arch from response to step:\n#{pc_data}"
  111. end
  112. {
  113. arch: my_arch,
  114. pc: Rex::Text.to_hex(Rex::Arch.pack_addr(my_arch, Integer(pc, 16)), ''),
  115. pc_raw: Integer(pc, 16)
  116. }
  117. end
  118. # Continues execution of the remote process
  119. # @param opts [Hash] the options hash
  120. # @option opts :read [Boolean] read the response
  121. def continue(opts={})
  122. send_cmd 'vCont;c'
  123. read_response if opts.fetch(:read, true)
  124. end
  125. # Detaches from the remote process
  126. # @param opts [Hash] the options hash
  127. # @option opts :read [Boolean] read the response
  128. def detach(opts={})
  129. send_cmd 'D'
  130. read_response if opts.fetch(:read, true)
  131. end
  132. # Executes one instruction on the remote process
  133. #
  134. # The results of running "step" will look like:
  135. # x86: $T0505:00000000;04:a0f7ffbf;08:d2f0fdb7;thread:p2d39.2d39;core:0;#53
  136. # x64: $T0506:0000000000000000;07:b0587f9fff7f0000;10:d3e29d03057f0000;thread:p8bf9.8bf9;core:0;#df
  137. # The third comma-separated field will contain EIP, and the register index
  138. # will let us deduce the remote architecture (through PC_REGISTERS lookup)
  139. #
  140. # @return [String] a list of key/value pairs, including current PC
  141. def step
  142. send_cmd 'vCont;s'
  143. read_response(decode: true)
  144. end
  145. def run(filename)
  146. send_cmd "vRun;#{Rex::Text.to_hex(filename, '')}"
  147. read_response
  148. end
  149. def enable_extended_mode
  150. send_cmd("!")
  151. read_response
  152. end
  153. # Performs a handshake packet exchange
  154. # @param features [String] the list of supported features to tell the remote
  155. # host that the client supports (defaults to +DEFAULT_GDB_FEATURES+)
  156. def handshake(features=GDB_FEATURES)
  157. send_cmd features
  158. read_response # lots of flags, nothing interesting
  159. end
  160. end
  161. end