one_gadget 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 469c960b795a87ce7f7e02b91c46b2f8e75f4a7d
4
+ data.tar.gz: c05c6387725951eaee40a2733f33909aa7d81daa
5
+ SHA512:
6
+ metadata.gz: fa08575754ee8a545db7cc1f60ba307670eadcb2df17750d0504b4a6ac8eb55897bdb2b77aeff6e0ceb207fbe6e15a58b975bee6aed0411b0bfd10beabe00b63
7
+ data.tar.gz: 92e091b662abf384bd4cc791a27d9478e3bd17c8b9c6fe7f75aa314479b8e50738ba40da8ec40c554fbb166a05e071147999911bd63f6cc21b3445b4a902fb76
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ [![Build Status](https://travis-ci.org/david942j/one_gadget.svg?branch=master)](https://travis-ci.org/david942j/one_gadget)
2
+ [![Code Climate](https://codeclimate.com/github/david942j/one_gadget/badges/gpa.svg)](https://codeclimate.com/github/david942j/one_gadget)
3
+ [![Issue Count](https://codeclimate.com/github/david942j/one_gadget/badges/issue_count.svg)](https://codeclimate.com/github/david942j/one_gadget)
4
+ [![Test Coverage](https://codeclimate.com/github/david942j/one_gadget/badges/coverage.svg)](https://codeclimate.com/github/david942j/one_gadget/coverage)
5
+ [![Inline docs](https://inch-ci.org/github/david942j/one_gadget.svg?branch=master)](https://inch-ci.org/github/david942j/one_gadget)
6
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](http://choosealicense.com/licenses/mit/)
7
+
8
+ ## One Gadget
9
+
10
+ When playing ctf pwn challenges we usually needs the one-gadget of `execve('/bin/sh', NULL, NULL)`.
11
+
12
+ This gem provides such gadget finder, no need to use IDA-pro every time like a fool.
13
+
14
+ Also provides the command-line tool `one_gadget` for easy usage.
15
+
16
+ Note: only supports x86-64 now.
17
+
18
+ ## Install
19
+
20
+ I'll push to rubygems.org..
21
+
22
+ ## Usage
23
+
24
+ ### Command Line Tool
25
+
26
+ ```bash
27
+ one_gadget
28
+ # Usage: one_gadget [file] [options]
29
+ # -b, --build-id BuildID BuildID[sha1] of libc
30
+ # -r, --[no-]raw Output gadgets offset only, split with one space
31
+ # -s, --script exploit-script Run exploit script with all possible gadgets
32
+ # The script will be run as 'exploit-script $offset'.
33
+
34
+ one_gadget -b 60131540dadc6796cab33388349e6e4e68692053
35
+ # offset: 0x4526a
36
+ # constraints:
37
+ # [rsp+0x30] == NULL
38
+ #
39
+ # offset: 0xef6c4
40
+ # constraints:
41
+ # [rsp+0x50] == NULL
42
+ #
43
+ # offset: 0xf0567
44
+ # constraints:
45
+ # [rsp+0x70] == NULL
46
+ ```
47
+
48
+ #### Combine with exploit script
49
+ Pass your exploit script as `one_gadget`'s arguments, it can
50
+ try all gadgets one by one, so you don't need to try every possible gadgets manually.
51
+
52
+ ```bash
53
+ one_gadget ./spec/data/libc-2.19.so -s 'echo "offset ->"'
54
+ ```
55
+
56
+ ![--script](https://github.com/david942j/one_gadget/blob/master/examples/script.png?raw=true)
57
+
58
+ ### Directly use in script
59
+ ```ruby
60
+ require 'one_gadget'
61
+ OneGadget.gadgets(file: '/lib/x86_64-linux-gnu/libc.so.6')
62
+ # => [283242, 980676, 984423]
63
+ ```
64
+
65
+ ## Screenshots
66
+
67
+ ### Search gadgets from file
68
+ ![from file](https://github.com/david942j/one_gadget/blob/master/examples/from_file.png?raw=true)
69
+
70
+ ### Fetch gadgets from database
71
+ ![build id](https://github.com/david942j/one_gadget/blob/master/examples/from_build_id.png?raw=true)
72
+
data/bin/one_gadget ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bun/env ruby
2
+ require 'one_gadget'
3
+ require 'optionparser'
4
+
5
+ options = { raw: false }
6
+ usage = 'Usage: one_gadget [file] [options]'
7
+ parser = OptionParser.new do |opts|
8
+ opts.banner = usage
9
+
10
+ opts.on('-b', '--build-id BuildID', 'BuildID[sha1] of libc') do |b|
11
+ options[:build_id] = b
12
+ end
13
+
14
+ opts.on('-r', '--[no-]raw', 'Output gadgets offset only, split with one space') do |v|
15
+ options[:raw] = v
16
+ end
17
+
18
+ opts.on('-s', '--script exploit-script', 'Run exploit script with all possible gadgets.',
19
+ 'The script will be run as \'exploit-script $offset\'.') do |script|
20
+ options[:script] = script
21
+ end
22
+ end
23
+ parser.parse!
24
+
25
+ def execute(script, offset)
26
+ pid = fork do
27
+ exec([script, offset.to_s].join(' '))
28
+ end
29
+ Process.wait pid
30
+ end
31
+
32
+ if options[:build_id]
33
+ gadgets = OneGadget.gadgets(build_id: options[:build_id], details: true)
34
+ elsif ARGV[0]
35
+ gadgets = OneGadget.gadgets(file: ARGV[0], details: true)
36
+ else
37
+ puts parser.help
38
+ exit(1)
39
+ end
40
+
41
+ extend OneGadget::Helper::ClassMethods
42
+ if options[:script]
43
+ gadgets.map(&:offset).each do |offset|
44
+ puts "[#{colorize('OneGadget', sev: :reg)}] Trying #{colorize(format('0x%x', offset), sev: :integer)}..."
45
+ execute(options[:script], offset)
46
+ end
47
+ exit(0)
48
+ end
49
+
50
+ if options[:raw]
51
+ puts gadgets.map(&:offset).join(' ')
52
+ else
53
+ puts gadgets.map(&:inspect).join("\n")
54
+ end
data/lib/one_gadget.rb ADDED
@@ -0,0 +1,35 @@
1
+ # OneGadget - To find the execve(/bin/sh, 0, 0) in glibc.
2
+ #
3
+ # @author david942j
4
+ module OneGadget
5
+ class << self
6
+ # The man entry of gem +one_gadget+.
7
+ # If want to find gadgets from file, it will search gadgets by its
8
+ # build id first.
9
+ #
10
+ # @param [String] file
11
+ # The relative path of libc.so.6.
12
+ # @param [String] build_id
13
+ # The BuildID of target libc.so.6.
14
+ # @return [Array<OneGadget::Gadget::Gadget>, Array<Integer>]
15
+ # The gadgets found.
16
+ # @example
17
+ # OneGadget.gadgets(file: './libc.so.6')
18
+ # OneGadget.gadgets(build_id: '60131540dadc6796cab33388349e6e4e68692053')
19
+ def gadgets(file: nil, build_id: nil, details: false)
20
+ if build_id
21
+ OneGadget::Fetcher.from_build_id(build_id, details: details)
22
+ elsif file
23
+ file = OneGadget::Helper.abspath(file)
24
+ build_id = OneGadget::Helper.build_id_of(file)
25
+ gadgets = OneGadget::Fetcher.from_build_id(build_id, details: details)
26
+ return gadgets unless gadgets.empty?
27
+ OneGadget::Fetcher.from_file(file, details: details)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require 'one_gadget/fetcher'
34
+ require 'one_gadget/helper'
35
+ require 'one_gadget/version'
@@ -0,0 +1,15 @@
1
+ module OneGadget
2
+ # define the abi of different architecture.
3
+ module ABI
4
+ # Define class methods here.
5
+ module ClassMethods
6
+ LINUX_X86_32 = %w(eax ebx ecx edx edi esi ebp esp).freeze
7
+ LINUX_X86_64 = LINUX_X86_32 + %w(rax rbx rcx rdx rdi rsi rbp rsp) + 7.upto(15).map { |i| "r#{i}" }
8
+ # Only support x86-64 now.
9
+ def registers
10
+ LINUX_X86_64
11
+ end
12
+ end
13
+ extend ClassMethods
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ require 'one_gadget/gadget'
2
+ # Ubuntu GLIBC 2.23-0ubuntu5
3
+ # ELF 64-bit LSB shared object, x86-64
4
+ build_id = File.basename(__FILE__, '.rb').split('-').last
5
+ OneGadget::Gadget.add(build_id, 0x4526a, constraints: ['[rsp+0x30] == NULL'])
6
+ OneGadget::Gadget.add(build_id, 0xef6c4, constraints: ['[rsp+0x50] == NULL'])
7
+ OneGadget::Gadget.add(build_id, 0xf0567, constraints: ['[rsp+0x70] == NULL'])
8
+ OneGadget::Gadget.add(build_id, 0xf5b10, constraints: ['[rbp-0xf8] == NULL', 'rcx == NULL'])
@@ -0,0 +1,75 @@
1
+ require 'one_gadget/helper'
2
+ require 'one_gadget/gadget'
3
+
4
+ module OneGadget
5
+ # To find gadgets.
6
+ module Fetcher
7
+ # Define class methods here.
8
+ module ClassMethods
9
+ # Fetch one-gadget offsets of this build id.
10
+ # @param [String] build_id The targets' BuildID.
11
+ # @param [Boolean] details
12
+ # If needs to return the gadgets' constraints.
13
+ # @return [Array<Integer>, Array<OneGadget::Gadget::Gadget>]
14
+ # If +details+ is +false+, +Array<Integer>+ is returned, which
15
+ # contains offset only.
16
+ # Otherwise, array of gadgets is returned.
17
+ def from_build_id(build_id, details: false)
18
+ if (build_id =~ /\A#{OneGadget::Helper::BUILD_ID_FORMAT}\Z/).nil?
19
+ raise ArgumentError, format('invalid BuildID format: %p', build_id)
20
+ end
21
+ gadgets = OneGadget::Gadget.builds(build_id)
22
+ return gadgets if details
23
+ gadgets.map(&:offset)
24
+ end
25
+
26
+ # Fetch one-gadget offsets from file.
27
+ # @param [String] file The absolute path of libc file.
28
+ # @param [Boolean] details
29
+ # If needs to return the gadgets' constraints.
30
+ # @return [Array<Integer>, Array<OneGadget::Gadget::Gadget>]
31
+ # If +details+ is +false+, +Array<Integer>+ is returned, which
32
+ # contains offset only.
33
+ # Otherwise, array of gadgets is returned.
34
+ def from_file(file, details: false)
35
+ bin_sh_hex = str_offset(file, '/bin/sh').to_s(16)
36
+ candidates = `objdump -d -M intel #{file}|egrep '<execve[^+]*>$' -B 10`.split('--').select do |candidate|
37
+ next false unless candidate.include?(bin_sh_hex)
38
+ next false unless candidate.lines.last.include?('call') # last line must be +call execve+
39
+ true
40
+ end
41
+ candidates.map! do |candidate|
42
+ # remove other calls
43
+ lines = candidate.lines
44
+ to_rm = lines[0...-1].rindex { |c| c.include?('call') }
45
+ lines = lines[to_rm + 1..-1] unless to_rm.nil?
46
+ lines.map! { |s| s.gsub(/#\s+#{bin_sh_hex}\s+<.*>$/, "# #{bin_sh_hex} \"/bin/sh\"") }
47
+ lines.join
48
+ end
49
+ gadgets = candidates.map { |c| convert_to_gadget(c) }
50
+ return gadgets if details
51
+ gadgets.map(&:offset)
52
+ end
53
+
54
+ private
55
+
56
+ def str_offset(file, str)
57
+ match = `strings -tx #{file} | grep '#{str}'`.lines.map(&:strip).first
58
+ return nil if match.nil?
59
+ # 17c8c3 /bin/sh
60
+ match.split.first.to_i(16)
61
+ end
62
+
63
+ def convert_to_gadget(assembly)
64
+ lines = assembly.lines.map(&:strip)
65
+ offset = lines.first.scan(/^([\da-f]+):/)[0][0].to_i(16)
66
+ # fetch those might be constraints lines.
67
+ important_lines = lines.select { |line| ['rsi'].any? { |r| line.include?(r) } }.map do |line|
68
+ line.split("\t").last.gsub(/\s+/, ' ')
69
+ end
70
+ OneGadget::Gadget::Gadget.new(offset, constraints: important_lines)
71
+ end
72
+ end
73
+ extend ClassMethods
74
+ end
75
+ end
@@ -0,0 +1,77 @@
1
+ require 'one_gadget/abi'
2
+
3
+ module OneGadget
4
+ # Module for define gadgets.
5
+ module Gadget
6
+ # Information of a gadget.
7
+ class Gadget
8
+ # @return [Integer] The gadget's address offset.
9
+ attr_accessor :offset
10
+ # @return [Array<String>] The constraints need for this gadget.
11
+ attr_accessor :constraints
12
+
13
+ # Initialize method of {Gadget} instance.
14
+ # @param [Integer] offset The relative address offset of this gadget.
15
+ # @option options [Array<String>] :constraints
16
+ # The constraints need for this gadget. Defaults to +[]+.
17
+ # @example
18
+ # OneGadget::Gadget::Gadget.new(0x12345, constraints: ['rax == 0'])
19
+ def initialize(offset, **options)
20
+ @offset = offset
21
+ @constraints = options[:constraints] || []
22
+ end
23
+
24
+ # Show gadget in a pretty way.
25
+ def inspect
26
+ str = format("#{OneGadget::Helper.colorize('offset', sev: :sym)}: 0x%x\n", offset)
27
+ unless constraints.empty?
28
+ str += "#{OneGadget::Helper.colorize('constraints')}:\n "
29
+ str += constraints.join("\n ")
30
+ end
31
+ str.gsub!(/0x[\da-f]+/) { |s| OneGadget::Helper.colorize(s, sev: :integer) }
32
+ OneGadget::ABI.registers.each { |reg| str.gsub!(reg, OneGadget::Helper.colorize(reg, sev: :reg)) }
33
+ str + "\n"
34
+ end
35
+ end
36
+
37
+ # Define class methods here.
38
+ module ClassMethods
39
+ BUILDS_PATH = File.join(File.dirname(__FILE__), 'builds').freeze
40
+ BUILDS = Hash.new { |h, k| h[k] = [] }
41
+ # Get gadgets from pre-defined corpus.
42
+ # @param [String] build_id Desired build id.
43
+ # @return [Array<Gadget::Gadget>] Gadgets.
44
+ def builds(build_id)
45
+ require_all if BUILDS.empty?
46
+ return BUILDS[build_id] if BUILDS.key?(build_id)
47
+ # fetch remote builds
48
+ table = OneGadget::Helper.remote_builds.find { |c| c.include?(build_id) }
49
+ return [] if table.nil? # remote doesn't have this one either.
50
+ # builds found in remote! Ask update gem and download remote gadgets.
51
+ OneGadget::Helper.ask_update(msg: 'The desired one-gadget can be found in lastest version!')
52
+ tmp_file = OneGadget::Helper.download_build(table)
53
+ require tmp_file.path
54
+ tmp_file.unlink
55
+ BUILDS[build_id]
56
+ end
57
+
58
+ # Add a gadget, for scripts in builds/ to use.
59
+ # @param [String] build_id The target's build id.
60
+ # @param [Integer] offset The relative address offset of this gadget.
61
+ # @param [Hash] options See {Gadget::Gadget#initialize} for more information.
62
+ # @return [void]
63
+ def add(build_id, offset, **options)
64
+ BUILDS[build_id] << OneGadget::Gadget::Gadget.new(offset, **options)
65
+ end
66
+
67
+ private
68
+
69
+ def require_all
70
+ Dir.glob(File.join(BUILDS_PATH, '**', '*.rb')).each do |dic|
71
+ require dic
72
+ end
73
+ end
74
+ end
75
+ extend ClassMethods
76
+ end
77
+ end
@@ -0,0 +1,128 @@
1
+ require 'pathname'
2
+ require 'shellwords'
3
+ require 'net/http'
4
+ require 'openssl'
5
+ require 'tempfile'
6
+
7
+ module OneGadget
8
+ # Define some helpful methods here.
9
+ module Helper
10
+ BUILD_ID_FORMAT = /[0-9a-f]{40}/
11
+ # Define class methods here.
12
+ module ClassMethods
13
+ # Get absolute path from relative path. Support symlink.
14
+ # @param [String] path Relative path.
15
+ # @return [String] Absolute path, with symlink resolved.
16
+ # @example
17
+ # abspath('/lib/x86_64-linux-gnu/libc.so.6')
18
+ # #=> '/lib/x86_64-linux-gnu/libc-2.23.so'
19
+ def abspath(path)
20
+ Pathname.new(File.expand_path(path)).realpath.to_s
21
+ end
22
+
23
+ # Get the Build ID of target ELF.
24
+ # @param [String] path Absolute file path.
25
+ # @return [String] Target build id.
26
+ # @example
27
+ # build_id_of('/lib/x86_64-linux-gnu/libc-2.23.so')
28
+ # #=> '60131540dadc6796cab33388349e6e4e68692053'
29
+ def build_id_of(path)
30
+ cmd = 'readelf -n ' + ::Shellwords.escape(path)
31
+ bid = `#{cmd}`.scan(/Build ID: (#{BUILD_ID_FORMAT})$/).first
32
+ return nil if bid.nil?
33
+ bid.first
34
+ end
35
+
36
+ # Disable colorize
37
+ def color_off!
38
+ @disable_color = true
39
+ end
40
+
41
+ # Enable colorize
42
+ def color_on!
43
+ @disable_color = false
44
+ end
45
+
46
+ # Color codes for pretty print
47
+ COLOR_CODE = {
48
+ esc_m: "\e[0m",
49
+ normal_s: "\e[38;5;1m", # red
50
+ integer: "\e[38;5;12m", # light blue
51
+ fatal: "\e[38;5;197m", # dark red
52
+ reg: "\e[38;5;120m", # light green
53
+ sym: "\e[38;5;229m", # pry like
54
+ }.freeze
55
+
56
+ # Wrapper color codes for pretty inspect.
57
+ # @param [String] str Contents to colorize.
58
+ # @option [Symbol] sev Specific which kind of color want to use, valid symbols are defined in +COLOR_CODE+.
59
+ # @return [String] Wrapper with color codes.
60
+ def colorize(str, sev: :normal_s)
61
+ return str if @disable_color
62
+ cc = COLOR_CODE
63
+ color = cc.key?(sev) ? cc[sev] : ''
64
+ "#{color}#{str.sub(cc[:esc_m], color)}#{cc[:esc_m]}"
65
+ end
66
+
67
+ # Fetch the latest release version's tag name.
68
+ # @return [String] The tag name, in form +vx.x.x+.
69
+ def latest_tag
70
+ latest = url_request('https://github.com/david942j/one_gadget/releases').scan(%r{/tree/v([\d.]+)"}).map do |tag|
71
+ Gem::Version.new(tag.first)
72
+ end.max.to_s
73
+ 'v' + latest
74
+ end
75
+
76
+ # Get the url which can fetch +filename+ from remote repo.
77
+ # @param [String] filename
78
+ # @return [String] The url.
79
+ def url_of_file(filename)
80
+ raw_file_url = 'https://raw.githubusercontent.com/david942j/one_gadget/@tag/@file'
81
+ raw_file_url.gsub('@tag', latest_tag).gsub('@file', filename)
82
+ end
83
+
84
+ # Download the latest version of +file+ in +lib/one_gadget/builds/+ from remote repo.
85
+ #
86
+ # @param [String] file The filename desired.
87
+ # @return [Tempfile] The temp file be created.
88
+ def download_build(file)
89
+ temp = Tempfile.new(['gadgets', file + '.rb'])
90
+ url_request(url_of_file(File.join('lib', 'one_gadget', 'builds', file + '.rb')))
91
+ temp.write url_request(url_of_file(File.join('lib', 'one_gadget', 'builds', file + '.rb')))
92
+ temp.close
93
+ temp
94
+ end
95
+
96
+ # Get the latest builds list from repo.
97
+ # @return [Array<String>] List of build ids.
98
+ def remote_builds
99
+ url_request(url_of_file('builds_list')).lines.map(&:strip)
100
+ end
101
+
102
+ # Get request.
103
+ # @param [String] url The url.
104
+ # @return [String] The request response body.
105
+ def url_request(url)
106
+ # TODO: add timeout to handle github crashed or in no network environment.
107
+ uri = URI.parse(url)
108
+ http = Net::HTTP.new(uri.host, uri.port)
109
+ http.use_ssl = true
110
+ http.verify_mode = ::OpenSSL::SSL::VERIFY_NONE
111
+
112
+ request = Net::HTTP::Get.new(uri.request_uri)
113
+
114
+ response = http.request(request)
115
+ response.body
116
+ end
117
+
118
+ # Show the message of ask user to update gem.
119
+ # @return [void]
120
+ def ask_update(msg: '')
121
+ name = 'one_gadget'
122
+ cmd = colorize("gem update #{name}")
123
+ STDERR.puts msg + "\n" + "Update with: $ #{cmd}"
124
+ end
125
+ end
126
+ extend ClassMethods
127
+ end
128
+ end
@@ -0,0 +1,3 @@
1
+ module OneGadget
2
+ VERSION = '1.0.0'.freeze
3
+ end
Binary file
Binary file
@@ -0,0 +1,22 @@
1
+ require 'one_gadget/gadget'
2
+ require 'one_gadget/helper'
3
+ describe OneGadget::Gadget do
4
+ before(:all) do
5
+ @build_id = 'fake_id'
6
+ OneGadget::Helper.color_off! # disable colorize for easy testing.
7
+ OneGadget::Gadget.add(@build_id, 0x1234, constraints: ['[rsp+0x30] == NULL', 'rax == 0'])
8
+ end
9
+
10
+ after(:all) do
11
+ OneGadget::Gadget::ClassMethods::BUILDS.delete @build_id
12
+ end
13
+
14
+ it 'inspect' do
15
+ expect(OneGadget::Gadget.builds(@build_id).map(&:inspect).join).to eq <<-EOS
16
+ offset: 0x1234
17
+ constraints:
18
+ [rsp+0x30] == NULL
19
+ rax == 0
20
+ EOS
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ require 'one_gadget/helper'
2
+
3
+ describe OneGadget::Helper do
4
+ before(:all) do
5
+ OneGadget::Helper.color_on!
6
+ @libcpath = File.join(File.dirname(__FILE__), 'data', 'libc-2.23.so')
7
+ end
8
+ it 'abspath' do
9
+ expect(OneGadget::Helper.abspath('./spec/data/libc-2.23.so')).to eq @libcpath
10
+ end
11
+
12
+ it 'build_id_of' do
13
+ expect(OneGadget::Helper.build_id_of(@libcpath)).to eq '60131540dadc6796cab33388349e6e4e68692053'
14
+ end
15
+
16
+ it 'colorize' do
17
+ expect(OneGadget::Helper.colorize('123', sev: :integer)).to eq "\e[38;5;12m123\e[0m"
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ require 'one_gadget'
2
+
3
+ describe 'one_gadget' do
4
+ before(:each) do
5
+ @build_id = '60131540dadc6796cab33388349e6e4e68692053'
6
+ @libcpath = File.join(File.dirname(__FILE__), 'data', 'libc-2.19.so')
7
+ end
8
+
9
+ it 'from file' do
10
+ expect(OneGadget.gadgets(file: @libcpath)).to eq [0x4647c, 0xe5765, 0xe66bd]
11
+ end
12
+
13
+ describe 'from build id' do
14
+ it 'normal' do
15
+ # only check not empty because the gadgets might add frequently.
16
+ expect(OneGadget.gadgets(build_id: @build_id)).not_to be_empty
17
+ end
18
+
19
+ it 'invalid' do
20
+ expect { OneGadget.gadgets(build_id: '^_^') }.to raise_error(ArgumentError, 'invalid BuildID format: "^_^"')
21
+ end
22
+
23
+ it 'fetch from remote' do
24
+ entry = OneGadget::Gadget::ClassMethods::BUILDS.delete(@build_id)
25
+ OneGadget::Gadget::ClassMethods::BUILDS[:a] = 1
26
+ expect(OneGadget.gadgets(build_id: @build_id)).not_to be_empty
27
+ OneGadget::Gadget::ClassMethods::BUILDS.delete(:a)
28
+ OneGadget::Gadget::ClassMethods::BUILDS[@build_id] = entry unless entry.nil?
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ require 'codeclimate-test-reporter'
2
+ require 'simplecov'
3
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
4
+ [SimpleCov::Formatter::HTMLFormatter, CodeClimate::TestReporter::Formatter]
5
+ )
6
+ SimpleCov.start do
7
+ add_filter '/spec/'
8
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: one_gadget
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - david942j
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.46'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.46'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.13.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.13.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: codeclimate-test-reporter
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.6'
83
+ description: |2
84
+ When playing ctf pwn challenges we usually needs the one-gadget of `execve('/bin/sh', NULL, NULL)`.
85
+ This gem provides such gadget finder, no need to use IDA-pro every time like a fool.
86
+ Also provides the command-line tool `one_gadget` for easy usage.
87
+ email:
88
+ - david942j@gmail.com
89
+ executables:
90
+ - one_gadget
91
+ extensions: []
92
+ extra_rdoc_files: []
93
+ files:
94
+ - README.md
95
+ - bin/one_gadget
96
+ - lib/one_gadget.rb
97
+ - lib/one_gadget/abi.rb
98
+ - lib/one_gadget/builds/libc-2.23-60131540dadc6796cab33388349e6e4e68692053.rb
99
+ - lib/one_gadget/fetcher.rb
100
+ - lib/one_gadget/gadget.rb
101
+ - lib/one_gadget/helper.rb
102
+ - lib/one_gadget/version.rb
103
+ - spec/data/libc-2.19.so
104
+ - spec/data/libc-2.23.so
105
+ - spec/gadget_spec.rb
106
+ - spec/helper_spec.rb
107
+ - spec/one_gadget_spec.rb
108
+ - spec/spec_helper.rb
109
+ homepage: https://github.com/david942j/one_gadget
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: 2.1.0
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.5.2
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: one_gadget
133
+ test_files:
134
+ - spec/data/libc-2.19.so
135
+ - spec/data/libc-2.23.so
136
+ - spec/spec_helper.rb
137
+ - spec/helper_spec.rb
138
+ - spec/one_gadget_spec.rb
139
+ - spec/gadget_spec.rb