class OneGadget::Gadget::Gadget
Information of a gadget.
Attributes
base[RW]
@return [Integer] Base address of libc. Default: 0.
constraints[R]
@return [Array<String>] The constraints need for this gadget.
effect[R]
@return [String] The final result of this gadget.
offset[R]
@return [Integer] The gadget's address offset.
Public Class Methods
new(offset, **options)
click to toggle source
Initialize method of {Gadget} instance. @param [Integer] offset The relative address offset of this gadget. @option options [Array<String>] :constraints
The constraints need for this gadget. Defaults to +[]+.
@example
OneGadget::Gadget::Gadget.new(0x12345, constraints: ['rax == 0'])
# File lib/one_gadget/gadget.rb, line 27 def initialize(offset, **options) @base = 0 @offset = offset @constraints = options[:constraints] || [] @effect = options[:effect] end
Public Instance Methods
inspect()
click to toggle source
Show gadget in a pretty way.
# File lib/one_gadget/gadget.rb, line 35 def inspect str = OneGadget::Helper.hex(value) str += effect ? " #{effect}\n" : "\n" unless constraints.empty? str += "#{OneGadget::Helper.colorize('constraints')}:\n " str += merge_constraints.join("\n ") end str.gsub!(/0x[\da-f]+/) { |s| OneGadget::Helper.colorize(s, sev: :integer) } OneGadget::ABI.all.each do |reg| str.gsub!(/([^\w])(#{reg})([^\w])/, "\\1#{OneGadget::Helper.colorize('\2', sev: :reg)}\\3") end "#{str}\n" end
score()
click to toggle source
@return [Float]
The success probability of the constraints.
# File lib/one_gadget/gadget.rb, line 57 def score @score ||= constraints.reduce(1.0) { |s, c| s * calculate_score(c) } end
value()
click to toggle source
@return [Integer]
Returns +base+ plus +offset+.
# File lib/one_gadget/gadget.rb, line 51 def value base + offset end
Private Instance Methods
calculate_null_score(expr)
click to toggle source
# File lib/one_gadget/gadget.rb, line 83 def calculate_null_score(expr) identity = expr.slice(0...expr.rindex(' == NULL')) # Thank God we are already able to parse this lmda = OneGadget::Emulators::Lambda.parse(identity) # raise Error::ArgumentError, expr unless OneGadget::ABI.all.include?(lmda.obj) # rax == 0 is easy; rax + 0x10 == 0 is damn hard. return lmda.immi.zero? ? 0.9 : 0.1 if lmda.deref_count.zero? # [sp+xx] == NULL is easy. base = OneGadget::ABI.stack_register?(lmda.obj) ? 0 : 1 0.9**(lmda.deref_count + base) end
calculate_score(expr)
click to toggle source
REG: OneGadget::ABI.all
IMM: [+-]0x+ Identity: <REG><IMM>? Identity: [<Identity>] Expr: <REG> is the GOT address of libc Expr: writable: <Identity> Expr: <Identity> == NULL Expr: <REG> & 0xf == <IMM> Expr: <Expr> || <Expr>
# File lib/one_gadget/gadget.rb, line 72 def calculate_score(expr) return expr.split(' || ').map(&method(:calculate_score)).max if expr.include?(' || ') case expr when / & 0xf/ then 0.95 when /GOT address/ then 0.9 when /^writable/ then 0.81 when / == NULL$/ then calculate_null_score(expr) end end
merge_constraints()
click to toggle source
# File lib/one_gadget/gadget.rb, line 96 def merge_constraints key = 'writable: ' w_cons, normal = constraints.partition { |c| c.start_with?(key) } return normal if w_cons.empty? w_cons.map! { |c| c[key.size..-1] } ["address#{w_cons.size > 1 ? 'es' : ''} #{w_cons.join(', ')} #{w_cons.size > 1 ? 'are' : 'is'} writable"] + normal end