one_gadget 1.3.4.1 → 1.3.5
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|