support fetch builds from repo
This commit is contained in:
parent
9cb7af4876
commit
a6c30074cd
|
@ -45,11 +45,14 @@ module OneGadget
|
||||||
require_all if BUILDS.empty?
|
require_all if BUILDS.empty?
|
||||||
return BUILDS[build_id] if BUILDS.key?(build_id)
|
return BUILDS[build_id] if BUILDS.key?(build_id)
|
||||||
# fetch remote builds
|
# fetch remote builds
|
||||||
# table = OneGadget::Helper.remote_builds.find { |c| c.include?(build_id) }
|
table = OneGadget::Helper.remote_builds.find { |c| c.include?(build_id) }
|
||||||
# return [] if table.nil? # remote doesn't have this one.
|
return [] if table.nil? # remote doesn't have this one either.
|
||||||
# builds found in remote! Ask update gem and download remote gadgets.
|
# builds found in remote! Ask update gem and download remote gadgets.
|
||||||
# TODO: fetch remote builds information.
|
OneGadget::Helper.ask_update(msg: 'The desired one-gadget can be found in lastest version!')
|
||||||
[]
|
tmp_file = OneGadget::Helper.download_build(table)
|
||||||
|
require tmp_file.path
|
||||||
|
tmp_file.unlink
|
||||||
|
BUILDS[build_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add a gadget, for scripts in builds/ to use.
|
# Add a gadget, for scripts in builds/ to use.
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
require 'pathname'
|
require 'pathname'
|
||||||
require 'shellwords'
|
require 'shellwords'
|
||||||
|
require 'net/http'
|
||||||
|
require 'openssl'
|
||||||
|
require 'tempfile'
|
||||||
|
|
||||||
module OneGadget
|
module OneGadget
|
||||||
# Define some helpful methods here.
|
# Define some helpful methods here.
|
||||||
|
@ -60,6 +63,65 @@ module OneGadget
|
||||||
color = cc.key?(sev) ? cc[sev] : ''
|
color = cc.key?(sev) ? cc[sev] : ''
|
||||||
"#{color}#{str.sub(cc[:esc_m], color)}#{cc[:esc_m]}"
|
"#{color}#{str.sub(cc[:esc_m], color)}#{cc[:esc_m]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Fetch the latest release version's tag name.
|
||||||
|
# @return [String] The tag name, in form +vx.x.x+.
|
||||||
|
def latest_tag
|
||||||
|
latest = url_request('https://github.com/david942j/one_gadget/releases').scan(%r{/tree/v([\d.]+)"}).map do |tag|
|
||||||
|
Gem::Version.new(tag.first)
|
||||||
|
end.max.to_s
|
||||||
|
'v' + latest
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get the url which can fetch +filename+ from remote repo.
|
||||||
|
# @param [String] filename
|
||||||
|
# @return [String] The url.
|
||||||
|
def url_of_file(filename)
|
||||||
|
raw_file_url = 'https://raw.githubusercontent.com/david942j/one_gadget/@tag/@file'
|
||||||
|
raw_file_url.gsub('@tag', latest_tag).gsub('@file', filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Download the latest version of +file+ in +lib/one_gadget/builds/+ from remote repo.
|
||||||
|
#
|
||||||
|
# @param [String] file The filename desired.
|
||||||
|
# @return [Tempfile] The temp file be created.
|
||||||
|
def download_build(file)
|
||||||
|
temp = Tempfile.new(['gadgets', file + '.rb'])
|
||||||
|
url_request(url_of_file(File.join('lib', 'one_gadget', 'builds', file + '.rb')))
|
||||||
|
temp.write url_request(url_of_file(File.join('lib', 'one_gadget', 'builds', file + '.rb')))
|
||||||
|
temp.close
|
||||||
|
temp
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get the latest builds list from repo.
|
||||||
|
# @return [Array<String>] List of build ids.
|
||||||
|
def remote_builds
|
||||||
|
url_request(url_of_file('builds_list')).lines.map(&:strip)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get request.
|
||||||
|
# @param [String] url The url.
|
||||||
|
# @return [String] The request response body.
|
||||||
|
def url_request(url)
|
||||||
|
# TODO: add timeout to handle github crashed or in no network environment.
|
||||||
|
uri = URI.parse(url)
|
||||||
|
http = Net::HTTP.new(uri.host, uri.port)
|
||||||
|
http.use_ssl = true
|
||||||
|
http.verify_mode = ::OpenSSL::SSL::VERIFY_NONE
|
||||||
|
|
||||||
|
request = Net::HTTP::Get.new(uri.request_uri)
|
||||||
|
|
||||||
|
response = http.request(request)
|
||||||
|
response.body
|
||||||
|
end
|
||||||
|
|
||||||
|
# Show the message of ask user to update gem.
|
||||||
|
# @return [void]
|
||||||
|
def ask_update(msg: '')
|
||||||
|
name = 'one_gadget'
|
||||||
|
cmd = colorize("gem update #{name}")
|
||||||
|
STDERR.puts msg + "\n" + "Update with: $ #{cmd}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
extend ClassMethods
|
extend ClassMethods
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,10 @@ describe OneGadget::Gadget do
|
||||||
OneGadget::Gadget.add(@build_id, 0x1234, constraints: ['[rsp+0x30] == NULL', 'rax == 0'])
|
OneGadget::Gadget.add(@build_id, 0x1234, constraints: ['[rsp+0x30] == NULL', 'rax == 0'])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after(:all) do
|
||||||
|
OneGadget::Gadget::ClassMethods::BUILDS.delete @build_id
|
||||||
|
end
|
||||||
|
|
||||||
it 'inspect' do
|
it 'inspect' do
|
||||||
expect(OneGadget::Gadget.builds(@build_id).map(&:inspect).join).to eq <<-EOS
|
expect(OneGadget::Gadget.builds(@build_id).map(&:inspect).join).to eq <<-EOS
|
||||||
offset: 0x1234
|
offset: 0x1234
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
require 'one_gadget'
|
require 'one_gadget'
|
||||||
|
|
||||||
describe 'one_gadget' do
|
describe 'one_gadget' do
|
||||||
before(:all) do
|
before(:each) do
|
||||||
# To force require all again.
|
|
||||||
OneGadget::Gadget::ClassMethods::BUILDS.clear
|
|
||||||
@build_id = '60131540dadc6796cab33388349e6e4e68692053'
|
@build_id = '60131540dadc6796cab33388349e6e4e68692053'
|
||||||
@libcpath = File.join(File.dirname(__FILE__), 'data', 'libc-2.19.so')
|
@libcpath = File.join(File.dirname(__FILE__), 'data', 'libc-2.19.so')
|
||||||
end
|
end
|
||||||
|
@ -21,5 +19,13 @@ describe 'one_gadget' do
|
||||||
it 'invalid' do
|
it 'invalid' do
|
||||||
expect { OneGadget.gadgets(build_id: '^_^') }.to raise_error(ArgumentError, 'invalid BuildID format: "^_^"')
|
expect { OneGadget.gadgets(build_id: '^_^') }.to raise_error(ArgumentError, 'invalid BuildID format: "^_^"')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'fetch from remote' do
|
||||||
|
entry = OneGadget::Gadget::ClassMethods::BUILDS.delete(@build_id)
|
||||||
|
OneGadget::Gadget::ClassMethods::BUILDS[:a] = 1
|
||||||
|
expect(OneGadget.gadgets(build_id: @build_id)).not_to be_empty
|
||||||
|
OneGadget::Gadget::ClassMethods::BUILDS.delete(:a)
|
||||||
|
OneGadget::Gadget::ClassMethods::BUILDS[@build_id] = entry unless entry.nil?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue