{"action":"created","comment":{"url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/comments/24145039","id":24145039,"diff_hunk":"@@ -0,0 +1,257 @@\n+# -*- coding: binary -*-\n+module Rex\n+  module Parser\n+\n+    ###\n+    #\n+    # This class parses the contents of an NTFS partition file.\n+    # Author : Danil Bazin <danil.bazin[at]hsc.fr> @danilbaz\n+    #\n+    ###\n+    class NTFS\n+      #\n+      # Initialize the NTFS class with an already open file handler\n+      #\n+      DATA_ATTRIBUTE_ID = 128\n+      INDEX_ROOT_ID = 144\n+      INDEX_ALLOCATION_ID = 160\n+      def initialize(file_handler)\n+        @file_handler = file_handler\n+        data = @file_handler.read(4096)\n+        # Boot sector reading\n+        @bytes_per_sector = data[11, 2].unpack(\"v\")[0]\n+        @sector_per_cluster = data[13].unpack(\"C\")[0]\n+        @cluster_per_mft_record = data[64].unpack(\"c\")[0]\n+        if @cluster_per_mft_record < 0\n+          @bytes_per_mft_record = 2**(-@cluster_per_mft_record)\n+          @cluster_per_mft_record = @bytes_per_mft_record.to_f / @bytes_per_sector / @sector_per_cluster\n+        else\n+          @bytes_per_mft_record = @bytes_per_sector * @sector_per_cluster * @cluster_per_mft_record\n+        end\n+        @bytes_per_cluster = @sector_per_cluster * @bytes_per_sector\n+        @mft_logical_cluster_number = data[48, 8].unpack(\"Q<\")[0]\n+        @mft_offset = @mft_logical_cluster_number * @sector_per_cluster * @bytes_per_sector\n+        @file_handler.seek(@mft_offset)\n+        @mft = @file_handler.read(@bytes_per_mft_record)\n+      end\n+\n+      #\n+      # Gather the MFT entry corresponding to his number\n+      #\n+      def mft_record_from_mft_num(mft_num)\n+        mft_num_offset = mft_num * @cluster_per_mft_record\n+        mft_data_attribute = mft_record_attribute(@mft)[DATA_ATTRIBUTE_ID][\"data\"]\n+        cluster_from_attribute_non_resident(mft_data_attribute, mft_num_offset, @bytes_per_mft_record)\n+      end\n+\n+      #\n+      # Get the size of the file in the $FILENAME (64) attribute\n+      #\n+      def real_size_from_filenameattribute(attribute)\n+        filename_attribute = attribute\n+        filename_attribute[48, 8].unpack(\"Q<\")[0]\n+      end\n+\n+      #\n+      # Gather the name of the file from the $FILENAME (64) attribute\n+      #\n+      def filename_from_filenameattribute(attribute)\n+        filename_attribute = attribute\n+        length_of_name = filename_attribute[64].ord\n+        # uft16 *2\n+        d = ::Encoding::Converter.new(\"UTF-16LE\", \"UTF-8\")\n+        d.convert(filename_attribute[66, (length_of_name * 2)])\n+      end\n+\n+      #\n+      # Get the file from the MFT number\n+      # The size must be gived because the $FILENAME attribute\n+      # in the MFT entry does not contain it\n+      # The file is in $DATA (128) Attribute\n+      #\n+      def file_content_from_mft_num(mft_num, size)\n+        mft_record = mft_record_from_mft_num(mft_num)\n+        attribute_list = mft_record_attribute(mft_record)\n+        if attribute_list[DATA_ATTRIBUTE_ID][\"resident\"]\n+          return attribute_list[DATA_ATTRIBUTE_ID][\"data\"]\n+        else\n+          data_attribute = attribute_list[DATA_ATTRIBUTE_ID][\"data\"]\n+          return cluster_from_attribute_non_resident(data_attribute)[0, size]\n+        end\n+      end\n+\n+      #\n+      # parse one index record and return the name, MFT number and size of the file\n+      #\n+      def parse_index(index_entry)\n+        res = {}\n+        filename_size = index_entry[10, 2].unpack(\"v\")[0]\n+        filename_attribute = index_entry[16, filename_size]\n+        # Should be 8 bytes but it doesn't work\n+        # mft_offset =  index_entry[0.unpack(\"Q<\",:8])[0]\n+        # work with 4 bytes\n+        mft_offset =  index_entry[0, 4].unpack(\"V\")[0]\n+        res[filename_from_filenameattribute(filename_attribute)] = { \"mft_offset\" => mft_offset, \n+          \"file_size\" => real_size_from_filenameattribute(filename_attribute) }\n+        res\n+      end\n+\n+      #\n+      # parse index_record in $INDEX_ROOT and recursively index_record in\n+      # INDEX_ALLOCATION\n+      #\n+      def parse_index_list(index_record, index_allocation_attribute)\n+        offset_index_entry_list = index_record[0, 4].unpack(\"V\")[0]\n+        index_size =  index_record[offset_index_entry_list + 8, 2].unpack(\"v\")[0]\n+        index_entry = index_record[offset_index_entry_list, index_size]\n+        res = {}\n+        while index_entry[12, 4].unpack(\"V\")[0] & 2 != 2\n+          res.update(parse_index(index_entry))\n+          # if son\n+          if index_entry[12, 4].unpack(\"V\")[0] & 1 == 1\n+            # should be 8 bytes length\n+            vcn =  index_entry[-8, 4].unpack(\"V\")[0]\n+            vcn_in_bytes = vcn * @bytes_per_cluster\n+            index_size_in_bytes = index_size * @bytes_per_cluster\n+            res_son = parse_index_list(index_allocation_attribute[vcn_in_bytes + 24, index_size_in_bytes], index_allocation_attribute)\n+            res.update(res_son)\n+          end\n+          offset_index_entry_list += index_size\n+          index_size =  index_record[offset_index_entry_list + 8, 2].unpack(\"v\")[0]\n+          index_entry = index_record [offset_index_entry_list, index_size]\n+        end\n+        # if son on the last\n+        if index_entry[12, 4].unpack(\"V\")[0] & 1 == 1\n+          # should be 8 bytes length\n+          vcn =  index_entry[-8, 4].unpack(\"V\")[0]\n+          vcn_in_bytes = vcn * @bytes_per_cluster\n+          index_size_in_bytes = index_size * @bytes_per_cluster\n+          res_son = parse_index_list(index_allocation_attribute[vcn_in_bytes + 24, index_size_in_bytes], index_allocation_attribute)\n+          res.update(res_son)\n+        end\n+        res\n+      end\n+\n+      #\n+      # return the list of files in attribute directory and their MFT number and size\n+      #\n+      def index_list_from_attributes(attributes)\n+        index_root_attribute = attributes[INDEX_ROOT_ID]\n+        index_record = index_root_attribute[16, index_root_attribute.length - 16]\n+        if attributes.key?(INDEX_ALLOCATION_ID)\n+          return parse_index_list(index_record, attributes[INDEX_ALLOCATION_ID])\n+        else\n+          return parse_index_list(index_record, \"\")\n+        end\n+      end\n+\n+      def cluster_from_attribute_non_resident(attribute, cluster_num = 0, size_max = ((2**31) - 1))\n+        lowvcn = attribute[16, 8].unpack(\"Q<\")[0]\n+        highvcn = attribute[24, 8].unpack(\"Q<\")[0]\n+        offset = attribute[32, 2].unpack(\"v\")[0]\n+        real_size = attribute[48, 8].unpack(\"Q<\")[0]\n+        attribut = \"\"\n+        run_list_num = lowvcn\n+        old_offset = 0\n+\n+        while run_list_num <= highvcn\n+          first_runlist_byte = attribute[offset].ord\n+          run_offset_size = first_runlist_byte >> 4\n+          run_length_size = first_runlist_byte & 15\n+          run_length = attribute[offset + 1, run_length_size]\n+          run_length += \"\\x00\" * (8 - run_length_size)\n+          run_length = run_length.unpack(\"Q<\")[0]\n+\n+          offset_run_offset = offset + 1 + run_length_size\n+          run_offset = attribute[offset_run_offset, run_offset_size]\n+          if run_offset[-1].ord & 128 == 128\n+            run_offset += \"\\xFF\" * (8 - run_offset_size)\n+          else\n+            run_offset += \"\\x00\" * (8 - run_offset_size)\n+          end\n+          run_offset = run_offset.unpack(\"q<\")[0]\n+\n+          size_wanted = [run_length * @bytes_per_cluster, size_max - attribut.length].min\n+\n+          if cluster_num + (size_wanted / @bytes_per_cluster) >= run_list_num && (cluster_num < run_length + run_list_num)\n+            run_list_offset_in_cluster = run_offset + old_offset + [cluster_num - run_list_num, 0].max\n+            run_list_offset = (run_list_offset_in_cluster) * @bytes_per_cluster\n+            run_list_offset = run_list_offset.to_i\n+            @file_handler.seek(run_list_offset)\n+\n+            data = \"\"\n+            while data.length < size_wanted\n+              data << @file_handler.read(size_wanted - data.length)\n+            end\n+            attribut += data\n+          end\n+          offset += run_offset_size + run_length_size + 1\n+          run_list_num += run_length\n+          old_offset = run_offset\n+        end\n+        attribut = attribut[0, real_size]\n+        attribut\n+      end\n+\n+      #\n+      # return the attribute list from the MFT record\n+      # deal with resident and non resident attributes (but not $DATA due to perforemence issue)\n+      #\n+      def mft_record_attribute(mft_record)\n+        attribute_list_offset = mft_record[20, 2].unpack(\"C\")[0]\n+        curs = attribute_list_offset\n+        attribute_identifier = mft_record[curs, 4].unpack(\"V\")[0]\n+        res = {}\n+        while attribute_identifier != 0xFFFFFFFF\n+          # attribute_size=mft_record[curs + 4, 4].unpack(\"V\")[0]\n+          # should be on 4 bytes but doesnt work\n+          attribute_size = mft_record[curs + 4, 2].unpack(\"v\")[0]\n+          #print_debug(\"attribute_size: #{attribute_size}, attribute_identifier: #{attribute_identifier}\")\n+          # resident\n+          if mft_record[curs + 8] == \"\\x00\"\n+            content_size = mft_record[curs + 16, 4].unpack(\"V\")[0]\n+            content_offset = mft_record[curs + 20, 2].unpack(\"v\")[0]\n+            res[attribute_identifier] = mft_record[curs + content_offset, content_size]\n+          else\n+            # non resident\n+            if attribute_identifier == DATA_ATTRIBUTE_ID\n+              res[attribute_identifier] = mft_record[curs, attribute_size]\n+            else\n+              res[attribute_identifier] = cluster_from_attribute_non_resident(mft_record[curs, attribute_size])\n+            end\n+          end\n+          if attribute_identifier == DATA_ATTRIBUTE_ID\n+            res[attribute_identifier] = { \"data\" => res[attribute_identifier], \n+              \"resident\" => mft_record[curs + 8] == \"\\x00\" }\n+          end\n+          curs += attribute_size\n+          attribute_identifier = mft_record[curs, 4].unpack(\"V\")[0]\n+        end\n+        res\n+      end\n+\n+      #\n+      # return the file path in the NTFS partition\n+      #\n+      def file(path)\n+        repertory = mft_record_from_mft_num(5)\n+        index_entry = {}\n+        for r in path.split(\"\\\\\")\n+          attributes = mft_record_attribute(repertory)\n+          index = index_list_from_attributes(attributes)\n+          #print_debug(\"#{index}\")","path":"lib/rex/parser/fs/ntfs.rb","position":242,"original_position":242,"commit_id":"03fcfc496a2cf90b05423a97dce84f8834e2c8e5","original_commit_id":"03fcfc496a2cf90b05423a97dce84f8834e2c8e5","user":{"login":"scriptjunkie","id":1174495,"avatar_url":"https://avatars.githubusercontent.com/u/1174495?v=3","gravatar_id":"","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":"ditto","created_at":"2015-02-05T06:10:14Z","updated_at":"2015-02-05T06:10:14Z","html_url":"https://github.com/rapid7/metasploit-framework/pull/4679#discussion_r24145039","pull_request_url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679","_links":{"self":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/comments/24145039"},"html":{"href":"https://github.com/rapid7/metasploit-framework/pull/4679#discussion_r24145039"},"pull_request":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679"}}},"pull_request":{"url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679","id":28384243,"html_url":"https://github.com/rapid7/metasploit-framework/pull/4679","diff_url":"https://github.com/rapid7/metasploit-framework/pull/4679.diff","patch_url":"https://github.com/rapid7/metasploit-framework/pull/4679.patch","issue_url":"https://api.github.com/repos/rapid7/metasploit-framework/issues/4679","number":4679,"state":"open","locked":false,"title":"Add an NTFS parser and a post module to dump files","user":{"login":"danilbaz","id":10693088,"avatar_url":"https://avatars.githubusercontent.com/u/10693088?v=3","gravatar_id":"","url":"https://api.github.com/users/danilbaz","html_url":"https://github.com/danilbaz","followers_url":"https://api.github.com/users/danilbaz/followers","following_url":"https://api.github.com/users/danilbaz/following{/other_user}","gists_url":"https://api.github.com/users/danilbaz/gists{/gist_id}","starred_url":"https://api.github.com/users/danilbaz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danilbaz/subscriptions","organizations_url":"https://api.github.com/users/danilbaz/orgs","repos_url":"https://api.github.com/users/danilbaz/repos","events_url":"https://api.github.com/users/danilbaz/events{/privacy}","received_events_url":"https://api.github.com/users/danilbaz/received_events","type":"User","site_admin":false},"body":"This commit add a draft of an NTFS Parser and a post module\r\nto gather files using the raw NTFS device (\\\\\\\\.\\\\C:)\r\nbypassing restriction like already open file with lock\r\nCan be used to retreive files like NTDS.DIT without volume shadow copy\r\n\r\n```\r\nmsf exploit(handler) > use post/windows/gather/file_in_raw_ntfs\r\nmsf post(file_in_raw_ntfs) > set FILE C:\\\\Windows\\\\System32\\\\drivers\\\\etc\\\\hosts\r\nFILE => C:\\Windows\\System32\\drivers\\etc\\hosts\r\nmsf post(file_in_raw_ntfs) > set SESSION 1\r\nSESSION => 1\r\nmsf post(file_in_raw_ntfs) > run\r\n\r\n[*] Successfuly opened C:\r\n[*] Saving file hosts\r\n[*] Post Successfuly\r\n[*] Post module execution completed\r\nmsf post(file_in_raw_ntfs) > cat hosts\r\n[*] exec: cat hosts\r\n\r\n# Copyright (c) 1993-2009 Microsoft Corp.\r\n#\r\n# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.\r\n#\r\n# This file contains the mappings of IP addresses to host names. Each\r\n# entry should be kept on an individual line. The IP address should\r\n# be placed in the first column followed by the corresponding host name.\r\n# The IP address and the host name should be separated by at least one\r\n# space.\r\n#\r\n# Additionally, comments (such as these) may be inserted on individual\r\n# lines or following the machine name denoted by a '#' symbol.\r\n#\r\n# For example:\r\n#\r\n#      102.54.94.97     rhino.acme.com          # source server\r\n#       38.25.63.10     x.acme.com              # x client host\r\n\r\n# localhost name resolution is handled within DNS itself.\r\n#\t127.0.0.1       localhost\r\n#\t::1             localhost\r\n```\r\n","created_at":"2015-01-30T18:58:59Z","updated_at":"2015-02-05T06:10:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"15adb4efbf4f2253b1edcbd00b256da50338a246","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679/commits","review_comments_url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679/comments","review_comment_url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/comments/{number}","comments_url":"https://api.github.com/repos/rapid7/metasploit-framework/issues/4679/comments","statuses_url":"https://api.github.com/repos/rapid7/metasploit-framework/statuses/03fcfc496a2cf90b05423a97dce84f8834e2c8e5","head":{"label":"danilbaz:ntfs-parser","ref":"ntfs-parser","sha":"03fcfc496a2cf90b05423a97dce84f8834e2c8e5","user":{"login":"danilbaz","id":10693088,"avatar_url":"https://avatars.githubusercontent.com/u/10693088?v=3","gravatar_id":"","url":"https://api.github.com/users/danilbaz","html_url":"https://github.com/danilbaz","followers_url":"https://api.github.com/users/danilbaz/followers","following_url":"https://api.github.com/users/danilbaz/following{/other_user}","gists_url":"https://api.github.com/users/danilbaz/gists{/gist_id}","starred_url":"https://api.github.com/users/danilbaz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danilbaz/subscriptions","organizations_url":"https://api.github.com/users/danilbaz/orgs","repos_url":"https://api.github.com/users/danilbaz/repos","events_url":"https://api.github.com/users/danilbaz/events{/privacy}","received_events_url":"https://api.github.com/users/danilbaz/received_events","type":"User","site_admin":false},"repo":{"id":29809771,"name":"metasploit-framework","full_name":"danilbaz/metasploit-framework","owner":{"login":"danilbaz","id":10693088,"avatar_url":"https://avatars.githubusercontent.com/u/10693088?v=3","gravatar_id":"","url":"https://api.github.com/users/danilbaz","html_url":"https://github.com/danilbaz","followers_url":"https://api.github.com/users/danilbaz/followers","following_url":"https://api.github.com/users/danilbaz/following{/other_user}","gists_url":"https://api.github.com/users/danilbaz/gists{/gist_id}","starred_url":"https://api.github.com/users/danilbaz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danilbaz/subscriptions","organizations_url":"https://api.github.com/users/danilbaz/orgs","repos_url":"https://api.github.com/users/danilbaz/repos","events_url":"https://api.github.com/users/danilbaz/events{/privacy}","received_events_url":"https://api.github.com/users/danilbaz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/danilbaz/metasploit-framework","description":"Metasploit Framework","fork":true,"url":"https://api.github.com/repos/danilbaz/metasploit-framework","forks_url":"https://api.github.com/repos/danilbaz/metasploit-framework/forks","keys_url":"https://api.github.com/repos/danilbaz/metasploit-framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/danilbaz/metasploit-framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/danilbaz/metasploit-framework/teams","hooks_url":"https://api.github.com/repos/danilbaz/metasploit-framework/hooks","issue_events_url":"https://api.github.com/repos/danilbaz/metasploit-framework/issues/events{/number}","events_url":"https://api.github.com/repos/danilbaz/metasploit-framework/events","assignees_url":"https://api.github.com/repos/danilbaz/metasploit-framework/assignees{/user}","branches_url":"https://api.github.com/repos/danilbaz/metasploit-framework/branches{/branch}","tags_url":"https://api.github.com/repos/danilbaz/metasploit-framework/tags","blobs_url":"https://api.github.com/repos/danilbaz/metasploit-framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/danilbaz/metasploit-framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/danilbaz/metasploit-framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/danilbaz/metasploit-framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/danilbaz/metasploit-framework/statuses/{sha}","languages_url":"https://api.github.com/repos/danilbaz/metasploit-framework/languages","stargazers_url":"https://api.github.com/repos/danilbaz/metasploit-framework/stargazers","contributors_url":"https://api.github.com/repos/danilbaz/metasploit-framework/contributors","subscribers_url":"https://api.github.com/repos/danilbaz/metasploit-framework/subscribers","subscription_url":"https://api.github.com/repos/danilbaz/metasploit-framework/subscription","commits_url":"https://api.github.com/repos/danilbaz/metasploit-framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/danilbaz/metasploit-framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/danilbaz/metasploit-framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/danilbaz/metasploit-framework/issues/comments/{number}","contents_url":"https://api.github.com/repos/danilbaz/metasploit-framework/contents/{+path}","compare_url":"https://api.github.com/repos/danilbaz/metasploit-framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/danilbaz/metasploit-framework/merges","archive_url":"https://api.github.com/repos/danilbaz/metasploit-framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/danilbaz/metasploit-framework/downloads","issues_url":"https://api.github.com/repos/danilbaz/metasploit-framework/issues{/number}","pulls_url":"https://api.github.com/repos/danilbaz/metasploit-framework/pulls{/number}","milestones_url":"https://api.github.com/repos/danilbaz/metasploit-framework/milestones{/number}","notifications_url":"https://api.github.com/repos/danilbaz/metasploit-framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/danilbaz/metasploit-framework/labels{/name}","releases_url":"https://api.github.com/repos/danilbaz/metasploit-framework/releases{/id}","created_at":"2015-01-25T10:00:04Z","updated_at":"2015-01-30T18:54:30Z","pushed_at":"2015-01-31T05:00:33Z","git_url":"git://github.com/danilbaz/metasploit-framework.git","ssh_url":"git@github.com:danilbaz/metasploit-framework.git","clone_url":"https://github.com/danilbaz/metasploit-framework.git","svn_url":"https://github.com/danilbaz/metasploit-framework","homepage":"http://www.metasploit.com/","size":391868,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"rapid7:master","ref":"master","sha":"cb076adb19fb37f134a66c5db26393c77cb67154","user":{"login":"rapid7","id":1013671,"avatar_url":"https://avatars.githubusercontent.com/u/1013671?v=3","gravatar_id":"","url":"https://api.github.com/users/rapid7","html_url":"https://github.com/rapid7","followers_url":"https://api.github.com/users/rapid7/followers","following_url":"https://api.github.com/users/rapid7/following{/other_user}","gists_url":"https://api.github.com/users/rapid7/gists{/gist_id}","starred_url":"https://api.github.com/users/rapid7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rapid7/subscriptions","organizations_url":"https://api.github.com/users/rapid7/orgs","repos_url":"https://api.github.com/users/rapid7/repos","events_url":"https://api.github.com/users/rapid7/events{/privacy}","received_events_url":"https://api.github.com/users/rapid7/received_events","type":"Organization","site_admin":false},"repo":{"id":2293158,"name":"metasploit-framework","full_name":"rapid7/metasploit-framework","owner":{"login":"rapid7","id":1013671,"avatar_url":"https://avatars.githubusercontent.com/u/1013671?v=3","gravatar_id":"","url":"https://api.github.com/users/rapid7","html_url":"https://github.com/rapid7","followers_url":"https://api.github.com/users/rapid7/followers","following_url":"https://api.github.com/users/rapid7/following{/other_user}","gists_url":"https://api.github.com/users/rapid7/gists{/gist_id}","starred_url":"https://api.github.com/users/rapid7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rapid7/subscriptions","organizations_url":"https://api.github.com/users/rapid7/orgs","repos_url":"https://api.github.com/users/rapid7/repos","events_url":"https://api.github.com/users/rapid7/events{/privacy}","received_events_url":"https://api.github.com/users/rapid7/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rapid7/metasploit-framework","description":"Metasploit Framework","fork":false,"url":"https://api.github.com/repos/rapid7/metasploit-framework","forks_url":"https://api.github.com/repos/rapid7/metasploit-framework/forks","keys_url":"https://api.github.com/repos/rapid7/metasploit-framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rapid7/metasploit-framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rapid7/metasploit-framework/teams","hooks_url":"https://api.github.com/repos/rapid7/metasploit-framework/hooks","issue_events_url":"https://api.github.com/repos/rapid7/metasploit-framework/issues/events{/number}","events_url":"https://api.github.com/repos/rapid7/metasploit-framework/events","assignees_url":"https://api.github.com/repos/rapid7/metasploit-framework/assignees{/user}","branches_url":"https://api.github.com/repos/rapid7/metasploit-framework/branches{/branch}","tags_url":"https://api.github.com/repos/rapid7/metasploit-framework/tags","blobs_url":"https://api.github.com/repos/rapid7/metasploit-framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rapid7/metasploit-framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rapid7/metasploit-framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/rapid7/metasploit-framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rapid7/metasploit-framework/statuses/{sha}","languages_url":"https://api.github.com/repos/rapid7/metasploit-framework/languages","stargazers_url":"https://api.github.com/repos/rapid7/metasploit-framework/stargazers","contributors_url":"https://api.github.com/repos/rapid7/metasploit-framework/contributors","subscribers_url":"https://api.github.com/repos/rapid7/metasploit-framework/subscribers","subscription_url":"https://api.github.com/repos/rapid7/metasploit-framework/subscription","commits_url":"https://api.github.com/repos/rapid7/metasploit-framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/rapid7/metasploit-framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/rapid7/metasploit-framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/rapid7/metasploit-framework/issues/comments/{number}","contents_url":"https://api.github.com/repos/rapid7/metasploit-framework/contents/{+path}","compare_url":"https://api.github.com/repos/rapid7/metasploit-framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rapid7/metasploit-framework/merges","archive_url":"https://api.github.com/repos/rapid7/metasploit-framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rapid7/metasploit-framework/downloads","issues_url":"https://api.github.com/repos/rapid7/metasploit-framework/issues{/number}","pulls_url":"https://api.github.com/repos/rapid7/metasploit-framework/pulls{/number}","milestones_url":"https://api.github.com/repos/rapid7/metasploit-framework/milestones{/number}","notifications_url":"https://api.github.com/repos/rapid7/metasploit-framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rapid7/metasploit-framework/labels{/name}","releases_url":"https://api.github.com/repos/rapid7/metasploit-framework/releases{/id}","created_at":"2011-08-30T06:13:20Z","updated_at":"2015-02-05T05:50:10Z","pushed_at":"2015-02-05T05:44:22Z","git_url":"git://github.com/rapid7/metasploit-framework.git","ssh_url":"git@github.com:rapid7/metasploit-framework.git","clone_url":"https://github.com/rapid7/metasploit-framework.git","svn_url":"https://github.com/rapid7/metasploit-framework","homepage":"http://www.metasploit.com/","size":1224998,"stargazers_count":3278,"watchers_count":3278,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2751,"mirror_url":null,"open_issues_count":193,"forks":2751,"open_issues":193,"watchers":3278,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679"},"html":{"href":"https://github.com/rapid7/metasploit-framework/pull/4679"},"issue":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/issues/4679"},"comments":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/issues/4679/comments"},"review_comments":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679/comments"},"review_comment":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/pulls/4679/commits"},"statuses":{"href":"https://api.github.com/repos/rapid7/metasploit-framework/statuses/03fcfc496a2cf90b05423a97dce84f8834e2c8e5"}}}}