class OneGadget::Gadget::Gadget
Information of a gadget.
Attributes
@return [Integer] Base address of libc. Default: 0.
@return [Array<String>] The constraints need for this gadget.
@return [String] The final result of this gadget.
@return [Integer] The gadget’s address offset.
Public Class Methods
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
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
@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
@return [Integer]
Returns +base+ plus +offset+.
# File lib/one_gadget/gadget.rb, line 51 def value base + offset end
Private Instance Methods
# File lib/one_gadget/gadget.rb, line 87 def calculate_null_score(identity) # remove <CAST> identity.sub!(/^\([s|u]\d+\)/, '') # Thank God we are already able to parse this lmda = OneGadget::Emulators::Lambda.parse(identity) # 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
REG: OneGadget::ABI.all
IMM: [+-]0x+ BITS: 8, 16, 32, 64 CAST: (<s|u><BITS>) Identity: <REG><IMM>? Identity: [<Identity>] Expr: <REG> is the GOT address of libc Expr: writable: <Identity> Expr: <CAST>?<Identity> == NULL Expr: <REG> & 0xf == <IMM> Expr: (
# File lib/one_gadget/gadget.rb, line 75
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.slice(0...expr.rindex(' == NULL')))
when / <= 0$/ then calculate_null_score(expr.slice(0...expr.rindex(' <= ')))
end
end
# File lib/one_gadget/gadget.rb, line 100 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