Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ISeqで遊ぼう

Avatar for Tsukasa OISHI Tsukasa OISHI
September 22, 2018

 ISeqで遊ぼう

Avatar for Tsukasa OISHI

Tsukasa OISHI

September 22, 2018
Tweet

More Decks by Tsukasa OISHI

Other Decks in Programming

Transcript

  1. class HookLoadIseq def attach RubyVM::InstructionSequence.singleton_class.prepend build_module end private def build_module

    inst = self Module.new do define_method("load_iseq") do |path| source_code = File.read(path) ruby_code = inst.syntax(source_code) RubyVM::InstructionSequence.compile(ruby_code) end end end end
  2. class HookLoadIseq def attach RubyVM::InstructionSequence.singleton_class.prepend build_module end private def build_module

    inst = self Module.new do define_method("load_iseq") do |path| source_code = File.read(path) ruby_code = inst.syntax(source_code) RubyVM::InstructionSequence.compile(ruby_code) end end end end
  3. class HookLoadIseq def attach RubyVM::InstructionSequence.singleton_class.prepend build_module end private def build_module

    inst = self Module.new do define_method("load_iseq") do |path| source_code = File.read(path) ruby_code = inst.syntax(source_code) RubyVM::InstructionSequence.compile(ruby_code) end end end end
  4. class HookLoadIseq def attach RubyVM::InstructionSequence.singleton_class.prepend build_module end private def build_module

    inst = self Module.new do define_method("load_iseq") do |path| source_code = File.read(path) ruby_code = inst.syntax(source_code) RubyVM::InstructionSequence.compile(ruby_code) end end end end
  5. class HookLoadIseq def attach RubyVM::InstructionSequence.singleton_class.prepend build_module end private def build_module

    inst = self Module.new do define_method("load_iseq") do |path| source_code = File.read(path) ruby_code = inst.syntax(source_code) RubyVM::InstructionSequence.compile(ruby_code) end end end end
  6. class HookLoadIseq def attach RubyVM::InstructionSequence.singleton_class.prepend build_module end private def build_module

    inst = self Module.new do define_method("load_iseq") do |path| source_code = File.read(path) ruby_code = inst.syntax(source_code) RubyVM::InstructionSequence.compile(ruby_code) end end end end
  7. class Tsuka var kazu int = 1 var moji string

    = "tsuka" var kuji bool = false end ͜Μͳจ๏΋࣮ߦՄೳʹ
  8. ͜Μͳจ๏΋࣮ߦՄೳʹ දࣔ 1 + 2 ശ Ͷ͜ ಈ࡞ ͳ͘ "ʹΌʔ"

    ͓ΘΓ ͓ΘΓ ͨ· = Ͷ͜.͏·ΕΔ දࣔ ͨ·.ͳ͘
  9. 0000 getinstancevariable :@user, <is:0> 0003 dup 0004 branchnil 12 0006

    send <callinfo!mid:address, argc:0, …>,… 0010 jump 12 0012 leave
  10. ["YARVInstructionSequence/SimpleDataFormat", 2, 5, 1, {:arg_size=>0, :local_size=>0, :stack_max=>1, :code_range=>[1, 0, 1,

    13]}, "<compiled>", "<compiled>", nil, 1, :top, [], {}, [], [1, :RUBY_EVENT_LINE, [:getinstancevariable, :@user, 0], [:send, {:mid=>:address, :flag=>32, :orig_argc=>0}, false, nil], [:leave]]]
  11. ["YARVInstructionSequence/SimpleDataFormat", 2, 5, 1, {:arg_size=>0, :local_size=>0, :stack_max=>1, :code_range=>[1, 0, 1,

    13]}, "<compiled>", "<compiled>", nil, 1, :top, [], {}, [], [1, :RUBY_EVENT_LINE, [:getinstancevariable, :@user, 0], [:send, {:mid=>:address, :flag=>32, :orig_argc=>0}, false, nil], [:leave]]]
  12. ϝιουίʔϧͷ෦෼Λ΅ͬͪΦϖϨʔλʹॻ͖׵͑Δ ary = iseq.to_a new_bytecode = [] bytecode = ary[13]

    pc = 0 bytecode.each do |b| unless b.is_a?(Array) new_bytecode << b next end unless [ :send, :opt_send_without_block].include?(b[0]) pc += b.size new_bytecode << b next end
  13. ϝιουίʔϧͷ෦෼Λ΅ͬͪΦϖϨʔλʹॻ͖׵͑Δ buffer = [] pc += 1 buffer << [

    :dup ] pc += 2 buffer << [ :branchnil, :temp ] pc += b.size buffer << b pc += 2 label = "label_#{pc}".to_sym buffer << [ :jump, label ] buffer[1][1] = label buffer << label new_bytecode += buffer end ary[13] = new_bytecode
  14. pEEMFΛ࢖ͬͯ$ͷؔ਺ΛݺͿ def load_from_array(ary) rb_iseq_load.call(Fiddle.dlwrap(ary), nil, nil).to_value end def rb_iseq_load return

    @rb_iseq_load if @rb_iseq_load address = Fiddle::Handle::DEFAULT['rb_iseq_load'] @rb_iseq_load = Fiddle::Function.new( address, [Fiddle::TYPE_VOIDP] * 3, Fiddle::TYPE_VOIDP ) end
  15. module GuardNil2 def translate(iseq) ary = iseq.to_a ary2 = {όΠτίʔυॻ͖׵͑ॲཧ}(ideq)

    load_from_array(ary2) end end RubyVM::InstructionSequence.singleton_class.prepend GuardNil2