one_gadget 1.3.4.1 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/lib/one_gadget.rb +2 -2
- data/lib/one_gadget/abi.rb +2 -0
- data/lib/one_gadget/emulators/i386.rb +1 -0
- data/lib/one_gadget/emulators/lambda.rb +11 -6
- data/lib/one_gadget/fetcher.rb +5 -5
- data/lib/one_gadget/fetchers/base.rb +11 -4
- data/lib/one_gadget/gadget.rb +3 -1
- data/lib/one_gadget/helper.rb +4 -2
- data/lib/one_gadget/version.rb +2 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 769666a5afd3ce890eea834682b010137958e50a
|
4
|
+
data.tar.gz: 303399584d0b4163058ad74c0e9f80a8fea13694
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb098f44596a0bd6f9a51ae533fbb2456c66c65a64a11bd7c8bc031bdd08684ccee0a549a7d833d26cfe3314a1caf34bfbd294ed67960d9843ea21b72927c931
|
7
|
+
data.tar.gz: 743e95a1efac018fc6e887348b234bd08da77776494bfcd8f793a2b8612e2ccd69fecab26d948ae55525de15fc298179d04c4ff772b7c6c02b3e19120c98d03b
|
data/README.md
CHANGED
@@ -8,9 +8,10 @@
|
|
8
8
|
|
9
9
|
## One Gadget
|
10
10
|
|
11
|
-
When playing ctf pwn challenges we usually need the one-gadget
|
11
|
+
When playing ctf pwn challenges we usually need the one-gadget RCE (remote code execution),
|
12
|
+
which leads to call `execve('/bin/sh', NULL, NULL)`.
|
12
13
|
|
13
|
-
This gem provides such
|
14
|
+
This gem provides such gadgets finder, no need to use IDA-pro every time like a fool.
|
14
15
|
|
15
16
|
This work provides the command-line tool `one_gadget` for easy usage.
|
16
17
|
|
data/lib/one_gadget.rb
CHANGED
@@ -26,8 +26,8 @@ module OneGadget
|
|
26
26
|
OneGadget::Fetcher.from_build_id(build_id, details: details)
|
27
27
|
elsif file
|
28
28
|
file = OneGadget::Helper.abspath(file)
|
29
|
-
|
30
|
-
|
29
|
+
build_id = OneGadget::Helper.build_id_of(file)
|
30
|
+
if !force_file && build_id
|
31
31
|
gadgets = OneGadget::Fetcher.from_build_id(build_id, details: details)
|
32
32
|
return gadgets unless gadgets.empty?
|
33
33
|
end
|
data/lib/one_gadget/abi.rb
CHANGED
@@ -3,7 +3,9 @@ module OneGadget
|
|
3
3
|
module ABI
|
4
4
|
# Define class methods here.
|
5
5
|
module ClassMethods
|
6
|
+
# Registers in i386.
|
6
7
|
LINUX_X86_32 = %w(eax ebx ecx edx edi esi ebp esp).freeze
|
8
|
+
# Registers in x86_64/
|
7
9
|
LINUX_X86_64 = LINUX_X86_32 + %w(rax rbx rcx rdx rdi rsi rbp rsp) + 7.upto(15).map { |i| "r#{i}" }
|
8
10
|
# Registers' name in amd64.
|
9
11
|
# @return [Array<String>] List of registers.
|
@@ -3,10 +3,10 @@ require 'one_gadget/helper'
|
|
3
3
|
module OneGadget
|
4
4
|
module Emulators
|
5
5
|
# A {Lambda} object can be:
|
6
|
-
# 1.
|
7
|
-
# 2.
|
8
|
-
# 3. {Lambda} +
|
9
|
-
# 4.
|
6
|
+
# 1. +String+ (variable name)
|
7
|
+
# 2. +Numeric+
|
8
|
+
# 3. {Lambda} + +Numeric+
|
9
|
+
# 4. dereferenced {Lambda}
|
10
10
|
class Lambda
|
11
11
|
attr_accessor :obj # @return [String, Lambda] The object currently related to.
|
12
12
|
attr_accessor :immi # @return [Integer] The immidiate value currently added.
|
@@ -49,6 +49,7 @@ module OneGadget
|
|
49
49
|
|
50
50
|
# Decrease dreference count with 1.
|
51
51
|
# @return [void]
|
52
|
+
# @raise [ArgumentError] When this object cannot be referenced anymore.
|
52
53
|
def ref!
|
53
54
|
raise ArgumentError, 'Cannot reference anymore!' if @deref_count <= 0
|
54
55
|
@deref_count -= 1
|
@@ -86,14 +87,18 @@ module OneGadget
|
|
86
87
|
end
|
87
88
|
|
88
89
|
class << self
|
89
|
-
# Target: parse
|
90
|
+
# Target: parse things like <tt>[rsp+0x50]</tt> into a {Lambda} object.
|
90
91
|
# @param [String] arg
|
91
92
|
# @param [Hash{String => Lambda}] predefined
|
93
|
+
# Predfined values.
|
92
94
|
# @return [OneGadget::Emulators::Lambda, Integer]
|
93
95
|
# If +arg+ contains number only, return it.
|
94
96
|
# Otherwise, return a {Lambda} object.
|
95
97
|
# @example
|
96
|
-
# parse('[rsp+0x50]')
|
98
|
+
# obj = parse('[rsp+0x50]')
|
99
|
+
# #=> #<Lambda @obj='rsp', @immi=80, @deref_count=1>
|
100
|
+
# parse('obj+0x30', predefined: { 'obj' => obj }).to_s
|
101
|
+
# #=> '[rsp+0x50]+0x30'
|
97
102
|
def parse(arg, predefined: {})
|
98
103
|
deref_count = 0
|
99
104
|
if arg[0] == '[' # a little hack because there should nerver something like +[[rsp+1]+2]+ to parse.
|
data/lib/one_gadget/fetcher.rb
CHANGED
@@ -34,12 +34,12 @@ module OneGadget
|
|
34
34
|
# contains offset only.
|
35
35
|
# Otherwise, array of gadgets is returned.
|
36
36
|
def from_file(file, details: false)
|
37
|
-
|
37
|
+
klass = {
|
38
38
|
amd64: OneGadget::Fetcher::Amd64,
|
39
|
-
i386: OneGadget::Fetcher::I386
|
40
|
-
|
41
|
-
|
42
|
-
gadgets = trim_gadgets(
|
39
|
+
i386: OneGadget::Fetcher::I386
|
40
|
+
}[OneGadget::Helper.architecture(file)]
|
41
|
+
raise ArgumentError, 'Unsupported architecture!' if klass.nil?
|
42
|
+
gadgets = trim_gadgets(klass.new(file).find)
|
43
43
|
return gadgets if details
|
44
44
|
gadgets.map(&:offset)
|
45
45
|
end
|
@@ -2,7 +2,7 @@ require 'shellwords'
|
|
2
2
|
|
3
3
|
module OneGadget
|
4
4
|
module Fetcher
|
5
|
-
#
|
5
|
+
# Define common methods for gadget fetchers.
|
6
6
|
class Base
|
7
7
|
# The absolute path of glibc.
|
8
8
|
# @return [String] The filename.
|
@@ -10,7 +10,7 @@ module OneGadget
|
|
10
10
|
# Instantiate a fetcher object.
|
11
11
|
# @param [String] file Absolute path of target libc.
|
12
12
|
def initialize(file)
|
13
|
-
@file =
|
13
|
+
@file = file
|
14
14
|
end
|
15
15
|
|
16
16
|
# Method need to be implemented in inheritors.
|
@@ -19,6 +19,12 @@ module OneGadget
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Fetch candidates that end with call exec*.
|
22
|
+
#
|
23
|
+
# Give a block to filter gadget candidates.
|
24
|
+
# @yieldparam [String] cand
|
25
|
+
# Is this candidate valid?
|
26
|
+
# @yieldreturn [Boolean]
|
27
|
+
# True for valid.
|
22
28
|
# @return [Array<String>]
|
23
29
|
# Each +String+ returned is multi-lines of assembly code.
|
24
30
|
def candidates(&block)
|
@@ -34,7 +40,7 @@ module OneGadget
|
|
34
40
|
private
|
35
41
|
|
36
42
|
def objdump_cmd(start: nil, stop: nil)
|
37
|
-
cmd = %(objdump -w -d -M intel
|
43
|
+
cmd = %(objdump -w -d -M intel #{::Shellwords.escape(file)})
|
38
44
|
cmd.concat(" --start-address #{start}") if start
|
39
45
|
cmd.concat(" --stop-address #{stop}") if stop
|
40
46
|
cmd
|
@@ -55,7 +61,8 @@ module OneGadget
|
|
55
61
|
end
|
56
62
|
|
57
63
|
def str_offset(str)
|
58
|
-
match = `strings -tx #{file} -n #{str.size} | grep
|
64
|
+
match = `strings -tx #{::Shellwords.escape(file)} -n #{str.size} | grep #{::Shellwords.escape(' ' + str)}`
|
65
|
+
match = match.lines.map(&:strip).first
|
59
66
|
return nil if match.nil?
|
60
67
|
# 17c8c3 /bin/sh
|
61
68
|
match.split.first.to_i(16)
|
data/lib/one_gadget/gadget.rb
CHANGED
@@ -40,7 +40,9 @@ module OneGadget
|
|
40
40
|
|
41
41
|
# Define class methods here.
|
42
42
|
module ClassMethods
|
43
|
-
|
43
|
+
# Path to the pre-build files.
|
44
|
+
BUILDS_PATH = File.join(__dir__, 'builds').freeze
|
45
|
+
# Cache.
|
44
46
|
BUILDS = Hash.new { |h, k| h[k] = [] }
|
45
47
|
# Get gadgets from pre-defined corpus.
|
46
48
|
# @param [String] build_id Desired build id.
|
data/lib/one_gadget/helper.rb
CHANGED
@@ -9,6 +9,7 @@ require 'one_gadget/logger'
|
|
9
9
|
module OneGadget
|
10
10
|
# Define some helpful methods here.
|
11
11
|
module Helper
|
12
|
+
# Format of build-id, 40 hex numbers.
|
12
13
|
BUILD_ID_FORMAT = /[0-9a-f]{40}/
|
13
14
|
# Define class methods here.
|
14
15
|
module ClassMethods
|
@@ -125,15 +126,16 @@ module OneGadget
|
|
125
126
|
end
|
126
127
|
|
127
128
|
# Fetch the file archiecture of +file+.
|
128
|
-
# @param [String] The target ELF filename.
|
129
|
+
# @param [String] file The target ELF filename.
|
129
130
|
# @return [String]
|
130
131
|
# Only supports :amd64, :i386 now.
|
131
132
|
def architecture(file)
|
132
133
|
str = ELFTools::ELFFile.new(File.open(file)).machine
|
133
134
|
return :amd64 if str.include?('X86-64')
|
134
135
|
return :i386 if str.include?('Intel 80386')
|
135
|
-
rescue ELFTools::ELFError # not a valid ELF
|
136
136
|
:unknown
|
137
|
+
rescue ELFTools::ELFError # not a valid ELF
|
138
|
+
:invalid
|
137
139
|
end
|
138
140
|
|
139
141
|
# Present number in hex format.
|
data/lib/one_gadget/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: one_gadget
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- david942j
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: elftools
|
@@ -99,7 +99,7 @@ description: |2
|
|
99
99
|
|
100
100
|
This gem provides such gadget finder, no need to use IDA-pro every time like a fool :p.
|
101
101
|
|
102
|
-
|
102
|
+
Typing `one_gadget /path/to/libc` in terminal and having fun!
|
103
103
|
email:
|
104
104
|
- david942j@gmail.com
|
105
105
|
executables:
|